/**
 * 定时任务调度器
 * - 每分钟执行一次数据同步任务
 * - 每 6 分钟执行一次预警工单同步任务
 * - 内置锁机制，防止任务重叠执行
 * - 任务锁死时（超时未释放），会主动强制释放锁，确保后续任务能正常执行
 */

import { dataintegration } from "tencentcloud-sdk-nodejs";
import { region, device, deviceData, alertWorkData, processFaultStatus } from "../biz/dataIntegration";

// 锁超时时间（毫秒），任务执行超过此时间视为锁死
const LOCK_TIMEOUT_MS = 55 * 1000; // 55秒，留5秒余量给下一次执行

// 定时器执行间隔（毫秒）
const TASK_INTERVAL_MS = 60 * 1000; // 1分钟

interface TaskLock {
    locked: boolean;
    lockTime: number; // 加锁时的时间戳
    lockKey: string;  // 锁标识，用于追踪
}

const taskLock: TaskLock = {
    locked: false,
    lockTime: 0,
    lockKey: '',
};

/**
 * 尝试获取任务锁
 * @returns 是否成功获取锁
 */
function tryAcquireLock(): boolean {
    if (taskLock.locked) {
        const elapsed = Date.now() - taskLock.lockTime;
        if (elapsed > LOCK_TIMEOUT_MS) {
            // 锁已超时，强制释放
            console.warn(`[定时任务] 检测到锁死，强制释放锁。已锁定 ${elapsed}ms，锁标识: ${taskLock.lockKey}`);
            releaseLock();
            return tryAcquireLock();
        }
        // 上一次任务还在执行中，跳过本次
        console.log(`[定时任务] 上一次任务尚未完成，跳过本次执行。已锁定 ${elapsed}ms`);
        return false;
    }

    taskLock.locked = true;
    taskLock.lockTime = Date.now();
    taskLock.lockKey = `${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
    return true;
}

/**
 * 释放任务锁
 */
function releaseLock(): void {
    taskLock.locked = false;
    taskLock.lockTime = 0;
    taskLock.lockKey = '';
}

/**
 * 获取当前锁状态（供外部查询）
 */
export function getLockStatus(): { locked: boolean; lockDuration: number; lockKey: string } {
    return {
        locked: taskLock.locked,
        lockDuration: taskLock.locked ? Date.now() - taskLock.lockTime : 0,
        lockKey: taskLock.lockKey,
    };
}

/**
 * 主动强制释放锁（供外部调用，用于紧急情况手动释放）
 */
export function forceReleaseLock(): void {
    if (taskLock.locked) {
        const elapsed = Date.now() - taskLock.lockTime;
        console.warn(`[定时任务] 外部主动强制释放锁。已锁定 ${elapsed}ms，锁标识: ${taskLock.lockKey}`);
        releaseLock();
    }
}

/**
 * 定时任务的具体业务逻辑
 * 在这里编写需要定时执行的任务代码
 */
async function scheduledTask(): Promise<void> {
    // 尝试获取锁，未获取到则跳过
    if (!tryAcquireLock()) {
        return;
    }

    try {
        // ====== 在此处编写定时任务的具体逻辑 ======
        console.log(`[定时任务] 开始执行 - ${new Date().toLocaleString()}`);

        await region();
        await device();
        await deviceData();

        console.log(`[定时任务] 执行完成 - ${new Date().toLocaleString()}`);
        // =========================================
    } catch (err) {
        console.error('[定时任务] 执行异常:', err);
    } finally {
        // 无论任务成功或失败，都要释放锁
        releaseLock();
    }
}

// 定时器句柄
let timerHandle: NodeJS.Timeout | null = null;
let alertTimerHandle: NodeJS.Timeout | null = null;
let faultStatusTimerHandle: NodeJS.Timeout | null = null;

// 预警工单定时任务专用锁
const alertTaskLock: TaskLock = {
    locked: false,
    lockTime: 0,
    lockKey: '',
};

/** 预警工单锁超时（毫秒） */
const ALERT_LOCK_TIMEOUT_MS = 5 * 60 * 1000; // 5 分钟

/** 预警工单执行间隔（毫秒） */
const ALERT_TASK_INTERVAL_MS = 6 * 60 * 1000; // 6 分钟

/**
 * 尝试获取预警工单任务锁
 */
function tryAcquireAlertLock(): boolean {
    if (alertTaskLock.locked) {
        const elapsed = Date.now() - alertTaskLock.lockTime;
        if (elapsed > ALERT_LOCK_TIMEOUT_MS) {
            console.warn(`[预警工单定时任务] 检测到锁死，强制释放锁。已锁定 ${elapsed}ms`);
            alertTaskLock.locked = false;
            alertTaskLock.lockTime = 0;
            alertTaskLock.lockKey = '';
            return tryAcquireAlertLock();
        }
        console.log(`[预警工单定时任务] 上一次任务尚未完成，跳过本次执行`);
        return false;
    }
    alertTaskLock.locked = true;
    alertTaskLock.lockTime = Date.now();
    alertTaskLock.lockKey = `${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
    return true;
}

/**
 * 启动定时任务
 * 在项目启动时调用
 */
export function startSchedule(): void {
    if (timerHandle) {
        console.warn('[定时任务] 定时器已在运行中，无需重复启动');
        return;
    }

    console.log(`[定时任务] 数据同步定时器已启动，间隔 ${TASK_INTERVAL_MS / 1000} 秒`);

    // 使用 setInterval 实现每分钟执行一次
    timerHandle = setInterval(() => {
        scheduledTask();
    }, TASK_INTERVAL_MS);
}

/**
 * 启动预警工单定时任务
 * 独立于数据同步定时任务，每 10 分钟执行一次
 */
export function startAlertSchedule(): void {
    if (alertTimerHandle) {
        console.warn('[预警工单定时任务] 定时器已在运行中，无需重复启动');
        return;
    }

    console.log(`[预警工单定时任务] 定时器已启动，间隔 ${ALERT_TASK_INTERVAL_MS / 1000} 秒`);

    alertTimerHandle = setInterval(() => {
        scheduledAlertTask();
    }, ALERT_TASK_INTERVAL_MS);
}

/**
 * 预警工单定时任务的具体业务逻辑
 */
async function scheduledAlertTask(): Promise<void> {
    if (!tryAcquireAlertLock()) {
        return;
    }

    try {
        console.log(`[预警工单定时任务] 开始执行 - ${new Date().toLocaleString()}`);
        await alertWorkData();
        console.log(`[预警工单定时任务] 执行完成 - ${new Date().toLocaleString()}`);
    } catch (err) {
        console.error('[预警工单定时任务] 执行异常:', err);
    } finally {
        alertTaskLock.locked = false;
        alertTaskLock.lockTime = 0;
        alertTaskLock.lockKey = '';
    }
}

// ==================== 故障状态更新定时任务 ====================

/** 故障状态更新锁超时（毫秒） */
const FAULT_STATUS_LOCK_TIMEOUT_MS = 4 * 60 * 1000; // 4 分钟

/** 故障状态更新执行间隔（毫秒） */
const FAULT_STATUS_TASK_INTERVAL_MS = 5 * 60 * 1000; // 5 分钟

/** 故障状态更新专用锁 */
const faultStatusTaskLock: TaskLock = {
    locked: false,
    lockTime: 0,
    lockKey: '',
};

/**
 * 尝试获取故障状态更新任务锁
 */
function tryAcquireFaultStatusLock(): boolean {
    if (faultStatusTaskLock.locked) {
        const elapsed = Date.now() - faultStatusTaskLock.lockTime;
        if (elapsed > FAULT_STATUS_LOCK_TIMEOUT_MS) {
            console.warn(`[故障状态更新任务] 检测到锁死，强制释放锁。已锁定 ${elapsed}ms`);
            faultStatusTaskLock.locked = false;
            faultStatusTaskLock.lockTime = 0;
            faultStatusTaskLock.lockKey = '';
            return tryAcquireFaultStatusLock();
        }
        console.log(`[故障状态更新任务] 上一次任务尚未完成，跳过本次执行`);
        return false;
    }
    faultStatusTaskLock.locked = true;
    faultStatusTaskLock.lockTime = Date.now();
    faultStatusTaskLock.lockKey = `${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
    return true;
}

/**
 * 故障状态更新定时任务
 */
async function scheduledFaultStatusTask(): Promise<void> {
    if (!tryAcquireFaultStatusLock()) {
        return;
    }

    try {
        console.log(`[故障状态更新任务] 开始执行 - ${new Date().toLocaleString()}`);
        await processFaultStatus();
        console.log(`[故障状态更新任务] 执行完成 - ${new Date().toLocaleString()}`);
    } catch (err) {
        console.error('[故障状态更新任务] 执行异常:', err);
    } finally {
        faultStatusTaskLock.locked = false;
        faultStatusTaskLock.lockTime = 0;
        faultStatusTaskLock.lockKey = '';
    }
}

/**
 * 启动故障状态更新定时任务
 */
export function startFaultStatusSchedule(): void {
    if (faultStatusTimerHandle) {
        console.warn('[故障状态更新任务] 定时器已在运行中，无需重复启动');
        return;
    }

    console.log(`[故障状态更新任务] 定时器已启动，间隔 ${FAULT_STATUS_TASK_INTERVAL_MS / 60000} 分钟`);

    faultStatusTimerHandle = setInterval(() => {
        scheduledFaultStatusTask();
    }, FAULT_STATUS_TASK_INTERVAL_MS);
}

/**
 * 停止故障状态更新定时任务
 */
export function stopFaultStatusSchedule(): void {
    if (faultStatusTimerHandle) {
        clearInterval(faultStatusTimerHandle);
        faultStatusTimerHandle = null;
        console.log('[故障状态更新任务] 定时器已停止');
    }
}

/**
 * 停止定时任务
 */
export function stopSchedule(): void {
    if (timerHandle) {
        clearInterval(timerHandle);
        timerHandle = null;
        console.log('[定时任务] 定时器已停止');
    }
}

/**
 * 停止预警工单定时任务
 */
export function stopAlertSchedule(): void {
    if (alertTimerHandle) {
        clearInterval(alertTimerHandle);
        alertTimerHandle = null;
        console.log('[预警工单定时任务] 定时器已停止');
    }
}
