"use client";

import Link from "next/link";
import { useEffect, useState } from "react";
import { flushSync } from "react-dom";

import StageIndicator from "@/components/game/StageIndicator";
import VariableChoiceAnswerForm from "@/components/game/VariableChoiceAnswerForm";
import VariableFeedbackPanel from "@/components/game/VariableFeedbackPanel";
import VariableScoreSummary from "@/components/game/VariableScoreSummary";
import KatexRenderer from "@/components/math/KatexRenderer";
import { formatVariableTermLatex } from "@/lib/engine/variable-parenthesis";
import {
  useVariableGameStore,
  type VariableMaxTermCount,
  type VariableProblemCount,
} from "@/store/variableGameStore";

interface VariablePlayClientProps {
  problemCount: VariableProblemCount;
  maxTermCount: VariableMaxTermCount;
}

export default function VariablePlayClient({
  problemCount,
  maxTermCount,
}: VariablePlayClientProps) {
  const session = useVariableGameStore((state) => state.session);
  const selectedProblemCount = useVariableGameStore(
    (state) => state.selectedProblemCount,
  );
  const setProblemCount = useVariableGameStore(
    (state) => state.setProblemCount,
  );
  const selectedMaxTermCount = useVariableGameStore(
    (state) => state.selectedMaxTermCount,
  );
  const setMaxTermCount = useVariableGameStore(
    (state) => state.setMaxTermCount,
  );
  const initSession = useVariableGameStore((state) => state.initSession);
  const submitAnswer = useVariableGameStore((state) => state.submitAnswer);
  const nextProblem = useVariableGameStore((state) => state.nextProblem);
  const resetSession = useVariableGameStore((state) => state.resetSession);

  const [selectedChoiceIds, setSelectedChoiceIds] = useState<(string | null)[]>(
    () => Array.from({ length: maxTermCount }, () => null),
  );
  const [activeTermIndex, setActiveTermIndex] = useState(0);

  const sessionProblemCount = session?.problems.length ?? null;
  const currentProblem = session?.problems[session.currentIndex] ?? null;
  const currentResult = session?.results[session.currentIndex] ?? null;
  const isComplete = Boolean(
    session && session.currentIndex >= session.problems.length,
  );
  const sessionNeedsInit =
    sessionProblemCount !== problemCount || session?.termCount !== maxTermCount;
  const correctCount =
    session?.results.filter((result) => result?.correct).length ?? 0;
  const totalCount = session?.problems.length ?? 0;

  useEffect(() => {
    if (selectedProblemCount !== problemCount) {
      setProblemCount(problemCount);
    }

    if (selectedMaxTermCount !== maxTermCount) {
      setMaxTermCount(maxTermCount);
    }

    if (sessionNeedsInit) {
      initSession(problemCount, maxTermCount);
    }
  }, [
    initSession,
    maxTermCount,
    problemCount,
    selectedMaxTermCount,
    selectedProblemCount,
    sessionProblemCount,
    sessionNeedsInit,
    setMaxTermCount,
    setProblemCount,
  ]);

  useEffect(() => {
    setSelectedChoiceIds(
      Array.from({ length: currentProblem?.terms.length ?? maxTermCount }, () => null),
    );
    setActiveTermIndex(0);
  }, [currentProblem?.key, currentProblem?.terms.length, maxTermCount]);

  function handleSelectChoice(termIndex: number, choiceId: string) {
    const nextSelectedChoiceIds = [...selectedChoiceIds];
    nextSelectedChoiceIds[termIndex] = choiceId;

    setSelectedChoiceIds(nextSelectedChoiceIds);

    if (termIndex < nextSelectedChoiceIds.length - 1) {
      setActiveTermIndex(termIndex + 1);
      return;
    }

    if (currentResult || !currentProblem) return;
    if (
      nextSelectedChoiceIds.some((selectedChoiceId) => selectedChoiceId === null)
    ) {
      return;
    }

    submitAnswer({ selectedChoiceIds: nextSelectedChoiceIds });
  }

  function handleNextProblem() {
    flushSync(() => {
      nextProblem();
    });
  }

  if (!session || sessionNeedsInit) {
    return (
      <main className="flex min-h-screen items-center bg-slate-50 px-6 py-12 text-slate-950">
        <section className="mx-auto w-full max-w-3xl">
          <p className="text-lg font-semibold text-slate-700">
            문제를 준비하고 있습니다.
          </p>
        </section>
      </main>
    );
  }

  if (isComplete) {
    return (
      <VariableScoreSummary
        correctCount={correctCount}
        totalCount={totalCount}
        problems={session.problems}
        results={session.results}
        onRestart={resetSession}
      />
    );
  }

  if (!currentProblem) {
    return (
      <main className="flex min-h-screen items-center bg-slate-50 px-6 py-12 text-slate-950">
        <section className="mx-auto w-full max-w-3xl">
          <p className="text-lg font-semibold text-slate-700">
            현재 문제를 불러올 수 없습니다.
          </p>
        </section>
      </main>
    );
  }

  const submitted = currentResult !== null;
  const isLastProblem = session.currentIndex === session.problems.length - 1;
  const pendingChoiceLabels = currentProblem.terms.map((term, index) =>
    formatVariableTermLatex({
      ...term,
      coefficient:
        index > 0 && currentProblem.operators[index - 1] === "-"
          ? -term.coefficient
          : term.coefficient,
    }),
  );

  return (
    <main className="min-h-screen bg-slate-50 px-6 py-10 text-slate-950">
      <section className="mx-auto flex w-full max-w-3xl flex-col gap-8">
        <div className="flex flex-wrap items-center justify-between gap-4">
          <div className="space-y-2">
            <p className="text-sm font-semibold text-emerald-700">
              미지수 괄호 풀기
            </p>
            <h1 className="text-3xl font-bold tracking-normal sm:text-4xl">
              문제 풀이
            </h1>
          </div>
          <Link
            href="/variable-parentheses"
            onClick={resetSession}
            className="inline-flex h-10 items-center justify-center rounded-md bg-red-700 px-4 text-sm font-semibold text-white transition hover:bg-red-800 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
          >
            포기
          </Link>
        </div>

        <div className="rounded-md bg-white px-6 pt-6 pb-4 shadow-sm ring-1 ring-slate-200 sm:p-8">
          <div className="text-3xl font-semibold text-slate-950 sm:text-4xl">
            <KatexRenderer latex={currentProblem.latexBefore} displayMode />
          </div>
          <div className="mt-6">
            <StageIndicator
              currentIndex={session.currentIndex}
              results={session.results}
            />
          </div>
        </div>

        {!submitted ? (
          <VariableChoiceAnswerForm
            choices={currentProblem.choices}
            selectedChoiceIds={selectedChoiceIds}
            activeTermIndex={activeTermIndex}
            pendingChoiceLabels={pendingChoiceLabels}
            onSelectChoice={handleSelectChoice}
          />
        ) : null}

        {currentResult ? (
          <VariableFeedbackPanel
            result={currentResult}
            problem={currentProblem}
            isLastProblem={isLastProblem}
            onNext={handleNextProblem}
          />
        ) : null}
      </section>
    </main>
  );
}
