"use client"

import { useState, useCallback } from "react"
import { toast } from "sonner"
import { useRouter } from "next/navigation"
import { useTranslations } from "next-intl"

import { undoBatchCreateGradeRecordsAction } from "../actions"

/**
 * 撤销批量成绩录入的 Hook。
 *
 * P1-6/P1-7 重构：从 batch-grade-entry.tsx 拆分而来。
 * - 用 `isUndoData` 类型守卫替代 `as` 断言（P1-7）
 * - 撤销令牌持久化在 sessionStorage，5 分钟内有效
 */

/** 撤销令牌存储结构 */
interface UndoData {
  ids: string[]
  timestamp: number
}

/** 类型守卫：校验从 sessionStorage 解析的撤销数据结构 */
export function isUndoData(v: unknown): v is UndoData {
  if (typeof v !== "object" || v === null) return false
  const obj = v
  return (
    "ids" in obj &&
    Array.isArray(obj.ids) &&
    obj.ids.every((id) => typeof id === "string") &&
    "timestamp" in obj &&
    typeof obj.timestamp === "number"
  )
}

const STORAGE_KEY = "lastBatchGradeRecordIds"
const UNDO_TTL_MS = 5 * 60 * 1000

/** 序列化撤销数据 */
function serializeUndoData(ids: string[]): string {
  return JSON.stringify({ ids, timestamp: Date.now() })
}

export function useBatchGradeEntryUndo(): {
  saveUndoToken: (ids: string[]) => void
  handleUndo: () => Promise<void>
} {
  const router = useRouter()
  const t = useTranslations("grades")
  const [isUndoing, setIsUndoing] = useState(false)

  const saveUndoToken = useCallback((ids: string[]): void => {
    if (ids.length === 0) return
    try {
      sessionStorage.setItem(STORAGE_KEY, serializeUndoData(ids))
    } catch {
      // sessionStorage 不可用时静默失败
    }
  }, [])

  const handleUndo = useCallback(async (): Promise<void> => {
    if (isUndoing) return
    setIsUndoing(true)
    try {
      const raw = sessionStorage.getItem(STORAGE_KEY)
      if (!raw) {
        toast.error(t("batchByExam.undoNoRecord"))
        return
      }

      const parsed: unknown = JSON.parse(raw)
      // P1-7 修复：使用类型守卫替代 `as` 断言
      if (!isUndoData(parsed)) {
        toast.error(t("batchByExam.undoFailed"))
        return
      }

      if (Date.now() - parsed.timestamp > UNDO_TTL_MS) {
        toast.error(t("batchByExam.undoExpired"))
        return
      }

      const result = await undoBatchCreateGradeRecordsAction(parsed.ids)
      if (result.success) {
        sessionStorage.removeItem(STORAGE_KEY)
        toast.success(result.message)
        router.refresh()
      } else {
        toast.error(result.message || t("batchByExam.undoFailed"))
      }
    } catch {
      toast.error(t("batchByExam.undoFailed"))
    } finally {
      setIsUndoing(false)
    }
  }, [isUndoing, router, t])

  return { saveUndoToken, handleUndo }
}
