import React, { useState, useEffect } from "react";
import { Header } from "./components/Header";
import { DocumentPane } from "./components/DocumentPane";
import { ChatPane } from "./components/ChatPane";
import { ActionBar } from "./components/ActionBar";
import type { Project, Session, Message, Phase, TokenUsage } from "./types";
import "./styles/globals.css";

const api = window.api;

type Theme = "dark" | "light";

export function App() {
  const [projects, setProjects] = useState<Project[]>([]);
  const [sessions, setSessions] = useState<Session[]>([]);
  const [selectedProject, setSelectedProject] = useState<Project | null>(null);
  const [selectedSession, setSelectedSession] = useState<Session | null>(null);
  const [messages, setMessages] = useState<Message[]>([]);
  const [documentContent, setDocumentContent] = useState<string>("");
  const [originalContent, setOriginalContent] = useState<string>("");
  const [isLoading, setIsLoading] = useState(false);
  const [tokenUsage, setTokenUsage] = useState<TokenUsage>({
    inputTokens: 0,
    outputTokens: 0,
  });
  const [error, setError] = useState<string | null>(null);

  const [theme, setTheme] = useState<Theme>(
    () => (localStorage.getItem("cf-theme") as Theme) ?? "dark"
  );

  // Keep document.documentElement in sync and persist to localStorage
  useEffect(() => {
    document.documentElement.setAttribute("data-theme", theme);
    localStorage.setItem("cf-theme", theme);
  }, [theme]);

  const handleToggleTheme = () =>
    setTheme((t) => (t === "dark" ? "light" : "dark"));

  const hasChanges = documentContent !== originalContent;

  // Clear error after 5 seconds
  useEffect(() => {
    if (error) {
      const timer = setTimeout(() => setError(null), 5000);
      return () => clearTimeout(timer);
    }
  }, [error]);

  // Keyboard shortcuts
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      // Escape to interrupt
      if (e.key === "Escape" && isLoading && selectedSession) {
        api.interruptSession(selectedSession.id);
        setIsLoading(false);
      }
      // Cmd/Ctrl + Enter to submit
      if (
        e.key === "Enter" &&
        (e.metaKey || e.ctrlKey) &&
        selectedSession &&
        selectedSession.phase !== "implement" &&
        !isLoading
      ) {
        e.preventDefault();
        handleSubmit();
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [selectedSession, isLoading]);

  // Load projects on mount
  useEffect(() => {
    api.listProjects().then(setProjects);
  }, []);

  // Load sessions when project changes
  useEffect(() => {
    if (selectedProject) {
      api.listSessions(selectedProject.id).then(setSessions);
    } else {
      setSessions([]);
    }
  }, [selectedProject]);

  // Load messages and artifact when session changes
  useEffect(() => {
    if (selectedSession && selectedProject) {
      // Load messages
      api.listMessages(selectedSession.id).then(setMessages);

      // Load session-specific artifact (from ~/.claude-flow/)
      const filename =
        selectedSession.phase === "research" ? "research.md" : "plan.md";
      api.readSessionArtifact(selectedProject.id, selectedSession.id, filename).then((content) => {
        const text = content || "";
        setDocumentContent(text);
        setOriginalContent(text);
      });
    } else {
      setMessages([]);
      setDocumentContent("");
      setOriginalContent("");
    }
  }, [selectedSession?.id, selectedSession?.phase, selectedProject]);

  // Subscribe to Claude messages
  useEffect(() => {
    const unsubscribe = api.onClaudeMessage((sessionId, msg) => {
      if (sessionId !== selectedSession?.id) return;

      if (msg.type === "result" && msg.subtype === "success") {
        setIsLoading(false);
        if (msg.usage) {
          setTokenUsage({
            inputTokens: msg.usage.input_tokens,
            outputTokens: msg.usage.output_tokens,
            cacheHits: msg.usage.cache_read_input_tokens,
          });
        }
        // Reload artifact after Claude updates it
        if (selectedProject && selectedSession) {
          const filename =
            selectedSession.phase === "research" ? "research.md" : "plan.md";
          api.readSessionArtifact(selectedProject.id, selectedSession.id, filename).then((content) => {
            const text = content || "";
            setDocumentContent(text);
            setOriginalContent(text);
          });
        }
      }

      if (msg.type === "assistant") {
        const content = (
          msg.message.content as Array<{ type: string; text?: string }>
        )
          .filter((c) => c.type === "text" && c.text)
          .map((c) => c.text!)
          .join("\n");

        if (content) {
          setMessages((prev) => {
            const last = prev[prev.length - 1];
            if (last?.role === "assistant") {
              // Update existing assistant message
              return [...prev.slice(0, -1), { ...last, content }];
            }
            // Add new assistant message
            return [
              ...prev,
              {
                id: crypto.randomUUID(),
                session_id: sessionId,
                role: "assistant",
                content,
                created_at: Date.now() / 1000,
              },
            ];
          });
        }
      }
    });

    return unsubscribe;
  }, [selectedSession?.id, selectedSession?.phase, selectedProject]);

  const handleSendMessage = async (message: string) => {
    if (!selectedSession) return;
    setIsLoading(true);
    setError(null);
    setMessages((prev) => [
      ...prev,
      {
        id: crypto.randomUUID(),
        session_id: selectedSession.id,
        role: "user",
        content: message,
        created_at: Date.now() / 1000,
      },
    ]);
    try {
      await api.sendMessage(selectedSession.id, message);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to send message");
      setIsLoading(false);
    }
  };

  const handleReview = async () => {
    if (!selectedSession || !selectedProject) return;
    setError(null);
    try {
      // Save user edits first (session-specific, stored in ~/.claude-flow/)
      const filename =
        selectedSession.phase === "research" ? "research.md" : "plan.md";
      await api.writeSessionArtifact(selectedProject.id, selectedSession.id, filename, documentContent);
      setOriginalContent(documentContent);
      setIsLoading(true);
      await api.triggerReview(selectedSession.id);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Review failed");
      setIsLoading(false);
    }
  };

  const handleSubmit = async () => {
    if (!selectedSession || !selectedProject) return;
    setError(null);
    try {
      // Save any pending edits (session-specific, stored in ~/.claude-flow/)
      const filename =
        selectedSession.phase === "research" ? "research.md" : "plan.md";
      await api.writeSessionArtifact(selectedProject.id, selectedSession.id, filename, documentContent);

      const nextPhase = await api.advancePhase(selectedSession.id);
      if (nextPhase) {
        setSelectedSession({ ...selectedSession, phase: nextPhase });
        // Trigger initial message for next phase
        setIsLoading(true);
        const initialMsg =
          nextPhase === "plan"
            ? "Create a detailed implementation plan based on the research."
            : "Begin implementing the plan.";
        await api.sendMessage(selectedSession.id, initialMsg);
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : "Submit failed");
      setIsLoading(false);
    }
  };

  const handleCreateProject = async () => {
    const path = await api.selectDirectory();
    if (!path) return;
    const name = path.split("/").pop() || "New Project";
    const project = await api.createProject(name, path);
    setProjects((prev) => [project, ...prev]);
    setSelectedProject(project);
  };

  const handleCreateSession = async () => {
    if (!selectedProject) return;
    const name = `Session ${sessions.length + 1}`;
    const session = await api.createSession(selectedProject.id, name);
    setSessions((prev) => [session, ...prev]);
    setSelectedSession(session);
    setMessages([]);
    setDocumentContent("");
    setOriginalContent("");
    // Note: Each session has its own artifact directory, no need to clear
  };

  const handleDeleteProject = async (id: string) => {
    try {
      await api.deleteProject(id);
      setProjects((prev) => prev.filter((p) => p.id !== id));
      if (selectedProject?.id === id) {
        setSelectedProject(null);
        setSelectedSession(null);
        setSessions([]);
        setMessages([]);
        setDocumentContent("");
        setOriginalContent("");
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to delete project");
    }
  };

  const handleDeleteSession = async (id: string) => {
    try {
      await api.deleteSession(id);
      setSessions((prev) => prev.filter((s) => s.id !== id));
      if (selectedSession?.id === id) {
        setSelectedSession(null);
        setMessages([]);
        setDocumentContent("");
        setOriginalContent("");
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to delete session");
    }
  };

  return (
    <div className="app">
      <Header
        projects={projects}
        sessions={sessions}
        selectedProject={selectedProject}
        selectedSession={selectedSession}
        onSelectProject={setSelectedProject}
        onSelectSession={setSelectedSession}
        onCreateProject={handleCreateProject}
        onCreateSession={handleCreateSession}
        onDeleteProject={handleDeleteProject}
        onDeleteSession={handleDeleteSession}
        theme={theme}
        onToggleTheme={handleToggleTheme}
      />

      <div className="main-content">
        <DocumentPane
          content={documentContent}
          onChange={setDocumentContent}
          phase={selectedSession?.phase || "research"}
          disabled={!selectedSession || selectedSession.phase === "implement"}
          showOnboarding={!selectedProject}
          theme={theme}
        />

        <ChatPane
          messages={messages}
          onSend={handleSendMessage}
          isLoading={isLoading}
          disabled={!selectedSession}
          placeholder={
            selectedSession
              ? `Chat with Claude (${selectedSession.phase})...`
              : "Select a session to start"
          }
        />
      </div>

      {error && (
        <div className="error-bar">
          <span>⚠️ {error}</span>
          <button onClick={() => setError(null)}>×</button>
        </div>
      )}

      <ActionBar
        phase={selectedSession?.phase || "research"}
        hasChanges={hasChanges}
        isLoading={isLoading}
        tokenUsage={tokenUsage}
        permissionMode={selectedSession?.permission_mode || "acceptEdits"}
        onReview={handleReview}
        onSubmit={handleSubmit}
        onPermissionModeChange={(mode) => {
          if (selectedSession) {
            api.setPermissionMode(selectedSession.id, mode);
            setSelectedSession({ ...selectedSession, permission_mode: mode });
          }
        }}
        disabled={!selectedSession}
      />
    </div>
  );
}
