import React, { useCallback, useEffect, useRef, useState } from "react";

export default function SignaturePad({
  initialValue = null,
  onChange,
  height = 160,
  showActions = true,
  showHint = true
}) {
  const canvasRef = useRef(null);
  const drawing = useRef(false);
  const [hasStroke, setHasStroke] = useState(false);

  const getCtx = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return null;
    return canvas.getContext("2d");
  }, []);

  const setupCanvas = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return null;
    const rect = canvas.getBoundingClientRect();
    const dpr = window.devicePixelRatio || 1;
    canvas.width = Math.max(1, Math.floor(rect.width * dpr));
    canvas.height = Math.max(1, Math.floor(height * dpr));
    const ctx = canvas.getContext("2d");
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.scale(dpr, dpr);
    ctx.strokeStyle = "#1a1a1a";
    ctx.lineWidth = 2;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    return { ctx, width: rect.width, height };
  }, [height]);

  const paintValue = useCallback(
    (blob) => {
      const setup = setupCanvas();
      if (!setup) return;
      const { ctx, width, height: canvasHeight } = setup;

      if (!blob) {
        ctx.clearRect(0, 0, width, canvasHeight);
        setHasStroke(false);
        return;
      }

      const url = URL.createObjectURL(blob);
      const img = new Image();
      img.onload = () => {
        ctx.clearRect(0, 0, width, canvasHeight);
        ctx.drawImage(img, 0, 0, width, canvasHeight);
        setHasStroke(true);
        URL.revokeObjectURL(url);
      };
      img.onerror = () => {
        URL.revokeObjectURL(url);
        setHasStroke(false);
      };
      img.src = url;
    },
    [setupCanvas]
  );

  useEffect(() => {
    paintValue(initialValue);
  }, [initialValue, height, paintValue]);

  const emitChange = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    canvas.toBlob((blob) => {
      onChange?.(blob);
    }, "image/png");
  }, [onChange]);

  function pointerPos(e) {
    const canvas = canvasRef.current;
    const rect = canvas.getBoundingClientRect();
    const clientX = e.touches ? e.touches[0].clientX : e.clientX;
    const clientY = e.touches ? e.touches[0].clientY : e.clientY;
    return { x: clientX - rect.left, y: clientY - rect.top };
  }

  function startDraw(e) {
    e.preventDefault();
    drawing.current = true;
    const ctx = getCtx();
    if (!ctx) return;
    const { x, y } = pointerPos(e);
    ctx.beginPath();
    ctx.moveTo(x, y);
  }

  function draw(e) {
    if (!drawing.current) return;
    e.preventDefault();
    const ctx = getCtx();
    if (!ctx) return;
    const { x, y } = pointerPos(e);
    ctx.lineTo(x, y);
    ctx.stroke();
    setHasStroke(true);
  }

  function endDraw(e) {
    if (!drawing.current) return;
    e.preventDefault();
    drawing.current = false;
    emitChange();
  }

  function clear() {
    paintValue(null);
    onChange?.(null);
  }

  return (
    <div className="ptw-signature-pad">
      <canvas
        ref={canvasRef}
        className="ptw-signature-pad__canvas"
        style={{ height }}
        onMouseDown={startDraw}
        onMouseMove={draw}
        onMouseUp={endDraw}
        onMouseLeave={endDraw}
        onTouchStart={startDraw}
        onTouchMove={draw}
        onTouchEnd={endDraw}
      />
      {showActions ? (
        <div className="ptw-signature-pad__actions">
          <button type="button" className="swi-btn swi-btn--ghost" onClick={clear}>
            Clear signature
          </button>
          {showHint && !hasStroke ? (
            <span className="ptw-muted">Sign above with mouse or touch</span>
          ) : null}
        </div>
      ) : null}
    </div>
  );
}
