"use client";

import { useState, useCallback } from "react";
import { Card } from "@/components/ui/card";
import { StepControls } from "./step-controls";
import { gcd, lcm, toKatex, Fraction } from "@/lib/math/fractions";
import { MathDisplay } from "@/components/math/math-display";

type Operation = "add" | "subtract" | "multiply" | "divide";

interface Step {
  label: string;
  math: string;
  barA: { filled: number; total: number };
  barB: { filled: number; total: number };
  barResult?: { filled: number; total: number };
}

function buildSteps(
  n1: number, d1: number,
  n2: number, d2: number,
  op: Operation,
): Step[] {
  const steps: Step[] = [];

  // Step 0: Show the original fractions
  const opSymbol = { add: "+", subtract: "-", multiply: "\\times", divide: "\\div" }[op];
  steps.push({
    label: "Start with the two fractions",
    math: `${toKatex(n1, d1)} ${opSymbol} ${toKatex(n2, d2)}`,
    barA: { filled: n1, total: d1 },
    barB: { filled: n2, total: d2 },
  });

  if (op === "add" || op === "subtract") {
    // Step 1: Find LCD
    const lcd = lcm(d1, d2);
    const mult1 = lcd / d1;
    const mult2 = lcd / d2;
    const cn1 = n1 * mult1;
    const cn2 = n2 * mult2;

    if (d1 !== d2) {
      steps.push({
        label: `Find the LCD of ${d1} and ${d2}`,
        math: `\\text{LCD}(${d1}, ${d2}) = ${lcd}`,
        barA: { filled: n1, total: d1 },
        barB: { filled: n2, total: d2 },
      });

      // Step 2: Convert both fractions
      steps.push({
        label: "Convert to equivalent fractions with the LCD",
        math: `${toKatex(n1, d1)} = ${toKatex(cn1, lcd)} \\quad ${toKatex(n2, d2)} = ${toKatex(cn2, lcd)}`,
        barA: { filled: cn1, total: lcd },
        barB: { filled: cn2, total: lcd },
      });
    }

    // Step 3: Perform the operation
    const resultNum = op === "add" ? cn1 + cn2 : cn1 - cn2;
    steps.push({
      label: op === "add" ? "Add the numerators" : "Subtract the numerators",
      math: `${toKatex(cn1, lcd)} ${opSymbol} ${toKatex(cn2, lcd)} = ${toKatex(resultNum, lcd)}`,
      barA: { filled: cn1, total: lcd },
      barB: { filled: cn2, total: lcd },
      barResult: { filled: Math.abs(resultNum), total: lcd },
    });

    // Step 4: Simplify if needed
    const { n: sn, d: sd } = new Fraction(resultNum, lcd).simplified();
    if (Math.abs(sn) !== Math.abs(resultNum) || sd !== lcd) {
      const g = gcd(Math.abs(resultNum), lcd);
      steps.push({
        label: `Simplify by dividing by GCD = ${g}`,
        math: `${toKatex(resultNum, lcd)} = ${toKatex(sn, sd)}`,
        barA: { filled: cn1, total: lcd },
        barB: { filled: cn2, total: lcd },
        barResult: { filled: Math.abs(sn), total: sd },
      });
    }
  } else if (op === "multiply") {
    // Step 1: Multiply numerators and denominators
    const rn = n1 * n2;
    const rd = d1 * d2;
    steps.push({
      label: "Multiply numerators and denominators",
      math: `\\frac{${n1} \\times ${n2}}{${d1} \\times ${d2}} = ${toKatex(rn, rd)}`,
      barA: { filled: n1, total: d1 },
      barB: { filled: n2, total: d2 },
      barResult: { filled: rn, total: rd },
    });

    // Step 2: Simplify
    const { n: sn, d: sd } = new Fraction(rn, rd).simplified();
    if (sn !== rn || sd !== rd) {
      const g = gcd(Math.abs(rn), rd);
      steps.push({
        label: `Simplify by dividing by GCD = ${g}`,
        math: `${toKatex(rn, rd)} = ${toKatex(sn, sd)}`,
        barA: { filled: n1, total: d1 },
        barB: { filled: n2, total: d2 },
        barResult: { filled: Math.abs(sn), total: sd },
      });
    }
  } else {
    // divide: invert and multiply
    steps.push({
      label: "Invert the second fraction (reciprocal)",
      math: `${toKatex(n1, d1)} \\times ${toKatex(d2, n2)}`,
      barA: { filled: n1, total: d1 },
      barB: { filled: d2, total: n2 },
    });

    const rn = n1 * d2;
    const rd = d1 * n2;
    steps.push({
      label: "Multiply numerators and denominators",
      math: `\\frac{${n1} \\times ${d2}}{${d1} \\times ${n2}} = ${toKatex(rn, rd)}`,
      barA: { filled: n1, total: d1 },
      barB: { filled: d2, total: n2 },
      barResult: { filled: rn, total: rd },
    });

    const { n: sn, d: sd } = new Fraction(rn, rd).simplified();
    if (sn !== rn || sd !== rd) {
      const g = gcd(Math.abs(rn), rd);
      steps.push({
        label: `Simplify by dividing by GCD = ${g}`,
        math: `${toKatex(rn, rd)} = ${toKatex(sn, sd)}`,
        barA: { filled: n1, total: d1 },
        barB: { filled: d2, total: n2 },
        barResult: { filled: Math.abs(sn), total: sd },
      });
    }
  }

  return steps;
}

function FractionBar({
  filled,
  total,
  color,
  label,
}: {
  filled: number;
  total: number;
  color: string;
  label?: string;
}) {
  const maxSegments = Math.min(total, 24);
  const fillCount = Math.min(filled, maxSegments);

  return (
    <div className="flex flex-col items-center gap-1">
      {label && <span className="text-xs font-medium text-muted">{label}</span>}
      <div className="flex h-10 w-full max-w-[280px] overflow-hidden rounded-lg border-2 border-border">
        {Array.from({ length: maxSegments }, (_, i) => (
          <div
            key={i}
            className="border-r border-border/30 transition-colors duration-500 last:border-r-0"
            style={{
              flex: 1,
              backgroundColor: i < fillCount ? color : "transparent",
            }}
          />
        ))}
      </div>
      <span className="text-xs text-muted">
        {filled}/{total}
      </span>
    </div>
  );
}

export function FractionOperationExplorer({
  initialOperation = "add",
}: {
  initialOperation?: Operation;
} = {}) {
  const [op, setOp] = useState<Operation>(initialOperation);
  const [n1, setN1] = useState("1");
  const [d1, setD1] = useState("3");
  const [n2, setN2] = useState("1");
  const [d2, setD2] = useState("4");
  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 handleGo() {
    setError("");
    const nums = [parseInt(n1), parseInt(d1), parseInt(n2), parseInt(d2)];
    if (nums.some(isNaN) || nums.some((n) => n === 0)) {
      setError("Enter valid non-zero numbers.");
      return;
    }
    if (nums[1] < 0 || nums[3] < 0) {
      setError("Denominators must be positive.");
      return;
    }
    if (nums.some((n) => Math.abs(n) > 99)) {
      setError("Keep numbers under 100.");
      return;
    }
    try {
      const s = buildSteps(nums[0], nums[1], nums[2], nums[3], op);
      setSteps(s);
      setCurrentStep(0);
      setIsPlaying(false);
    } catch {
      setError("Could not compute. Check your inputs.");
    }
  }

  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 reset = useCallback(() => {
    setSteps(null);
    setCurrentStep(0);
    setIsPlaying(false);
  }, []);

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

  const opLabels: Record<Operation, string> = {
    add: "Add (+)",
    subtract: "Subtract (−)",
    multiply: "Multiply (×)",
    divide: "Divide (÷)",
  };

  return (
    <div className="space-y-4">
      {/* Operation tabs */}
      <div className="flex flex-wrap gap-2">
        {(["add", "subtract", "multiply", "divide"] as Operation[]).map((o) => (
          <button
            key={o}
            onClick={() => {
              setOp(o);
              reset();
            }}
            className={`rounded-full border-2 px-4 py-2 text-sm font-semibold transition-colors ${
              op === o
                ? "border-unit-1 bg-unit-1 text-white"
                : "border-unit-1/40 text-unit-1 hover:bg-unit-1-light"
            }`}
          >
            {opLabels[o]}
          </button>
        ))}
      </div>

      {/* Input Card */}
      <Card>
        <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-1">
          Enter two fractions
        </p>
        <div className="flex flex-wrap items-center gap-3">
          <div className="flex items-center gap-1">
            <div className="flex flex-col items-center">
              <input
                type="number"
                value={n1}
                onChange={(e) => setN1(e.target.value)}
                className="w-14 rounded-lg border-2 border-border bg-surface px-2 py-1.5 text-center text-lg font-bold outline-none focus:border-unit-1"
                aria-label="Numerator 1"
              />
              <div className="my-0.5 h-0.5 w-12 bg-foreground" />
              <input
                type="number"
                value={d1}
                onChange={(e) => setD1(e.target.value)}
                className="w-14 rounded-lg border-2 border-border bg-surface px-2 py-1.5 text-center text-lg font-bold outline-none focus:border-unit-1"
                aria-label="Denominator 1"
              />
            </div>
          </div>
          <span className="text-xl font-bold text-muted">
            {{ add: "+", subtract: "−", multiply: "×", divide: "÷" }[op]}
          </span>
          <div className="flex items-center gap-1">
            <div className="flex flex-col items-center">
              <input
                type="number"
                value={n2}
                onChange={(e) => setN2(e.target.value)}
                className="w-14 rounded-lg border-2 border-border bg-surface px-2 py-1.5 text-center text-lg font-bold outline-none focus:border-unit-1"
                aria-label="Numerator 2"
              />
              <div className="my-0.5 h-0.5 w-12 bg-foreground" />
              <input
                type="number"
                value={d2}
                onChange={(e) => setD2(e.target.value)}
                className="w-14 rounded-lg border-2 border-border bg-surface px-2 py-1.5 text-center text-lg font-bold outline-none focus:border-unit-1"
                aria-label="Denominator 2"
              />
            </div>
          </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 */}
      <Card className="flex min-h-[240px] flex-col items-center justify-center gap-5 p-6">
        {!step ? (
          <p className="text-muted/50">
            Enter fractions 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" />
            <div className="flex w-full max-w-md flex-col gap-3">
              <FractionBar
                filled={step.barA.filled}
                total={step.barA.total}
                color="var(--unit-1)"
                label="First"
              />
              <FractionBar
                filled={step.barB.filled}
                total={step.barB.total}
                color="var(--unit-1-dark)"
                label="Second"
              />
              {step.barResult && (
                <FractionBar
                  filled={step.barResult.filled}
                  total={step.barResult.total}
                  color="var(--correct)"
                  label="Result"
                />
              )}
            </div>
          </>
        )}
      </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">Answer</p>
            <div className="text-3xl font-extrabold max-sm:text-2xl">
              <MathDisplay math={steps[steps.length - 1].math} />
            </div>
          </>
        )}
      </Card>
    </div>
  );
}
