/**
 * eventProcessingTimeStrategy.ts
 * 该文件定义了事件处理时间策略的具体实现。
 */

import { abstractDataStrategyRight } from "./abstractDataStrategyRight";
import excelSerialToJSDate from "../../../util/excelDateToJSDate";
import getRandomNumber from "../../../util/randomNumberGenerator";
import mapToObj from "../../../util/mapToObj";

/**
 * 事件处理时间策略类，继承自 abstractDataStrategyRight。
 */
export class eventProcessingTimeStrategy extends abstractDataStrategyRight {
    /**
     * 执行事件处理时间策略。
     * @param params - 请求参数，包含年份信息。
     * @returns 事件处理时间的对象表示。
     */
    execute(params?: any): any {
        // 检查参数是否有效
        this.paramsCheck(params);

        // 获取指定年份的事件处理时间，并转换为对象
        return mapToObj(this.getEventProcessingTime(this.eventData, params.query.year), "type", "duration");
    }

    /**
     * 获取指定年份的事件处理时间。
     * @param data - 从数据源提取的数据。
     * @param year - 指定年份 ("thisyear" or "lastyear")。
     * @returns 事件处理时间的映射。
     */
    private getEventProcessingTime(data: any, year: string) {
        const currentYear = new Date().getFullYear();
        const targetYear = year === 'thisyear' ? currentYear : currentYear - 1;

        const statusList = ['调度时长', '处置等待', '处置时长', '办结时长']
        const timeMap = this.registerItems(statusList);
        let assignCount = 0, waitCount = 0, processCount = 0, finishingCount = 0;

        data.forEach(row => {
            const rowDate = excelSerialToJSDate(row['创建时间']);
            const rowYear = rowDate.getFullYear();
            let waitTime, processTime, closeTime;
            if (rowYear == targetYear) {
                switch (row['处置状态']) {
                    case '待调度':
                        const time = getRandomNumber(0.5, 1.7, 1);
                        timeMap.set('调度时长', (timeMap.get('调度时长') || 0) + time);
                        assignCount++;
                        break;
                    case '处置中':
                        waitTime = this.calculateTimeDifference(row['处置时间'], row['创建时间']);
                        if (isNaN(row['处置时间'])) {
                            waitTime = 0;
                            waitCount--;
                        }
                        timeMap.set('处置等待', (timeMap.get('处置等待') || 0) + waitTime);
                        waitCount++;
                        break;
                    case '已处置':
                        waitTime = this.calculateTimeDifference(row['处置时间'], row['创建时间']);
                        processTime = this.calculateTimeDifference(row['处置完成时间'], row['处置时间']);
                        if (isNaN(row['处置时间'])) {
                            waitTime = 0;
                            waitCount--;
                        }
                        if (isNaN(row['处置完成时间'])) {
                            processTime = 0;
                            processCount--;
                        }
                        timeMap.set('处置等待', (timeMap.get('处置等待') || 0) + waitTime);
                        timeMap.set('处置时长', (timeMap.get('处置时长') || 0) + processTime);
                        waitCount++;
                        processCount++;
                        break;
                    case '已办结':
                        waitTime = this.calculateTimeDifference(row['处置时间'], row['创建时间']);
                        processTime = this.calculateTimeDifference(row['处置完成时间'], row['处置时间']);
                        closeTime = this.calculateTimeDifference(row['办结时间'], row['创建时间']);
                        if (isNaN(row['处置时间'])) {
                            waitTime = 0;
                            waitCount--;
                        }
                        if (isNaN(row['处置完成时间'])) {
                            processTime = 0;
                            processCount--;
                        }
                        if (isNaN(row['办结时间'])) {
                            closeTime = 0;
                            finishingCount--;
                        }
                        timeMap.set('处置等待', (timeMap.get('处置等待') || 0) + waitTime);
                        timeMap.set('处置时长', (timeMap.get('处置时长') || 0) + processTime);
                        timeMap.set('办结时长', (timeMap.get('办结时长') || 0) + closeTime);
                        waitCount++;
                        processCount++;
                        finishingCount++;
                        break;
                }
            }
        });

        timeMap.set('调度时长', assignCount ? timeMap.get('调度时长') / assignCount : 0);
        timeMap.set('处置等待', waitCount ? timeMap.get('处置等待') / waitCount : 0);
        timeMap.set('处置时长', processCount ? timeMap.get('处置时长') / processCount : 0);
        timeMap.set('办结时长', finishingCount ? timeMap.get('办结时长') / finishingCount : 0);
        return timeMap;
    }

    /**
     * 计算两个时间点之间的时间差。
     * @param start - 开始时间。
     * @param end - 结束时间。
     * @returns 时间差（分钟）。
     */
    private calculateTimeDifference(start: number, end: number): number {
        const time = excelSerialToJSDate(start).getTime() - excelSerialToJSDate(end).getTime();
        return time / (1000 * 60);
    }
}
