import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';

export interface SignaturePadHandle {
  clear: () => void;
  isEmpty: () => boolean;
  getDataURL: () => string;
}

interface SignaturePadProps {
  width?: number;
  height?: number;
  onChange?: (dataUrl: string) => void;
}

const SignaturePad = forwardRef<SignaturePadHandle, SignaturePadProps>(function SignaturePad(
  { width = 480, height = 180, onChange },
  ref,
) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const drawingRef = useRef(false);
  const emptyRef = useRef(true);
  const lastPointRef = useRef<{ x: number; y: number } | null>(null);

  const getContext = () => canvasRef.current?.getContext('2d') ?? null;

  const resetCanvas = () => {
    const canvas = canvasRef.current;
    const ctx = getContext();
    if (!canvas || !ctx) return;
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.lineWidth = 2.5;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    ctx.strokeStyle = '#111827';
    emptyRef.current = true;
  };

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    // 高 DPI 适配
    const ratio = window.devicePixelRatio || 1;
    canvas.width = width * ratio;
    canvas.height = height * ratio;
    canvas.style.width = `${width}px`;
    canvas.style.height = `${height}px`;
    const ctx = canvas.getContext('2d');
    if (ctx) ctx.scale(ratio, ratio);
    resetCanvas();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [width, height]);

  const pointFromEvent = (
    e: React.PointerEvent<HTMLCanvasElement>,
  ): { x: number; y: number } | null => {
    const canvas = canvasRef.current;
    if (!canvas) return null;
    const rect = canvas.getBoundingClientRect();
    return {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top,
    };
  };

  const handlePointerDown = (e: React.PointerEvent<HTMLCanvasElement>) => {
    e.preventDefault();
    const ctx = getContext();
    const pt = pointFromEvent(e);
    if (!ctx || !pt) return;
    drawingRef.current = true;
    lastPointRef.current = pt;
    canvasRef.current?.setPointerCapture(e.pointerId);
    // 画一个点（防止只点一下没移动看不到痕迹）
    ctx.beginPath();
    ctx.arc(pt.x, pt.y, 1.2, 0, Math.PI * 2);
    ctx.fillStyle = '#111827';
    ctx.fill();
    emptyRef.current = false;
  };

  const handlePointerMove = (e: React.PointerEvent<HTMLCanvasElement>) => {
    if (!drawingRef.current) return;
    e.preventDefault();
    const ctx = getContext();
    const pt = pointFromEvent(e);
    const last = lastPointRef.current;
    if (!ctx || !pt || !last) return;
    ctx.beginPath();
    ctx.moveTo(last.x, last.y);
    ctx.lineTo(pt.x, pt.y);
    ctx.stroke();
    lastPointRef.current = pt;
    emptyRef.current = false;
  };

  const handlePointerUp = (e: React.PointerEvent<HTMLCanvasElement>) => {
    if (!drawingRef.current) return;
    drawingRef.current = false;
    lastPointRef.current = null;
    canvasRef.current?.releasePointerCapture(e.pointerId);
    if (onChange && canvasRef.current) {
      onChange(canvasRef.current.toDataURL('image/png'));
    }
  };

  useImperativeHandle(ref, () => ({
    clear: () => {
      resetCanvas();
      onChange?.('');
    },
    isEmpty: () => emptyRef.current,
    getDataURL: () => (canvasRef.current ? canvasRef.current.toDataURL('image/png') : ''),
  }));

  return (
    <canvas
      ref={canvasRef}
      className="signature-pad-canvas"
      onPointerDown={handlePointerDown}
      onPointerMove={handlePointerMove}
      onPointerUp={handlePointerUp}
      onPointerCancel={handlePointerUp}
      onPointerLeave={handlePointerUp}
      style={{ touchAction: 'none' }}
    />
  );
});

export default SignaturePad;
