import { useEffect, useState } from 'react';
import { Input } from '@/components/ui/input';
import { evaluateExpression } from '@/lib/totals';
import { cn } from '@/lib/utils';

const fmt2 = (n: number) => (Math.round(n * 100) / 100).toFixed(2);

/**
 * Money field in dollars, stored as integer cents. Accepts a simple calculation
 * ("12*150", "(3+4)*95") which is evaluated when the field loses focus or on Enter.
 */
export function MoneyInput({ cents, onChange, allowNegative = true, className, invalid, ...rest }: {
    cents: number | null; onChange: (cents: number | null) => void; allowNegative?: boolean; invalid?: boolean;
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'>) {
    const shown = cents === null ? '' : fmt2(cents / 100);
    const [text, setText] = useState(shown);
    const [focused, setFocused] = useState(false);
    useEffect(() => { if (!focused) setText(shown); }, [shown, focused]);

    const commit = () => {
        if (text.trim() === '') { onChange(rest.required ? 0 : null); setText(rest.required ? '0.00' : ''); return; }
        const v = evaluateExpression(text);
        if (v === null || (!allowNegative && v < 0)) { setText(shown); return; }
        const c = Math.round(v * 100);
        onChange(c);
        setText(fmt2(c / 100));
    };

    return (
        <div className="relative">
            <span className="pointer-events-none absolute inset-y-0 left-2 flex items-center text-sm text-ink-muted" aria-hidden>$</span>
            <Input {...rest} inputMode="decimal" value={text} aria-invalid={invalid || undefined}
                className={cn('pl-5 text-right tabular-nums', invalid && 'border-danger', className)}
                onFocus={(e) => { setFocused(true); e.target.select(); }}
                onChange={(e) => setText(e.target.value)}
                onBlur={() => { setFocused(false); commit(); }}
                onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); commit(); } }} />
        </div>
    );
}

/** Percentage field stored as basis points (10% = 1000). */
export function PercentInput({ bp, onChange, max = 100, className, invalid, ...rest }: {
    bp: number | null; onChange: (bp: number) => void; max?: number; invalid?: boolean;
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'max'>) {
    const shown = bp === null ? '' : String(Math.round(bp) / 100);
    const [text, setText] = useState(shown);
    const [focused, setFocused] = useState(false);
    useEffect(() => { if (!focused) setText(shown); }, [shown, focused]);

    const commit = () => {
        const v = text.trim() === '' ? 0 : evaluateExpression(text);
        if (v === null || v < 0 || v > max) { setText(shown); return; }
        const next = Math.round(v * 100);
        onChange(next);
        setText(String(next / 100));
    };

    return (
        <div className="relative">
            <Input {...rest} inputMode="decimal" value={text} aria-invalid={invalid || undefined}
                className={cn('pr-6 text-right tabular-nums', invalid && 'border-danger', className)}
                onFocus={(e) => { setFocused(true); e.target.select(); }}
                onChange={(e) => setText(e.target.value)}
                onBlur={() => { setFocused(false); commit(); }}
                onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); commit(); } }} />
            <span className="pointer-events-none absolute inset-y-0 right-2 flex items-center text-sm text-ink-muted" aria-hidden>%</span>
        </div>
    );
}

/** Quantity (> 0, up to 3 decimal places) kept as a decimal string; accepts calculations too. */
export function QtyInput({ value, onChange, className, invalid, ...rest }: {
    value: string; onChange: (qty: string) => void; invalid?: boolean;
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'>) {
    const [text, setText] = useState(value);
    const [focused, setFocused] = useState(false);
    useEffect(() => { if (!focused) setText(value); }, [value, focused]);

    const commit = () => {
        const v = evaluateExpression(text);
        if (v === null || v <= 0) { setText(value); return; }
        const q = String(Math.round(v * 1000) / 1000);
        onChange(q);
        setText(q);
    };

    return (
        <Input {...rest} inputMode="decimal" value={text} aria-invalid={invalid || undefined}
            className={cn('text-right tabular-nums', invalid && 'border-danger', className)}
            onFocus={(e) => { setFocused(true); e.target.select(); }}
            onChange={(e) => setText(e.target.value)}
            onBlur={() => { setFocused(false); commit(); }}
            onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); commit(); } }} />
    );
}
