import { _decorator } from 'cc';
import BaseManager from '../../base/BaseManager';
const { ccclass } = _decorator;

type ICallback = (...args: any[]) => any;

class DailyTimer {
    // 获取当前时间相对于当日零点的毫秒数
    private static getDayTimeMs(date: Date): number {
        return (
            date.getHours() * 3600 +
            date.getMinutes() * 60 +
            date.getSeconds()
        ) * 1000 + date.getMilliseconds();
    }

    // 静态方法解析时间为毫秒数
    private static parseTimeToMs(h: number, m: number, s: number): number {
        return ((h * 3600 + m * 60 + s) * 1000) % 86400000;
    }

    private readonly startMs: number;  // 起始时间毫秒数（相对于当日零点）
    private readonly endMs: number;    // 结束时间毫秒数

    // 用于检查当前时间是否可触发回调
    private checkDay = 0;

    constructor(
        time: string,
        public readonly callback: ICallback,
        public readonly target?: unknown,
        public readonly once: boolean = false
    ) {
        // 使用解构赋值提高可读性
        const [startSegment, endSegment = startSegment] = time.split('-');

        // 开始时间
        const [startH = 0, startM = 0, startS = 0] = startSegment.split(':').map(
            part => Math.max(0, parseInt(part, 10) || 0)
        );
        this.startMs = DailyTimer.parseTimeToMs(startH, startM, startS);

        // 结束时间
        const [endH = 0, endM = 0, endS = 0] = endSegment.split(':').map(
            part => Math.max(0, parseInt(part, 10) || 0)
        );
        this.endMs = DailyTimer.parseTimeToMs(endH, endM, endS);
        // 结束时间与开始时间不能相同
        if (this.endMs === this.startMs) {
            if (startM === 0 && startS === 0) {
                this.endMs = DailyTimer.parseTimeToMs(startH + 1, startM, startS);
            } else if (startS === 0) {
                this.endMs = DailyTimer.parseTimeToMs(startH, startM + 1, startS);
            } else {
                this.endMs = DailyTimer.parseTimeToMs(startH, startM, startS + 1);
            }
        }
    }

    // 获取当前时间是否在时间范围内
    private isInRange(now: Date): boolean {
        const currentMs = DailyTimer.getDayTimeMs(now);

        // 处理跨天时间段（如 23:00-01:00）
        return this.startMs <= this.endMs
            ? currentMs >= this.startMs && currentMs < this.endMs
            : currentMs >= this.startMs || currentMs < this.endMs;
    }

    update(now: Date): boolean {
        const dateDay = now.getDay();

        if (this.checkDay === dateDay) return false;
        if (!this.isInRange(now)) return false;

        this.checkDay = dateDay;
        this.callback.call(this.target);

        return this.once;
    }
}

class IntervalTimer {
    private elapsed: number = 0;

    constructor(
        public readonly interval: number,
        public readonly callback: ICallback,
        public readonly target?: unknown,
        public readonly once: boolean = false
    ) { }

    update(dt: number): boolean {
        this.elapsed += dt;
        let completed = false;

        // 处理可能多次触发的情况（当dt > interval时）
        while (this.elapsed >= this.interval) {
            this.callback.call(this.target);
            this.elapsed -= this.interval;

            if (this.once) {
                completed = true;
                break;
            }
        }

        return completed;
    }
}

class Timer {
    static update(timer: Timer, dt: number) {
        return timer.update(dt);
    }

    private intervalTimer: IntervalTimer[] = [];

    /**
     * 注册定时器
     * @param interval 
     * @param callback 
     * @param target 
     * @param once 
     */
    register(
        interval: number,
        callback: ICallback,
        target?: unknown,
        once?: boolean
    ): void {
        const timer = new IntervalTimer(interval, callback, target, once || false);
        this.intervalTimer.push(timer);
    }

    /**
     * 取消定时器
     * @param callback 
     * @param target 
     */
    unregister(callback: ICallback, target?: unknown): void {
        if (typeof target === 'undefined') {
            this.intervalTimer = this.intervalTimer.filter(
                timer => timer.callback !== callback
            );
        } else {
            this.intervalTimer = this.intervalTimer.filter(
                timer => !(timer.callback === callback && timer.target === target)
            );
        }
    }

    /**
     * 取消所有定时器
     */
    unregisterAll() {
        this.intervalTimer = [];
    }

    private dailyTimers: DailyTimer[] = [];

    /**
     * 注册每日触发器
     * @param time 24小时制,精确到秒
     * 
     * @example
     * registerDailyTrigger('16', ...) 等同于 registerDailyTrigger('16-17', ...)
     * registerDailyTrigger('8-9:00', ...) 等同于 registerDailyTrigger('8', ...)
     * registerDailyTrigger('8:00:01-24', ...)
     */
    registerDailyTrigger(
        time: string,
        callback: ICallback,
        target?: unknown,
        once?: boolean
    ) {
        const timer = new DailyTimer(time, callback, target, once || false);
        this.dailyTimers.push(timer);
    }

    /**
     * 取消每日触发器
     */
    unregisterDailyTrigger(callback: ICallback, target?: unknown) {
        if (typeof target === 'undefined') {
            this.dailyTimers = this.dailyTimers.filter(
                timer => timer.callback !== callback
            );
        } else {
            this.dailyTimers = this.dailyTimers.filter(
                timer => !(timer.callback === callback && timer.target === target)
            );
        }
    }

    /**
     * 取消所有每日触发器
     */
    unregisterAllDailyTrigger() {
        this.dailyTimers = [];
    }

    /**
     * 清除所有定时器和触发器
     */
    clear() {
        this.intervalTimer = [];
        this.dailyTimers = [];
    }

    protected update(dt: number): void {
        for (let index = 0; index < this.intervalTimer.length; index++) {
            const timer = this.intervalTimer[index];
            if (timer.update(dt)) {
                this.intervalTimer.splice(index, 1);
                index--;
            }
        }

        const date = new Date();
        for (let index = 0; index < this.dailyTimers.length; index++) {
            const timer = this.dailyTimers[index];
            if (timer.update(date)) {
                this.dailyTimers.splice(index, 1);
                index--;
            }
        }
    }
}

@ccclass('TimerManager')
export default class TimerManager extends BaseManager {
    private timers: Map<string | number | Symbol, Timer> = new Map();

    /**
     * 清除所有定时器
     */
    clear() {
        this.timers.forEach((timer) => {
            timer.clear();
        });
        this.timers.clear();
    }

    /**
     * 删除定时器
     * @param key 定时器key
     */
    delete(key: string | number | Symbol) {
        const timer = this.timers.get(key);
        if (!timer) return;

        this.timers.delete(key);
        timer.clear();
    }

    /**
     * 获取定时器
     * @param key 定时器key
     */
    get(key: string | number | Symbol): Timer {
        if (this.timers.has(key)) {
            return this.timers.get(key);
        }

        const timer = new Timer();
        this.timers.set(key, timer);
        return timer;
    }

    protected update(dt: number): void {
        this.timers.forEach((timer) => {
            Timer.update(timer, dt);
        });
    }
}
