import { jsxs, jsx } from 'react/jsx-runtime';
import React__default, { useRef, useState, useEffect, useCallback } from 'react';
import { cn } from '../../../utils/cn.js';
import { signatureTheme } from './Signature.theme.js';
import { FormLabel } from '../FormLabel/FormLabel.js';
import { Button } from '../../core/Button/Button.js';

const Signature = React__default.forwardRef(({ id, label, labelClassName, helperText, helperTextClassName, wrapperClassName, size = 'md', state = 'default', required = false, disabled = false, width = 400, height = 200, strokeColor = '#000000', strokeWidth = 2, backgroundColor = 'transparent', className, theme: customTheme = {}, onChange, onClear, showControls = true, placeholder = 'Sign here', ...props }, ref) => {
    var _a, _b;
    const canvasRef = useRef(null);
    const [isDrawing, setIsDrawing] = useState(false);
    const [isEmpty, setIsEmpty] = useState(true);
    const lastPointRef = useRef(null);
    // Generate unique ID if not provided
    const generatedId = React__default.useId();
    const signatureId = id || generatedId;
    // Derived state flags
    const isDisabled = state === 'disabled' || disabled;
    const isInvalid = state === 'invalid';
    // State class for CSS selectors
    const stateClass = isInvalid
        ? 'state-invalid'
        : isDisabled
            ? 'state-disabled'
            : 'state-default';
    // Merge theme with defaults
    const theme = {
        ...signatureTheme,
        ...customTheme,
    };
    useEffect(() => {
        const canvas = canvasRef.current;
        if (!canvas)
            return;
        const ctx = canvas.getContext('2d');
        if (!ctx)
            return;
        // Set canvas size
        canvas.width = width;
        canvas.height = height;
        // Configure drawing context
        ctx.lineCap = 'round';
        ctx.lineJoin = 'round';
        ctx.strokeStyle = strokeColor;
        ctx.lineWidth = strokeWidth;
        // Set background
        if (backgroundColor !== 'transparent') {
            ctx.fillStyle = backgroundColor;
            ctx.fillRect(0, 0, width, height);
        }
    }, [width, height, strokeColor, strokeWidth, backgroundColor]);
    const getPointFromEvent = useCallback((event) => {
        const canvas = canvasRef.current;
        if (!canvas)
            return { x: 0, y: 0 };
        const rect = canvas.getBoundingClientRect();
        if ('touches' in event) {
            return {
                x: event.touches[0].clientX - rect.left,
                y: event.touches[0].clientY - rect.top,
            };
        }
        return {
            x: event.clientX - rect.left,
            y: event.clientY - rect.top,
        };
    }, []);
    const startDrawing = useCallback((event) => {
        if (isDisabled)
            return;
        event.preventDefault();
        // Focus the canvas to trigger focus-within on parent
        const canvas = canvasRef.current;
        if (canvas) {
            canvas.focus();
        }
        setIsDrawing(true);
        setIsEmpty(false);
        const point = getPointFromEvent(event.nativeEvent);
        lastPointRef.current = point;
    }, [isDisabled, getPointFromEvent]);
    const draw = useCallback((event) => {
        if (isDisabled)
            return;
        event.preventDefault();
        if (!isDrawing)
            return;
        const canvas = canvasRef.current;
        if (!canvas)
            return;
        const ctx = canvas.getContext('2d');
        if (!ctx)
            return;
        const currentPoint = getPointFromEvent(event.nativeEvent);
        if (lastPointRef.current) {
            ctx.beginPath();
            ctx.moveTo(lastPointRef.current.x, lastPointRef.current.y);
            ctx.lineTo(currentPoint.x, currentPoint.y);
            ctx.stroke();
        }
        lastPointRef.current = currentPoint;
    }, [isDisabled, isDrawing, getPointFromEvent]);
    const stopDrawing = useCallback(() => {
        setIsDrawing(false);
        lastPointRef.current = null;
        // Only call toDataURL and onChange on mouseup/touchend, not on every draw event
        const canvas = canvasRef.current;
        if (canvas && onChange) {
            const dataURL = canvas.toDataURL();
            onChange(dataURL);
        }
    }, [onChange]);
    const clear = useCallback(() => {
        const canvas = canvasRef.current;
        if (!canvas)
            return;
        const ctx = canvas.getContext('2d');
        if (!ctx)
            return;
        ctx.clearRect(0, 0, width, height);
        // Reset background
        if (backgroundColor !== 'transparent') {
            ctx.fillStyle = backgroundColor;
            ctx.fillRect(0, 0, width, height);
        }
        setIsEmpty(true);
        onClear === null || onClear === void 0 ? void 0 : onClear();
        onChange === null || onChange === void 0 ? void 0 : onChange('');
    }, [width, height, backgroundColor, onClear, onChange]);
    const save = useCallback(() => {
        const canvas = canvasRef.current;
        if (!canvas)
            return;
        const dataURL = canvas.toDataURL();
        // Create download link
        const link = document.createElement('a');
        link.download = 'signature.png';
        link.href = dataURL;
        link.click();
    }, []);
    // Get theme classes
    const wrapperClasses = theme.wrapperStyle;
    const inputGroupClasses = theme.inputGroupStyle;
    const baseClasses = theme.baseStyle;
    const sizeClasses = ((_a = theme.sizes) === null || _a === void 0 ? void 0 : _a[size]) || '';
    const stateClasses = ((_b = theme.states) === null || _b === void 0 ? void 0 : _b[state]) || '';
    const helperTextClasses = theme.helperText || '';
    return (jsxs("div", { className: cn(wrapperClasses, stateClass, wrapperClassName), children: [label && (jsx("div", { className: "mb-1", children: jsx(FormLabel, { htmlFor: signatureId, className: labelClassName, state: state, required: required, children: label }) })), jsx("div", { className: cn(inputGroupClasses, sizeClasses, stateClasses, className), style: { width, height }, children: jsxs("div", { ref: ref, className: baseClasses, ...props, children: [jsx("canvas", { ref: canvasRef, id: signatureId, className: cn(theme.canvasStyle, customTheme.canvasStyle), tabIndex: isDisabled ? -1 : 0, onMouseDown: startDrawing, onMouseMove: draw, onMouseUp: stopDrawing, onMouseLeave: stopDrawing, onTouchStart: startDrawing, onTouchMove: draw, onTouchEnd: stopDrawing, "aria-label": label || 'Signature canvas', "aria-required": required, "aria-invalid": isInvalid, "aria-disabled": isDisabled }), isEmpty && placeholder && !isDisabled && (jsx("div", { className: cn(theme.placeholderStyle, customTheme.placeholderStyle), children: placeholder })), showControls && !isDisabled && (jsxs("div", { className: cn(theme.controlsStyle, customTheme.controlsStyle), children: [jsx(Button, { size: "sm", variant: "outline", color: 'neutral', onClick: clear, type: "button", children: "Clear" }), jsx(Button, { size: "sm", variant: "filled", onClick: save, disabled: isEmpty, type: "button", children: "Save" })] }))] }) }), helperText && (jsx("div", { className: cn(helperTextClasses, helperTextClassName), children: helperText }))] }));
});
Signature.displayName = 'Signature';

export { Signature };
