"use client";

import { useMemo, useState } from "react";
import { EndScreen } from "./components/EndScreen";
import { GameScreen } from "./components/GameScreen";
import { StartScreen } from "./components/StartScreen";
import { usePkAudio } from "./hooks/usePkAudio";
import { usePkSetup } from "./hooks/usePkSetup";
import type { AnswerState, Team, WordItem } from "./types";
import { getFairRoundCount, normalizeOptionCount, shuffleArray } from "./utils";

export default function PkPage() {
  const {
    selectedGrade,
    setSelectedGrade,
    classTypes,
    selectedClassTypeId,
    setSelectedClassTypeId,
    availableWords,
    setAvailableWords,
    loadingSetup,
    settings,
  } = usePkSetup();
  const [started, setStarted] = useState(false);
  const [ended, setEnded] = useState(false);
  const [roundWords, setRoundWords] = useState<WordItem[]>([]);
  const [questionIndex, setQuestionIndex] = useState(0);
  const [currentTeam, setCurrentTeam] = useState<Team>("red");
  const [scoreRed, setScoreRed] = useState(0);
  const [scoreBlue, setScoreBlue] = useState(0);
  const [answerState, setAnswerState] = useState<AnswerState>("idle");
  const [selectedWord, setSelectedWord] = useState<number | null>(null);

  const { speechTip, setSpeechTip, playTone, speakWord } = usePkAudio({
    onGeneratedAudio: (word) => {
      setRoundWords((items) => items.map((item) => (item.id === word.id ? word : item)));
      setAvailableWords((items) => items.map((item) => (item.id === word.id ? word : item)));
    },
  });

  const selectedClassType = classTypes.find((classType) => classType.id === selectedClassTypeId);
  const currentWord = roundWords[questionIndex] ?? availableWords[0];
  const optionCount = normalizeOptionCount(settings.pkOptionCount);
  const options = useMemo(() => {
    if (!currentWord) return [];
    const wrongOptions = availableWords.filter((word) => word.id !== currentWord.id);
    return shuffleArray([currentWord, ...shuffleArray(wrongOptions).slice(0, optionCount - 1)]);
  }, [currentWord, availableWords, optionCount]);
  const roundWordLimit = Math.max(0, Math.floor(settings.pkWordCount || 0));
  const plannedRoundCount = getFairRoundCount(availableWords.length, roundWordLimit);
  const winner = scoreRed > scoreBlue ? "red" : scoreBlue > scoreRed ? "blue" : "draw";

  function startGame() {
    const nextRound = shuffleArray(availableWords).slice(0, plannedRoundCount);
    if (nextRound.length === 0) return;

    setRoundWords(nextRound);
    setQuestionIndex(0);
    setCurrentTeam("red");
    setScoreRed(0);
    setScoreBlue(0);
    setAnswerState("idle");
    setSelectedWord(null);
    setStarted(true);
    setEnded(false);
    setSpeechTip(settings.autoSpeak ? "准备朗读中..." : "自动朗读已关闭。");
    if (settings.autoSpeak) window.setTimeout(() => void speakWord(nextRound[0]), 350);
  }

  function checkAnswer(option: WordItem) {
    if (answerState !== "idle") return;
    const correct = option.id === currentWord.id;
    setSelectedWord(option.id);
    setAnswerState(correct ? "correct" : "wrong");
    void playTone(correct);

    if (correct) {
      if (currentTeam === "red") setScoreRed((score) => score + settings.scorePerCorrect);
      else setScoreBlue((score) => score + settings.scorePerCorrect);
    } else if (settings.scorePerWrong > 0) {
      if (currentTeam === "red") setScoreRed((score) => Math.max(0, score - settings.scorePerWrong));
      else setScoreBlue((score) => Math.max(0, score - settings.scorePerWrong));
    }
  }

  function nextQuestion() {
    window.speechSynthesis?.cancel();
    const nextIndex = questionIndex + 1;
    const nextTeam = currentTeam === "red" ? "blue" : "red";
    setCurrentTeam(nextTeam);
    setAnswerState("idle");
    setSelectedWord(null);

    if (nextIndex >= roundWords.length) {
      setEnded(true);
      return;
    }

    setQuestionIndex(nextIndex);
    setSpeechTip(settings.autoSpeak ? "准备朗读中..." : "自动朗读已关闭。");
    if (settings.autoSpeak) window.setTimeout(() => void speakWord(roundWords[nextIndex]), 350);
  }

  if (!started) {
    return (
      <StartScreen
        selectedGrade={selectedGrade}
        classTypes={classTypes}
        selectedClassTypeId={selectedClassTypeId}
        selectedClassTypeName={selectedClassType?.name}
        availableWordCount={availableWords.length}
        plannedRoundCount={plannedRoundCount}
        loadingSetup={loadingSetup}
        scorePerCorrect={settings.scorePerCorrect}
        scorePerWrong={settings.scorePerWrong}
        onSelectGrade={setSelectedGrade}
        onSelectClassType={setSelectedClassTypeId}
        onStartGame={startGame}
      />
    );
  }

  if (ended) {
    return <EndScreen winner={winner} scoreRed={scoreRed} scoreBlue={scoreBlue} onRestart={startGame} />;
  }

  return (
    <GameScreen
      selectedGrade={selectedGrade}
      selectedClassTypeName={selectedClassType?.name}
      showCurrentWord={selectedClassType?.showCurrentWord ?? true}
      roundWords={roundWords}
      currentWord={currentWord}
      options={options}
      optionCount={optionCount}
      questionIndex={questionIndex}
      currentTeam={currentTeam}
      scoreRed={scoreRed}
      scoreBlue={scoreBlue}
      answerState={answerState}
      selectedWord={selectedWord}
      speechTip={speechTip}
      settings={settings}
      onSpeakWord={(word) => void speakWord(word)}
      onCheckAnswer={checkAnswer}
      onNextQuestion={nextQuestion}
    />
  );
}
