import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect, useRef, useState } from "react";
import { agentApi, type AgentRunDTO, type AgentStepDTO } from "../lib/api/agent";

const runKey = (projectId: string) => ["agent-run", projectId];

export function useLatestAgentRun(projectId: string) {
  return useQuery({
    queryKey: runKey(projectId),
    queryFn: () => agentApi.getLatestRun(projectId),
    enabled: !!projectId,
    refetchInterval: false,
  });
}

export function useStartAgentRun(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (goal: string) => agentApi.startRun(projectId, goal),
    onSuccess: (run) => {
      qc.setQueryData(runKey(projectId), run);
    },
  });
}

export function usePauseAgentRun(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (runId: number) => agentApi.pauseRun(runId),
    onSuccess: () => qc.invalidateQueries({ queryKey: runKey(projectId) }),
  });
}

export function useResumeAgentRun(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (runId: number) => agentApi.resumeRun(runId),
    onSuccess: () => qc.invalidateQueries({ queryKey: runKey(projectId) }),
  });
}

export interface SseLog {
  id: number;
  time: string;
  level: "info" | "warn" | "error" | "agent";
  message: string;
}

interface SseEvent {
  type: string;
  data: Record<string, unknown>;
}

/** 连接 SSE 并实时更新 run 状态。当 runId 为 null 时不连接 */
export function useAgentSse(runId: number | null, projectId: string) {
  const qc = useQueryClient();
  const [logs, setLogs] = useState<SseLog[]>([]);
  const logIdRef = useRef(0);

  useEffect(() => {
    // 从 localStorage 直接取原始 token（不带 Bearer 前缀）
    const token = localStorage.getItem("yaoai_token");
    if (!runId || !token) return;

    const BASE = import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8080";
    const url = `${BASE}/agent/runs/${runId}/events?Authorization=${encodeURIComponent(token)}`;
    const es = new EventSource(url);

    const addLog = (level: SseLog["level"], message: string) => {
      setLogs((prev) => [
        ...prev,
        {
          id: ++logIdRef.current,
          time: new Date().toLocaleTimeString("zh-CN", { hour12: false }),
          level,
          message,
        },
      ]);
    };

    const refreshRun = () => {
      qc.invalidateQueries({ queryKey: runKey(projectId) });
    };

    es.onmessage = (e) => {
      try {
        const evt: SseEvent = JSON.parse(e.data);
        const { type, data } = evt;

        if (type === "log") {
          addLog((data.level as SseLog["level"]) || "info", data.message as string);
        } else if (type === "step.start") {
          addLog("info", `步骤开始：${data.stepKey}`);
          refreshRun();
        } else if (type === "step.done") {
          addLog("agent", `步骤完成：${data.stepKey}（${data.durationMs}ms）`);
          refreshRun();
        } else if (type === "step.failed") {
          addLog("error", `步骤失败：${data.stepKey} — ${data.error}`);
          refreshRun();
        } else if (type === "run.done") {
          addLog("agent", "制作完成！");
          refreshRun();
          es.close();
        } else if (type === "run.failed") {
          addLog("error", `制作失败：${data.error}`);
          refreshRun();
          es.close();
        } else if (type === "run.paused") {
          addLog("info", "制作已暂停");
          refreshRun();
        } else if (type === "run.resumed") {
          addLog("info", "制作已继续");
          refreshRun();
        }
      } catch {
        // ignore parse errors
      }
    };

    let errCount = 0;
    es.onerror = () => {
      errCount++;
      if (errCount === 1) addLog("warn", "SSE 连接断开，尝试重连...");
      // 如果连续出错说明鉴权失败或服务不可用，停止重连
      if (errCount >= 3) {
        addLog("error", "SSE 无法连接，请刷新页面重试");
        es.close();
      }
    };

    return () => es.close();
  // token 每次从 localStorage 读取，不需要作为依赖
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [runId, projectId]);

  return { logs };
}
