/**
 * 服务器时间同步 Hook（ai14）
 *
 * 定期轮询服务器时间，计算客户端与服务器的时间偏移
 * 用于考试倒计时校正，防止客户端篡改时间
 * 同步失败时保持上次偏移，标记为降级模式
 */

import { useState, useEffect, useCallback, useRef } from "react";
import type { ServerTimeSyncState } from "@/lib/exam-types";

const DEFAULT_SYNC_INTERVAL = 300; // 默认 5 分钟（秒）
const GRAPHQL_ENDPOINT =
  process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT ?? "/api/v1/student/graphql";

/** 获取同步间隔（毫秒） */
function getSyncIntervalMs(): number {
  const seconds = Number(process.env.NEXT_PUBLIC_EXAM_TIME_SYNC_INTERVAL);
  return (
    (Number.isFinite(seconds) && seconds > 0
      ? seconds
      : DEFAULT_SYNC_INTERVAL) * 1000
  );
}

/** 查询服务器时间 */
async function fetchServerTime(): Promise<number> {
  const response = await fetch(GRAPHQL_ENDPOINT, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query: "{ serverTime }" }),
  });
  if (!response.ok) {
    throw new Error(`服务器时间查询失败: ${response.status}`);
  }
  const result = (await response.json()) as { data?: { serverTime?: string } };
  const serverTimeStr = result.data?.serverTime;
  if (!serverTimeStr) {
    throw new Error("服务器时间响应格式错误");
  }
  return new Date(serverTimeStr).getTime();
}

export function useServerTimeSync(): ServerTimeSyncState {
  const [state, setState] = useState<ServerTimeSyncState>({
    serverTime: Date.now(),
    offset: 0,
    isSyncing: false,
    lastSyncAt: null,
    isDegraded: false,
  });
  const offsetRef = useRef(0);

  const sync = useCallback(async () => {
    setState((prev) => ({ ...prev, isSyncing: true }));
    const requestStart = Date.now();
    try {
      const serverTime = await fetchServerTime();
      const requestEnd = Date.now();
      const roundTrip = requestEnd - requestStart;
      // 估算服务器响应时的客户端时间（取往返中点）
      const estimatedClientAtServer = requestStart + roundTrip / 2;
      const newOffset = serverTime - estimatedClientAtServer;
      offsetRef.current = newOffset;
      setState({
        serverTime,
        offset: newOffset,
        isSyncing: false,
        lastSyncAt: Date.now(),
        isDegraded: false,
      });
    } catch {
      // 同步失败：保持上次偏移，标记降级
      setState((prev) => ({
        ...prev,
        isSyncing: false,
        isDegraded: true,
      }));
    }
  }, []);

  useEffect(() => {
    sync();
    const interval = setInterval(sync, getSyncIntervalMs());
    return () => clearInterval(interval);
  }, [sync]);

  return state;
}
