"use client";

import { useState, useCallback } from "react";
import { Card } from "@/components/ui/card";
import { StepControls } from "./step-controls";

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

interface Step {
  label: string;
  columns: ColumnDisplay[];
  carry?: string;
  resultRow?: string;
}

interface ColumnDisplay {
  rows: string[];
  highlight?: number; // which row is highlighted
  separator?: boolean; // line above this row
}

function padAndAlign(a: string, b: string): { aStr: string; bStr: string; dotPos: number } {
  const aParts = a.split(".");
  const bParts = b.split(".");
  const aInt = aParts[0] || "0";
  const bInt = bParts[0] || "0";
  const aDec = aParts[1] || "";
  const bDec = bParts[1] || "";

  const maxInt = Math.max(aInt.length, bInt.length);
  const maxDec = Math.max(aDec.length, bDec.length);

  const aAligned = aInt.padStart(maxInt, " ") + (maxDec > 0 ? "." + aDec.padEnd(maxDec, "0") : "");
  const bAligned = bInt.padStart(maxInt, " ") + (maxDec > 0 ? "." + bDec.padEnd(maxDec, "0") : "");

  return { aStr: aAligned, bStr: bAligned, dotPos: maxInt };
}

function buildAddSubSteps(a: number, b: number, op: DecOp): Step[] {
  const steps: Step[] = [];
  const aStr = a.toString();
  const bStr = b.toString();
  const { aStr: aAligned, bStr: bAligned } = padAndAlign(aStr, bStr);

  const opSymbol = op === "add" ? "+" : "−";
  const result = op === "add" ? a + b : a - b;
  const resultStr = parseFloat(result.toFixed(10)).toString();

  // Step 0: Show the problem
  steps.push({
    label: `${aStr} ${opSymbol} ${bStr}`,
    columns: [],
  });

  // Step 1: Align decimal points
  steps.push({
    label: "Align the decimal points",
    columns: [
      { rows: [aAligned, `${opSymbol} ${bAligned}`] },
    ],
  });

  // Step 2: Add trailing zeros
  steps.push({
    label: "Fill in zeros as placeholders",
    columns: [
      { rows: [aAligned, `${opSymbol} ${bAligned}`], separator: true },
    ],
  });

  // Step 3: Compute
  const { aStr: aFinal, bStr: bFinal } = padAndAlign(aStr, bStr);
  const resultAligned = padAndAlign(resultStr, aStr).aStr;

  steps.push({
    label: `Compute column by column`,
    columns: [
      { rows: [aFinal, `${opSymbol} ${bFinal}`, resultAligned], separator: true, highlight: 2 },
    ],
  });

  // Step 4: Result
  steps.push({
    label: `${aStr} ${opSymbol} ${bStr} = ${resultStr}`,
    columns: [
      { rows: [aFinal, `${opSymbol} ${bFinal}`, resultAligned], separator: true, highlight: 2 },
    ],
    resultRow: resultStr,
  });

  return steps;
}

function buildMultiplySteps(a: number, b: number): Step[] {
  const steps: Step[] = [];
  const aStr = a.toString();
  const bStr = b.toString();
  const aDec = (aStr.split(".")[1] || "").length;
  const bDec = (bStr.split(".")[1] || "").length;
  const totalDec = aDec + bDec;

  // Remove decimals for integer multiplication
  const aInt = Math.round(a * Math.pow(10, aDec));
  const bInt = Math.round(b * Math.pow(10, bDec));
  const result = a * b;
  const resultStr = parseFloat(result.toFixed(10)).toString();

  steps.push({
    label: `${aStr} × ${bStr}`,
    columns: [],
  });

  if (totalDec > 0) {
    steps.push({
      label: `Count decimal places: ${aDec} + ${bDec} = ${totalDec}`,
      columns: [
        { rows: [`${aStr} → ${aDec} d.p.`, `${bStr} → ${bDec} d.p.`, `Total: ${totalDec} d.p.`] },
      ],
    });

    steps.push({
      label: `Multiply as whole numbers: ${aInt} × ${bInt}`,
      columns: [
        { rows: [`${aInt}`, `× ${bInt}`, `${aInt * bInt}`], separator: true, highlight: 2 },
      ],
    });

    steps.push({
      label: `Place decimal point ${totalDec} place${totalDec !== 1 ? "s" : ""} from the right`,
      columns: [
        { rows: [`${aInt * bInt}`, `→ ${resultStr}`], highlight: 1 },
      ],
      resultRow: resultStr,
    });
  } else {
    const intResult = a * b;
    steps.push({
      label: `Multiply: ${aStr} × ${bStr} = ${intResult}`,
      columns: [
        { rows: [`${aStr}`, `× ${bStr}`, `${intResult}`], separator: true, highlight: 2 },
      ],
      resultRow: intResult.toString(),
    });
  }

  return steps;
}

function buildDivideSteps(a: number, b: number): Step[] {
  const steps: Step[] = [];
  const aStr = a.toString();
  const bStr = b.toString();
  const result = a / b;
  const resultStr = parseFloat(result.toFixed(10)).toString();

  steps.push({
    label: `${aStr} ÷ ${bStr}`,
    columns: [],
  });

  // Make divisor a whole number
  const bDec = (bStr.split(".")[1] || "").length;
  if (bDec > 0) {
    const factor = Math.pow(10, bDec);
    const newA = parseFloat((a * factor).toFixed(10));
    const newB = parseFloat((b * factor).toFixed(10));
    steps.push({
      label: `Make divisor whole: multiply both by ${factor}`,
      columns: [
        { rows: [`${aStr} × ${factor} = ${newA}`, `${bStr} × ${factor} = ${newB}`] },
      ],
    });
    steps.push({
      label: `Now divide: ${newA} ÷ ${newB}`,
      columns: [
        { rows: [`${newA} ÷ ${newB}`, `= ${resultStr}`], highlight: 1 },
      ],
    });
  } else {
    steps.push({
      label: `Divide: ${aStr} ÷ ${bStr}`,
      columns: [
        { rows: [`${aStr} ÷ ${bStr}`, `= ${resultStr}`], highlight: 1 },
      ],
    });
  }

  steps.push({
    label: `${aStr} ÷ ${bStr} = ${resultStr}`,
    columns: [
      { rows: [`${aStr} ÷ ${bStr} = ${resultStr}`] },
    ],
    resultRow: resultStr,
  });

  return steps;
}

function ColumnArithmetic({
  columns,
}: {
  columns: ColumnDisplay[];
}) {
  if (columns.length === 0) return null;

  return (
    <div className="flex flex-col items-center gap-0.5 font-mono text-xl">
      {columns.map((col, ci) =>
        col.rows.map((row, ri) => (
          <div key={`${ci}-${ri}`}>
            {col.separator && ri === col.rows.length - 1 && (
              <div className="mb-1 h-0.5 bg-foreground" />
            )}
            <div
              className={`rounded-lg px-6 py-1.5 text-right tracking-wider transition-all duration-300 ${
                ri === col.highlight
                  ? "bg-unit-3-light font-bold text-foreground"
                  : "text-foreground"
              }`}
            >
              {row}
            </div>
          </div>
        )),
      )}
    </div>
  );
}

export function DecimalArithmeticExplorer({
  initialOperation = "add",
}: {
  initialOperation?: DecOp;
} = {}) {
  const [op, setOp] = useState<DecOp>(initialOperation);
  const [aInput, setAInput] = useState("12.45");
  const [bInput, setBInput] = useState("3.7");
  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 a = parseFloat(aInput);
    const b = parseFloat(bInput);
    if (isNaN(a) || isNaN(b)) {
      setError("Enter valid decimal numbers.");
      return;
    }
    if (op === "divide" && b === 0) {
      setError("Cannot divide by zero.");
      return;
    }
    try {
      let s: Step[];
      if (op === "add" || op === "subtract") {
        s = buildAddSubSteps(a, b, op);
      } else if (op === "multiply") {
        s = buildMultiplySteps(a, b);
      } else {
        s = buildDivideSteps(a, b);
      }
      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<DecOp, 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 DecOp[]).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-3 bg-unit-3 text-white"
                : "border-unit-3/40 text-unit-3 hover:bg-unit-3-light"
            }`}
          >
            {opLabels[o]}
          </button>
        ))}
      </div>

      {/* Input */}
      <Card>
        <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-3">
          Enter two decimal numbers
        </p>
        <div className="flex flex-wrap items-center gap-2.5">
          <input
            type="text"
            value={aInput}
            onChange={(e) => setAInput(e.target.value)}
            placeholder="e.g. 12.45"
            autoComplete="off"
            className="max-w-[140px] 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"
            aria-label="First number"
          />
          <span className="text-xl font-bold text-muted">
            {{ add: "+", subtract: "−", multiply: "×", divide: "÷" }[op]}
          </span>
          <input
            type="text"
            value={bInput}
            onChange={(e) => setBInput(e.target.value)}
            onKeyDown={(e) => e.key === "Enter" && handleGo()}
            placeholder="e.g. 3.7"
            autoComplete="off"
            className="max-w-[140px] 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"
            aria-label="Second number"
          />
          <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"
          >
            Go →
          </button>
        </div>
        {error && <p className="mt-2 text-sm text-incorrect">{error}</p>}
      </Card>

      {/* Display */}
      <Card className="flex min-h-[220px] flex-col items-center justify-center gap-4 p-6">
        {!step ? (
          <p className="text-muted/50">
            Enter numbers above and click <strong>Go</strong>
          </p>
        ) : (
          <>
            <p className="text-sm font-medium text-muted">{step.label}</p>
            <ColumnArithmetic columns={step.columns} />
          </>
        )}
      </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 || !step?.resultRow ? (
          <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>
            <p className="text-3xl font-extrabold text-foreground max-sm:text-2xl">
              {step.resultRow}
            </p>
          </>
        )}
      </Card>
    </div>
  );
}
