import { useCallback, useEffect, useRef, useState, type Dispatch, type SetStateAction } from 'react';
import type { ChatConversationSummary } from '../../mainChatPanel/types';
import { emitChatConversationsUpdated } from '../data/chatClientEvents';
import { chatGateway } from '../data/chatGateway';
import { mergeConversationItemsPreservingRequestedSession } from './conversationListMerge';

type UseConversationListDataOptions = {
  requestedSessionId: string;
  enabled?: boolean;
};

type UseConversationListDataResult = {
  conversationItems: ChatConversationSummary[];
  setConversationItems: Dispatch<SetStateAction<ChatConversationSummary[]>>;
  isConversationListLoading: boolean;
  reloadConversationItems: () => Promise<void>;
  conversationSearch: string;
  setConversationSearch: Dispatch<SetStateAction<string>>;
};

export function useConversationListData({
  requestedSessionId,
  enabled = true,
}: UseConversationListDataOptions): UseConversationListDataResult {
  const [conversationItems, setConversationItems] = useState<ChatConversationSummary[]>([]);
  const [isConversationListLoading, setIsConversationListLoading] = useState(false);
  const [conversationSearch, setConversationSearch] = useState('');
  const isMountedRef = useRef(true);
  const listRequestIdRef = useRef(0);
  const pendingRequestRef = useRef<Promise<void> | null>(null);

  const loadConversationItems = useCallback(async (options?: { silent?: boolean }) => {
    if (pendingRequestRef.current) {
      return pendingRequestRef.current;
    }

    const requestId = listRequestIdRef.current + 1;
    listRequestIdRef.current = requestId;
    const isSilent = options?.silent === true;

    if (!isSilent) {
      setIsConversationListLoading(true);
    }

    const requestPromise = (async () => {
      try {
        const items = await chatGateway.listConversations();
        if (!isMountedRef.current || listRequestIdRef.current !== requestId) {
          return;
        }

        setConversationItems((previous) => {
          const nextItems = mergeConversationItemsPreservingRequestedSession(items, previous, requestedSessionId);
          return nextItems;
        });
      } catch {
        if (!isMountedRef.current || listRequestIdRef.current !== requestId) {
          return;
        }

        setConversationItems((previous) => previous);
      } finally {
        pendingRequestRef.current = null;

        if (!isMountedRef.current || listRequestIdRef.current !== requestId || isSilent) {
          return;
        }

        setIsConversationListLoading(false);
      }
    })();

    pendingRequestRef.current = requestPromise;
    return requestPromise;
  }, [requestedSessionId]);

  useEffect(() => {
    isMountedRef.current = true;
    if (enabled) {
      setIsConversationListLoading(true);
      void loadConversationItems();
    } else {
      setIsConversationListLoading(false);
    }

    return () => {
      isMountedRef.current = false;
    };
  }, [enabled, loadConversationItems]);

  useEffect(() => {
    emitChatConversationsUpdated(conversationItems);
  }, [conversationItems]);

  return {
    conversationItems,
    setConversationItems,
    isConversationListLoading,
    reloadConversationItems: loadConversationItems,
    conversationSearch,
    setConversationSearch,
  };
}
