"use client";

import { useState, useCallback } from "react";
import { Card } from "@/components/ui/card";
import { ClientOnly } from "@/components/ui/client-only";
import { StepControls } from "./step-controls";
import { MathDisplay } from "@/components/math/math-display";

type Mode = "expand" | "index";
type IndexOp = "multiply" | "divide";

interface Step {
  label: string;
  math: string;
}

function repeat(base: number, count: number): string {
  return Array.from({ length: count }, () => `${base}`).join(" \\times ");
}

function buildExpandSteps(base: number, exp: number): Step[] {
  if (exp === 0) {
    return [
      { label: "The power (index) is 0.", math: `${base}^{0}` },
      { label: "Any number raised to the power 0 is equal to 1.", math: `${base}^{0} = 1` },
    ];
  }
  if (exp === 1) {
    return [
      { label: "The power (index) is 1.", math: `${base}^{1}` },
      { label: "Any number raised to the power 1 is itself.", math: `${base}^{1} = ${base}` },
    ];
  }

  const steps: Step[] = [
    {
      label: `The base is ${base} and the power is ${exp}: multiply the base by itself ${exp} times.`,
      math: `${base}^{${exp}}`,
    },
  ];
  let running = base;
  for (let k = 2; k <= exp; k++) {
    running *= base;
    steps.push({
      label: `Multiply on another ${base}.`,
      math: `${repeat(base, k)} = ${running}`,
    });
  }
  steps.push({ label: "So the power is worked out.", math: `${base}^{${exp}} = ${running}` });
  return steps;
}

function buildIndexSteps(base: number, m: number, n: number, op: IndexOp): Step[] {
  if (op === "multiply") {
    const total = m + n;
    const value = Math.pow(base, total);
    const steps: Step[] = [
      { label: "Multiplying powers of the SAME base.", math: `${base}^{${m}} \\times ${base}^{${n}}` },
      { label: "Write each power out in full.", math: `(${repeat(base, m)}) \\times (${repeat(base, n)})` },
      { label: `Count the factors: ${m} + ${n} = ${total}. When multiplying, ADD the powers.`, math: `${base}^{${m}} \\times ${base}^{${n}} = ${base}^{${m}+${n}} = ${base}^{${total}}` },
    ];
    if (value <= 1e7) steps.push({ label: "Work out the value.", math: `${base}^{${total}} = ${value}` });
    return steps;
  }
  // divide, m >= n
  const diff = m - n;
  const value = Math.pow(base, diff);
  const steps: Step[] = [
    { label: "Dividing powers of the SAME base.", math: `\\frac{${base}^{${m}}}{${base}^{${n}}}` },
    { label: "Write each power out in full.", math: `\\frac{${repeat(base, m)}}{${repeat(base, n)}}` },
    { label: `Cancel the ${n} matching factor${n === 1 ? "" : "s"} from top and bottom.`, math: `${base}^{${m}} \\div ${base}^{${n}} = ${base}^{${m}-${n}} = ${base}^{${diff}}` },
  ];
  if (value <= 1e7) steps.push({ label: "Work out the value.", math: `${base}^{${diff}} = ${value}` });
  return steps;
}

// ── Quick practice ───────────────────────────────────────────────────────────

interface PracticeQ {
  prompt: string;
  answer: number;
}

function randInt(min: number, max: number) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

const SUPERSCRIPT: Record<string, string> = {
  "0": "⁰", "1": "¹", "2": "²", "3": "³", "4": "⁴",
  "5": "⁵", "6": "⁶", "7": "⁷", "8": "⁸", "9": "⁹",
};
function sup(n: number): string {
  return String(n).split("").map((c) => SUPERSCRIPT[c] ?? c).join("");
}

function makeQuestion(): PracticeQ {
  const roll = Math.floor(Math.random() * 5);
  if (roll === 0) {
    const base = randInt(2, 7);
    const exp = randInt(2, 3);
    return { prompt: `What is ${base}${sup(exp)}?`, answer: Math.pow(base, exp) };
  }
  if (roll === 1) {
    const base = randInt(2, 9);
    return { prompt: `What is ${base}${sup(0)}?`, answer: 1 };
  }
  if (roll === 2) {
    const base = randInt(2, 4);
    const a = randInt(2, 3);
    const b = 1;
    return { prompt: `What is ${base}${sup(a)} − ${base}${sup(b)}?`, answer: Math.pow(base, a) - Math.pow(base, b) };
  }
  if (roll === 3) {
    const base = randInt(2, 5);
    const m = randInt(3, 6);
    const n = randInt(1, m - 1);
    return { prompt: `Simplify ${base}${sup(m)} ÷ ${base}${sup(n)}. The answer is ${base} to what power?`, answer: m - n };
  }
  const base = randInt(2, 6);
  const m = randInt(1, 4);
  const n = randInt(1, 4);
  return { prompt: `Simplify ${base}${sup(m)} × ${base}${sup(n)}. The answer is ${base} to what power?`, answer: m + n };
}

function QuickPractice() {
  const [q, setQ] = useState<PracticeQ>(() => makeQuestion());
  const [val, setVal] = useState("");
  const [feedback, setFeedback] = useState<"correct" | "incorrect" | null>(null);
  const [score, setScore] = useState({ correct: 0, total: 0 });

  function check() {
    const parsed = parseInt(val, 10);
    if (isNaN(parsed)) return;
    const correct = parsed === q.answer;
    setFeedback(correct ? "correct" : "incorrect");
    setScore((s) => ({ correct: s.correct + (correct ? 1 : 0), total: s.total + 1 }));
  }

  function next() {
    setQ(makeQuestion());
    setVal("");
    setFeedback(null);
  }

  return (
    <Card className="space-y-4">
      <div className="flex items-center justify-between">
        <p className="text-xs font-bold uppercase tracking-wider text-unit-8">Quick Practice</p>
        <span className="rounded-full bg-unit-8-light px-3 py-1 text-xs font-bold text-unit-8-dark">
          {score.correct}/{score.total}
        </span>
      </div>
      <p className="text-center text-lg font-bold">{q.prompt}</p>
      <div className="flex flex-wrap items-center justify-center gap-3">
        <input
          type="number"
          value={val}
          onChange={(e) => {
            setVal(e.target.value);
            setFeedback(null);
          }}
          onKeyDown={(e) => {
            if (e.key === "Enter") {
              if (feedback !== null) next();
              else check();
            }
          }}
          className={`w-24 rounded-lg border-2 px-3 py-2 text-center text-xl font-bold outline-none transition-colors ${
            feedback === "correct"
              ? "border-correct bg-correct-light"
              : feedback === "incorrect"
                ? "border-incorrect bg-incorrect-light"
                : "border-border focus:border-unit-8"
          }`}
          placeholder="?"
          aria-label="Your answer"
        />
        {feedback === null ? (
          <button onClick={check} className="rounded-lg bg-unit-8 px-5 py-2.5 text-sm font-bold text-white hover:bg-unit-8-dark">
            Check
          </button>
        ) : (
          <button onClick={next} className="rounded-lg bg-foreground px-5 py-2.5 text-sm font-bold text-background hover:bg-foreground/80">
            Next →
          </button>
        )}
      </div>
      {feedback === "correct" && <p className="text-center text-sm font-bold text-correct">Correct!</p>}
      {feedback === "incorrect" && (
        <p className="text-center text-sm font-bold text-incorrect">Not quite — the answer is {q.answer}.</p>
      )}
    </Card>
  );
}

// ── Main explorer ────────────────────────────────────────────────────────────

export function ExponentsExplorer() {
  const [mode, setMode] = useState<Mode>("expand");
  const [indexOp, setIndexOp] = useState<IndexOp>("multiply");
  const [base, setBase] = useState("2");
  const [power, setPower] = useState("4");
  const [m, setM] = useState("4");
  const [n, setN] = useState("3");
  const [error, setError] = useState("");

  const [steps, setSteps] = useState<Step[] | null>(null);
  const [currentStep, setCurrentStep] = useState(0);
  const [isPlaying, setIsPlaying] = useState(false);

  const done = steps ? currentStep >= steps.length - 1 : false;

  const reset = useCallback(() => {
    setSteps(null);
    setCurrentStep(0);
    setIsPlaying(false);
  }, []);

  function switchMode(md: Mode) {
    setMode(md);
    setError("");
    reset();
  }

  function handleGo() {
    setError("");
    const b = parseInt(base, 10);
    if (isNaN(b) || b < 2 || b > 12) return setError("Use a base between 2 and 12.");

    if (mode === "expand") {
      const e = parseInt(power, 10);
      if (isNaN(e) || e < 0 || e > 6) return setError("Use a power between 0 and 6.");
      if (Math.pow(b, e) > 1_000_000) return setError("That gets too big. Try a smaller base or power.");
      setSteps(buildExpandSteps(b, e));
    } else {
      const mm = parseInt(m, 10);
      const nn = parseInt(n, 10);
      if (isNaN(mm) || isNaN(nn) || mm < 1 || nn < 1 || mm > 8 || nn > 8) return setError("Use powers between 1 and 8.");
      if (indexOp === "divide" && mm < nn) return setError("For division, the top power must be at least the bottom power.");
      setSteps(buildIndexSteps(b, mm, nn, indexOp));
    }
    setCurrentStep(0);
    setIsPlaying(false);
  }

  const stepForward = useCallback(() => {
    if (!steps || currentStep >= steps.length - 1) return;
    setCurrentStep((s) => s + 1);
    if (currentStep + 1 >= steps.length - 1) setIsPlaying(false);
  }, [steps, currentStep]);

  const stepBack = useCallback(() => {
    if (currentStep <= 0) return;
    setCurrentStep((s) => s - 1);
  }, [currentStep]);

  const togglePlay = useCallback(() => setIsPlaying((p) => !p), []);

  const step = steps ? steps[currentStep] : null;

  return (
    <div className="space-y-4">
      {/* Mode toggle */}
      <div className="flex flex-wrap gap-2">
        {(["expand", "index"] as Mode[]).map((md) => (
          <button
            key={md}
            onClick={() => switchMode(md)}
            className={`rounded-full border-2 px-4 py-2 text-sm font-semibold transition-colors ${
              mode === md
                ? "border-unit-8 bg-unit-8 text-white"
                : "border-unit-8/40 text-unit-8 hover:bg-unit-8-light"
            }`}
          >
            {md === "expand" ? "Expand a Power" : "Index Laws"}
          </button>
        ))}
      </div>

      {/* Index op tabs */}
      {mode === "index" && (
        <div className="flex flex-wrap gap-2">
          {(["multiply", "divide"] as IndexOp[]).map((o) => (
            <button
              key={o}
              onClick={() => {
                setIndexOp(o);
                reset();
              }}
              className={`rounded-full border-2 px-4 py-2 text-sm font-semibold transition-colors ${
                indexOp === o
                  ? "border-unit-8-dark bg-unit-8-dark text-white"
                  : "border-unit-8/30 text-unit-8-dark hover:bg-unit-8-light"
              }`}
            >
              {o === "multiply" ? "Multiply (add powers)" : "Divide (subtract powers)"}
            </button>
          ))}
        </div>
      )}

      {/* Input card */}
      <Card>
        {mode === "expand" ? (
          <>
            <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-8">Enter a base and a power</p>
            <div className="flex flex-wrap items-center gap-3">
              <input type="number" value={base} onChange={(e) => setBase(e.target.value)} className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-8" aria-label="Base" />
              <span className="text-sm font-bold text-muted">to the power</span>
              <input type="number" value={power} onChange={(e) => setPower(e.target.value)} className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-8" aria-label="Power" />
              <button onClick={handleGo} className="rounded-lg bg-unit-8 px-6 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-8-dark">
                Go →
              </button>
            </div>
          </>
        ) : (
          <>
            <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-8">
              Same base, two powers {indexOp === "multiply" ? "to multiply" : "to divide"}
            </p>
            <div className="flex flex-wrap items-center gap-3">
              <span className="text-sm font-bold text-muted">base</span>
              <input type="number" value={base} onChange={(e) => setBase(e.target.value)} className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-8" aria-label="Base" />
              <span className="text-sm font-bold text-muted">powers</span>
              <input type="number" value={m} onChange={(e) => setM(e.target.value)} className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-8" aria-label="First power" />
              <span className="text-lg font-bold text-muted">{indexOp === "multiply" ? "×" : "÷"}</span>
              <input type="number" value={n} onChange={(e) => setN(e.target.value)} className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-8" aria-label="Second power" />
              <button onClick={handleGo} className="rounded-lg bg-unit-8 px-6 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-8-dark">
                Go →
              </button>
            </div>
          </>
        )}
        {error && <p className="mt-2 text-sm text-incorrect">{error}</p>}
      </Card>

      {/* Display card */}
      <Card className="flex min-h-[220px] flex-col items-center justify-center gap-4 p-6">
        {!step ? (
          <p className="text-muted/50">
            Enter values above and click <strong>Go</strong>
          </p>
        ) : (
          <>
            <p className="text-center text-sm font-medium text-muted">{step.label}</p>
            <MathDisplay math={step.math} className="text-2xl" />
          </>
        )}
      </Card>

      {/* Controls */}
      <Card className="p-4">
        <StepControls
          currentStep={currentStep + 1}
          totalSteps={steps?.length ?? 0}
          isPlaying={isPlaying}
          onStepForward={stepForward}
          onStepBack={stepBack}
          onTogglePlay={togglePlay}
          onReset={reset}
          canStepForward={!!steps && !done}
          canStepBack={!!steps && currentStep > 0}
        />
      </Card>

      {/* Quick practice */}
      <ClientOnly fallback={<Card className="min-h-[220px]" />}>
        <QuickPractice />
      </ClientOnly>
    </div>
  );
}
