import { useRef, useEffect, useState, createContext, useContext, useMemo, type ReactNode } from 'react';

// ---------------------------------------------------------------------------
// ConversationContext — shared state for child ai-elements components
// ---------------------------------------------------------------------------

interface ConversationContextValue {
  isStreaming: boolean;
  setIsStreaming: (v: boolean) => void;
  messages: unknown[];
  setMessages: (msgs: unknown[]) => void;
}

const ConversationContext = createContext<ConversationContextValue | null>(null);

export function useConversationContext() {
  const ctx = useContext(ConversationContext);
  if (!ctx) {
    throw new Error('useConversationContext must be used within ConversationProvider');
  }
  return ctx;
}

export function ConversationProvider({ children }: { children: ReactNode }) {
  const [isStreaming, setIsStreaming] = useState(false);
  const [messages, setMessages] = useState<unknown[]>([]);

  const value = useMemo(
    () => ({ isStreaming, setIsStreaming, messages, setMessages }),
    [isStreaming, messages],
  );

  return (
    <ConversationContext.Provider value={value}>
      {children}
    </ConversationContext.Provider>
  );
}

// ---------------------------------------------------------------------------
// Conversation container with auto-stick-to-bottom scroll behavior
// ---------------------------------------------------------------------------

/**
 * Conversation container with auto-stick-to-bottom scroll behavior.
 *
 * Inspired by DeerFlow's use-stick-to-bottom pattern:
 * - Stays pinned to bottom during streaming
 * - Remembers user's scroll position when they scroll up
 * - Auto-scrolls back to bottom on new content when near the bottom
 */
interface ConversationProps {
  children: ReactNode;
  className?: string;
}

const SCROLL_THRESHOLD = 80; // px from bottom to consider "at bottom"

export function Conversation({ children, className = '' }: ConversationProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const isAtBottomRef = useRef(true);
  const observerRef = useRef<ResizeObserver | null>(null);

  // Track whether user is near the bottom
  const handleScroll = () => {
    const el = containerRef.current;
    if (!el) return;
    const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
    isAtBottomRef.current = distanceFromBottom < SCROLL_THRESHOLD;
  };

  // Auto-scroll to bottom when content changes and user is at bottom
  useEffect(() => {
    const el = containerRef.current;
    if (!el) return;

    observerRef.current = new ResizeObserver(() => {
      if (isAtBottomRef.current) {
        el.scrollTop = el.scrollHeight;
      }
    });

    observerRef.current.observe(el);

    return () => {
      observerRef.current?.disconnect();
    };
  }, []);

  // Also observe child list changes (new messages)
  useEffect(() => {
    const el = containerRef.current;
    if (!el) return;

    const mutationObserver = new MutationObserver(() => {
      if (isAtBottomRef.current) {
        el.scrollTop = el.scrollHeight;
      }
    });

    mutationObserver.observe(el, { childList: true, subtree: true });

    return () => {
      mutationObserver.disconnect();
    };
  }, []);

  return (
    <div
      ref={containerRef}
      onScroll={handleScroll}
      className={`overflow-y-auto custom-scrollbar ${className}`}
    >
      {children}
    </div>
  );
}
