'use client';

import { useRef, useEffect } from 'react';
import { AnnotationData } from '../../lib/api';

export const COLORS = [
  { name: 'Red',    value: '#ef4444' },
  { name: 'Orange', value: '#f97316' },
  { name: 'Yellow', value: '#eab308' },
  { name: 'Green',  value: '#22c55e' },
  { name: 'Blue',   value: '#3b82f6' },
  { name: 'Purple', value: '#a855f7' },
  { name: 'White',  value: '#ffffff' },
];

export type Tool = 'pen' | 'arrow' | 'rect' | 'ellipse';

// ── Standalone render function (used by both draw canvas and display canvas) ──
export function drawShape(ctx: CanvasRenderingContext2D, ann: AnnotationData) {
  ctx.save();
  ctx.strokeStyle = ann.color;
  ctx.fillStyle = ann.color;
  ctx.lineWidth = 3;
  ctx.lineCap = 'round';
  ctx.lineJoin = 'round';

  if (ann.type === 'pen' && ann.points && ann.points.length >= 2) {
    ctx.beginPath();
    ctx.moveTo(ann.points[0][0] * ctx.canvas.width, ann.points[0][1] * ctx.canvas.height);
    for (let i = 1; i < ann.points.length; i++) {
      ctx.lineTo(ann.points[i][0] * ctx.canvas.width, ann.points[i][1] * ctx.canvas.height);
    }
    ctx.stroke();
  } else if (ann.type === 'arrow' && ann.points && ann.points.length >= 2) {
    const [x1, y1] = ann.points[0];
    const [x2, y2] = ann.points[ann.points.length - 1];
    const sx = x1 * ctx.canvas.width, sy = y1 * ctx.canvas.height;
    const ex = x2 * ctx.canvas.width, ey = y2 * ctx.canvas.height;
    const angle = Math.atan2(ey - sy, ex - sx);
    const headLen = 16;
    ctx.beginPath();
    ctx.moveTo(sx, sy); ctx.lineTo(ex, ey); ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(ex, ey);
    ctx.lineTo(ex - headLen * Math.cos(angle - Math.PI / 6), ey - headLen * Math.sin(angle - Math.PI / 6));
    ctx.moveTo(ex, ey);
    ctx.lineTo(ex - headLen * Math.cos(angle + Math.PI / 6), ey - headLen * Math.sin(angle + Math.PI / 6));
    ctx.stroke();
  } else if (ann.type === 'rect' && ann.boundingBox) {
    const { x, y, width: w, height: h } = ann.boundingBox;
    ctx.strokeRect(x * ctx.canvas.width, y * ctx.canvas.height, w * ctx.canvas.width, h * ctx.canvas.height);
  } else if (ann.type === 'ellipse' && ann.boundingBox) {
    const { x, y, width: w, height: h } = ann.boundingBox;
    ctx.beginPath();
    ctx.ellipse(
      (x + w / 2) * ctx.canvas.width, (y + h / 2) * ctx.canvas.height,
      (w / 2) * ctx.canvas.width, (h / 2) * ctx.canvas.height, 0, 0, 2 * Math.PI
    );
    ctx.stroke();
  }
  ctx.restore();
}

interface Props {
  isActive: boolean;
  tool: Tool;
  color: string;
  width: number;
  height: number;
  // Already-saved strokes to keep on canvas until Save/Undo
  pendingStrokes: AnnotationData[];
  onStrokeComplete: (stroke: AnnotationData) => void;
}

interface DrawState {
  type: Tool;
  color: string;
  startX: number;
  startY: number;
  points: [number, number][];
}

export function AnnotationCanvas({
  isActive,
  tool,
  color,
  width,
  height,
  pendingStrokes,
  onStrokeComplete,
}: Props) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const isDrawingRef = useRef(false);
  const drawRef = useRef<DrawState | null>(null);

  // ── Full canvas redraw (clear + all saved strokes + live stroke) ─────────────
  function redraw() {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // Draw all strokes that are still pending (not yet saved)
    for (const stroke of pendingStrokes) {
      drawShape(ctx, stroke);
    }
    // Draw the stroke currently being drawn
    if (drawRef.current) drawShape(ctx, toAnnotation(drawRef.current));
  }

  // ── Convert draw state → AnnotationData ────────────────────────────────────
  function toAnnotation(ds: DrawState): AnnotationData {
    if (ds.type === 'rect') {
      const minX = Math.min(ds.startX, ds.points[ds.points.length - 1][0]);
      const minY = Math.min(ds.startY, ds.points[ds.points.length - 1][1]);
      const maxX = Math.max(ds.startX, ds.points[ds.points.length - 1][0]);
      const maxY = Math.max(ds.startY, ds.points[ds.points.length - 1][1]);
      return { type: 'rect', color: ds.color, boundingBox: { x: minX, y: minY, width: maxX - minX, height: maxY - minY }, points: ds.points };
    }
    if (ds.type === 'ellipse') {
      const minX = Math.min(ds.startX, ds.points[ds.points.length - 1][0]);
      const minY = Math.min(ds.startY, ds.points[ds.points.length - 1][1]);
      const maxX = Math.max(ds.startX, ds.points[ds.points.length - 1][0]);
      const maxY = Math.max(ds.startY, ds.points[ds.points.length - 1][1]);
      return { type: 'ellipse', color: ds.color, boundingBox: { x: minX, y: minY, width: maxX - minX, height: maxY - minY }, points: ds.points };
    }
    return { type: ds.type === 'arrow' ? 'arrow' : 'pen', color: ds.color, points: ds.points };
  }

  // ── Canvas resize ────────────────────────────────────────────────────────────
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    canvas.width = width;
    canvas.height = height;
    redraw();
  }, [width, height, pendingStrokes]);

  // ── Normalise mouse / touch position ────────────────────────────────────────
  function pos(e: React.MouseEvent<HTMLCanvasElement>): [number, number] {
    const rect = canvasRef.current!.getBoundingClientRect();
    return [
      (e.clientX - rect.left) / rect.width,
      (e.clientY - rect.top) / rect.height,
    ];
  }

  // ── Mouse handlers ───────────────────────────────────────────────────────────
  const onDown = (e: React.MouseEvent<HTMLCanvasElement>) => {
    if (!isActive) return;
    e.preventDefault();
    e.stopPropagation();
    const [x, y] = pos(e);
    isDrawingRef.current = true;
    drawRef.current = { type: tool, color, startX: x, startY: y, points: [[x, y]] };
  };

  const onMove = (e: React.MouseEvent<HTMLCanvasElement>) => {
    if (!isDrawingRef.current || !drawRef.current) return;
    e.preventDefault();
    e.stopPropagation();
    const [x, y] = pos(e);
    const pts = drawRef.current.points;
    drawRef.current = { ...drawRef.current, points: [...pts, [x, y]] };
    redraw();
  };

  const onUp = (e: React.MouseEvent<HTMLCanvasElement>) => {
    if (!isDrawingRef.current || !drawRef.current) return;
    e.preventDefault();
    e.stopPropagation();
    isDrawingRef.current = false;
    const [x, y] = pos(e);
    const pts = [...drawRef.current.points, [x, y] as [number, number]];
    drawRef.current = { ...drawRef.current, points: pts };
    onStrokeComplete(toAnnotation(drawRef.current));
    drawRef.current = null;
    redraw();
  };

  return (
    <canvas
      ref={canvasRef}
      className="absolute inset-0 z-10"
      style={{
        cursor: isActive ? 'crosshair' : 'default',
        pointerEvents: isActive ? 'auto' : 'none',
      }}
      onClick={e => { if (isActive) e.stopPropagation(); }}
      onMouseDown={onDown}
      onMouseMove={onMove}
      onMouseUp={onUp}
      onMouseLeave={onUp}
    />
  );
}
