"use client";

import { useCallback, useEffect, useRef, useState } from "react";

export type WikiProgressPhase =
  | "scanning"
  | "building-tree"
  | "planning"
  | "leaf-docs"
  | "parent-docs"
  | "overview"
  | "guides"
  | "dd-docs"
  | "done";

export interface WikiProgressStatus {
  repositoryId: string;
  state: "idle" | "running" | "done" | "error";
  phase?: WikiProgressPhase;
  message?: string;
  pagesGenerated?: number;
  errors?: number;
  completedSteps?: number;
  totalSteps?: number;
  completedPageIds?: string[];
  startedAt?: string;
  updatedAt?: string;
  elapsedMs?: number;
  etaMs?: number;
}

export function useWikiProgress(repositoryId: string | null) {
  const [status, setStatus] = useState<WikiProgressStatus | null>(null);
  const [connectKey, setConnectKey] = useState(0);
  const cancelledRef = useRef(false);

  const reconnect = useCallback(() => {
    cancelledRef.current = false;
    setConnectKey((k) => k + 1);
  }, []);

  /** Optimistically mark as cancelled. Ignores stale "running" SSE updates. */
  const markCancelled = useCallback(() => {
    cancelledRef.current = true;
    setStatus((prev) =>
      prev ? { ...prev, state: "error", phase: "done", message: "Generation cancelled by user" } : prev,
    );
  }, []);

  useEffect(() => {
    if (!repositoryId) {
      setStatus(null);
      return;
    }

    cancelledRef.current = false;
    setStatus({ repositoryId, state: "idle" });

    const stream = new EventSource(`/api/repositories/${repositoryId}/wiki/status/stream`);
    stream.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data) as WikiProgressStatus;
        // After optimistic cancel, ignore "running" updates from the old generation.
        // Accept terminal states ("done"/"error") which confirm the cancel landed,
        // and accept new "running" states only after reconnect clears the flag.
        if (cancelledRef.current && data.state === "running") {
          return;
        }
        if (data.state !== "running") {
          cancelledRef.current = false;
        }
        setStatus(data);
      } catch {
        // Ignore malformed events.
      }
    };

    return () => {
      stream.close();
    };
  }, [repositoryId, connectKey]);

  return { status, reconnect, markCancelled };
}
