"use client";

import { useState, useCallback } from "react";
import { Card } from "@/components/ui/card";
import { ClientOnly } from "@/components/ui/client-only";
import { StepControls } from "./step-controls";
import { MathDisplay } from "@/components/math/math-display";
import { CartesianGrid, type GridPoint, type GridSegment, type GridArrow } from "./cartesian-grid";

type Mode = "plot" | "shape";

interface Step {
  label: string;
  math: string;
  points: GridPoint[];
  arrows?: GridArrow[];
  segments?: GridSegment[];
  highlight?: { x: number; y: number };
}

// ── Plot a single point ──────────────────────────────────────────────────────

function buildPlotSteps(x: number, y: number): Step[] {
  const steps: Step[] = [
    {
      label: "Start at the origin (0, 0) — where the two axes cross.",
      math: `(0,\\ 0)`,
      points: [{ x: 0, y: 0, label: "start", tone: "muted" }],
    },
  ];

  // Move along x
  if (x === 0) {
    steps.push({
      label: "The x-coordinate is 0, so stay on the y-axis — don't move left or right.",
      math: `x = 0`,
      points: [{ x: 0, y: 0, tone: "muted" }],
    });
  } else {
    steps.push({
      label: `Move ALONG the x-axis: ${Math.abs(x)} to the ${x > 0 ? "RIGHT" : "LEFT"}.`,
      math: `x = ${x}`,
      points: [{ x: 0, y: 0, tone: "muted" }],
      arrows: [{ from: { x: 0, y: 0 }, to: { x, y: 0 } }],
    });
  }

  // Move along y
  if (y === 0) {
    steps.push({
      label: "The y-coordinate is 0, so stay on the x-axis — don't move up or down.",
      math: `y = 0`,
      points: [{ x, y: 0, tone: "muted" }],
      arrows: x === 0 ? [] : [{ from: { x: 0, y: 0 }, to: { x, y: 0 } }],
    });
  } else {
    steps.push({
      label: `Now move parallel to the y-axis: ${Math.abs(y)} ${y > 0 ? "UP" : "DOWN"}.`,
      math: `y = ${y}`,
      points: [{ x, y: 0, tone: "muted" }],
      arrows: [
        ...(x === 0 ? [] : [{ from: { x: 0, y: 0 }, to: { x, y: 0 } }]),
        { from: { x, y: 0 }, to: { x, y } },
      ],
      highlight: { x, y },
    });
  }

  steps.push({
    label: `Mark the point (${x}, ${y}). Remember: the x-coordinate always comes first!`,
    math: `(${x},\\ ${y})`,
    points: [{ x, y, label: `(${x}, ${y})`, tone: "solid" }],
    highlight: { x, y },
  });

  return steps;
}

// ── Shape reveal presets ─────────────────────────────────────────────────────

interface Shape {
  name: string;
  points: { label: string; x: number; y: number }[];
}

const SHAPES: Record<string, Shape> = {
  mystery: {
    name: "Mystery Shape",
    points: [
      { label: "A", x: -4, y: -8 },
      { label: "B", x: -3, y: -9 },
      { label: "C", x: -2, y: -8 },
      { label: "D", x: -2, y: 0 },
      { label: "E", x: -5, y: 0 },
      { label: "F", x: -6, y: 4 },
      { label: "G", x: -2, y: 5 },
      { label: "H", x: 2, y: 4 },
      { label: "I", x: 5, y: 0 },
    ],
  },
  square: {
    name: "Square",
    points: [
      { label: "A", x: 2, y: 2 },
      { label: "B", x: 7, y: 2 },
      { label: "C", x: 7, y: 7 },
      { label: "D", x: 2, y: 7 },
    ],
  },
  house: {
    name: "House",
    points: [
      { label: "A", x: -5, y: -4 },
      { label: "B", x: 5, y: -4 },
      { label: "C", x: 5, y: 3 },
      { label: "D", x: 0, y: 7 },
      { label: "E", x: -5, y: 3 },
    ],
  },
};

function buildShapeSteps(shape: Shape): Step[] {
  const pts = shape.points;
  const steps: Step[] = [];

  for (let i = 0; i < pts.length; i++) {
    const plotted = pts.slice(0, i + 1);
    const segments: GridSegment[] = [];
    for (let j = 1; j <= i; j++) {
      segments.push({ from: pts[j - 1], to: pts[j] });
    }
    const p = pts[i];
    steps.push({
      label:
        i === 0
          ? `Plot the first point ${p.label} at (${p.x}, ${p.y}).`
          : `Plot ${p.label} at (${p.x}, ${p.y}) and join it to ${pts[i - 1].label}.`,
      math: `${p.label} = (${p.x},\\ ${p.y})`,
      points: plotted.map((q) => ({ x: q.x, y: q.y, label: q.label, tone: "solid" as const })),
      segments,
      highlight: { x: p.x, y: p.y },
    });
  }

  // Closing segment
  const allSegments: GridSegment[] = [];
  for (let j = 1; j < pts.length; j++) allSegments.push({ from: pts[j - 1], to: pts[j] });
  allSegments.push({ from: pts[pts.length - 1], to: pts[0] });
  steps.push({
    label: `Finally, join ${pts[pts.length - 1].label} back to ${pts[0].label} to close the shape. What is it?`,
    math: `${pts[pts.length - 1].label} \\to ${pts[0].label}`,
    points: pts.map((q) => ({ x: q.x, y: q.y, label: q.label, tone: "solid" as const })),
    segments: allSegments,
  });

  return steps;
}

// ── Quick practice: click the point ──────────────────────────────────────────

function randInt(min: number, max: number) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function ClickPractice() {
  const [target, setTarget] = useState(() => ({ x: randInt(-8, 8), y: randInt(-8, 8) }));
  const [clicked, setClicked] = useState<{ x: number; y: number } | null>(null);
  const [score, setScore] = useState({ correct: 0, total: 0 });

  const isCorrect = clicked && clicked.x === target.x && clicked.y === target.y;

  function handleClick(x: number, y: number) {
    if (clicked) return;
    const correct = x === target.x && y === target.y;
    setClicked({ x, y });
    setScore((s) => ({ correct: s.correct + (correct ? 1 : 0), total: s.total + 1 }));
  }

  function next() {
    setTarget({ x: randInt(-8, 8), y: randInt(-8, 8) });
    setClicked(null);
  }

  const points: GridPoint[] = [];
  if (clicked) {
    if (isCorrect) {
      points.push({ x: target.x, y: target.y, label: `(${target.x}, ${target.y})`, tone: "target" });
    } else {
      points.push({ x: clicked.x, y: clicked.y, label: "you", tone: "wrong" });
      points.push({ x: target.x, y: target.y, label: `(${target.x}, ${target.y})`, tone: "target" });
    }
  }

  return (
    <Card className="space-y-4">
      <div className="flex items-center justify-between">
        <p className="text-xs font-bold uppercase tracking-wider text-unit-7">Quick Practice</p>
        <span className="rounded-full bg-unit-7-light px-3 py-1 text-xs font-bold text-unit-7-dark">
          {score.correct}/{score.total}
        </span>
      </div>
      <p className="text-center text-lg font-bold">
        Click where <span className="text-unit-7-dark">({target.x}, {target.y})</span> belongs
      </p>
      <div className="mx-auto max-w-md">
        <CartesianGrid points={points} highlight={isCorrect ? target : undefined} onGridClick={clicked ? undefined : handleClick} />
      </div>
      {clicked && (
        <div className="space-y-2 text-center">
          {isCorrect ? (
            <p className="text-sm font-bold text-correct">Spot on! That is ({target.x}, {target.y}).</p>
          ) : (
            <p className="text-sm font-bold text-incorrect">
              You clicked ({clicked.x}, {clicked.y}). The target ({target.x}, {target.y}) is shown in green.
            </p>
          )}
          <button onClick={next} className="rounded-lg bg-foreground px-5 py-2 text-sm font-bold text-background hover:bg-foreground/80">
            Next →
          </button>
        </div>
      )}
    </Card>
  );
}

// ── Main explorer ────────────────────────────────────────────────────────────

export function PlotPointsExplorer() {
  const [mode, setMode] = useState<Mode>("plot");
  const [inputX, setInputX] = useState("4");
  const [inputY, setInputY] = useState("3");
  const [shapeKey, setShapeKey] = useState<keyof typeof SHAPES>("mystery");
  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;

  const reset = useCallback(() => {
    setSteps(null);
    setCurrentStep(0);
    setIsPlaying(false);
  }, []);

  function switchMode(m: Mode) {
    setMode(m);
    setError("");
    reset();
  }

  function handlePlot() {
    setError("");
    const x = parseInt(inputX, 10);
    const y = parseInt(inputY, 10);
    if (isNaN(x) || isNaN(y)) return setError("Enter whole numbers for x and y.");
    if ([x, y].some((v) => v < -10 || v > 10)) return setError("Keep both coordinates between -10 and 10.");
    setSteps(buildPlotSteps(x, y));
    setCurrentStep(0);
    setIsPlaying(false);
  }

  function handleShape() {
    setError("");
    setSteps(buildShapeSteps(SHAPES[shapeKey]));
    setCurrentStep(0);
    setIsPlaying(false);
  }

  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 step = steps ? steps[currentStep] : null;

  return (
    <div className="space-y-4">
      {/* Mode toggle */}
      <div className="flex flex-wrap gap-2">
        {(["plot", "shape"] as Mode[]).map((m) => (
          <button
            key={m}
            onClick={() => switchMode(m)}
            className={`rounded-full border-2 px-4 py-2 text-sm font-semibold transition-colors ${
              mode === m
                ? "border-unit-7 bg-unit-7 text-white"
                : "border-unit-7/40 text-unit-7 hover:bg-unit-7-light"
            }`}
          >
            {m === "plot" ? "Plot a Point" : "Shape Reveal"}
          </button>
        ))}
      </div>

      {/* Input card */}
      <Card>
        {mode === "plot" ? (
          <>
            <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-7">
              Enter the coordinates to plot
            </p>
            <div className="flex flex-wrap items-center gap-3">
              <span className="text-lg font-bold text-muted">(</span>
              <input
                type="number"
                value={inputX}
                onChange={(e) => setInputX(e.target.value)}
                className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-7"
                aria-label="x coordinate"
              />
              <span className="text-lg font-bold text-muted">,</span>
              <input
                type="number"
                value={inputY}
                onChange={(e) => setInputY(e.target.value)}
                className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-7"
                aria-label="y coordinate"
              />
              <span className="text-lg font-bold text-muted">)</span>
              <button
                onClick={handlePlot}
                className="rounded-lg bg-unit-7 px-6 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-7-dark"
              >
                Plot →
              </button>
            </div>
          </>
        ) : (
          <>
            <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-7">
              Pick a shape, then step through the points to reveal it
            </p>
            <div className="flex flex-wrap items-center gap-3">
              <select
                value={shapeKey}
                onChange={(e) => {
                  setShapeKey(e.target.value as keyof typeof SHAPES);
                  reset();
                }}
                className="rounded-lg border-2 border-border bg-surface px-3 py-2 text-sm font-bold outline-none focus:border-unit-7"
                aria-label="Choose a shape"
              >
                {Object.entries(SHAPES).map(([key, s]) => (
                  <option key={key} value={key}>
                    {s.name}
                  </option>
                ))}
              </select>
              <button
                onClick={handleShape}
                className="rounded-lg bg-unit-7 px-6 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-7-dark"
              >
                Start →
              </button>
            </div>
          </>
        )}
        {error && <p className="mt-2 text-sm text-incorrect">{error}</p>}
      </Card>

      {/* Display card */}
      <Card className="flex min-h-[320px] flex-col items-center justify-center gap-4 p-6">
        {!step ? (
          <p className="text-muted/50">
            {mode === "plot" ? (
              <>Enter coordinates above and click <strong>Plot</strong></>
            ) : (
              <>Pick a shape and click <strong>Start</strong></>
            )}
          </p>
        ) : (
          <>
            <p className="text-center text-sm font-medium text-muted">{step.label}</p>
            <MathDisplay math={step.math} className="text-2xl" />
            <div className="w-full max-w-md">
              <CartesianGrid
                points={step.points}
                segments={step.segments}
                arrows={step.arrows}
                highlight={step.highlight}
              />
            </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>

      {/* Quick practice */}
      <ClientOnly fallback={<Card className="min-h-[220px]" />}>
        <ClickPractice />
      </ClientOnly>
    </div>
  );
}
