<script lang="ts">

    import type {OnChangeHandler} from "../common/OnChangeHandler";
    import utils from "../common/utils";
    import {tick} from "svelte";

    export let disabled: boolean = false;
    export let readonly: boolean = false;
    export let style: string = '';
    export let value: number | null;
    export let precision: number | null = null;
    export let placeholder: string;
    export let allowNegative: boolean = false;
    export let max: number | null = null;
    export let min: number | null = null;
    export let onchange: OnChangeHandler<number | null> = null as unknown as OnChangeHandler<number | null>;
    export let onfocus: (() => void) | null = null;
    export let onblur: (() => void) | null = null;
    export let textValue: string = '';

    export const focus = () => {
        editor.focus();
    }

    export const setFocus = () => {
        setTimeout(() => {
            editor && editor.focus();
        }, 50);
    }

    let regex: RegExp;
    let editor: HTMLInputElement;
    let composing: boolean = false;
    let currentText: string;
    let isFocused = false;

    /**
     * 将数字格式化为带千分位的字符串
     * 例：1234567.89 → "1,234,567.89"
     */
    const formatWithThousands = (num: number, prec: number | null): string => {
        const base = utils.formatNumber(num, prec);
        if (!base) return base;
        const parts = base.split('.');
        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
        return parts.join('.');
    };

    /**
     * 剥离千分位逗号，还原为可供 parseFloat 使用的原始字符串
     */
    const stripThousands = (s: string): string => s.replace(/,/g, '');

    const handleFocusEvent = (e: FocusEvent) => {
        isFocused = true;
        // 获焦时剥掉千分位逗号，让用户直接编辑原始数字
        textValue = stripThousands(textValue);
        onfocus?.();
    }

    const handleBlurEvent = (e: FocusEvent) => {
        isFocused = false;
        onblur?.();
        if (!readonly) {
            // 解析前先剥逗号（容错）
            const raw = stripThousands(textValue);
            value = parseFloat(raw);
            if (isNaN(value)) {
                value = null;
            }
            if (value != null) {
                if (min != null && value < min) {
                    value = min;
                }
                if (max != null && value > max) {
                    value = max;
                }
                // 失焦后格式化为千分位
                textValue = formatWithThousands(value, precision);
            } else {
                textValue = '';
            }
            onchange?.(value);
        } else {
            e.stopPropagation();
        }
    }

    const checkNewInputText = (s: string): boolean => {
        // 编辑过程中 editor.value 不含逗号（获焦时已剥），直接使用
        const currentValue = editor.value;
        const cursorStart = editor.selectionStart;
        const cursorEnd = editor.selectionEnd;
        const resultingString = currentValue.slice(0, cursorStart!) + s + currentValue.slice(cursorEnd!);
        if (/[^0-9.\-]/.test(resultingString)) {
            return false;
        }
        return regex.test(resultingString) &&
            utils.isValidNumber(parseFloat(resultingString), precision, allowNegative, max, min);
    }

    const handlePaste = (event: ClipboardEvent) => {
        const pasteData = event.clipboardData?.getData('text') || '';
        if (!checkNewInputText(pasteData)) {
            event.preventDefault();
        }
    }

    const handleKeyDown = (event: KeyboardEvent) => {
        // 拦截全角/非 ASCII 字符
        if (/[^\x00-\x7F]/.test(event.key)) {
            event.preventDefault();
            event.stopPropagation();
            return;
        }

        // 允许功能键
        const allowKeys = ['Backspace', 'Delete', 'Tab', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
        if (allowKeys.includes(event.key)) return;

        // 允许数字、小数点、负号
        if (/[\d.\-]/.test(event.key)) return;

        event.preventDefault();
        event.stopPropagation();
    };

    const handleInput = () => {
        if (composing) return;

        const raw = editor.value;

        // 拦截中文/全角字符（输入法直接上屏的情况）
        if (/[^\x00-\x7F]/.test(raw)) {
            editor.value = textValue;
            return;
        }

        if (regex.test(raw)) {
            const parsed = parseFloat(raw);
            // 仅在数值合法时同步 value，此处不触发格式化
            if (!isNaN(parsed) && utils.isValidNumber(parsed, precision, allowNegative, max, min)) {
                value = parsed;
                onchange?.(value);
            }
        }

        // 编辑过程中只更新原始字符串，禁止在此处对 textValue 做任何格式化
        textValue = raw;
    }

    const handleCompositionStart = (event: CompositionEvent) => {
        currentText = editor.value;
        composing = true;
    };

    const handleCompositionEnd = (event: CompositionEvent) => {
        composing = false;
        if (/[^\x00-\x7F]/.test(editor.value)) {
            editor.value = currentText;
            textValue = currentText;
        } else {
            handleInput();
        }
    };

    /**
     * 仅在非焦点状态下根据外部 value 更新显示文本（含千分位）。
     * 焦点状态下绝不重写 textValue，避免干扰用户输入过程。
     */
    $: if (!isFocused) {
        textValue = value == null ? '' : formatWithThousands(value, precision);
    }

    $: regex = new RegExp(utils.getNumberRegex(precision, allowNegative));

</script>
<input class="number-editor" bind:this={editor} type="text" {readonly} {style} {disabled}
       placeholder={readonly || disabled ? '' : placeholder}
       bind:value={textValue}
       on:focus={handleFocusEvent}
       on:blur={handleBlurEvent}
       on:compositionstart={handleCompositionStart}
       on:input={handleInput}
       on:keydown={handleKeyDown}
       on:compositionend={handleCompositionEnd}
       on:paste={handlePaste}/>