class FileNameSorter {
    /**
     * 判断是否为纯数字字符串
     * @param {any} value - 要检查的值
     * @returns {boolean} 是否为纯数字
     */
    static isPureNumber(value) {
        if (typeof value !== 'string') return false;
        return /^\d+$/.test(value);
    }

    /**
     * 获取排序键值
     * @param {any} item - 要排序的项目
     * @returns {Array} 排序键值数组
     */
    static getSortKey(item) {
        const str = String(item);
        const isNumber = this.isPureNumber(str);

        // 排序优先级: [类型优先级, 数字值/字符串值]
        if (isNumber) {
            // 纯数字: 类型优先级为0, 使用数字值排序
            return [0, BigInt(str)];
        } else {
            // 非纯数字: 类型优先级为1, 使用字符串排序
            return [1, str.toLowerCase()];
        }
    }

    /**
     * 文件名排序
     * @param {Array} arr - 要排序的数组
     * @param {Object} options - 排序选项
     * @returns {Array} 排序后的数组
     */
    static sortFileNames(arr, options = {}) {
        if (!Array.isArray(arr)) {
            throw new TypeError('输入必须是一个数组');
        }

        const {
            direction = 'asc', // 'asc' 升序, 'desc' 降序
            caseSensitive = false, // 是否区分大小写
            trim = true, // 是否去除前后空格
            key = null
        } = options;

        // 创建数组的副本
        const result = [...arr];

        return result.sort((a, b) => {
            let aStr = key ? String(a[key]).split(".")[0] : String(a);
            let bStr = key ? String(b[key]).split(".")[0] : String(b);
            // 处理空格
            if (trim) {
                aStr = aStr.trim();
                bStr = bStr.trim();
            }

            // 处理大小写
            if (!caseSensitive) {
                aStr = aStr.toLowerCase();
                bStr = bStr.toLowerCase();
            }

            // 获取排序键值
            const aKey = this.getSortKey(aStr);
            const bKey = this.getSortKey(bStr);

            // 比较类型优先级
            if (aKey[0] !== bKey[0]) {
                // 纯数字(0) < 非纯数字(1)
                return direction === 'asc' ? aKey[0] - bKey[0] : bKey[0] - aKey[0];
            }

            // 相同类型下的比较
            if (aKey[0] === 0) {
                // 都是纯数字，按数字大小比较
                if (aKey[1] < bKey[1]) return direction === 'asc' ? -1 : 1;
                if (aKey[1] > bKey[1]) return direction === 'asc' ? 1 : -1;
                return 0;
            } else {
                // 都是非纯数字，按字符串比较
                if (aStr < bStr) return direction === 'asc' ? -1 : 1;
                if (aStr > bStr) return direction === 'asc' ? 1 : -1;
                return 0;
            }
        });
    }

    /**
     * 自然排序 - 处理文件名中的数字序列
     * 例如: file1, file2, file10
     * @param {Array} arr - 要排序的数组
     * @param {Object} options - 排序选项
     * @returns {Array} 排序后的数组
     */
    static naturalSort(arr, options = {}) {
        const {
            direction = 'asc',
            caseSensitive = false
        } = options;

        return [...arr].sort((a, b) => {
            const aStr = String(a);
            const bStr = String(b);

            // 检查是否都是纯数字
            const aIsPureNumber = this.isPureNumber(aStr);
            const bIsPureNumber = this.isPureNumber(bStr);

            // 如果一个纯数字，一个非纯数字
            if (aIsPureNumber && !bIsPureNumber) {
                return direction === 'asc' ? -1 : 1;
            }
            if (!aIsPureNumber && bIsPureNumber) {
                return direction === 'asc' ? 1 : -1;
            }

            // 都是纯数字，按数字比较
            if (aIsPureNumber && bIsPureNumber) {
                const aNum = BigInt(aStr);
                const bNum = BigInt(bStr);

                if (aNum < bNum) return direction === 'asc' ? -1 : 1;
                if (aNum > bNum) return direction === 'asc' ? 1 : -1;
                return 0;
            }

            // 都是非纯数字，使用自然排序算法
            return this.naturalCompare(aStr, bStr, direction, caseSensitive);
        });
    }

    /**
     * 自然比较算法
     * @private
     */
    static naturalCompare(a, b, direction = 'asc', caseSensitive = false) {
        let aStr = caseSensitive ? a : a.toLowerCase();
        let bStr = caseSensitive ? b : b.toLowerCase();

        const regex = /(\d+|\D+)/g;
        const aParts = aStr.match(regex) || [];
        const bParts = bStr.match(regex) || [];

        const maxLength = Math.max(aParts.length, bParts.length);

        for (let i = 0; i < maxLength; i++) {
            const aPart = aParts[i] || '';
            const bPart = bParts[i] || '';

            const aIsNumber = /^\d+$/.test(aPart);
            const bIsNumber = /^\d+$/.test(bPart);

            // 如果都是数字，按数字比较
            if (aIsNumber && bIsNumber) {
                const aNum = BigInt(aPart);
                const bNum = BigInt(bPart);

                if (aNum < bNum) return direction === 'asc' ? -1 : 1;
                if (aNum > bNum) return direction === 'asc' ? 1 : -1;
                continue;
            }

            // 都是文本，按字符串比较
            if (aPart < bPart) return direction === 'asc' ? -1 : 1;
            if (aPart > bPart) return direction === 'asc' ? 1 : -1;
        }

        return 0;
    }

    /**
     * 分组排序 - 将纯数字和非纯数字分开显示
     * @param {Array} arr - 要排序的数组
     * @param {Object} options - 排序选项
     * @returns {Array} 排序后的数组
     */
    static groupSort(arr, options = {}) {
        const {
            direction = 'asc',
            groupOrder = 'numbers-first' // 'numbers-first' 或 'names-first'
        } = options;

        // 分组
        const numbers = [];
        const names = [];

        arr.forEach(item => {
            const str = String(item);
            if (this.isPureNumber(str)) {
                numbers.push(item);
            } else {
                names.push(item);
            }
        });

        // 对各组排序
        const sortedNumbers = this.sortFileNames(numbers, { direction });
        const sortedNames = this.sortFileNames(names, { direction });

        // 按指定顺序合并
        if (groupOrder === 'numbers-first') {
            return [...sortedNumbers, ...sortedNames];
        } else {
            return [...sortedNames, ...sortedNumbers];
        }
    }

    /**
     * 文件扩展名排序 - 先按扩展名排序，再按文件名排序
     * @param {Array} arr - 要排序的数组
     * @param {Object} options - 排序选项
     * @returns {Array} 排序后的数组
     */
    static sortByExtension(arr, options = {}) {
        const {
            direction = 'asc',
            extensionsFirst = false // 扩展名优先还是文件名优先
        } = options;

        return [...arr].sort((a, b) => {
            const aStr = String(a);
            const bStr = String(b);

            // 分离文件名和扩展名
            const getFileParts = (str) => {
                const lastDotIndex = str.lastIndexOf('.');
                if (lastDotIndex > 0) {
                    return {
                        name: str.substring(0, lastDotIndex),
                        ext: str.substring(lastDotIndex + 1)
                    };
                }
                return { name: str, ext: '' };
            };

            const aParts = getFileParts(aStr);
            const bParts = getFileParts(bStr);

            let compareResult;

            if (extensionsFirst) {
                // 先比较扩展名
                compareResult = this.sortFileNames([aParts.ext, bParts.ext], { direction })[0] === aParts.ext ? -1 : 1;
                if (compareResult !== 0) return compareResult;

                // 扩展名相同，再比较文件名
                return this.sortFileNames([aParts.name, bParts.name], { direction })[0] === aParts.name ? -1 : 1;
            } else {
                // 先比较文件名
                compareResult = this.sortFileNames([aParts.name, bParts.name], { direction })[0] === aParts.name ? -1 : 1;
                if (compareResult !== 0) return compareResult;

                // 文件名相同，再比较扩展名
                return this.sortFileNames([aParts.ext, bParts.ext], { direction })[0] === aParts.ext ? -1 : 1;
            }
        });
    }

    /**
     * 测试和演示函数
     */
    static demonstrate() {
        const testData = [
            '100',
            '23',
            '1',
            '003',
            'file.txt',
            '10',
            '5',
            'alpha',
            'beta',
            'gamma',
            '00100',
            'zebra',
            'apple',
            'banana',
            '123',
            'file10.txt',
            'file2.txt',
            'File1.txt',
            'file20.txt',
            'image.jpg',
            'document.pdf',
            'data.xlsx'
        ];

        console.log('=== 文件名排序演示 ===\n');

        console.log('原始数据:');
        console.log(testData);

        console.log('\n1. 基本排序 (纯数字 < 非纯数字):');
        const basicSorted = this.sortFileNames(testData);
        console.log(basicSorted);

        console.log('\n2. 自然排序 (智能数字识别):');
        const naturalSorted = this.naturalSort(testData);
        console.log(naturalSorted);

        console.log('\n3. 分组排序 (数字组和文件组):');
        const groupSorted = this.groupSort(testData);
        console.log(groupSorted);

        console.log('\n4. 降序排序:');
        const descSorted = this.sortFileNames(testData, { direction: 'desc' });
        console.log(descSorted);

        console.log('\n5. 按扩展名排序:');
        const extSorted = this.sortByExtension(testData);
        console.log(extSorted);

        console.log('\n6. 大小写敏感排序:');
        const caseSensitiveSorted = this.sortFileNames(testData, { caseSensitive: true });
        console.log(caseSensitiveSorted);

        // 验证排序规则
        console.log('\n=== 排序规则验证 ===');
        const validationData = ['100', '23', 'file.txt', '1', 'alpha', '003', '10'];
        console.log('验证数据:', validationData);
        console.log('排序结果:', this.sortFileNames(validationData));
        console.log('规则验证:');
        console.log('  - 纯数字: 1, 3(003), 10, 23, 100 (按数字大小)');
        console.log('  - 非纯数字: alpha, file.txt (按字母顺序)');
        console.log('  - 非纯数字 > 纯数字');

        return {
            basic: basicSorted,
            natural: naturalSorted,
            group: groupSorted,
            descending: descSorted,
            byExtension: extSorted,
            caseSensitive: caseSensitiveSorted
        };
    }
}

if (typeof module !== 'undefined' && module.exports) {
    module.exports = FileNameSorter;
} else if (typeof window !== 'undefined') {
    window.FileNameSorter = FileNameSorter;
}