"use client";

import { useState, useCallback } from "react";
import { motion, AnimatePresence } from "framer-motion";
import type { MathProblem, Difficulty } from "@/lib/problems/types";
import { checkFractionAnswer, checkDecimalAnswer, checkRatioAnswer, checkIntegerAnswer, type AnswerResult } from "@/lib/math/validation";
import { FractionInput, DecimalInput, RatioInput } from "./fraction-input";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import katex from "katex";

interface PracticeSectionProps {
  title: string;
  generator: (difficulty: Difficulty) => MathProblem;
  unitColor?: "unit-1" | "unit-2" | "unit-3" | "unit-4";
}

type UnitColor = NonNullable<PracticeSectionProps["unitColor"]>;

const activeDifficultyStyle: Record<UnitColor, string> = {
  "unit-1": "bg-unit-1 text-white",
  "unit-2": "bg-unit-2 text-white",
  "unit-3": "bg-unit-3 text-white",
  "unit-4": "bg-unit-4 text-white",
};

export function PracticeSection({ title, generator, unitColor = "unit-1" }: PracticeSectionProps) {
  const [difficulty, setDifficulty] = useState<Difficulty>(1);
  const [problem, setProblem] = useState<MathProblem>(() => generator(1));
  const [userAnswer, setUserAnswer] = useState<Record<string, string>>({});
  const [result, setResult] = useState<AnswerResult | null>(null);
  const [showHint, setShowHint] = useState(false);
  const [hintIndex, setHintIndex] = useState(0);
  const [showSolution, setShowSolution] = useState(false);
  const [score, setScore] = useState({ correct: 0, total: 0 });

  const generateNew = useCallback((diff: Difficulty) => {
    setProblem(generator(diff));
    setUserAnswer({});
    setResult(null);
    setShowHint(false);
    setHintIndex(0);
    setShowSolution(false);
  }, [generator]);

  function checkAnswer() {
    const answer = problem.answer;
    let res: AnswerResult;

    switch (answer.kind) {
      case "fraction": {
        const num = parseInt(userAnswer.numerator || "0");
        const den = parseInt(userAnswer.denominator || "0");
        if (isNaN(num) || isNaN(den)) {
          res = { correct: false, message: "Enter valid numbers" };
        } else {
          res = checkFractionAnswer(num, den, answer.numerator, answer.denominator);
        }
        break;
      }
      case "decimal": {
        const val = parseFloat(userAnswer.value || "");
        if (isNaN(val)) {
          res = { correct: false, message: "Enter a valid number" };
        } else {
          res = checkDecimalAnswer(val, answer.value);
        }
        break;
      }
      case "integer": {
        const val = parseInt(userAnswer.value || "");
        if (isNaN(val)) {
          res = { correct: false, message: "Enter a valid number" };
        } else {
          res = checkIntegerAnswer(val, answer.value);
        }
        break;
      }
      case "ratio": {
        const parts = (userAnswer.ratio || "").split(":").map((p) => parseInt(p.trim()));
        if (parts.some(isNaN)) {
          res = { correct: false, message: "Enter valid ratio parts" };
        } else {
          res = checkRatioAnswer(parts, answer.parts);
        }
        break;
      }
      case "standardForm": {
        const coeff = parseFloat(userAnswer.coefficient || "");
        const exp = parseInt(userAnswer.exponent || "");
        if (isNaN(coeff) || isNaN(exp)) {
          res = { correct: false, message: "Enter valid numbers" };
        } else if (
          Math.abs(coeff - answer.coefficient) < 0.01 &&
          exp === answer.exponent
        ) {
          res = { correct: true, simplified: true };
        } else {
          res = { correct: false, message: "That's not quite right. Try again!" };
        }
        break;
      }
    }

    setResult(res);
    if (res.correct) {
      setScore((s) => ({ correct: s.correct + 1, total: s.total + 1 }));
    } else {
      setScore((s) => ({ ...s, total: s.total + 1 }));
    }
  }

  function nextHint() {
    if (hintIndex < problem.hints.length - 1) {
      setHintIndex((i) => i + 1);
    }
    setShowHint(true);
  }

  const promptHtml = katex.renderToString(problem.prompt, { throwOnError: false, displayMode: true });

  return (
    <Card className="mt-8 border-2">
      <div className="mb-4 flex items-center justify-between">
        <h3 className="text-lg font-extrabold">{title}</h3>
        <div className="flex items-center gap-2 text-sm">
          <span className="rounded-full bg-background px-2.5 py-1 font-bold text-muted">
            {score.correct}/{score.total}
          </span>
          <div className="flex gap-1">
            {([1, 2, 3] as Difficulty[]).map((d) => (
              <button
                key={d}
                onClick={() => {
                  setDifficulty(d);
                  generateNew(d);
                }}
                className={`rounded-lg px-2.5 py-1 text-xs font-extrabold transition-colors ${
                  difficulty === d
                    ? activeDifficultyStyle[unitColor]
                    : "bg-border/70 text-muted hover:bg-border hover:text-foreground"
                }`}
              >
                L{d}
              </button>
            ))}
          </div>
        </div>
      </div>

      {/* Problem */}
      <div
        className="mb-6 text-center text-xl"
        dangerouslySetInnerHTML={{ __html: promptHtml }}
      />

      {/* Input */}
      <div className="mb-4 flex flex-wrap items-center justify-center gap-4">
        {problem.answer.kind === "fraction" && (
          <FractionInput
            numerator={userAnswer.numerator || ""}
            denominator={userAnswer.denominator || ""}
            onNumeratorChange={(v) => setUserAnswer((a) => ({ ...a, numerator: v }))}
            onDenominatorChange={(v) => setUserAnswer((a) => ({ ...a, denominator: v }))}
            disabled={result?.correct === true}
          />
        )}

        {(problem.answer.kind === "decimal" || problem.answer.kind === "integer") && (
          <DecimalInput
            value={userAnswer.value || ""}
            onChange={(v) => setUserAnswer((a) => ({ ...a, value: v }))}
            disabled={result?.correct === true}
          />
        )}

        {problem.answer.kind === "ratio" && (() => {
          const ratioParts = (problem.answer as { kind: "ratio"; parts: number[] }).parts;
          return (
            <RatioInput
              parts={
                userAnswer.ratioParts
                  ? JSON.parse(userAnswer.ratioParts)
                  : ratioParts.map(() => "")
              }
              onChange={(i, v) => {
                const current = userAnswer.ratioParts
                  ? JSON.parse(userAnswer.ratioParts)
                  : ratioParts.map(() => "");
                current[i] = v;
                setUserAnswer((a) => ({
                  ...a,
                  ratioParts: JSON.stringify(current),
                  ratio: current.join(":"),
                }));
              }}
              disabled={result?.correct === true}
            />
          );
        })()}

        {problem.answer.kind === "standardForm" && (
          <div className="flex items-center gap-1">
            <input
              type="text"
              inputMode="decimal"
              value={userAnswer.coefficient || ""}
              onChange={(e) => setUserAnswer((a) => ({ ...a, coefficient: e.target.value }))}
              disabled={result?.correct === true}
              className="w-16 rounded-lg border border-border bg-surface px-2 py-2 text-center font-bold focus:border-unit-2 focus:outline-none"
              placeholder="?"
              aria-label="Coefficient"
            />
            <span className="text-lg font-bold">x 10</span>
            <input
              type="text"
              inputMode="numeric"
              value={userAnswer.exponent || ""}
              onChange={(e) => setUserAnswer((a) => ({ ...a, exponent: e.target.value }))}
              disabled={result?.correct === true}
              className="w-12 -translate-y-2 rounded-lg border border-border bg-surface px-2 py-1 text-center text-sm font-bold focus:border-unit-2 focus:outline-none"
              placeholder="?"
              aria-label="Exponent"
            />
          </div>
        )}
      </div>

      {/* Actions */}
      <div className="mb-4 flex flex-wrap justify-center gap-3">
        {!result?.correct && (
          <>
            <Button variant={unitColor} size="sm" onClick={checkAnswer}>
              Check Answer
            </Button>
            <Button variant="secondary" size="sm" onClick={nextHint}>
              Hint
            </Button>
            <Button variant="ghost" size="sm" onClick={() => setShowSolution(true)}>
              Show Solution
            </Button>
          </>
        )}
        {result?.correct && (
          <Button variant={unitColor} size="sm" onClick={() => generateNew(difficulty)}>
            Next Problem
          </Button>
        )}
      </div>

      {/* Feedback */}
      <AnimatePresence>
        {result && (
          <motion.div
            initial={{ opacity: 0, y: -10 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0 }}
            className={`rounded-xl px-4 py-3 text-center text-sm font-medium ${
              result.correct
                ? result.simplified
                  ? "bg-correct-light text-correct"
                  : "bg-hint-light text-hint"
                : "bg-incorrect-light text-incorrect"
            }`}
          >
            {result.correct
              ? result.simplified
                ? "Correct!"
                : "Correct, but can you simplify further?"
              : result.message}
          </motion.div>
        )}
      </AnimatePresence>

      {/* Hint */}
      <AnimatePresence>
        {showHint && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            className="mt-3 rounded-xl bg-hint-light px-4 py-3 text-sm text-hint"
          >
            {problem.hints[hintIndex]}
          </motion.div>
        )}
      </AnimatePresence>

      {/* Solution */}
      <AnimatePresence>
        {showSolution && (
          <motion.div
            initial={{ opacity: 0, height: 0 }}
            animate={{ opacity: 1, height: "auto" }}
            className="mt-3 space-y-2 rounded-xl bg-background p-4"
          >
            <p className="text-xs font-semibold uppercase text-muted">Solution</p>
            {problem.steps.map((step, i) => (
              <div key={i} className="flex gap-2 text-sm">
                <span className="shrink-0 font-bold text-muted">{i + 1}.</span>
                <span>{step.explanation}</span>
              </div>
            ))}
          </motion.div>
        )}
      </AnimatePresence>
    </Card>
  );
}
