import { useEffect, useRef, useState } from "react";
import { Button } from "@/components/ui/button";

interface Props {
  photoFile: File;
  zoneLabel: string;
  /** Called when user submits. annotated=null если "без линий". */
  onSubmit: (annotated: Blob | null) => void | Promise<void>;
  onCancel: () => void;
}

interface Stroke {
  pts: { x: number; y: number }[]; // in image-space pixels
}

/** Pen-on-photo step: показывает только что снятое фото, даёт обвести
 *  пальцем красным. Flatten в JPEG при submit. Координаты strokes в native
 *  пикселях фото — canvas resize'нут на тот же размер. */
export function PhotoAnnotateStep({ photoFile, zoneLabel, onSubmit, onCancel }: Props) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const imgRef = useRef<HTMLImageElement | null>(null);
  const [imgLoaded, setImgLoaded] = useState(false);
  const [strokes, setStrokes] = useState<Stroke[]>([]);
  const currentStroke = useRef<Stroke | null>(null);
  const [submitting, setSubmitting] = useState(false);

  // Load image once
  useEffect(() => {
    const url = URL.createObjectURL(photoFile);
    const img = new Image();
    img.onload = () => {
      imgRef.current = img;
      const canvas = canvasRef.current;
      if (canvas) {
        canvas.width = img.naturalWidth;
        canvas.height = img.naturalHeight;
      }
      setImgLoaded(true);
      URL.revokeObjectURL(url);
      redraw([]);
    };
    img.onerror = () => URL.revokeObjectURL(url);
    img.src = url;
    return () => {
      URL.revokeObjectURL(url);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [photoFile]);

  function redraw(allStrokes: Stroke[]) {
    const canvas = canvasRef.current;
    const img = imgRef.current;
    if (!canvas || !img) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
    // Linewidth scaled to image — на 4К фото 4px тонко смотрится
    const lw = Math.max(6, Math.round(canvas.width / 250));
    ctx.strokeStyle = "rgb(220, 38, 38)";
    ctx.lineWidth = lw;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    for (const s of allStrokes) {
      if (s.pts.length < 2) {
        // single tap → dot
        if (s.pts.length === 1) {
          ctx.fillStyle = "rgb(220, 38, 38)";
          ctx.beginPath();
          ctx.arc(s.pts[0].x, s.pts[0].y, lw / 2, 0, Math.PI * 2);
          ctx.fill();
        }
        continue;
      }
      ctx.beginPath();
      ctx.moveTo(s.pts[0].x, s.pts[0].y);
      for (let i = 1; i < s.pts.length; i++) {
        ctx.lineTo(s.pts[i].x, s.pts[i].y);
      }
      ctx.stroke();
    }
  }

  // Re-draw whenever strokes change
  useEffect(() => {
    if (imgLoaded) redraw(strokes);
  }, [strokes, imgLoaded]);

  function pointFromEvent(e: React.PointerEvent<HTMLCanvasElement>): { x: number; y: number } | null {
    const canvas = canvasRef.current;
    if (!canvas) return null;
    const rect = canvas.getBoundingClientRect();
    if (rect.width === 0 || rect.height === 0) return null;
    // CSS px → canvas px
    const x = ((e.clientX - rect.left) / rect.width) * canvas.width;
    const y = ((e.clientY - rect.top) / rect.height) * canvas.height;
    return { x, y };
  }

  function onPointerDown(e: React.PointerEvent<HTMLCanvasElement>) {
    e.preventDefault();
    (e.target as HTMLCanvasElement).setPointerCapture(e.pointerId);
    const pt = pointFromEvent(e);
    if (!pt) return;
    currentStroke.current = { pts: [pt] };
    // Immediate visual feedback: draw a partial stroke without setState
    drawPartialStroke(currentStroke.current);
  }

  function onPointerMove(e: React.PointerEvent<HTMLCanvasElement>) {
    if (!currentStroke.current) return;
    const pt = pointFromEvent(e);
    if (!pt) return;
    currentStroke.current.pts.push(pt);
    drawPartialStroke(currentStroke.current);
  }

  function onPointerUp(e: React.PointerEvent<HTMLCanvasElement>) {
    if (!currentStroke.current) return;
    try {
      (e.target as HTMLCanvasElement).releasePointerCapture(e.pointerId);
    } catch {
      // ignore — pointer wasn't captured
    }
    const finished = currentStroke.current;
    currentStroke.current = null;
    if (finished.pts.length > 0) {
      setStrokes((s) => [...s, finished]);
    }
  }

  /** Avoid re-running full redraw on every move — just append last segment. */
  function drawPartialStroke(s: Stroke) {
    const canvas = canvasRef.current;
    if (!canvas || s.pts.length < 2) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
    const lw = Math.max(6, Math.round(canvas.width / 250));
    ctx.strokeStyle = "rgb(220, 38, 38)";
    ctx.lineWidth = lw;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    const a = s.pts[s.pts.length - 2];
    const b = s.pts[s.pts.length - 1];
    ctx.beginPath();
    ctx.moveTo(a.x, a.y);
    ctx.lineTo(b.x, b.y);
    ctx.stroke();
  }

  function clearAll() {
    setStrokes([]);
  }

  function undoLast() {
    setStrokes((s) => s.slice(0, -1));
  }

  async function finishWithAnnotation() {
    const canvas = canvasRef.current;
    if (!canvas) return;
    setSubmitting(true);
    try {
      const blob = await new Promise<Blob | null>((resolve) =>
        canvas.toBlob(resolve, "image/jpeg", 0.85)
      );
      await onSubmit(blob);
    } finally {
      setSubmitting(false);
    }
  }

  async function finishWithoutAnnotation() {
    setSubmitting(true);
    try {
      await onSubmit(null);
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <div className="fixed inset-0 z-50 bg-background flex flex-col">
      <header className="p-4 border-b flex items-center justify-between">
        <div>
          <div className="text-xs text-muted-foreground">Обведите повреждение</div>
          <h2 className="text-lg font-semibold capitalize">{zoneLabel}</h2>
        </div>
        <div className="flex gap-2">
          <button
            onClick={undoLast}
            disabled={strokes.length === 0 || submitting}
            className="text-sm px-3 py-1 border rounded-md disabled:opacity-40"
            title="Отменить последний штрих"
          >
            ↶
          </button>
          <button
            onClick={clearAll}
            disabled={strokes.length === 0 || submitting}
            className="text-sm px-3 py-1 border rounded-md disabled:opacity-40"
            title="Очистить"
          >
            Очистить
          </button>
        </div>
      </header>

      <main className="flex-1 overflow-auto p-2 flex items-center justify-center bg-black">
        <canvas
          ref={canvasRef}
          onPointerDown={onPointerDown}
          onPointerMove={onPointerMove}
          onPointerUp={onPointerUp}
          onPointerCancel={onPointerUp}
          className="max-w-full max-h-full block"
          style={{ touchAction: "none", cursor: "crosshair" }}
        />
      </main>

      <footer className="border-t p-3 flex gap-2 bg-card">
        <Button
          variant="outline"
          onClick={onCancel}
          disabled={submitting}
          className="flex-none"
        >
          Назад
        </Button>
        <Button
          variant="outline"
          onClick={finishWithoutAnnotation}
          disabled={submitting}
          className="flex-1"
        >
          Без линий
        </Button>
        <Button
          onClick={finishWithAnnotation}
          disabled={submitting || strokes.length === 0}
          className="flex-1"
        >
          {submitting ? "Сохраняю…" : "Готово"}
        </Button>
      </footer>
    </div>
  );
}
