"use client"

import { useState, useCallback, useMemo } from "react"

export type Mode = "single" | "multi"

function getRandomDistinct(total: number, count: number, forbidSet: Set<number> = new Set()): number[] | null {
  // 构建可用数字数组
  const available: number[] = []
  for (let i = 1; i <= total; i++) {
    if (!forbidSet.has(i)) available.push(i)
  }
  
  if (count > available.length) return null
  
  // Fisher-Yates 洗牌算法
  for (let i = available.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1))
    ;[available[i], available[j]] = [available[j], available[i]]
  }
  
  return available.slice(0, count)
}

function generateGroups(
  total: number,
  perPick: number,
  rounds: number,
  allowGroupRepeat: boolean
): { success: boolean; groups: { numbers: number[]; colorIndex: number }[]; errorMsg: string } {
  if (total <= 0) return { success: false, groups: [], errorMsg: "总人数必须大于 0" }
  if (perPick <= 0) return { success: false, groups: [], errorMsg: "每次人数必须大于 0" }
  if (rounds <= 0) return { success: false, groups: [], errorMsg: "抽取组数必须为正整数" }
  if (perPick > total) return { success: false, groups: [], errorMsg: `每次人数 (${perPick}) 不能大于总人数 (${total})` }
  if (!allowGroupRepeat && rounds * perPick > total) {
    return {
      success: false,
      groups: [],
      errorMsg: `组间不可重复时，总抽取数 (${rounds}×${perPick}=${rounds * perPick}) 超出总人数 (${total})`,
    }
  }

  const groups: { numbers: number[]; colorIndex: number }[] = []
  const globalUsed = new Set<number>()

  for (let i = 0; i < rounds; i++) {
    const nums = allowGroupRepeat
      ? getRandomDistinct(total, perPick)
      : getRandomDistinct(total, perPick, globalUsed)
    if (!nums) return { success: false, groups: [], errorMsg: `第 ${i + 1} 组抽取失败，剩余人数不足` }
    if (!allowGroupRepeat) nums.forEach((n) => globalUsed.add(n))
    groups.push({ numbers: nums, colorIndex: i % COLORS.length })
  }
  return { success: true, groups, errorMsg: "" }
}

export interface RollCallState {
  mode: Mode
  totalTasks: number
  pickCount: number
  rounds: number
  allowRepeat: boolean
  // Multi mode
  groups: { numbers: number[]; colorIndex: number }[]
  highlighted: Set<number>
  usedAll: Set<number>
  hasResult: boolean
  // Single mode
  selectedRecords: { number: number; colorIndex: number }[]
  singleBatches: { numbers: number[]; colorIndex: number; batchNumber: number }[]
  singleHighlighted: number[]
  isSingleComplete: boolean
  singleAllowRepeat: boolean
  // Common
  isRolling: boolean
  errorMsg: string
}

export interface RollCallActions {
  setMode: (v: Mode) => void
  setTotalTasks: (v: number) => void
  setPickCount: (v: number) => void
  setRounds: (v: number) => void
  setAllowRepeat: (v: boolean) => void
  setSingleAllowRepeat: (v: boolean) => void
  handleRoll: () => void
  handleSingleRoll: () => void
  resetSingle: () => void
  clearResult: () => void
  getBallState: (n: number) => "idle" | "highlighted" | "used"
  getBallColorIndex: (n: number) => number | undefined
  getBallDimmed: (n: number) => boolean
}

export const COLORS = [
  "#d92d20",
  "#0070f3",
  "#6d6df6",
  "#00b8d9",
  "#36b37e",
  "#ff991f", 
  "#8754ad", 
  "#e63946",
  "#457b9d",
  "#2a9d8f",
  "#f4a261",
  "#264653",
  "#9d4edd",
  "#fb5607",
  "#06d6a0",
  "#118ab2",
  "#ffd166",
]

export function useRollCallLogic(): [RollCallState, RollCallActions] {
  const [mode, setMode] = useState<Mode>("single")
  const [totalTasks, setTotalTasks] = useState<number>(35)
  const [pickCount, setPickCount] = useState<number>(1)
  const [rounds, setRounds] = useState<number>(1)
  const [allowRepeat, setAllowRepeat] = useState(false)
  // Multi mode state
  const [groups, setGroups] = useState<{ numbers: number[]; colorIndex: number }[]>([])
  const [highlighted, setHighlighted] = useState<Set<number>>(new Set())
  const [usedAll, setUsedAll] = useState<Set<number>>(new Set())
  const [hasResult, setHasResult] = useState(false)
  // Single mode state
  const [singleBatches, setSingleBatches] = useState<{ numbers: number[]; colorIndex: number; batchNumber: number }[]>([])
  const [singleHighlighted, setSingleHighlighted] = useState<number[]>([])
  const [isSingleComplete, setIsSingleComplete] = useState(false)
  const [singleAllowRepeat, setSingleAllowRepeat] = useState(false)
  // Common state
  const [isRolling, setIsRolling] = useState(false)
  const [errorMsg, setErrorMsg] = useState("")

  // 从 singleBatches 计算 selectedRecords，消除数据冗余
  const selectedRecords = useMemo(() => {
    return singleBatches.flatMap(batch => 
      batch.numbers.map(n => ({ number: n, colorIndex: batch.colorIndex }))
    )
  }, [singleBatches])

  const resetAllState = useCallback(() => {
    setHighlighted(new Set())
    setUsedAll(new Set())
    setGroups([])
    setHasResult(false)
    setSingleBatches([])
    setSingleHighlighted([])
    setIsSingleComplete(false)
    setErrorMsg("")
  }, [])

  const handleModeChange = useCallback((newMode: Mode) => {
    setMode(newMode)
    resetAllState()
  }, [resetAllState])

  const handleTotalChange = useCallback((v: number) => {
    setTotalTasks(v)
    resetAllState()
  }, [resetAllState])

  const handleRoundsChange = useCallback((v: number) => {
    setRounds(v)
    if (v < 2) setAllowRepeat(false)
    setHighlighted(new Set())
    setGroups([])
    setHasResult(false)
    setErrorMsg("")
  }, [])

  const handleRoll = useCallback(async () => {
    setErrorMsg("")
    
    setIsRolling(true)
    await new Promise((r) => setTimeout(r, 240))

    const effectiveRepeat = rounds < 2 ? false : allowRepeat
    const result = generateGroups(totalTasks, pickCount, rounds, effectiveRepeat)

    if (!result.success) {
      setErrorMsg(result.errorMsg)
      setIsRolling(false)
      return
    }

    const allPicked = new Set(result.groups.flatMap(g => g.numbers))
    setGroups(result.groups)
    setHighlighted(allPicked)
    if (!effectiveRepeat) {
      setUsedAll(allPicked)
    } else {
      setUsedAll(new Set())
    }
    setHasResult(true)
    setIsRolling(false)
  }, [totalTasks, pickCount, rounds, allowRepeat])

  const handleSingleRoll = useCallback(async () => {
    setErrorMsg("")
    
    setIsRolling(true)
    setIsSingleComplete(false)
    await new Promise((r) => setTimeout(r, 240))

    const usedNumbers = new Set(selectedRecords.map(r => r.number))

    if (!singleAllowRepeat && pickCount > totalTasks - usedNumbers.size) {
      setErrorMsg(`剩余可选人数不足 ${pickCount} 人`)
      setIsRolling(false)
      return
    }

    const forbidSet = singleAllowRepeat ? new Set<number>() : usedNumbers
    const nums = getRandomDistinct(totalTasks, pickCount, forbidSet)
    if (!nums) {
      setErrorMsg("抽取失败，人数不足")
      setIsRolling(false)
      return
    }

    const newColorIndex = singleBatches.length % COLORS.length
    const newBatchNumber = singleBatches.length + 1
    const newBatch = { numbers: nums, colorIndex: newColorIndex, batchNumber: newBatchNumber }
    
    setSingleBatches([...singleBatches, newBatch])
    setSingleHighlighted(nums)
    setIsSingleComplete(true)
    setIsRolling(false)
  }, [totalTasks, pickCount, selectedRecords, singleBatches, singleAllowRepeat])

  const resetSingle = useCallback(() => {
    setSingleBatches([])
    setSingleHighlighted([])
    setIsSingleComplete(false)
    setErrorMsg("")
  }, [])

  const clearResult = useCallback(() => {
    setGroups([])
    setHighlighted(new Set())
    setUsedAll(new Set())
    setHasResult(false)
  }, [])

  const getBallState = useCallback((n: number): "idle" | "highlighted" | "used" => {
    if (mode === "single") {
      // Only highlight current round's selections
      const isCurrentRound = singleHighlighted.includes(n)
      if (isCurrentRound) return "highlighted"
      return "idle"
    }
    if (highlighted.has(n)) return "highlighted"
    if (hasResult && usedAll.size > 0 && !usedAll.has(n)) return "used"
    return "idle"
  }, [mode, singleHighlighted, highlighted, hasResult, usedAll])

  const getBallColorIndex = useCallback((n: number): number | undefined => {
    if (mode === "single") {
      // Find the LAST occurrence (latest color when repeats are allowed)
      const record = [...selectedRecords].reverse().find(r => r.number === n)
      return record?.colorIndex
    }
    // Group mode: find which group this number belongs to (use last matching group)
    for (let i = groups.length - 1; i >= 0; i--) {
      if (groups[i].numbers.includes(n)) {
        return groups[i].colorIndex
      }
    }
    return undefined
  }, [mode, selectedRecords, groups])

  const getBallDimmed = useCallback((n: number): boolean => {
    // Only dim in single mode when there are highlighted numbers
    if (mode === "single" && singleHighlighted.length > 0) {
      return !singleHighlighted.includes(n)
    }
    return false
  }, [mode, singleHighlighted])

  const state: RollCallState = {
    mode,
    totalTasks,
    pickCount,
    rounds,
    allowRepeat,
    groups,
    highlighted,
    usedAll,
    hasResult,
    selectedRecords,
    singleBatches,
    singleHighlighted,
    isSingleComplete,
    singleAllowRepeat,
    isRolling,
    errorMsg,
  }

  const actions: RollCallActions = {
    setMode: handleModeChange,
    setTotalTasks: handleTotalChange,
    setPickCount: (v: number) => { setPickCount(v); setErrorMsg("") },
    setRounds: handleRoundsChange,
    setAllowRepeat,
    setSingleAllowRepeat,
    handleRoll,
    handleSingleRoll,
    resetSingle,
    clearResult,
    getBallState,
    getBallColorIndex,
    getBallDimmed,
  }

  return [state, actions]
}
