"use client";

import React, {
  useCallback,
  useEffect,
  useRef,
  useState,
} from "react";
import { Box, Drawer, alpha, useTheme } from "@mui/material";

import type { AgentModel } from "@/lib/chatStream";
import { useProjectStore } from "@/store/projectStore";
import { AgentComposer } from "./AgentComposer";
import { AgentHeader } from "./AgentHeader";
import { AgentHistoryPanel } from "./AgentHistoryPanel";
import { AgentWorkspace } from "./AgentWorkspace";
import { Blob } from "./GlobalChatbox.parts";
import type { Props } from "./GlobalChatbox.types";
import { PRESET_PROMPTS } from "./GlobalChatbox.utils";
import { useSpeechRecognition, useSpeechSynthesis } from "./GlobalChatbox.voice";
import { useAgentChatSession } from "./hooks/useAgentChatSession";
import { useAgentToolActions } from "./hooks/useAgentToolActions";

export const GlobalChatbox: React.FC<Props> = ({ open, onClose }) => {
  const [input, setInput] = useState("");
  const [width, setWidth] = useState(520);
  const [isResizing, setIsResizing] = useState(false);
  const [isHistoryOpen, setIsHistoryOpen] = useState(false);
  const [selectedModel, setSelectedModel] = useState<AgentModel>(
    "deepseek/deepseek-v4-pro",
  );

  const bottomRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement | null>(null);
  const hasResetForOpenRef = useRef(false);
  const theme = useTheme();
  const currentProjectId = useProjectStore((state) => state.currentProjectId);

  const {
    speechState,
    speakingMessageId,
    speak: handleSpeak,
    pause: handlePauseSpeech,
    resume: handleResumeSpeech,
    stop: handleStopSpeech,
    isSupported: isTtsSupported,
  } = useSpeechSynthesis();

  const handleSpeechResult = useCallback((text: string) => {
    setInput((prev) => prev + text);
  }, []);

  const {
    isListening,
    start: startListening,
    stop: stopListening,
    isSupported: isSttSupported,
  } = useSpeechRecognition(handleSpeechResult);

  const handleToolCall = useAgentToolActions();
  const {
    messages,
    chatSessions,
    activeStorageSessionId,
    branchGroups,
    branchTransition,
    isHydrating,
    isStreaming,
    sessionTitle,
    sendPrompt,
    regenerate,
    editAndResubmit,
    cycleBranch,
    abort,
    createSession,
    renameSession,
    removeSession,
    switchSession,
  } = useAgentChatSession({
    projectId: currentProjectId,
    onToolCall: handleToolCall,
    onBeforeSend: stopListening,
    getModel: () => selectedModel,
  });

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages, isStreaming]);

  useEffect(() => {
    if (!open) {
      hasResetForOpenRef.current = false;
      return;
    }
    if (hasResetForOpenRef.current || isHydrating) return;
    hasResetForOpenRef.current = true;

    const timer = window.setTimeout(() => {
      createSession();
      setInput("");
      setIsHistoryOpen(false);
      inputRef.current?.focus();
      bottomRef.current?.scrollIntoView({ behavior: "auto" });
    }, 0);
    return () => window.clearTimeout(timer);
  }, [createSession, isHydrating, open]);

  const handleSend = useCallback(() => {
    const prompt = input.trim();
    if (!prompt || isStreaming) return;
    setInput("");
    void sendPrompt(prompt);
  }, [input, isStreaming, sendPrompt]);

  const handlePresetPromptSelect = useCallback((prompt: string) => {
    setInput(prompt);
    window.setTimeout(() => {
      inputRef.current?.focus();
    }, 0);
  }, []);

  const handleNewConversation = useCallback(() => {
    handleStopSpeech();
    stopListening();
    createSession();
    setInput("");
    window.setTimeout(() => {
      inputRef.current?.focus();
    }, 0);
  }, [createSession, handleStopSpeech, stopListening]);

  const handleHistoryToggle = useCallback(() => {
    setIsHistoryOpen((prev) => !prev);
  }, []);

  const handleSelectSession = useCallback(
    (storageSessionId: string) => {
      setInput("");
      void switchSession(storageSessionId);
    },
    [switchSession],
  );

  const handleDeleteSession = useCallback(
    (storageSessionId: string) => {
      void removeSession(storageSessionId);
    },
    [removeSession],
  );

  const handleRenameSession = useCallback(
    (storageSessionId: string, title: string) => {
      void renameSession(storageSessionId, title);
    },
    [renameSession],
  );

  const handleRenameActiveSession = useCallback(
    (title: string) => {
      if (!activeStorageSessionId) return;
      void renameSession(activeStorageSessionId, title);
    },
    [activeStorageSessionId, renameSession],
  );

  const handleMouseDown = useCallback((event: React.MouseEvent) => {
    event.preventDefault();
    setIsResizing(true);
  }, []);

  useEffect(() => {
    const handleMouseMove = (event: MouseEvent) => {
      if (!isResizing) return;
      const newWidth = window.innerWidth - event.clientX;
      if (newWidth > 360 && newWidth < 800) {
        setWidth(newWidth);
      }
    };

    const handleMouseUp = () => {
      setIsResizing(false);
    };

    if (isResizing) {
      window.addEventListener("mousemove", handleMouseMove);
      window.addEventListener("mouseup", handleMouseUp);
    }

    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
      window.removeEventListener("mouseup", handleMouseUp);
    };
  }, [isResizing]);

  return (
    <Drawer
      anchor="right"
      variant="temporary"
      open={open}
      onClose={onClose}
      hideBackdrop
      disableScrollLock
      disableEnforceFocus
      sx={{
        zIndex: (muiTheme) => muiTheme.zIndex.modal + 100,
        pointerEvents: "none",
      }}
      PaperProps={{
        sx: {
          width: { xs: "100%", sm: width },
          background: "transparent",
          boxShadow: "none",
          overflow: open ? "visible" : "hidden",
          zIndex: (muiTheme) => muiTheme.zIndex.modal + 100,
          pointerEvents: "auto",
          transition: isResizing ? "none" : undefined,
        },
      }}
    >
      <Box
        sx={{
          height: "100%",
          display: "flex",
          flexDirection: "column",
          bgcolor: alpha("#fff", 0.76),
          backdropFilter: "blur(30px)",
          position: "relative",
        }}
      >
        <Box
          onMouseDown={handleMouseDown}
          sx={{
            position: "absolute",
            left: 0,
            top: 0,
            bottom: 0,
            width: "6px",
            cursor: "col-resize",
            zIndex: 200,
            "&:hover": {
              bgcolor: alpha(theme.palette.primary.main, 0.2),
            },
            "&::after": {
              content: '""',
              position: "absolute",
              left: "50%",
              top: "50%",
              transform: "translate(-50%, -50%)",
              width: "2px",
              height: "40px",
              bgcolor: alpha(theme.palette.divider, 0.4),
              borderRadius: "1px",
            },
          }}
        />

        <Blob color={alpha(theme.palette.primary.main, 0.28)} size={300} top="-10%" left="-20%" delay={0} />
        <Blob color={alpha(theme.palette.secondary.main, 0.24)} size={250} top="40%" left="60%" delay={2} />
        <Blob color={alpha(theme.palette.success.light, 0.18)} size={200} top="80%" left="-10%" delay={4} />

        <AgentHeader
          sessionTitle={sessionTitle}
          canRenameSessionTitle={Boolean(activeStorageSessionId)}
          isHydrating={isHydrating}
          isStreaming={isStreaming}
          isHistoryOpen={isHistoryOpen}
          onHistoryToggle={handleHistoryToggle}
          onRenameSessionTitle={handleRenameActiveSession}
          onNewConversation={handleNewConversation}
          onClose={onClose}
        />

        <Box sx={{ flex: 1, display: "flex", minHeight: 0, position: "relative", overflow: "hidden" }}>
          <Box
            onClick={() => setIsHistoryOpen(false)}
            sx={{
              position: "absolute",
              inset: 0,
              bgcolor: alpha("#000", 0.05),
              backdropFilter: "blur(2px)",
              opacity: isHistoryOpen ? 1 : 0,
              pointerEvents: isHistoryOpen ? "auto" : "none",
              transition: "opacity 0.3s ease",
              zIndex: 10,
            }}
          />
          <Box
            sx={{
              position: "absolute",
              top: 0,
              bottom: 0,
              left: 0,
              width: 268,
              zIndex: 20,
              transform: isHistoryOpen ? "translateX(0)" : "translateX(-100%)",
              transition: "transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1)",
              boxShadow: isHistoryOpen ? `4px 0 24px ${alpha("#000", 0.08)}` : "none",
            }}
          >
            <AgentHistoryPanel
              sessions={chatSessions}
              activeSessionId={activeStorageSessionId}
              isHydrating={isHydrating}
              onNewSession={() => {
                handleNewConversation();
                setIsHistoryOpen(false);
              }}
              onSelectSession={(id) => {
                handleSelectSession(id);
                setIsHistoryOpen(false);
              }}
              onRenameSession={handleRenameSession}
              onDeleteSession={handleDeleteSession}
            />
          </Box>

          <Box sx={{ flex: 1, display: "flex", minWidth: 0, flexDirection: "column" }}>
            <AgentWorkspace
              messages={messages}
              branchGroups={branchGroups}
              branchTransition={branchTransition}
              isStreaming={isStreaming}
              bottomRef={bottomRef}
              speakingMessageId={speakingMessageId}
              speechState={speechState}
              onSpeak={handleSpeak}
              onPauseSpeech={handlePauseSpeech}
              onResumeSpeech={handleResumeSpeech}
              onStopSpeech={handleStopSpeech}
              isTtsSupported={isTtsSupported}
              onRegenerate={regenerate}
              onEditResubmit={editAndResubmit}
              onCycleBranch={cycleBranch}
            />

            <AgentComposer
              input={input}
              inputRef={inputRef}
              isHydrating={isHydrating}
              isStreaming={isStreaming}
              isListening={isListening}
              isSttSupported={isSttSupported}
              presets={PRESET_PROMPTS}
              onInputChange={setInput}
              onSend={handleSend}
              onAbort={abort}
              onStartListening={startListening}
              onStopListening={stopListening}
              onPresetSelect={handlePresetPromptSelect}
              selectedModel={selectedModel}
              onModelChange={setSelectedModel}
            />
          </Box>
        </Box>
      </Box>
    </Drawer>
  );
};
