"use client";

import { useState, useCallback, useRef, useEffect } from "react";
import type { AguiMessage } from "@optage/sdk/client";
import type { ChatMessage, AnalysisStateSnapshot, InterruptPayload } from "@optage/sdk/client";
import {
  fetchSessions,
  fetchSession,
  createSessionApi,
  updateSessionApi,
  deleteSessionApi,
  deriveTitle,
  groupByDate,
  type SessionSummary,
  type ChatSession,
} from "@/lib/sessions";

export interface UseSessionManagerReturn {
  sessions: SessionSummary[];
  activeSessionId: string | null;
  activeSession: ChatSession | null;
  sidebarOpen: boolean;
  repositoryId: string | null;
  setRepositoryId: (id: string) => void;
  createNewSession: () => Promise<ChatSession>;
  switchSession: (id: string) => Promise<void>;
  deleteSessionById: (id: string) => Promise<void>;
  toggleSidebar: () => void;
  persistMessages: (
    messages: ChatMessage[],
    aguiHistory: AguiMessage[],
    analysisState?: AnalysisStateSnapshot,
    pendingInterrupt?: InterruptPayload | null,
  ) => void;
  groupedSessions: ReturnType<typeof groupByDate>;
  refreshSessions: () => Promise<void>;
  initFromBootstrap: (data: { sessions: SessionSummary[]; activeSession: ChatSession | null }) => void;
  clearBootstrapped: () => void;
}

export function useSessionManager(): UseSessionManagerReturn {
  const [sessions, setSessions] = useState<SessionSummary[]>([]);
  const [activeSessionId, setActiveSessionId] = useState<string | null>(null);
  const [activeSession, setActiveSession] = useState<ChatSession | null>(null);
  const [sidebarOpen, setSidebarOpen] = useState(true);
  const [repositoryId, setRepositoryIdState] = useState<string | null>(() => {
    if (typeof window === "undefined") return null;
    return window.localStorage.getItem("activeRepositoryId");
  });
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const bootstrappedRef = useRef(false);

  const refreshSessionsForRepo = useCallback(async (repoId: string) => {
    const list = await fetchSessions(repoId);
    setSessions(list);
    return list;
  }, []);

  const setRepositoryId = useCallback(
    (id: string) => {
      bootstrappedRef.current = true;
      setRepositoryIdState(id);
      if (typeof window !== "undefined") {
        window.localStorage.setItem("activeRepositoryId", id);
      }
      setActiveSessionId(null);
      setActiveSession(null);
    },
    [],
  );

  const clearBootstrapped = useCallback(() => {
    bootstrappedRef.current = false;
  }, []);

  useEffect(() => {
    if (!repositoryId) return;
    if (bootstrappedRef.current) {
      bootstrappedRef.current = false;
      return;
    }
    let cancelled = false;
    (async () => {
      const list = await refreshSessionsForRepo(repositoryId);
      if (cancelled) return;
      if (list.length > 0) {
        const session = await fetchSession(list[0].id);
        if (!cancelled && session) {
          setActiveSessionId(session.id);
          setActiveSession(session);
        }
      } else {
        const session = await createSessionApi(repositoryId);
        if (!cancelled) {
          setActiveSessionId(session.id);
          setActiveSession(session);
          await refreshSessionsForRepo(repositoryId);
        }
      }
    })();
    return () => { cancelled = true; };
  }, [repositoryId, refreshSessionsForRepo]);

  const initFromBootstrap = useCallback(
    (data: { sessions: SessionSummary[]; activeSession: ChatSession | null }) => {
      setSessions(data.sessions);
      if (data.activeSession) {
        setActiveSessionId(data.activeSession.id);
        setActiveSession(data.activeSession);
      } else {
        setActiveSessionId(null);
        setActiveSession(null);
      }
    },
    [],
  );

  const createNewSession = useCallback(async (): Promise<ChatSession> => {
    if (!repositoryId) throw new Error("No repository selected");
    const session = await createSessionApi(repositoryId);
    setActiveSessionId(session.id);
    setActiveSession(session);
    await refreshSessionsForRepo(repositoryId);
    return session;
  }, [repositoryId, refreshSessionsForRepo]);

  const switchSession = useCallback(
    async (id: string) => {
      if (id === activeSessionId) return;
      const session = await fetchSession(id);
      if (!session) return;
      setActiveSessionId(id);
      setActiveSession(session);
    },
    [activeSessionId],
  );

  const deleteSessionById = useCallback(
    async (id: string) => {
      await deleteSessionApi(id);
      if (!repositoryId) return;
      const list = await refreshSessionsForRepo(repositoryId);
      if (id === activeSessionId) {
        if (list.length > 0) {
          const session = await fetchSession(list[0].id);
          setActiveSessionId(session?.id ?? null);
          setActiveSession(session);
        } else {
          setActiveSessionId(null);
          setActiveSession(null);
        }
      }
    },
    [activeSessionId, repositoryId, refreshSessionsForRepo],
  );

  const toggleSidebar = useCallback(() => {
    setSidebarOpen((prev) => !prev);
  }, []);

  const persistMessages = useCallback(
    (
      messages: ChatMessage[],
      aguiHistory: AguiMessage[],
      analysisState?: AnalysisStateSnapshot,
      pendingInterrupt?: InterruptPayload | null,
    ) => {
      if (!activeSessionId) return;
      if (debounceRef.current) clearTimeout(debounceRef.current);
      debounceRef.current = setTimeout(() => {
        const title = deriveTitle(messages);
        updateSessionApi(activeSessionId, {
          title,
          messages,
          agui_history: aguiHistory,
          analysis_state: analysisState ?? null,
          pending_interrupt: pendingInterrupt ?? null,
        }).then(() => {
          setActiveSession((prev) =>
            prev && prev.id === activeSessionId
              ? {
                  ...prev,
                  title,
                  messages,
                  agui_history: aguiHistory,
                  analysis_state: analysisState ?? null,
                  pending_interrupt: pendingInterrupt ?? null,
                  updated_at: new Date().toISOString(),
                }
              : prev,
          );
        });
      }, 2000);
    },
    [activeSessionId],
  );

  const groupedSessions = groupByDate(sessions);

  const refreshSessions = useCallback(async () => {
    if (repositoryId) await refreshSessionsForRepo(repositoryId);
  }, [repositoryId, refreshSessionsForRepo]);

  return {
    sessions,
    activeSessionId,
    activeSession,
    sidebarOpen,
    repositoryId,
    setRepositoryId,
    createNewSession,
    switchSession,
    deleteSessionById,
    toggleSidebar,
    persistMessages,
    groupedSessions,
    refreshSessions,
    initFromBootstrap,
    clearBootstrapped,
  };
}
