/**
 * 防作弊监控 Hook（ai14）
 *
 * 监听浏览器事件：visibilitychange / copy / paste / contextmenu / fullscreenchange
 * 记录违规行为，超阈值显示警告遮罩
 * 违规记录批量上报（防抖），上报失败静默保留本地
 */

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

const GRAPHQL_ENDPOINT =
  process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT ?? "/api/v1/student/graphql";
const FLUSH_THRESHOLD = 10; // 队列满 10 条后批量上报

/** 批量上报违规记录到服务端 */
async function flushViolations(
  examId: string,
  batch: ViolationRecord[],
): Promise<boolean> {
  try {
    const response = await fetch(GRAPHQL_ENDPOINT, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        query: `mutation RecordViolations($examId: ID!, $behaviors: [BehaviorInput!]!) {
          recordExamViolation(examId: $examId, behaviors: $behaviors) { ok }
        }`,
        variables: { examId, behaviors: batch },
      }),
    });
    return response.ok;
  } catch {
    return false;
  }
}

export interface UseAntiCheatReturn {
  violations: ViolationRecord[];
  isFullscreen: boolean;
  requestFullscreen: () => Promise<void>;
  exitFullscreen: () => Promise<void>;
  showWarning: boolean;
  warningMessage: string | null;
  dismissWarning: () => void;
}

export function useAntiCheat(examId: string): UseAntiCheatReturn {
  const [violations, setViolations] = useState<ViolationRecord[]>([]);
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [showWarning, setShowWarning] = useState(false);
  const [warningMessage, setWarningMessage] = useState<string | null>(null);
  const queueRef = useRef<ViolationRecord[]>([]);
  const tabSwitchCount = useRef(0);

  const record = useCallback(
    (type: ViolationType, details?: string): void => {
      const entry: ViolationRecord = { type, timestamp: Date.now(), details };
      setViolations((prev) => [...prev, entry]);
      queueRef.current.push(entry);
      if (queueRef.current.length >= FLUSH_THRESHOLD) {
        const batch = queueRef.current.splice(0);
        void flushViolations(examId, batch);
      }
    },
    [examId],
  );

  // 阻止默认行为并记录（ClipboardEvent / MouseEvent 均继承自 Event）
  useEffect(() => {
    const onCopy = (e: ClipboardEvent): void => {
      e.preventDefault();
      record("copy", "copy attempted");
    };
    const onPaste = (e: ClipboardEvent): void => {
      e.preventDefault();
      record("paste", "paste attempted");
    };
    const onContext = (e: MouseEvent): void => {
      e.preventDefault();
      record("contextmenu", "contextmenu attempted");
    };

    document.addEventListener("copy", onCopy);
    document.addEventListener("paste", onPaste);
    document.addEventListener("contextmenu", onContext);
    return () => {
      document.removeEventListener("copy", onCopy);
      document.removeEventListener("paste", onPaste);
      document.removeEventListener("contextmenu", onContext);
    };
  }, [record]);

  // 切屏检测
  useEffect(() => {
    const onVisibility = (): void => {
      if (document.visibilityState === "hidden") {
        tabSwitchCount.current += 1;
        record("tab-switch", `第 ${tabSwitchCount.current} 次切换`);
        if (tabSwitchCount.current >= 3) {
          setShowWarning(true);
          setWarningMessage("检测到多次切屏，已记录违规行为");
        }
      }
    };
    document.addEventListener("visibilitychange", onVisibility);
    return () => document.removeEventListener("visibilitychange", onVisibility);
  }, [record]);

  // 全屏状态检测
  useEffect(() => {
    const onFullscreen = (): void => {
      const isFs = document.fullscreenElement !== null;
      setIsFullscreen(isFs);
      if (!isFs) {
        record("fullscreen-exit", "退出全屏");
      }
    };
    document.addEventListener("fullscreenchange", onFullscreen);
    return () => document.removeEventListener("fullscreenchange", onFullscreen);
  }, [record]);

  // 卸载时 flush 剩余记录
  useEffect(() => {
    return () => {
      if (queueRef.current.length > 0) {
        const batch = queueRef.current.splice(0);
        void flushViolations(examId, batch);
      }
    };
  }, [examId]);

  const requestFullscreen = useCallback(async (): Promise<void> => {
    try {
      await document.documentElement.requestFullscreen();
    } catch {
      // 全屏请求失败，静默处理
    }
  }, []);

  const exitFullscreen = useCallback(async (): Promise<void> => {
    try {
      if (document.fullscreenElement) {
        await document.exitFullscreen();
      }
    } catch {
      // 退出全屏失败，静默处理
    }
  }, []);

  const dismissWarning = useCallback((): void => {
    setShowWarning(false);
    setWarningMessage(null);
  }, []);

  return {
    violations,
    isFullscreen,
    requestFullscreen,
    exitFullscreen,
    showWarning,
    warningMessage,
    dismissWarning,
  };
}
