"use client";

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

import { api } from "@/lib/api/client";
import {
  initialPollState,
  isTerminal,
  narrowJob,
  reducePoll,
  type PollState,
} from "./job";

const POLL_INTERVAL_MS = 1500;

export interface UseJobPoll extends PollState {
  // 开始轮询某个 job（替换正在轮询的 job）。
  poll: (jobId: string) => void;
  // 复位到初始（停止当前轮询）。
  reset: () => void;
}

// 轮询 GET /jobs/{job_id}：setTimeout 循环，done/failed 终态停止，卸载清理。
// 纯状态机在 job.ts（可单测）；本 hook 只负责定时器 + fetch 编排。
export function useJobPoll(): UseJobPoll {
  const [state, dispatch] = useReducer(reducePoll, initialPollState);
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const activeRef = useRef<string | null>(null);

  const clearTimer = useCallback((): void => {
    if (timerRef.current !== null) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
  }, []);

  const tick = useCallback(
    async (jobId: string): Promise<void> => {
      if (activeRef.current !== jobId) return;
      try {
        const { data, error } = await api.GET("/jobs/{job_id}", {
          params: { path: { job_id: jobId } },
        });
        if (activeRef.current !== jobId) return; // 中途切换/卸载。
        if (error || !data) {
          dispatch({ type: "fail", error: "轮询任务状态失败" });
          return;
        }
        const job = narrowJob(data);
        dispatch({ type: "tick", job });
        if (isTerminal(job.status)) {
          activeRef.current = null;
          return;
        }
        timerRef.current = setTimeout(() => void tick(jobId), POLL_INTERVAL_MS);
      } catch (err: unknown) {
        if (activeRef.current !== jobId) return;
        const message = err instanceof Error ? err.message : "未知网络错误";
        dispatch({ type: "fail", error: message });
      }
    },
    [],
  );

  const poll = useCallback(
    (jobId: string): void => {
      clearTimer();
      activeRef.current = jobId;
      void tick(jobId);
    },
    [clearTimer, tick],
  );

  const reset = useCallback((): void => {
    clearTimer();
    activeRef.current = null;
  }, [clearTimer]);

  // 卸载清理。
  useEffect(() => {
    return () => {
      if (timerRef.current !== null) clearTimeout(timerRef.current);
      activeRef.current = null;
    };
  }, []);

  return { ...state, poll, reset };
}
