import { Input } from '@repo/shadcn-ui/components';
import { cn } from '@repo/shadcn-ui/lib/utils';
import * as React from "react";
import { findFocusableInCell, focusAndSelect } from './input-utils';
import { InputEmptyMode, InputReadOnlyMode } from './quantity-input';

export type PercentageInputProps = {
    value: number | "" | string;           // "" → no mostrar nada; string puede venir con separadores
    onChange: (next: number | "") => void;
    readOnly?: boolean;
    readOnlyMode?: InputReadOnlyMode;           // default "textlike-input"
    id?: string;
    "aria-label"?: string;
    step?: number;                         // ↑/↓; default 0.1
    emptyMode?: InputEmptyMode;                 // cómo presentar vacío
    emptyText?: string;                    // texto en vacío para value/placeholder
    scale?: number;                        // decimales; default 2
    min?: number;                          // default 0 (p. ej. descuentos)
    max?: number;                          // default 100
    showSuffix?: boolean;                  // “%” en visual; default true
    locale?: string;                       // para formateo numérico
    className?: string;
};

export function PercentageInput({
    value,
    onChange,
    readOnly = false,
    readOnlyMode = "textlike-input",
    id,
    "aria-label": ariaLabel = "Percentage",
    step = 0.1,
    emptyMode = "blank",
    emptyText = "",
    scale = 2,
    min = 0,
    max = 100,
    showSuffix = true,
    locale,
    className,
    ...inputProps
}: PercentageInputProps) {
    const stripNumberish = (s: string) => s.replace(/[^\d.,\-]/g, "").trim();

    const parseLocaleNumber = React.useCallback((raw: string): number | null => {
        if (!raw) return null;
        const s = stripNumberish(raw);
        if (!s) return null;
        const lastComma = s.lastIndexOf(",");
        const lastDot = s.lastIndexOf(".");
        let normalized = s;
        if (lastComma > -1 && lastDot > -1) {
            normalized = lastComma > lastDot ? s.replace(/\./g, "").replace(",", ".") : s.replace(/,/g, "");
        } else if (lastComma > -1) {
            normalized = s.replace(",", ".");
        }
        const n = Number(normalized);
        return Number.isFinite(n) ? n : null;
    }, []);

    const roundToScale = React.useCallback((n: number, sc: number) => {
        const f = 10 ** sc;
        return Math.round(n * f) / f;
    }, []);

    const clamp = React.useCallback(
        (n: number) => Math.min(Math.max(n, min), max),
        [min, max]
    );


    const [raw, setRaw] = React.useState<string>("");
    const [focused, setFocused] = React.useState(false);

    const formatVisual = React.useCallback(
        (n: number) => {
            const txt = new Intl.NumberFormat(locale ?? undefined, {
                maximumFractionDigits: scale,
                minimumFractionDigits: Number.isInteger(n) ? 0 : 0,
                useGrouping: false,
            }).format(n);
            return showSuffix ? `${txt}%` : txt;
        },
        [locale, scale, showSuffix]
    );

    const visualText = React.useMemo(() => {
        if (value === "" || value == null) {
            return emptyMode === "value" ? emptyText : "";
        }
        const numeric =
            typeof value === "number" ? value : parseLocaleNumber(String(value));
        if (!Number.isFinite(numeric as number)) return emptyMode === "value" ? emptyText : "";
        const n = roundToScale(clamp(numeric as number), scale);
        return formatVisual(n);
    }, [value, emptyMode, emptyText, parseLocaleNumber, roundToScale, clamp, scale, formatVisual]);

    const isShowingEmptyValue = emptyMode === "value" && raw === emptyText;

    React.useEffect(() => {
        if (!focused) setRaw(visualText);
    }, [visualText, focused]);


    const handleChange = React.useCallback(
        (e: React.ChangeEvent<HTMLInputElement>) => {
            setRaw(e.currentTarget.value);
        },
        []
    );

    const handleFocus = React.useCallback(
        (e: React.FocusEvent<HTMLInputElement>) => {
            setFocused(true);
            if (emptyMode === "value" && e.currentTarget.value === emptyText) {
                setRaw("");
                return;
            }
            const n =
                parseLocaleNumber(e.currentTarget.value) ??
                (value === "" || value == null
                    ? null
                    : typeof value === "number"
                        ? value
                        : parseLocaleNumber(String(value)));
            setRaw(n !== null && n !== undefined ? String(n) : "");
        },
        [emptyMode, emptyText, parseLocaleNumber, value]
    );

    const handleBlur = React.useCallback(
        (e: React.FocusEvent<HTMLInputElement>) => {
            setFocused(false);
            const txt = e.currentTarget.value.trim().replace("%", "");
            if (txt === "" || isShowingEmptyValue) {
                onChange("");
                setRaw(emptyMode === "value" ? emptyText : "");
                return;
            }
            const parsed = parseLocaleNumber(txt);
            if (parsed === null) {
                onChange("");
                setRaw(emptyMode === "value" ? emptyText : "");
                return;
            }
            const rounded = roundToScale(clamp(parsed), scale);
            onChange(rounded);
            setRaw(formatVisual(rounded)); // vuelve a visual con %
        },
        [isShowingEmptyValue, onChange, emptyMode, emptyText, parseLocaleNumber, roundToScale, clamp, scale, formatVisual]
    );

    const handleKeyDown = React.useCallback(
        (e: React.KeyboardEvent<HTMLElement>) => {
            if (readOnly) return;

            const keys = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"];
            if (!keys.includes(e.key)) return;

            e.preventDefault();

            const current = e.currentTarget as HTMLElement;
            const rowIndex = Number(current.dataset.rowIndex);
            const colIndex = Number(current.dataset.colIndex);

            let nextRow = rowIndex;
            let nextCol = colIndex;

            switch (e.key) {
                case "ArrowUp":
                    nextRow--;
                    break;
                case "ArrowDown":
                    nextRow++;
                    break;
                case "ArrowLeft":
                    nextCol--;
                    break;
                case "ArrowRight":
                    nextCol++;
                    break;
            }

            const nextElement = findFocusableInCell(nextRow, nextCol);
            console.log(nextElement);
            if (nextElement) {
                focusAndSelect(nextElement);
            }
        },
        [readOnly]
    );

    // Bloquear foco/edición en modo texto
    const handleBlock = React.useCallback((e: React.SyntheticEvent<HTMLInputElement>) => {
        e.preventDefault();
        (e.target as HTMLInputElement).blur();
    }, []);


    if (readOnly && readOnlyMode === "textlike-input") {
        return (
            <Input
                id={id}
                aria-label={ariaLabel}
                readOnly
                tabIndex={-1}
                onFocus={handleBlock}
                onMouseDown={handleBlock}
                onKeyDown={(e) => e.preventDefault()}
                value={visualText}
                className={cn(
                    "w-full bg-transparent p-0 text-right tabular-nums border-0 shadow-none",
                    "focus:outline-none focus:ring-0 [caret-color:transparent] cursor-default",
                    className
                )}
                {...inputProps}
            />
        );
    }


    return (
        <Input
            id={id}
            aria-label={ariaLabel}
            inputMode="decimal"
            pattern="[0-9]*[.,]?[0-9]*%?"
            className={cn(
                "w-full bg-transparent p-0 text-right tabular-nums h-8 px-1 shadow-none",
                "border-none",
                "focus:bg-background",
                "focus-visible:border-ring focus-visible:ring-ring/20 focus-visible:ring-[2px]",
                "hover:border hover:ring-ring/20 hover:ring-[2px]",
                className
            )}
            readOnly={readOnly}
            placeholder={
                emptyMode === "placeholder" && (value === "" || value == null) ? emptyText : undefined
            }
            value={raw}
            onChange={handleChange}
            onFocus={handleFocus}
            onBlur={handleBlur}
            onKeyDown={handleKeyDown}
            {...inputProps}
        />
    );
}
