const dayjs = require('dayjs');

/**
 * 调度系统工具函数
 * 提供通用的辅助功能
 */
class ScheduleUtils {
    /**
     * 生成唯一任务ID
     * @returns {string} 任务ID
     */
    static generateTaskId() {
        return `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    }

    /**
     * 生成唯一指令ID
     * @returns {string} 指令ID
     */
    static generateCommandId() {
        return `cmd_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    }

    /**
     * 格式化时间戳
     * @param {number} timestamp - 时间戳
     * @returns {string} 格式化的时间
     */
    static formatTimestamp(timestamp) {
        return dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss');
    }

    /**
     * 格式化持续时间
     * @param {number} ms - 毫秒数
     * @returns {string} 格式化的持续时间
     */
    static formatDuration(ms) {
        if (ms < 1000) {
            return `${ms}ms`;
        } else if (ms < 60 * 1000) {
            return `${(ms / 1000).toFixed(1)}s`;
        } else if (ms < 60 * 60 * 1000) {
            return `${(ms / (60 * 1000)).toFixed(1)}min`;
        } else {
            return `${(ms / (60 * 60 * 1000)).toFixed(1)}h`;
        }
    }

    /**
     * 深度克隆对象
     * @param {object} obj - 要克隆的对象
     * @returns {object} 克隆后的对象
     */
    static deepClone(obj) {
        if (obj === null || typeof obj !== 'object') {
            return obj;
        }

        if (obj instanceof Date) {
            return new Date(obj.getTime());
        }

        if (obj instanceof Array) {
            return obj.map(item => this.deepClone(item));
        }

        const cloned = {};
        for (const key in obj) {
            if (obj.hasOwnProperty(key)) {
                cloned[key] = this.deepClone(obj[key]);
            }
        }

        return cloned;
    }

    /**
     * 安全解析JSON
     * @param {string} jsonString - JSON字符串
     * @param {any} defaultValue - 默认值
     * @returns {any} 解析结果或默认值
     */
    static safeJsonParse(jsonString, defaultValue = null) {
        try {
            return JSON.parse(jsonString);
        } catch (error) {
            return defaultValue;
        }
    }

    /**
     * 安全序列化JSON
     * @param {any} obj - 要序列化的对象
     * @param {string} defaultValue - 默认值
     * @returns {string} JSON字符串或默认值
     */
    static safeJsonStringify(obj, defaultValue = '{}') {
        try {
            return JSON.stringify(obj);
        } catch (error) {
            return defaultValue;
        }
    }

    /**
     * 延迟执行
     * @param {number} ms - 延迟毫秒数
     * @returns {Promise} Promise对象
     */
    static delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    /**
     * 重试执行函数
     * @param {function} fn - 要执行的函数
     * @param {number} maxRetries - 最大重试次数
     * @param {number} delay - 重试延迟（毫秒）
     * @returns {Promise} 执行结果
     */
    static async retry(fn, maxRetries = 3, delay = 1000) {
        let lastError;

        for (let i = 0; i <= maxRetries; i++) {
            try {
                return await fn();
            } catch (error) {
                lastError = error;

                if (i < maxRetries) {
                    console.log(`[工具函数] 执行失败，${delay}ms后重试 (${i + 1}/${maxRetries + 1}):`, error.message);
                    await this.delay(delay);
                }
            }
        }

        throw lastError;
    }

    /**
     * 限制并发执行数量
     * @param {Array} tasks - 任务数组
     * @param {number} concurrency - 并发数量
     * @returns {Promise<Array>} 执行结果数组
     */
    static async limitConcurrency(tasks, concurrency = 5) {
        const results = [];
        const executing = [];

        for (const task of tasks) {
            const promise = Promise.resolve(task()).then(result => {
                executing.splice(executing.indexOf(promise), 1);
                return result;
            });

            results.push(promise);

            if (tasks.length >= concurrency) {
                executing.push(promise);

                if (executing.length >= concurrency) {
                    await Promise.race(executing);
                }
            }
        }

        return Promise.all(results);
    }

    /**
     * 创建带超时的Promise
     * @param {Promise} promise - 原始Promise
     * @param {number} timeout - 超时时间（毫秒）
     * @param {string} timeoutMessage - 超时错误消息
     * @returns {Promise} 带超时的Promise
     */
    static withTimeout(promise, timeout, timeoutMessage = 'Operation timed out') {
        return Promise.race([
            promise,
            new Promise((_, reject) => {
                setTimeout(() => reject(new Error(timeoutMessage)), timeout);
            })
        ]);
    }

    /**
     * 获取今天的日期字符串
     * @returns {string} 日期字符串 YYYY-MM-DD
     */
    static getTodayString() {
        return dayjs().format('YYYY-MM-DD');
    }

    /**
     * 检查日期是否为今天
     * @param {string|Date} date - 日期
     * @returns {boolean} 是否为今天
     */
    static isToday(date) {
        return dayjs(date).format('YYYY-MM-DD') === this.getTodayString();
    }

    /**
     * 获取随机延迟时间
     * @param {number} min - 最小延迟（毫秒）
     * @param {number} max - 最大延迟（毫秒）
     * @returns {number} 随机延迟时间
     */
    static getRandomDelay(min = 1000, max = 5000) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    /**
     * 格式化文件大小
     * @param {number} bytes - 字节数
     * @returns {string} 格式化的文件大小
     */
    static formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes';

        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));

        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }

    /**
     * 计算成功率
     * @param {number} success - 成功次数
     * @param {number} total - 总次数
     * @returns {string} 百分比字符串
     */
    static calculateSuccessRate(success, total) {
        if (total === 0) return '0%';
        return ((success / total) * 100).toFixed(2) + '%';
    }

    /**
     * 验证设备SN码格式
     * @param {string} sn_code - 设备SN码
     * @returns {boolean} 是否有效
     */
    static isValidSnCode(sn_code) {
        return typeof sn_code === 'string' && sn_code.length > 0 && sn_code.length <= 50;
    }

    /**
     * 清理对象中的空值
     * @param {object} obj - 要清理的对象
     * @returns {object} 清理后的对象
     */
    static cleanObject(obj) {
        const cleaned = {};
        for (const key in obj) {
            if (obj.hasOwnProperty(key) && obj[key] !== null && obj[key] !== undefined && obj[key] !== '') {
                cleaned[key] = obj[key];
            }
        }
        return cleaned;
    }
}

module.exports = ScheduleUtils;