import { useState } from 'react';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { cn } from '@/lib/utils';

type InputCodeMode = 'numeric' | 'alpha' | 'alphanumeric';

type InputCodeProps = {
    name?: string;
    label: string;
    value: string;
    onChange?: (value: string) => void;
    digits?: number;
    mode?: InputCodeMode;
    readOnly?: boolean;
    required?: boolean;
    placeholder?: string;
    className?: string;
};

function normalizeValue(value: string, mode: InputCodeMode, digits?: number) {
    const cleaned = value
        .toUpperCase()
        .replace(
            mode === 'numeric'
                ? /\D/g
                : mode === 'alpha'
                  ? /[^A-Z]/g
                  : /[^A-Z0-9]/g,
            '',
        );

    const sliced = digits ? cleaned.slice(0, digits) : cleaned;

    if (mode !== 'numeric' || sliced === '') {
        return sliced;
    }

    return sliced.replace(/^0+(?=\d)/, '');
}

function formatValue(value: string, mode: InputCodeMode, digits?: number) {
    if (mode !== 'numeric' || !digits || value === '') {
        return value;
    }

    return value.padStart(digits, '0');
}

export function InputCode({
    name,
    label,
    value,
    onChange,
    digits,
    mode = 'numeric',
    readOnly = false,
    required = false,
    placeholder,
    className,
}: InputCodeProps) {
    const [focused, setFocused] = useState(false);
    const inputId =
        name ?? `input-code-${label.toLowerCase().replace(/\s+/g, '-')}`;
    const displayValue =
        focused && !readOnly ? value : formatValue(value, mode, digits);

    return (
        <div className={cn('grid gap-2', className)}>
            <Label htmlFor={inputId}>{label}</Label>
            {name ? <input type="hidden" name={name} value={value} /> : null}
            <Input
                id={inputId}
                value={displayValue}
                inputMode={mode === 'numeric' ? 'numeric' : 'text'}
                maxLength={digits}
                readOnly={readOnly}
                required={required}
                placeholder={placeholder}
                className={cn(
                    'h-12 text-center font-mono text-base font-semibold tracking-wide',
                    readOnly &&
                        'border-dashed bg-muted/40 text-muted-foreground shadow-none focus-visible:ring-0',
                )}
                onChange={(event) => {
                    onChange?.(
                        normalizeValue(event.target.value, mode, digits),
                    );
                }}
                onFocus={() => setFocused(true)}
                onBlur={() => setFocused(false)}
            />
        </div>
    );
}
