import { useCallback } from 'react';
import { removeChatRuntimeJob } from '../../mainChatPanel';
import { chatConnectionGateway } from '../data/chatConnectionGateway';
import { chatGateway } from '../data/chatGateway';
import type {
  ChatComposerAttachment,
  ChatConversationRequest,
  ChatConversationSummary,
  ChatMessage,
  ChatPromptContextRef,
} from '../../mainChatPanel/types';

type PendingChatRequest = {
  sessionId: string;
  requestId: string;
  text: string;
  mode: 'queue' | 'direct';
  promptContextRef?: ChatPromptContextRef | null;
  omitPromptHistory?: boolean;
  codexModel: string;
  chatTypeId: string;
  chatTypeLabel: string;
  chatTypeDescription: string;
  chatTypeBaseDescription?: string;
  defaultContexts?: Array<{
    id: string;
    title: string;
    content: string;
  }>;
  customContextTitle?: string | null;
  customContextContent?: string | null;
  retryCount: number;
  failed: boolean;
};

type UseConversationRoomActionsControllerOptions = {
  activeSessionId: string;
  requestedSessionId: string;
  handledRequestedSessionIdRef: { current: string };
  isClosingConversationRef: { current: boolean };
  conversationItems: ChatConversationSummary[];
  isMobileViewport: boolean;
  pendingRequestsRef: { current: PendingChatRequest[] };
  sessionMessageCacheRef: { current: Map<string, ChatMessage[]> };
  socketRef: { current: WebSocket | null };
  setConversationItems: React.Dispatch<React.SetStateAction<ChatConversationSummary[]>>;
  setMessages: React.Dispatch<React.SetStateAction<ChatMessage[]>>;
  setRequestItems: React.Dispatch<React.SetStateAction<ChatConversationRequest[]>>;
  setActiveSessionId: (value: string) => void;
  setDraft: (value: string) => void;
  setComposerAttachments: React.Dispatch<React.SetStateAction<ChatComposerAttachment[]>>;
  setCopiedMessageId: (value: number | null) => void;
  setActivePreviewId: (value: string | null) => void;
  setIsPreviewModalOpen: (value: boolean) => void;
  setActiveSystemStatus: (value: string | null) => void;
  setIsSystemStatusPending: (value: boolean) => void;
  setIsResourceStripOpen: (value: boolean) => void;
  setIsConversationPaneClosed: (value: boolean) => void;
  setIsMobileConversationView: (value: boolean) => void;
  setPreserveEmptyConversationSelection: (value: boolean) => void;
  updatePendingMessageStatus: (requestId: string, status: 'retrying' | 'failed' | null, retryCount?: number) => void;
  sendChatRequest: (socket: WebSocket, request: PendingChatRequest) => void;
  createLocalMessage: (text: string) => ChatMessage;
  replaceChatSessionInUrl: (sessionId: string) => void;
  messageApi: {
    error: (content: string) => void;
  };
};

export function useConversationRoomActionsController({
  activeSessionId,
  requestedSessionId,
  handledRequestedSessionIdRef,
  isClosingConversationRef,
  conversationItems,
  isMobileViewport,
  pendingRequestsRef,
  sessionMessageCacheRef,
  socketRef,
  setConversationItems,
  setMessages,
  setRequestItems,
  setActiveSessionId,
  setDraft,
  setComposerAttachments,
  setCopiedMessageId,
  setActivePreviewId,
  setIsPreviewModalOpen,
  setActiveSystemStatus,
  setIsSystemStatusPending,
  setIsResourceStripOpen,
  setIsConversationPaneClosed,
  setIsMobileConversationView,
  setPreserveEmptyConversationSelection,
  updatePendingMessageStatus,
  sendChatRequest,
  createLocalMessage,
  replaceChatSessionInUrl,
  messageApi,
}: UseConversationRoomActionsControllerOptions) {
  const removeOptimisticRequestMessages = useCallback(
    (requestId: string) => {
      setMessages((previous) => previous.filter((message) => message.clientRequestId !== requestId));
    },
    [setMessages],
  );

  const retryPendingRequest = useCallback(
    (requestId: string) => {
      const currentRequest = pendingRequestsRef.current.find(
        (request) => request.requestId === requestId && request.sessionId === activeSessionId,
      );

      if (!currentRequest) {
        setMessages((previous) => [
          ...previous.slice(-39),
          createLocalMessage('재전송할 요청 정보를 찾지 못했습니다. 같은 내용을 다시 보내 주세요.'),
        ]);
        return;
      }

      const resetRequest: PendingChatRequest = {
        ...currentRequest,
        retryCount: 0,
        failed: false,
      };

      setActiveSystemStatus('전송 재시도 중...');
      setIsSystemStatusPending(true);

      const socket = socketRef.current;

      if (!socket || socket.readyState !== WebSocket.OPEN) {
        updatePendingMessageStatus(requestId, 'retrying', 0);
        pendingRequestsRef.current = [
          ...pendingRequestsRef.current.filter((request) => request.requestId !== requestId),
          resetRequest,
        ];
        return;
      }

      try {
        sendChatRequest(socket, resetRequest);
        updatePendingMessageStatus(requestId, null, 0);
        pendingRequestsRef.current = pendingRequestsRef.current.filter((request) => request.requestId !== requestId);
      } catch {
        updatePendingMessageStatus(requestId, 'retrying', 0);
        pendingRequestsRef.current = [
          ...pendingRequestsRef.current.filter((request) => request.requestId !== requestId),
          resetRequest,
        ];
      }
    },
    [
      activeSessionId,
      createLocalMessage,
      pendingRequestsRef,
      sendChatRequest,
      setActiveSystemStatus,
      setIsSystemStatusPending,
      setMessages,
      socketRef,
      updatePendingMessageStatus,
    ],
  );

  const cancelPendingRequest = useCallback(
    (requestId: string) => {
      const currentRequest = pendingRequestsRef.current.find(
        (request) => request.requestId === requestId && request.sessionId === activeSessionId,
      );

      if (!currentRequest) {
        removeOptimisticRequestMessages(requestId);
        setActiveSystemStatus('미접수 요청을 화면에서 제거했습니다.');
        setIsSystemStatusPending(false);
        return;
      }

      pendingRequestsRef.current = pendingRequestsRef.current.filter((request) => request.requestId !== requestId);
      removeOptimisticRequestMessages(requestId);
      setRequestItems((previous) =>
        previous.filter((item) => !(item.sessionId === activeSessionId && item.requestId === requestId)),
      );
      setActiveSystemStatus('실패한 요청을 취소했습니다.');
      setIsSystemStatusPending(false);
    },
    [
      activeSessionId,
      pendingRequestsRef,
      removeOptimisticRequestMessages,
      setActiveSystemStatus,
      setIsSystemStatusPending,
      setRequestItems,
    ],
  );

  const removeQueuedComposerRequest = useCallback(
    async (requestId: string) => {
      try {
        await removeChatRuntimeJob(requestId);
        setRequestItems((previous) =>
          previous.map((item) =>
            item.sessionId === activeSessionId && item.requestId === requestId
              ? {
                  ...item,
                  status: 'removed',
                  statusMessage: '대기열에서 제거되었습니다.',
                  terminalAt: new Date().toISOString(),
                  updatedAt: new Date().toISOString(),
                }
              : item,
          ),
        );
        setActiveSystemStatus('대기 요청을 삭제했습니다.');
        setIsSystemStatusPending(false);
      } catch (error) {
        setMessages((previous) => [
          ...previous.slice(-39),
          createLocalMessage(error instanceof Error ? error.message : '대기 요청 제거 중 오류가 발생했습니다.'),
        ]);
      }
    },
    [activeSessionId, createLocalMessage, setActiveSystemStatus, setIsSystemStatusPending, setMessages, setRequestItems],
  );

  const deleteStoredRequest = useCallback(
    async (requestId: string) => {
      try {
        await chatGateway.deleteConversationRequest(activeSessionId, requestId);
        setMessages((previous) => previous.filter((message) => message.clientRequestId !== requestId));
        setRequestItems((previous) =>
          previous.filter((item) => !(item.sessionId === activeSessionId && item.requestId === requestId)),
        );
        setConversationItems((previous) =>
          previous.map((item) =>
            item.sessionId === activeSessionId
              ? {
                  ...item,
                  currentRequestId: item.currentRequestId === requestId ? null : item.currentRequestId,
                  currentJobStatus: item.currentRequestId === requestId ? null : item.currentJobStatus,
                  currentJobMessage: item.currentRequestId === requestId ? null : item.currentJobMessage,
                  currentQueueSize: item.currentRequestId === requestId ? 0 : item.currentQueueSize,
                }
              : item,
          ),
        );
        setActiveSystemStatus('요청을 삭제했습니다.');
        setIsSystemStatusPending(false);
      } catch (error) {
        setMessages((previous) => [
          ...previous.slice(-39),
          createLocalMessage(error instanceof Error ? error.message : '요청 삭제 중 오류가 발생했습니다.'),
        ]);
      }
    },
    [
      activeSessionId,
      createLocalMessage,
      setActiveSystemStatus,
      setConversationItems,
      setIsSystemStatusPending,
      setMessages,
      setRequestItems,
    ],
  );

  const handleDeleteConversation = useCallback(
    async (sessionId: string) => {
      try {
        const targetConversation = conversationItems.find((entry) => entry.sessionId === sessionId) ?? null;

        if (!targetConversation) {
          return;
        }

        if (!targetConversation.isDraftOnly) {
          await chatGateway.deleteConversation(sessionId);
        }

        const remaining = conversationItems.filter((entry) => entry.sessionId !== sessionId);
        sessionMessageCacheRef.current.delete(sessionId);
        setConversationItems(remaining);

        if (sessionId === activeSessionId) {
          isClosingConversationRef.current = true;
          handledRequestedSessionIdRef.current = '';
          setPreserveEmptyConversationSelection(true);
          replaceChatSessionInUrl('');
          chatConnectionGateway.resetLastReceivedEventId('');
          setActiveSessionId('');
          setMessages([]);
          setRequestItems([]);
          setDraft('');
          setComposerAttachments([]);
          setCopiedMessageId(null);
          setActivePreviewId(null);
          setIsPreviewModalOpen(false);
          setActiveSystemStatus(null);
          setIsSystemStatusPending(false);
          setIsResourceStripOpen(false);
          setIsConversationPaneClosed(true);
          setIsMobileConversationView(false);
        } else if (requestedSessionId === sessionId) {
          handledRequestedSessionIdRef.current = '';
          replaceChatSessionInUrl(activeSessionId);
        }
      } catch (error) {
        messageApi.error(error instanceof Error ? error.message : '대화방 삭제 중 오류가 발생했습니다.');
      }
    },
    [
      activeSessionId,
      conversationItems,
      handledRequestedSessionIdRef,
      isClosingConversationRef,
      isMobileViewport,
      messageApi,
      replaceChatSessionInUrl,
      requestedSessionId,
      sessionMessageCacheRef,
      setActivePreviewId,
      setActiveSessionId,
      setActiveSystemStatus,
      setComposerAttachments,
      setConversationItems,
      setCopiedMessageId,
      setDraft,
      setIsConversationPaneClosed,
      setIsMobileConversationView,
      setIsPreviewModalOpen,
      setIsResourceStripOpen,
      setIsSystemStatusPending,
      setPreserveEmptyConversationSelection,
      setMessages,
      setRequestItems,
    ],
  );

  const handleClearConversation = useCallback(
    async (sessionId: string) => {
      try {
        const item = await chatGateway.clearConversation(sessionId);
        sessionMessageCacheRef.current.set(sessionId, []);
        setConversationItems((previous) => previous.map((entry) => (entry.sessionId === sessionId ? item : entry)));

        if (sessionId === activeSessionId) {
          chatConnectionGateway.resetLastReceivedEventId(sessionId);
          setMessages([]);
          setRequestItems([]);
          setDraft('');
          setComposerAttachments([]);
          setCopiedMessageId(null);
          setActivePreviewId(null);
          setIsPreviewModalOpen(false);
          setActiveSystemStatus('채팅방 데이터를 초기화했습니다.');
          setIsSystemStatusPending(false);
          setIsResourceStripOpen(false);
        }
      } catch (error) {
        messageApi.error(error instanceof Error ? error.message : '채팅방 데이터 초기화 중 오류가 발생했습니다.');
      }
    },
    [
      activeSessionId,
      messageApi,
      sessionMessageCacheRef,
      setActivePreviewId,
      setActiveSystemStatus,
      setComposerAttachments,
      setConversationItems,
      setCopiedMessageId,
      setDraft,
      setIsPreviewModalOpen,
      setIsResourceStripOpen,
      setIsSystemStatusPending,
      setMessages,
      setRequestItems,
    ],
  );

  return {
    cancelPendingRequest,
    handleClearConversation,
    deleteStoredRequest,
    handleDeleteConversation,
    removeQueuedComposerRequest,
    retryPendingRequest,
  };
}
