"use client";

import { useState } from "react";
import { Card } from "@/components/ui/card";
import { StepControls } from "./step-controls";
import { MathDisplay } from "@/components/math/math-display";
import { toKatex, simplify, add, subtract, multiply, divide } from "@/lib/math/fractions";

interface FractionVal {
  num: number;
  den: number;
}

interface Expression {
  fractions: FractionVal[];
  operators: string[];
}

interface Step {
  label: string;
  math: string;
  highlightIndex: number | null; // which operator is being evaluated
}

const OP_PRIORITY: Record<string, number> = {
  "×": 2,
  "÷": 2,
  "+": 1,
  "−": 1,
};

function performOp(a: FractionVal, b: FractionVal, op: string): FractionVal {
  let result: [number, number];
  switch (op) {
    case "+":
      result = add(a.num, a.den, b.num, b.den);
      break;
    case "−":
      result = subtract(a.num, a.den, b.num, b.den);
      break;
    case "×":
      result = multiply(a.num, a.den, b.num, b.den);
      break;
    case "÷":
      result = divide(a.num, a.den, b.num, b.den);
      break;
    default:
      result = [0, 1];
  }
  return { num: result[0], den: result[1] };
}

function expressionToKatex(fracs: FractionVal[], ops: string[], highlightIdx: number | null): string {
  const parts: string[] = [];
  fracs.forEach((f, i) => {
    parts.push(toKatex(f.num, f.den));
    if (i < ops.length) {
      if (i === highlightIdx) {
        parts.push(`\\;\\boxed{${ops[i]}}\\;`);
      } else {
        parts.push(`\\;${ops[i]}\\;`);
      }
    }
  });
  return parts.join("");
}

function buildBodmasSteps(expr: Expression): Step[] {
  const steps: Step[] = [];
  let fracs = [...expr.fractions];
  let ops = [...expr.operators];

  // Step 0: Show the expression
  steps.push({
    label: "Start with the expression",
    math: expressionToKatex(fracs, ops, null),
    highlightIndex: null,
  });

  while (ops.length > 0) {
    // Find highest priority operator (leftmost if tie)
    let maxPri = 0;
    let opIdx = 0;
    ops.forEach((op, i) => {
      if (OP_PRIORITY[op] > maxPri) {
        maxPri = OP_PRIORITY[op];
        opIdx = i;
      }
    });

    // Highlight the operation to perform
    steps.push({
      label: `BODMAS: do ${ops[opIdx]} first (${OP_PRIORITY[ops[opIdx]] === 2 ? "multiplication/division" : "addition/subtraction"})`,
      math: expressionToKatex(fracs, ops, opIdx),
      highlightIndex: opIdx,
    });

    // Perform the operation
    const result = performOp(fracs[opIdx], fracs[opIdx + 1], ops[opIdx]);
    const [sn, sd] = simplify(result.num, result.den);

    const newFracs = [...fracs];
    newFracs.splice(opIdx, 2, { num: sn, den: sd });
    const newOps = [...ops];
    newOps.splice(opIdx, 1);

    steps.push({
      label: `${fracs[opIdx].num}/${fracs[opIdx].den} ${ops[opIdx]} ${fracs[opIdx + 1].num}/${fracs[opIdx + 1].den} = ${sn}/${sd}`,
      math: expressionToKatex(newFracs, newOps, null),
      highlightIndex: null,
    });

    fracs = newFracs;
    ops = newOps;
  }

  return steps;
}

const PRESETS: { label: string; fracs: FractionVal[]; ops: string[] }[] = [
  {
    label: "½ + ¼ × ⅗",
    fracs: [
      { num: 1, den: 2 },
      { num: 1, den: 4 },
      { num: 3, den: 5 },
    ],
    ops: ["+", "×"],
  },
  {
    label: "⅔ × ¾ − ½",
    fracs: [
      { num: 2, den: 3 },
      { num: 3, den: 4 },
      { num: 1, den: 2 },
    ],
    ops: ["×", "−"],
  },
  {
    label: "⅗ ÷ ¼ + ⅔",
    fracs: [
      { num: 3, den: 5 },
      { num: 1, den: 4 },
      { num: 2, den: 3 },
    ],
    ops: ["÷", "+"],
  },
];

export function BODMASExplorer() {
  const [fracs, setFracs] = useState<FractionVal[]>([
    { num: 1, den: 2 },
    { num: 1, den: 4 },
    { num: 3, den: 5 },
  ]);
  const [ops, setOps] = useState<string[]>(["+", "×"]);
  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;

  function updateFrac(idx: number, field: "num" | "den", value: string) {
    setFracs((prev) => {
      const next = [...prev];
      next[idx] = { ...next[idx], [field]: parseInt(value) || 0 };
      return next;
    });
  }

  function handleGo() {
    setError("");
    if (fracs.some((f) => f.den === 0)) {
      setError("Denominators cannot be zero.");
      return;
    }
    if (fracs.some((f) => Math.abs(f.num) > 99 || Math.abs(f.den) > 99)) {
      setError("Keep numbers under 100.");
      return;
    }
    try {
      const s = buildBodmasSteps({ fractions: fracs, operators: ops });
      setSteps(s);
      setCurrentStep(0);
      setIsPlaying(false);
    } catch {
      setError("Could not compute. Check your inputs.");
    }
  }

  function loadPreset(idx: number) {
    const p = PRESETS[idx];
    setFracs([...p.fracs]);
    setOps([...p.ops]);
    reset();
  }

  function stepForward() {
    if (!steps || currentStep >= steps.length - 1) return;
    setCurrentStep((s) => s + 1);
    if (currentStep + 1 >= steps.length - 1) setIsPlaying(false);
  }

  function stepBack() {
    if (currentStep <= 0) return;
    setCurrentStep((s) => s - 1);
  }

  function togglePlay() {
    setIsPlaying((p) => !p);
  }

  function reset() {
    setSteps(null);
    setCurrentStep(0);
    setIsPlaying(false);
  }

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

  const opChoices = ["+", "−", "×", "÷"];

  return (
    <div className="space-y-4">
      {/* Presets */}
      <div className="flex flex-wrap gap-2">
        {PRESETS.map((p, i) => (
          <button
            key={i}
            onClick={() => loadPreset(i)}
            className="rounded-full border-2 border-unit-1/40 px-4 py-2 text-sm font-semibold text-unit-1 transition-colors hover:bg-unit-1-light"
          >
            {p.label}
          </button>
        ))}
      </div>

      {/* Input */}
      <Card>
        <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-1">
          Enter a BODMAS expression with fractions
        </p>
        <div className="flex flex-wrap items-center gap-2">
          {fracs.map((f, i) => (
            <div key={i} className="flex items-center gap-2">
              <div className="flex flex-col items-center">
                <input
                  type="number"
                  value={f.num || ""}
                  onChange={(e) => updateFrac(i, "num", e.target.value)}
                  className="w-12 rounded-lg border-2 border-border bg-surface px-1.5 py-1 text-center text-base font-bold outline-none focus:border-unit-1"
                  aria-label={`Numerator ${i + 1}`}
                />
                <div className="my-0.5 h-0.5 w-10 bg-foreground" />
                <input
                  type="number"
                  value={f.den || ""}
                  onChange={(e) => updateFrac(i, "den", e.target.value)}
                  className="w-12 rounded-lg border-2 border-border bg-surface px-1.5 py-1 text-center text-base font-bold outline-none focus:border-unit-1"
                  aria-label={`Denominator ${i + 1}`}
                />
              </div>
              {i < ops.length && (
                <select
                  value={ops[i]}
                  onChange={(e) => {
                    const next = [...ops];
                    next[i] = e.target.value;
                    setOps(next);
                  }}
                  className="rounded-lg border-2 border-border bg-surface px-2 py-2 text-center text-lg font-bold text-foreground outline-none focus:border-unit-1"
                >
                  {opChoices.map((o) => (
                    <option key={o} value={o}>
                      {o}
                    </option>
                  ))}
                </select>
              )}
            </div>
          ))}
          <button
            onClick={handleGo}
            className="rounded-lg bg-unit-1 px-6 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-1-dark"
          >
            Go →
          </button>
        </div>
        {error && <p className="mt-2 text-sm text-incorrect">{error}</p>}
      </Card>

      {/* Display */}
      <Card className="flex min-h-[200px] flex-col items-center justify-center gap-4 p-6">
        {!step ? (
          <p className="text-muted/50">
            Enter an expression above and click <strong>Go</strong>
          </p>
        ) : (
          <>
            <p className="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>

      {/* Result */}
      <Card className="flex min-h-[80px] flex-col items-center justify-center gap-1.5 text-center">
        {!done || !steps ? (
          <p className="text-sm text-muted/40">Result will appear here when steps are complete</p>
        ) : (
          <>
            <p className="text-xs uppercase tracking-wider text-muted">Final Answer</p>
            <div className="text-3xl font-extrabold max-sm:text-2xl">
              <MathDisplay math={steps[steps.length - 1].math} />
            </div>
          </>
        )}
      </Card>
    </div>
  );
}
