"use client";

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

type ConvertMode = "decToFrac" | "fracToDec";

interface Step {
  label: string;
  math: string;
  gridFilled?: number; // out of 100 for decimal grid
  barFilled?: number;
  barTotal?: number;
}

function buildDecToFracSteps(decimal: string): Step[] {
  const steps: Step[] = [];
  const val = parseFloat(decimal);

  steps.push({
    label: `Convert ${decimal} to a fraction`,
    math: `${decimal} = \\;?`,
    gridFilled: Math.round(val * 100),
  });

  // Count decimal places
  const parts = decimal.split(".");
  const decPlaces = parts[1]?.length || 0;
  const denominator = Math.pow(10, decPlaces);
  const numerator = Math.round(val * denominator);

  steps.push({
    label: `${decPlaces} decimal place${decPlaces !== 1 ? "s" : ""} → denominator is ${denominator}`,
    math: `${decimal} = ${toKatex(numerator, denominator)}`,
    gridFilled: Math.round(val * 100),
    barFilled: numerator,
    barTotal: denominator,
  });

  // Simplify
  const { n: sn, d: sd } = new Fraction(numerator, denominator).simplified();
  if (sn !== numerator || sd !== denominator) {
    const g = gcd(numerator, denominator);
    steps.push({
      label: `Simplify by dividing by GCD = ${g}`,
      math: `${toKatex(numerator, denominator)} = ${toKatex(sn, sd)}`,
      gridFilled: Math.round(val * 100),
      barFilled: sn,
      barTotal: sd,
    });
  }

  steps.push({
    label: `Result: ${decimal} = ${sn}/${sd}`,
    math: `${decimal} = ${toKatex(sn, sd)}`,
    gridFilled: Math.round(val * 100),
    barFilled: sn,
    barTotal: sd,
  });

  return steps;
}

function buildFracToDecSteps(num: number, den: number): Step[] {
  const steps: Step[] = [];

  steps.push({
    label: `Convert ${num}/${den} to a decimal`,
    math: `${toKatex(num, den)} = \\;?`,
    barFilled: num,
    barTotal: den,
  });

  // Step: Perform the division
  const result = num / den;
  const resultStr = Number.isInteger(result) ? result.toString() : result.toFixed(6).replace(/0+$/, "");

  steps.push({
    label: `Divide numerator by denominator`,
    math: `${num} \\div ${den} = ${resultStr}`,
    barFilled: num,
    barTotal: den,
    gridFilled: Math.min(100, Math.round(result * 100)),
  });

  // Check for terminating vs repeating
  let tempDen = den;
  const { d: simpDen } = new Fraction(num, den).simplified();
  tempDen = simpDen;
  // Remove factors of 2 and 5
  while (tempDen % 2 === 0) tempDen /= 2;
  while (tempDen % 5 === 0) tempDen /= 5;
  const isTerminating = tempDen === 1;

  steps.push({
    label: isTerminating
      ? `This is a terminating decimal`
      : `This is a recurring decimal`,
    math: `${toKatex(num, den)} = ${resultStr}${!isTerminating ? "..." : ""}`,
    barFilled: num,
    barTotal: den,
    gridFilled: Math.min(100, Math.round(result * 100)),
  });

  return steps;
}

function DecimalGrid({ filled }: { filled: number }) {
  return (
    <div className="grid grid-cols-10 gap-0.5 rounded-lg border-2 border-border p-1" style={{ width: "fit-content" }}>
      {Array.from({ length: 100 }, (_, i) => (
        <div
          key={i}
          className="h-4 w-4 rounded-sm transition-colors duration-300"
          style={{
            backgroundColor: i < filled ? "var(--unit-3)" : "var(--background)",
          }}
        />
      ))}
    </div>
  );
}

function FractionBarSmall({ filled, total }: { filled: number; total: number }) {
  const segments = Math.min(total, 20);
  const fillCount = Math.min(filled, segments);
  return (
    <div className="flex h-8 w-full max-w-[240px] overflow-hidden rounded-lg border-2 border-border">
      {Array.from({ length: segments }, (_, i) => (
        <div
          key={i}
          className="border-r border-border/30 transition-colors duration-300 last:border-r-0"
          style={{
            flex: 1,
            backgroundColor: i < fillCount ? "var(--unit-3)" : "transparent",
          }}
        />
      ))}
    </div>
  );
}

export function ConversionExplorer() {
  const [mode, setMode] = useState<ConvertMode>("decToFrac");
  const [decInput, setDecInput] = useState("0.75");
  const [numInput, setNumInput] = useState("3");
  const [denInput, setDenInput] = useState("8");
  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("");
    try {
      let s: Step[];
      if (mode === "decToFrac") {
        const val = parseStrictDecimal(decInput);
        if (val === null || val < 0 || val >= 10) {
          setError("Enter a valid decimal between 0 and 10.");
          return;
        }
        s = buildDecToFracSteps(decInput.trim());
      } else {
        const n = parseStrictInt(numInput);
        const d = parseStrictInt(denInput);
        if (n === null || d === null || d === 0) {
          setError("Enter a valid fraction (denominator ≠ 0).");
          return;
        }
        s = buildFracToDecSteps(n, d);
      }
      setSteps(s);
      setCurrentStep(0);
      setIsPlaying(false);
    } catch {
      setError("Could not compute. Check your input.");
    }
  }

  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;

  return (
    <div className="space-y-4">
      {/* Mode tabs */}
      <div className="flex gap-2">
        <button
          onClick={() => {
            setMode("decToFrac");
            reset();
          }}
          className={`rounded-full border-2 px-4 py-2 text-sm font-semibold transition-colors ${
            mode === "decToFrac"
              ? "border-unit-3 bg-unit-3 text-white"
              : "border-unit-3/40 text-unit-3 hover:bg-unit-3-light"
          }`}
        >
          Decimal → Fraction
        </button>
        <button
          onClick={() => {
            setMode("fracToDec");
            reset();
          }}
          className={`rounded-full border-2 px-4 py-2 text-sm font-semibold transition-colors ${
            mode === "fracToDec"
              ? "border-unit-3 bg-unit-3 text-white"
              : "border-unit-3/40 text-unit-3 hover:bg-unit-3-light"
          }`}
        >
          Fraction → Decimal
        </button>
      </div>

      {/* Input */}
      <Card>
        <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-3">
          {mode === "decToFrac" ? "Enter a decimal" : "Enter a fraction"}
        </p>
        <div className="flex flex-wrap items-center gap-2.5">
          {mode === "decToFrac" ? (
            <input
              type="text"
              value={decInput}
              onChange={(e) => setDecInput(e.target.value)}
              onKeyDown={(e) => e.key === "Enter" && handleGo()}
              placeholder="e.g. 0.75"
              autoComplete="off"
              className="max-w-[180px] rounded-lg border-2 border-border bg-surface px-3.5 py-2.5 text-lg font-medium outline-none transition-colors focus:border-unit-3"
            />
          ) : (
            <div className="flex flex-col items-center">
              <input
                type="number"
                value={numInput}
                onChange={(e) => setNumInput(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-3"
                aria-label="Numerator"
              />
              <div className="my-0.5 h-0.5 w-12 bg-foreground" />
              <input
                type="number"
                value={denInput}
                onChange={(e) => setDenInput(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-3"
                aria-label="Denominator"
              />
            </div>
          )}
          <button
            onClick={handleGo}
            className="rounded-lg bg-unit-3 px-6 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-3-dark"
          >
            Convert →
          </button>
        </div>
        {error && <p className="mt-2 text-sm text-incorrect">{error}</p>}
      </Card>

      {/* Display */}
      <Card className="flex min-h-[260px] flex-col items-center justify-center gap-4 p-6">
        {!step ? (
          <p className="text-muted/50">
            Enter a value above and click <strong>Convert</strong>
          </p>
        ) : (
          <>
            <p className="text-sm font-medium text-muted">{step.label}</p>
            <MathDisplay math={step.math} className="text-2xl" />
            <div className="flex flex-wrap items-center justify-center gap-6">
              {step.gridFilled !== undefined && (
                <div className="flex flex-col items-center gap-1">
                  <DecimalGrid filled={step.gridFilled} />
                  <span className="text-xs text-muted">{step.gridFilled}/100</span>
                </div>
              )}
              {step.barFilled !== undefined && step.barTotal !== undefined && (
                <div className="flex flex-col items-center gap-1">
                  <FractionBarSmall filled={step.barFilled} total={step.barTotal} />
                  <span className="text-xs text-muted">
                    {step.barFilled}/{step.barTotal}
                  </span>
                </div>
              )}
            </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>
  );
}
