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

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

export function useLatestAgentRun(projectId: string) {
  const isAuthReady = useAuthStore((state) => state.hasHydrated && state.isAuthenticated);
  return useQuery({
    queryKey: runKey(projectId),
    queryFn: () => agentApi.getLatestRun(projectId),
    enabled: isAuthReady && !!projectId,
    refetchInterval: false,
  });
}

export function useStartAgentRun(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (request: string | AgentStartRequest) => agentApi.startRun(projectId, request),
    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);
  const isAuthReady = useAuthStore((state) => state.hasHydrated && state.isAuthenticated);

  useEffect(() => {
    const token = getAuthToken() ?? localStorage.getItem("yaoai_token");
    if (!runId || !token || !isAuthReady) return;

    const BASE = import.meta.env.VITE_API_BASE_URL ?? "/api";
    const url = `${BASE}/agent/runs/${runId}/events?Authorization=${encodeURIComponent(token)}`;
    let errCount = 0;
    let reconnectTimer: number | null = null;
    let shouldStop = false;
    let source: EventSource | null = null;

    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) });
    };

    const handleEventPayload = (payload: string) => {
      try {
        const evt: SseEvent = JSON.parse(payload);
        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 === "step.skipped") {
          addLog("info", `步骤跳过：${data.stepKey}（${data.output ?? "已复用现有内容"}）`);
          refreshRun();
        } else if (type === "run.done") {
          addLog("agent", "制作完成！");
          refreshRun();
          shouldStop = true;
          if (source) {
            source.close();
            source = null;
          }
        } else if (type === "run.failed") {
          addLog("error", `制作失败：${data.error}`);
          refreshRun();
          shouldStop = true;
          if (source) {
            source.close();
            source = null;
          }
        } else if (type === "run.paused") {
          addLog("info", "制作已暂停");
          refreshRun();
        } else if (type === "run.resumed") {
          addLog("info", "制作已继续");
          refreshRun();
        }
      } catch {
        // ignore parse errors
      }
    };

    const scheduleReconnect = () => {
      if (shouldStop) {
        return;
      }
      if (source) {
        source.close();
        source = null;
      }
      errCount++;
      if (errCount === 1) {
        addLog("warn", "SSE 连接断开，尝试重连...");
      }
      if (errCount >= 3) {
        addLog("error", "SSE 无法连接，请刷新页面重试");
        shouldStop = true;
        return;
      }
      reconnectTimer = window.setTimeout(() => {
        connect();
      }, 1000 * errCount);
    };

    const bindEvent = (eventType: string, eventSource: EventSource) => {
      eventSource.addEventListener(eventType, (event) => {
        const payload = (event as MessageEvent<string>).data;
        if (typeof payload === "string") {
          handleEventPayload(payload);
        }
      });
    };

    const connect = () => {
      if (shouldStop) return;
      const eventSource = new EventSource(url);
      source = eventSource;

      eventSource.onopen = () => {
        errCount = 0;
      };

      for (const eventType of [
        "log",
        "step.start",
        "step.done",
        "step.failed",
        "step.skipped",
        "run.done",
        "run.failed",
        "run.paused",
        "run.resumed",
      ]) {
        bindEvent(eventType, eventSource);
      }

      eventSource.onerror = () => {
        if (shouldStop) {
          return;
        }
        scheduleReconnect();
      };
    };

    connect();

    return () => {
      shouldStop = true;
      if (reconnectTimer != null) {
        window.clearTimeout(reconnectTimer);
      }
      if (source) {
        source.close();
      }
    };
  }, [runId, projectId, qc, isAuthReady]);

  return { logs };
}
