/**
 * 考试草稿管理 Hook（ai14）
 *
 * 使用 idb-keyval 持久化草稿到 IndexedDB
 * 支持断网恢复：进入考试页时检测已有草稿
 * 自动保存：每 NEXT_PUBLIC_EXAM_AUTOSAVE_INTERVAL 秒 + 组件卸载时
 */

import { useState, useEffect, useCallback, useRef } from "react";
import { get, set, del } from "idb-keyval";
import type { AnswerInput, ExamTakingDraft } from "@/lib/exam-types";
import { getStudentId, buildDraftKey } from "@/lib/exam-types";

const DEFAULT_AUTOSAVE_INTERVAL = 30; // 默认 30 秒

/** 获取自动保存间隔（毫秒） */
function getAutosaveIntervalMs(): number {
  const seconds = Number(process.env.NEXT_PUBLIC_EXAM_AUTOSAVE_INTERVAL);
  return (
    (Number.isFinite(seconds) && seconds > 0
      ? seconds
      : DEFAULT_AUTOSAVE_INTERVAL) * 1000
  );
}

export interface UseExamDraftReturn {
  draft: ExamTakingDraft | null;
  saveDraft: (answers: Record<string, AnswerInput>) => Promise<void>;
  /** 更新内部答案引用（不触发保存，供自动保存定时器使用） */
  setAnswers: (answers: Record<string, AnswerInput>) => void;
  clearDraft: () => Promise<void>;
  isSaving: boolean;
  hasDraft: boolean;
  lastSavedAt: number | null;
  /** 手动加载草稿（用于恢复确认后） */
  loadDraft: () => Promise<ExamTakingDraft | null>;
}

export function useExamDraft(
  examId: string,
  expiresAt?: string,
): UseExamDraftReturn {
  const [draft, setDraft] = useState<ExamTakingDraft | null>(null);
  const [isSaving, setIsSaving] = useState(false);
  const [lastSavedAt, setLastSavedAt] = useState<number | null>(null);
  const answersRef = useRef<Record<string, AnswerInput>>({});
  const expiresAtRef = useRef<string>(expiresAt ?? "");

  // 当外部传入新的 expiresAt 时更新引用
  useEffect(() => {
    if (expiresAt) {
      expiresAtRef.current = expiresAt;
    }
  }, [expiresAt]);

  /** 保存草稿到 IDB */
  const saveDraft = useCallback(
    async (answers: Record<string, AnswerInput>): Promise<void> => {
      const studentId = getStudentId();
      const key = buildDraftKey(examId, studentId);
      setIsSaving(true);
      try {
        const now = Date.now();
        const updated: ExamTakingDraft = draft
          ? { ...draft, answers, lastSavedAt: now }
          : {
              examId,
              studentId,
              answers,
              startedAt: now,
              serverStartedAt: now,
              lastSavedAt: now,
              durationSeconds: 0,
              expiresAt: expiresAtRef.current,
            };
        await set(key, updated);
        setDraft(updated);
        setLastSavedAt(now);
        answersRef.current = answers;
      } catch {
        // IDB 写入失败，静默处理（内存中仍保留）
      } finally {
        setIsSaving(false);
      }
    },
    [examId, draft],
  );

  /** 从 IDB 加载草稿 */
  const loadDraft = useCallback(async (): Promise<ExamTakingDraft | null> => {
    const studentId = getStudentId();
    const key = buildDraftKey(examId, studentId);
    try {
      const saved = (await get(key)) as ExamTakingDraft | undefined;
      return saved ?? null;
    } catch {
      return null;
    }
  }, [examId]);

  /** 清除草稿 */
  const clearDraft = useCallback(async (): Promise<void> => {
    const studentId = getStudentId();
    const key = buildDraftKey(examId, studentId);
    try {
      await del(key);
      setDraft(null);
      setLastSavedAt(null);
    } catch {
      // 清除失败静默处理
    }
  }, [examId]);

  /** 更新内部答案引用（不触发保存，供自动保存定时器使用） */
  const setAnswers = useCallback(
    (answers: Record<string, AnswerInput>): void => {
      answersRef.current = answers;
    },
    [],
  );

  /** 自动保存（定时器 + 卸载时） */
  const autoSave = useCallback(async (): Promise<void> => {
    if (Object.keys(answersRef.current).length === 0) return;
    await saveDraft(answersRef.current);
  }, [saveDraft]);

  // 进入时加载已有草稿
  useEffect(() => {
    loadDraft().then((saved) => {
      if (saved) {
        setDraft(saved);
        setLastSavedAt(saved.lastSavedAt);
        answersRef.current = saved.answers;
        expiresAtRef.current = saved.expiresAt;
      }
    });
  }, [loadDraft]);

  // 定时自动保存
  useEffect(() => {
    const interval = setInterval(autoSave, getAutosaveIntervalMs());
    return () => {
      clearInterval(interval);
      // 卸载时保存草稿
      autoSave();
    };
  }, [autoSave]);

  return {
    draft,
    saveDraft,
    setAnswers,
    clearDraft,
    isSaving,
    hasDraft: draft !== null && Object.keys(draft.answers).length > 0,
    lastSavedAt,
    loadDraft,
  };
}
