import React, {PointerEvent, useEffect, useRef, useState} from 'react';

type Props = {
    onChange: (file: File | null) => void;
};

export default function SignatureCanvas({onChange}: Props): JSX.Element {
    const canvasRef = useRef<HTMLCanvasElement | null>(null);
    const drawingRef = useRef(false);
    const [hasSignature, setHasSignature] = useState(false);

    useEffect(() => {
        const canvas = canvasRef.current;
        if (!canvas) return;
        const context = canvas.getContext('2d');
        if (!context) return;
        context.lineCap = 'round';
        context.lineJoin = 'round';
        context.lineWidth = 4;
        context.strokeStyle = '#111827';
    }, []);

    function point(event: PointerEvent<HTMLCanvasElement>): [number, number] {
        const canvas = event.currentTarget;
        const bounds = canvas.getBoundingClientRect();
        return [
            (event.clientX - bounds.left) * (canvas.width / bounds.width),
            (event.clientY - bounds.top) * (canvas.height / bounds.height),
        ];
    }

    function start(event: PointerEvent<HTMLCanvasElement>) {
        const context = event.currentTarget.getContext('2d');
        if (!context) return;
        event.currentTarget.setPointerCapture(event.pointerId);
        const [x, y] = point(event);
        context.beginPath();
        context.moveTo(x, y);
        drawingRef.current = true;
    }

    function draw(event: PointerEvent<HTMLCanvasElement>) {
        if (!drawingRef.current) return;
        const context = event.currentTarget.getContext('2d');
        if (!context) return;
        const [x, y] = point(event);
        context.lineTo(x, y);
        context.stroke();
        setHasSignature(true);
    }

    function finish(event: PointerEvent<HTMLCanvasElement>) {
        if (!drawingRef.current) return;
        drawingRef.current = false;
        event.currentTarget.getContext('2d')?.closePath();
        event.currentTarget.toBlob(blob => {
            onChange(blob ? new File([blob], 'drawn-signature.png', {type: 'image/png'}) : null);
        }, 'image/png');
    }

    function clear() {
        const canvas = canvasRef.current;
        canvas?.getContext('2d')?.clearRect(0, 0, canvas.width, canvas.height);
        setHasSignature(false);
        onChange(null);
    }

    return <div>
        <canvas
            ref={canvasRef}
            width={900}
            height={300}
            className="h-44 w-full touch-none rounded-lg border bg-white"
            aria-label="Draw your signature"
            onPointerDown={start}
            onPointerMove={draw}
            onPointerUp={finish}
            onPointerCancel={finish}
        />
        <div className="mt-2 flex items-center justify-between gap-3">
            <span className="text-xs text-gray-500">Draw with a mouse, stylus, or finger.</span>
            <button type="button" className="ti-btn ti-btn-sm ti-btn-light" disabled={!hasSignature} onClick={clear}>Clear</button>
        </div>
    </div>;
}
