"use client";

import { useRef, useState, useEffect, useCallback } from "react";
import { X, Undo2, Trash2, Save, Loader2, Pen, Eraser } from "lucide-react";
import { cn } from "@/lib/utils";
import type { TakeAttachmentData } from "./TakeEditorPanel";

// ─── Types ────────────────────────────────────────────────────────────────────

interface Stroke {
  color: string;
  width: number;
  points: { x: number; y: number }[];
}

interface Props {
  takeId: string;
  onSaved: (attachment: TakeAttachmentData) => void;
  onClose: () => void;
}

// ─── Config ───────────────────────────────────────────────────────────────────

const BG_COLOR = "#1c1c1e";

const COLORS = [
  "#ffffff", "#d4d4d8",
  "#f87171", "#fb923c", "#facc15",
  "#4ade80", "#60a5fa", "#c084fc",
];

const BRUSH_SIZES = [2, 4, 8, 14, 24];

// ─── Component ────────────────────────────────────────────────────────────────

export function SketchPad({ takeId, onSaved, onClose }: Props) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const strokesRef = useRef<Stroke[]>([]);
  const currentStrokeRef = useRef<Stroke | null>(null);
  const isDrawingRef = useRef(false);

  // strokeCount is only used to drive button enabled/disabled state reactively
  const [strokeCount, setStrokeCount] = useState(0);
  const [color, setColor] = useState("#ffffff");
  const [brushSize, setBrushSize] = useState(4);
  const [isEraser, setIsEraser] = useState(false);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // ── Redraw all committed strokes ───────────────────────────────────────────
  const redraw = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    ctx.fillStyle = BG_COLOR;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    for (const stroke of strokesRef.current) {
      ctx.beginPath();
      ctx.strokeStyle = stroke.color;
      ctx.fillStyle = stroke.color;
      ctx.lineWidth = stroke.width;
      ctx.lineCap = "round";
      ctx.lineJoin = "round";

      if (stroke.points.length === 1) {
        // Single tap → dot
        ctx.arc(stroke.points[0].x, stroke.points[0].y, stroke.width / 2, 0, Math.PI * 2);
        ctx.fill();
      } else {
        ctx.moveTo(stroke.points[0].x, stroke.points[0].y);
        for (let i = 1; i < stroke.points.length; i++) {
          ctx.lineTo(stroke.points[i].x, stroke.points[i].y);
        }
        ctx.stroke();
      }
    }
  }, []);

  // ── Size canvas to fill container on mount + window resize ────────────────
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const fit = () => {
      const parent = canvas.parentElement;
      if (!parent) return;
      const { width, height } = parent.getBoundingClientRect();
      canvas.width = Math.floor(width);
      canvas.height = Math.floor(height);
      redraw();
    };

    fit();
    window.addEventListener("resize", fit);
    return () => window.removeEventListener("resize", fit);
  }, [redraw]);

  // ── Keyboard shortcuts ────────────────────────────────────────────────────
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
      if (e.key === "p" && !e.metaKey && !e.ctrlKey) setIsEraser(false);
      if (e.key === "e" && !e.metaKey && !e.ctrlKey) setIsEraser(true);
      if ((e.metaKey || e.ctrlKey) && e.key === "z") {
        e.preventDefault();
        strokesRef.current = strokesRef.current.slice(0, -1);
        setStrokeCount(strokesRef.current.length);
        redraw();
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose, redraw]);

  // ── Coordinate helper — CSS px → canvas buffer px ────────────────────────
  const getPos = (e: React.PointerEvent<HTMLCanvasElement>) => {
    const canvas = canvasRef.current!;
    const rect = canvas.getBoundingClientRect();
    return {
      x: (e.clientX - rect.left) * (canvas.width / rect.width),
      y: (e.clientY - rect.top) * (canvas.height / rect.height),
    };
  };

  // ── Pointer handlers ──────────────────────────────────────────────────────
  const onPointerDown = (e: React.PointerEvent<HTMLCanvasElement>) => {
    e.preventDefault();
    (e.target as HTMLCanvasElement).setPointerCapture(e.pointerId);
    isDrawingRef.current = true;

    const pos = getPos(e);
    const stroke: Stroke = {
      color: isEraser ? BG_COLOR : color,
      width: isEraser ? brushSize * 4 : brushSize,
      points: [pos],
    };
    currentStrokeRef.current = stroke;

    // Immediate dot feedback
    const ctx = canvasRef.current!.getContext("2d")!;
    ctx.beginPath();
    ctx.fillStyle = stroke.color;
    ctx.arc(pos.x, pos.y, stroke.width / 2, 0, Math.PI * 2);
    ctx.fill();
  };

  const onPointerMove = (e: React.PointerEvent<HTMLCanvasElement>) => {
    if (!isDrawingRef.current || !currentStrokeRef.current) return;
    e.preventDefault();

    const pos = getPos(e);
    const stroke = currentStrokeRef.current;
    const prev = stroke.points[stroke.points.length - 1];
    stroke.points.push(pos);

    // Incremental draw — no full redraw needed during stroke
    const ctx = canvasRef.current!.getContext("2d")!;
    ctx.beginPath();
    ctx.strokeStyle = stroke.color;
    ctx.lineWidth = stroke.width;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.moveTo(prev.x, prev.y);
    ctx.lineTo(pos.x, pos.y);
    ctx.stroke();
  };

  const onPointerUp = () => {
    if (!isDrawingRef.current) return;
    isDrawingRef.current = false;
    if (currentStrokeRef.current) {
      strokesRef.current = [...strokesRef.current, currentStrokeRef.current];
      setStrokeCount(strokesRef.current.length);
      currentStrokeRef.current = null;
    }
  };

  const undo = () => {
    strokesRef.current = strokesRef.current.slice(0, -1);
    setStrokeCount(strokesRef.current.length);
    redraw();
  };

  const clear = () => {
    strokesRef.current = [];
    setStrokeCount(0);
    redraw();
  };

  // ── Save ──────────────────────────────────────────────────────────────────
  const save = async () => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    setSaving(true);
    setError(null);
    try {
      const blob = await new Promise<Blob | null>((resolve) =>
        canvas.toBlob(resolve, "image/png")
      );
      if (!blob) throw new Error("Canvas export failed");

      const fileName = `sketch_${Date.now()}.png`;
      const fd = new FormData();
      fd.append("file", new File([blob], fileName, { type: "image/png" }));
      fd.append("type", "image");

      const uploadRes = await fetch("/api/upload", { method: "POST", body: fd });
      if (!uploadRes.ok) throw new Error("Upload failed");
      const { url, key } = await uploadRes.json();

      const attRes = await fetch(`/api/shoot-log/takes/${takeId}/attachments`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          fileUrl: url,
          fileKey: key ?? "",
          fileName,
          fileSize: blob.size,
          fileType: "IMAGE",
          category: "MISCELLANEOUS",
          caption: "Sketch",
        }),
      });
      if (!attRes.ok) throw new Error("Failed to save attachment");
      const { attachment } = await attRes.json();
      onSaved(attachment as TakeAttachmentData);
      onClose();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Save failed");
    } finally {
      setSaving(false);
    }
  };

  // ─── Render ───────────────────────────────────────────────────────────────
  const activeColor = isEraser ? BG_COLOR : color;

  return (
    <div className="fixed inset-0 z-50 flex flex-col" style={{ background: BG_COLOR }}>

      {/* ── Toolbar ── */}
      <div className="flex items-center gap-3 px-4 py-2 border-b border-zinc-800 bg-zinc-900/80 backdrop-blur shrink-0 flex-wrap">

        {/* Pen / Eraser toggle */}
        <div className="flex items-center gap-0.5 bg-zinc-800 rounded-lg p-0.5">
          <button
            onClick={() => setIsEraser(false)}
            className={cn(
              "p-1.5 rounded-md transition-colors",
              !isEraser ? "bg-zinc-700 text-white shadow" : "text-zinc-500 hover:text-zinc-300"
            )}
            title="Pen (P)"
          >
            <Pen className="h-4 w-4" />
          </button>
          <button
            onClick={() => setIsEraser(true)}
            className={cn(
              "p-1.5 rounded-md transition-colors",
              isEraser ? "bg-zinc-700 text-red-400 shadow" : "text-zinc-500 hover:text-zinc-300"
            )}
            title="Eraser (E)"
          >
            <Eraser className="h-4 w-4" />
          </button>
        </div>

        <div className="w-px h-5 bg-zinc-700" />

        {/* Colour swatches */}
        <div className="flex items-center gap-1.5">
          {COLORS.map((c) => (
            <button
              key={c}
              onClick={() => { setColor(c); setIsEraser(false); }}
              className={cn(
                "rounded-full border-2 transition-all",
                color === c && !isEraser
                  ? "border-amber-400 scale-125"
                  : "border-zinc-700 hover:border-zinc-400"
              )}
              style={{ width: 20, height: 20, backgroundColor: c }}
            />
          ))}
        </div>

        <div className="w-px h-5 bg-zinc-700" />

        {/* Brush sizes */}
        <div className="flex items-center gap-2">
          {BRUSH_SIZES.map((s) => (
            <button
              key={s}
              onClick={() => setBrushSize(s)}
              className={cn(
                "flex items-center justify-center rounded-full transition-all bg-zinc-800",
                brushSize === s ? "ring-2 ring-amber-400" : "opacity-50 hover:opacity-100"
              )}
              style={{ width: s + 10, height: s + 10 }}
              title={`${s}px`}
            >
              <div
                className="rounded-full"
                style={{ width: s, height: s, backgroundColor: activeColor === BG_COLOR ? "#ef4444" : activeColor }}
              />
            </button>
          ))}
        </div>

        <div className="flex-1" />

        {error && <span className="text-xs text-red-400">{error}</span>}

        {/* Action buttons */}
        <div className="flex items-center gap-1.5">
          <button
            onClick={undo}
            disabled={strokeCount === 0}
            className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium text-zinc-400 hover:text-white hover:bg-zinc-800 disabled:opacity-30 transition-colors"
            title="Undo (Ctrl+Z)"
          >
            <Undo2 className="h-3.5 w-3.5" />
            Undo
          </button>
          <button
            onClick={clear}
            disabled={strokeCount === 0}
            className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium text-zinc-400 hover:text-white hover:bg-zinc-800 disabled:opacity-30 transition-colors"
          >
            <Trash2 className="h-3.5 w-3.5" />
            Clear
          </button>
          <button
            onClick={save}
            disabled={saving || strokeCount === 0}
            className="flex items-center gap-1.5 px-4 py-1.5 rounded-lg text-xs font-semibold bg-amber-600 hover:bg-amber-500 text-white disabled:opacity-50 transition-colors"
          >
            {saving ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Save className="h-3.5 w-3.5" />}
            {saving ? "Saving…" : "Save Sketch"}
          </button>
          <button
            onClick={onClose}
            className="p-1.5 rounded-lg text-zinc-500 hover:text-white hover:bg-zinc-800 transition-colors ml-1"
            title="Discard (Esc)"
          >
            <X className="h-4 w-4" />
          </button>
        </div>
      </div>

      {/* ── Canvas ── */}
      <div className="flex-1 relative overflow-hidden">
        {strokeCount === 0 && (
          <div className="absolute inset-0 flex items-center justify-center pointer-events-none select-none">
            <p className="text-zinc-700 text-base">Draw your sketch…</p>
          </div>
        )}
        <canvas
          ref={canvasRef}
          className="absolute inset-0 cursor-crosshair"
          style={{ touchAction: "none" }}
          onPointerDown={onPointerDown}
          onPointerMove={onPointerMove}
          onPointerUp={onPointerUp}
          onPointerLeave={onPointerUp}
        />
      </div>
    </div>
  );
}
