"use client";

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

type SortDirection = "ascending" | "descending";

interface Step {
  label: string;
  values: { value: number; str: string; sorted: boolean; comparing: boolean }[];
  comparingPair?: [number, number];
}

function padDecimal(s: string, maxInt: number, maxDec: number): string {
  const parts = s.split(".");
  const intPart = (parts[0] || "0").padStart(maxInt, "\u00A0"); // nbsp padding
  const decPart = (parts[1] || "").padEnd(maxDec, "0");
  return maxDec > 0 ? `${intPart}.${decPart}` : intPart;
}

function buildSortSteps(values: number[], direction: SortDirection): Step[] {
  const steps: Step[] = [];
  const strs = values.map((v) => v.toString());

  // Find max integer and decimal lengths for alignment
  const maxInt = Math.max(...strs.map((s) => s.split(".")[0].length));
  const maxDec = Math.max(...strs.map((s) => (s.split(".")[1] || "").length));

  // Step 0: Show unsorted
  steps.push({
    label: `Sort ${values.length} decimals in ${direction} order`,
    values: values.map((v, i) => ({
      value: v,
      str: padDecimal(strs[i], maxInt, maxDec),
      sorted: false,
      comparing: false,
    })),
  });

  // Step 1: Show aligned place values
  steps.push({
    label: "Align decimal points to compare place values",
    values: values.map((v, i) => ({
      value: v,
      str: padDecimal(strs[i], maxInt, maxDec),
      sorted: false,
      comparing: false,
    })),
  });

  // Bubble sort with steps
  const arr = [...values];
  const arrStrs = [...strs];
  const cmp = direction === "ascending" ? (a: number, b: number) => a > b : (a: number, b: number) => a < b;

  for (let i = 0; i < arr.length - 1; i++) {
    for (let j = 0; j < arr.length - 1 - i; j++) {
      // Show comparison
      steps.push({
        label: `Compare ${arrStrs[j]} and ${arrStrs[j + 1]}`,
        values: arr.map((v, k) => ({
          value: v,
          str: padDecimal(arrStrs[k], maxInt, maxDec),
          sorted: k >= arr.length - i,
          comparing: k === j || k === j + 1,
        })),
        comparingPair: [j, j + 1],
      });

      if (cmp(arr[j], arr[j + 1])) {
        // Swap
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
        [arrStrs[j], arrStrs[j + 1]] = [arrStrs[j + 1], arrStrs[j]];

        steps.push({
          label: `Swap: ${arrStrs[j]} ${direction === "ascending" ? "<" : ">"} ${arrStrs[j + 1]}`,
          values: arr.map((v, k) => ({
            value: v,
            str: padDecimal(arrStrs[k], maxInt, maxDec),
            sorted: k >= arr.length - i,
            comparing: k === j || k === j + 1,
          })),
        });
      }
    }
  }

  // Final step: Show sorted
  steps.push({
    label: `Sorted (${direction}): ${arrStrs.join(direction === "ascending" ? " < " : " > ")}`,
    values: arr.map((v, k) => ({
      value: v,
      str: padDecimal(arrStrs[k], maxInt, maxDec),
      sorted: true,
      comparing: false,
    })),
  });

  return steps;
}

function NumberLine({ values, min, max }: { values: { value: number; sorted: boolean; comparing: boolean }[]; min: number; max: number }) {
  const range = max - min || 1;
  return (
    <div className="w-full max-w-lg">
      <div className="relative h-2 rounded-full bg-border">
        {values.map((v, i) => {
          const pct = ((v.value - min) / range) * 100;
          return (
            <div
              key={i}
              className={`absolute -top-2.5 h-7 w-7 -translate-x-1/2 rounded-full border-2 text-center text-[0.6rem] font-bold leading-[1.5rem] transition-all duration-500 ${
                v.comparing
                  ? "border-hint bg-hint-light text-foreground z-10"
                  : v.sorted
                    ? "border-correct bg-correct-light text-foreground"
                    : "border-unit-2 bg-unit-2-light text-foreground"
              }`}
              style={{ left: `${Math.max(5, Math.min(95, pct))}%` }}
            >
              {i + 1}
            </div>
          );
        })}
      </div>
      <div className="mt-4 flex justify-between text-xs text-muted">
        <span>{min}</span>
        <span>{max}</span>
      </div>
    </div>
  );
}

export function DecimalOrderExplorer() {
  const [input, setInput] = useState("3.14, 3.1, 3.141, 3.04, 3.4");
  const [direction, setDirection] = useState<SortDirection>("ascending");
  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 parts = input
      .split(/[,\s]+/)
      .map((s) => s.trim())
      .filter(Boolean);
    if (parts.length < 2) {
      setError("Enter at least 2 decimals separated by commas.");
      return;
    }
    if (parts.length > 6) {
      setError("Maximum 6 decimals.");
      return;
    }
    const values = parts.map(Number);
    if (values.some(isNaN)) {
      setError("All values must be valid numbers.");
      return;
    }
    try {
      const s = buildSortSteps(values, direction);
      setSteps(s);
      setCurrentStep(0);
      setIsPlaying(false);
    } catch {
      setError("Could not process. 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">
      {/* Direction tabs */}
      <div className="flex gap-2">
        {(["ascending", "descending"] as SortDirection[]).map((d) => (
          <button
            key={d}
            onClick={() => {
              setDirection(d);
              reset();
            }}
            className={`rounded-full border-2 px-4 py-2 text-sm font-semibold capitalize transition-colors ${
              direction === d
                ? "border-unit-2 bg-unit-2 text-white"
                : "border-unit-2/40 text-unit-2 hover:bg-unit-2-light"
            }`}
          >
            {d}
          </button>
        ))}
      </div>

      {/* Input */}
      <Card>
        <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-2">
          Enter 2-6 decimal numbers (comma separated)
        </p>
        <div className="flex flex-wrap items-center gap-2.5">
          <input
            type="text"
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={(e) => e.key === "Enter" && handleGo()}
            placeholder="e.g. 3.14, 3.1, 3.141"
            autoComplete="off"
            className="max-w-[320px] 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-2"
          />
          <button
            onClick={handleGo}
            className="rounded-lg bg-unit-2 px-6 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-2-dark"
          >
            Sort →
          </button>
        </div>
        {error && <p className="mt-2 text-sm text-incorrect">{error}</p>}
      </Card>

      {/* Display */}
      <Card className="flex min-h-[280px] flex-col items-center justify-center gap-5 p-6">
        {!step ? (
          <p className="text-muted/50">
            Enter decimals above and click <strong>Sort</strong>
          </p>
        ) : (
          <>
            <p className="text-sm font-medium text-muted">{step.label}</p>
            {/* Place value columns */}
            <div className="flex flex-col gap-1.5 font-mono text-xl">
              {step.values.map((v, i) => (
                <div
                  key={i}
                  className={`rounded-lg border-2 px-4 py-2 text-center transition-all duration-300 ${
                    v.comparing
                      ? "border-hint bg-hint-light"
                      : v.sorted
                        ? "border-correct bg-correct-light"
                        : "border-border bg-surface"
                  }`}
                >
                  {v.str}
                </div>
              ))}
            </div>
            {/* Number line */}
            <NumberLine
              values={step.values}
              min={Math.min(...step.values.map((v) => v.value)) - 0.1}
              max={Math.max(...step.values.map((v) => v.value)) + 0.1}
            />
          </>
        )}
      </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">
              Sorted ({direction})
            </p>
            <p className="text-2xl font-extrabold text-foreground max-sm:text-xl">
              {step!.values.map((v) => v.value).join(direction === "ascending" ? " < " : " > ")}
            </p>
          </>
        )}
      </Card>
    </div>
  );
}
