/**
 * 喝水助手插件
 * 定时弹框提醒用户喝水和走动，显示当前时间
 * 使用 Electron BrowserWindow 创建 OS 级置顶弹框
 * 按整点时间提醒：每小时的 :00 和 :30（30 分钟模式）或仅 :00（60 分钟模式）
 */

const fs = require('fs');
const path = require('path');

// 用于生成唯一 IPC 通道名，防止多窗口冲突
let _ipcSeq = 0;

/**
 * 获取 @electron/remote 模块
 * 插件通过 plugin-manager require() 加载，模块解析路径不包含 app.asar，
 * 因此无法直接 require('@electron/remote')。
 * 利用 module.parent 链向上查找到 preload.js 的 require 来解析。
 */
function getElectronRemote() {
    // 方式1: 直接 require（在某些环境下可以工作）
    try {
        return require('@electron/remote');
    } catch (e) {
        // ignore
    }

    // 方式2: 通过 module.parent 链找到 app.asar 内的 require
    let parentModule = module.parent;
    while (parentModule) {
        try {
            return parentModule.require('@electron/remote');
        } catch (e) {
            parentModule = parentModule.parent;
        }
    }

    // 方式3: 通过 process.mainModule
    if (process.mainModule) {
        try {
            return process.mainModule.require('@electron/remote');
        } catch (e) {
            // ignore
        }
    }

    throw new Error('无法加载 @electron/remote 模块');
}

/**
 * 计算距离下一个整点提醒时间的毫秒数
 * @param {number} intervalMin - 提醒间隔（30 或 60 分钟）
 * @returns {{ delayMs: number, nextTime: Date }} 延迟毫秒数和下次提醒时间
 */
function calcNextAlignedTime(intervalMin) {
    const now = new Date();
    const currentMin = now.getMinutes();
    const currentSec = now.getSeconds();
    const currentMsInMin = now.getMilliseconds();

    let nextMin;
    if (intervalMin === 60) {
        // 60 分钟模式：只在 :00 提醒
        nextMin = 60; // 下一个整点
    } else {
        // 30 分钟模式：在 :00 和 :30 提醒
        if (currentMin < 30) {
            nextMin = 30;
        } else {
            nextMin = 60; // 下一个整点
        }
    }

    // 计算距离下一个目标时间的毫秒数
    const diffMin = nextMin - currentMin;
    const delayMs = (diffMin * 60 - currentSec) * 1000 - currentMsInMin;

    const nextTime = new Date(now.getTime() + delayMs);
    return { delayMs, nextTime };
}

module.exports = {
    name: '小憩提醒',
    description: '按整点时间提醒喝水和走动，支持 30/60 分钟间隔、强制提醒（OS 级置顶窗口）',
    version: 'dev',
    author: 'zfeng',
    defaultEnabled: false,

    defaultConfig: {
        interval: '30',       // '30' 或 '60'，单位：分钟
        forceReminder: false  // 强制提醒：弹框不可手动关闭，倒计时 10 秒后自动关闭
    },

    // 配置元数据：配置面板渲染下拉选择
    configMeta: {
        interval: {
            label: '⏰ 提醒间隔',
            options: [
                { value: '30', label: '每半小时（例如8:00,8:30,9:00）' },
                { value: '60', label: '每整小时（例如8:00,9:00）' },
            ]
        },
        forceReminder: {
            label: '🔒 强制提醒（倒计时 10 秒后自动关闭，期间无法手动关闭）'
        }
    },

    COUNTDOWN_SECONDS: 10,
    WATCHDOG_INTERVAL_MS: 5000,   // 看门狗轮询间隔
    WATCHDOG_MAX_ALIVE_MS: 15000, // 窗口最大存活时间（超过即强制销毁）

    /**
     * 读取外部 styles.css 样式文件
     */
    _loadCSS() {
        try {
            const cssPath = path.join(__dirname, 'styles.css');
            return fs.readFileSync(cssPath, 'utf-8');
        } catch (e) {
            console.error('[WaterReminder] 加载样式文件失败:', e);
            return '';
        }
    },

    /**
     * 构建完整的弹框 HTML 页面（用于独立窗口）
     */
    _buildFullHTML(isForce, ipcChannel) {
        const now = new Date();
        const timeStr = now.toLocaleTimeString('zh-CN', {
            hour: '2-digit',
            minute: '2-digit',
            hour12: false
        });

        const countdownSeconds = this.COUNTDOWN_SECONDS;
        const cssContent = this._loadCSS();

        const countdownHTML = isForce ? `
                <div class="wr-countdown">
                    <div class="wr-countdown-ring">
                        <svg viewBox="0 0 44 44">
                            <circle class="wr-ring-bg" cx="22" cy="22" r="20" />
                            <circle class="wr-ring-progress" id="wr-ring" cx="22" cy="22" r="20" />
                        </svg>
                        <div class="wr-countdown-number" id="wr-countdown-num">${countdownSeconds}</div>
                    </div>
                    <div class="wr-countdown-text">
                        🔒 <strong>强制提醒模式</strong><br>
                        窗口将在倒计时结束后自动关闭
                    </div>
                </div>` : '';

        const btnText = isForce
            ? '🔒 请等待倒计时结束'
            : '✅ 好的，我知道了';

        return `<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>喝水提醒</title>
    <style>${cssContent}</style>
</head>
<body>
    <div class="wr-container" id="wr-container">
        <div class="wr-header">
            <div class="wr-icon">💧</div>
            <p class="wr-title">喝水 &amp; 走动提醒</p>
        </div>
        <div class="wr-body">
            <div class="wr-time-box">
                <span class="wr-time-icon">🕐</span>
                <div>
                    <div class="wr-time-label">当前时间</div>
                    <div class="wr-time-value">${timeStr}</div>
                </div>
            </div>
            ${countdownHTML}
            <ul class="wr-tips">
                <li>
                    <span class="wr-tip-icon">💧</span>
                    <span>记得喝一杯温水，保持身体水分充足</span>
                </li>
                <li>
                    <span class="wr-tip-icon">🚶</span>
                    <span>起来走动几分钟，伸展一下身体放松肌肉</span>
                </li>
                <li>
                    <span class="wr-tip-icon">👁️</span>
                    <span>远眺窗外 20 秒，让眼睛休息一下</span>
                </li>
            </ul>
        </div>
        <div class="wr-footer">
            <button class="wr-btn" id="wr-dismiss-btn" ${isForce ? 'disabled' : ''}>${btnText}</button>
        </div>
    </div>

    <script>
        const { ipcRenderer } = require('electron');
        const isForce = ${isForce ? 'true' : 'false'};
        const totalSec = ${countdownSeconds};
        const circumference = 2 * Math.PI * 20;
        const ipcChannel = '${ipcChannel}';

        // 多重关闭机制，确保窗口一定能被销毁
        let _closeAttempted = false;
        function closeWindow() {
            if (_closeAttempted) return;
            _closeAttempted = true;

            const container = document.getElementById('wr-container');
            if (container) container.classList.add('wr-closing');

            // 动画结束后（200ms）执行多重关闭
            setTimeout(() => {
                // 方式1（首选）：通过 @electron/remote 直接销毁当前窗口
                try {
                    const remote = require('@electron/remote');
                    const win = remote.getCurrentWindow();
                    if (win && !win.isDestroyed()) {
                        win.destroy();
                        return;
                    }
                } catch (e) {
                    console.warn('[WaterReminder] remote.destroy 失败:', e.message);
                }

                // 方式2：通过 IPC 通知主进程销毁
                try {
                    ipcRenderer.send(ipcChannel);
                } catch (e) {
                    console.warn('[WaterReminder] IPC 关闭失败:', e.message);
                }

                // 方式3：兜底 window.close
                setTimeout(() => {
                    try { window.close(); } catch (e) { /* ignore */ }
                }, 500);
            }, 200);
        }

        // 渲染进程侧安全兜底：确保窗口在合理时间内一定关闭
        const rendererSafetyMs = isForce ? (totalSec + 3) * 1000 : 15000;
        setTimeout(() => {
            if (!_closeAttempted) {
                console.warn('[WaterReminder] ⚠️ 渲染进程安全兜底触发');
                closeWindow();
            }
        }, rendererSafetyMs);

        if (isForce) {
            // 强制提醒模式：倒计时自动关闭
            let remaining = totalSec;
            const numEl = document.getElementById('wr-countdown-num');
            const ringEl = document.getElementById('wr-ring');

            if (ringEl) {
                ringEl.style.strokeDasharray = circumference;
                ringEl.style.strokeDashoffset = '0';
            }

            const timer = setInterval(() => {
                remaining--;
                if (numEl) numEl.textContent = remaining;
                if (ringEl) {
                    const offset = circumference * (1 - remaining / totalSec);
                    ringEl.style.strokeDashoffset = offset;
                }
                if (remaining <= 0) {
                    clearInterval(timer);
                    closeWindow();
                }
            }, 1000);
        } else {
            // 普通模式：可手动关闭
            document.getElementById('wr-dismiss-btn').addEventListener('click', closeWindow);
        }
    </script>
</body>
</html>`;
    },

    /**
     * 显示提醒弹框（OS 级置顶窗口）
     */
    _showReminder(instance) {
        const isForce = !!instance.config.forceReminder;

        // 如果弹框已在显示中，先关闭
        this._hideReminder(instance);

        const remote = getElectronRemote();
        const { BrowserWindow } = remote;
        const { ipcMain } = remote.require('electron');

        // 生成唯一 IPC 通道名
        const ipcChannel = `wr-close-window-${++_ipcSeq}-${Date.now()}`;

        // 创建置顶窗口
        // 注意：不再设置 closable: false，因为这会导致 window.close() 失效
        // 强制模式下通过禁用按钮来阻止用户手动关闭
        const win = new BrowserWindow({
            width: 400,
            height: isForce ? 650 : 550,
            alwaysOnTop: true,
            frame: false,
            transparent: true,
            resizable: false,
            skipTaskbar: true,
            minimizable: false,
            maximizable: false,
            fullscreenable: false,
            show: false,
            webPreferences: {
                nodeIntegration: true,
                contextIsolation: false,
                enableRemoteModule: true,
            }
        });

        // 窗口居中显示
        win.center();

        // 注册 IPC 监听器：渲染进程通过此通道请求关闭窗口
        const ipcHandler = () => {
            if (win && !win.isDestroyed()) {
                console.log('[WaterReminder] 📩 收到 IPC 关闭请求，销毁窗口');
                win.destroy();
            }
        };
        ipcMain.once(ipcChannel, ipcHandler);

        // 加载 HTML 内容（传入 ipcChannel 供渲染进程使用）
        const htmlContent = this._buildFullHTML(isForce, ipcChannel);
        win.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(htmlContent)}`);

        // 为渲染进程启用 @electron/remote（用于直接关闭窗口）
        try {
            const remoteMain = remote.require('@electron/remote/main');
            remoteMain.enable(win.webContents);
        } catch (e) {
            console.warn('[WaterReminder] 启用 remote 失败（可降级到 IPC 方式）:', e.message);
        }

        // 内容加载完成后显示窗口
        win.webContents.once('did-finish-load', () => {
            if (win && !win.isDestroyed()) {
                win.show();
                win.focus();
            }
        });

        // 监听渲染进程异常/崩溃，自动销毁窗口
        win.webContents.on('render-process-gone', (_event, details) => {
            console.warn('[WaterReminder] ⚠️ 渲染进程异常:', details.reason);
            if (win && !win.isDestroyed()) {
                win.destroy();
            }
        });
        win.webContents.on('crashed', () => {
            console.warn('[WaterReminder] ⚠️ 渲染进程崩溃');
            if (win && !win.isDestroyed()) {
                win.destroy();
            }
        });

        // 窗口关闭时清理引用和 IPC 监听器
        win.on('closed', () => {
            ipcMain.removeListener(ipcChannel, ipcHandler);
            if (instance._safetyTimer) {
                clearTimeout(instance._safetyTimer);
                instance._safetyTimer = null;
            }
            instance._reminderWindow = null;
            instance._ipcChannel = null;
        });

        instance._reminderWindow = win;
        instance._ipcChannel = ipcChannel;
        instance._reminderShowTime = Date.now();

        // 安全兜底：超时后强制销毁窗口，防止窗口关闭失败后残留在最前面
        const safetyMs = isForce
            ? (this.COUNTDOWN_SECONDS + 5) * 1000   // 强制模式：倒计时 + 5 秒余量
            : 20 * 1000;                              // 普通模式：最长 20 秒（原 60 秒太长）
        instance._safetyTimer = setTimeout(() => {
            if (instance._reminderWindow && !instance._reminderWindow.isDestroyed()) {
                console.log('[WaterReminder] ⚠️ 安全兜底：窗口超时未关闭，强制销毁');
                instance._reminderWindow.destroy();
            }
            instance._reminderWindow = null;
            instance._safetyTimer = null;
        }, safetyMs);

        if (isForce) {
            console.log('[WaterReminder] 🔒💧 弹出 OS 级强制提醒（倒计时 10 秒）');
        } else {
            console.log('[WaterReminder] 💧 弹出 OS 级提醒');
        }
    },

    /**
     * 隐藏提醒弹框
     */
    _hideReminder(instance) {
        if (instance._safetyTimer) {
            clearTimeout(instance._safetyTimer);
            instance._safetyTimer = null;
        }
        // 清理 IPC 监听器
        if (instance._ipcChannel) {
            try {
                const remote = getElectronRemote();
                const { ipcMain } = remote.require('electron');
                ipcMain.removeAllListeners(instance._ipcChannel);
            } catch (e) {
                // ignore
            }
            instance._ipcChannel = null;
        }
        if (instance._reminderWindow && !instance._reminderWindow.isDestroyed()) {
            instance._reminderWindow.destroy();
        }
        instance._reminderWindow = null;
    },

    // ========== 生命周期 ==========

    /**
     * 启动提醒定时器（带休眠补偿的智能轮询）
     * 动态调整 setTimeout 的等待时间，平时长休眠，临近时才高频检查
     * 解决由于系统休眠/唤醒导致的延迟或提前触发问题，同时不浪费 CPU
     */
    _startAlignedTimer(instance, intervalMin) {
        const self = this;

        const fmtTime = (d) => d.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false });

        function scheduleNext() {
            const { nextTime } = calcNextAlignedTime(intervalMin);
            console.log(`[WaterReminder] ⏰ 下次提醒时间设定为: ${fmtTime(nextTime)}`);
            instance._nextReminderTime = nextTime.getTime();
            poll(); // 开启智能轮询
        }

        function poll() {
            const now = Date.now();
            const timeDiffMs = instance._nextReminderTime - now;

            if (timeDiffMs <= 0) {
                // 时间到了，或者超过了（比如电脑刚从休眠中唤醒）
                const overMissMs = Math.abs(timeDiffMs); // 错过了多久
                
                // 设定阈值为 5 分钟(300000ms)，错过超过 5 分钟就不再补偿弹框，直接算下个整点
                if (overMissMs < 300000) {
                    console.log(`[WaterReminder] ⏰ 触发提醒！预定: ${fmtTime(new Date(instance._nextReminderTime))} 实际: ${fmtTime(new Date(now))} 误差: ${overMissMs}ms`);
                    self._showReminder(instance);
                } else {
                    console.log(`[WaterReminder] ⏰ 探测到设备长时休眠，错过提醒时间 (${Math.round(overMissMs / 60000)} 分钟)，跳过本次提醒补偿`);
                }
                
                // 安排下一次的大周期
                scheduleNext(); 
            } else {
                // 还没到时间，动态决定下一次检查是什么时候
                let waitMs;
                if (timeDiffMs > 60000) {
                    // 如果距离下次提醒还大于 1 分钟，那就每 30 秒才醒来检查一次 (避免占CPU)
                    // 使用稍微短于1分钟的时间，防止错过最后冲刺阶段
                    waitMs = 30000;
                } else if (timeDiffMs > 10000) {
                    // 如果在 1 分钟 ~ 10 秒之间，每 5 秒检查一次
                    waitMs = 5000;
                } else {
                    // 最后的 10 秒钟内，为了精确对齐，1 秒钟检查一次
                    waitMs = 1000;
                }
                
                // console.log(`[WaterReminder] 此轮距下次提醒还有 ${timeDiffMs}ms，休眠 ${waitMs}ms`); // debug 用，平时注释掉
                instance._alignTimer = setTimeout(poll, waitMs);
            }
        }

        // 初始化第一次启动
        scheduleNext();
    },

    /**
     * 看门狗：每 5 秒轮询，暴力查找并销毁残留的喝水提醒窗口
     * 独立于所有其他关闭机制，作为最终保障
     */
    _startWatchdog(instance) {
        const self = this;
        instance._watchdog = setInterval(() => {
            try {
                const remote = getElectronRemote();
                const { BrowserWindow } = remote;
                const allWindows = BrowserWindow.getAllWindows();
                for (const win of allWindows) {
                    if (win.isDestroyed()) continue;
                    try {
                        const title = win.getTitle();
                        if (title === '喝水提醒') {
                            // 检查窗口是否已超过最大存活时间
                            // 利用 instance 上记录的弹出时间判断
                            const elapsed = Date.now() - (instance._reminderShowTime || 0);
                            if (elapsed > self.WATCHDOG_MAX_ALIVE_MS) {
                                console.log(`[WaterReminder] 🐕 看门狗：发现残留窗口（已存活 ${Math.round(elapsed / 1000)}s），强制销毁`);
                                win.destroy();
                                instance._reminderWindow = null;
                                instance._reminderShowTime = null;
                            }
                        }
                    } catch (e) {
                        // 窗口可能已被销毁，忽略
                    }
                }
            } catch (e) {
                // ignore
            }
        }, self.WATCHDOG_INTERVAL_MS);
        console.log('[WaterReminder] 🐕 看门狗已启动（每 5 秒巡查）');
    },

    _stopWatchdog(instance) {
        if (instance._watchdog) {
            clearInterval(instance._watchdog);
            instance._watchdog = null;
            console.log('[WaterReminder] 🐕 看门狗已停止');
        }
    },

    async init(config, pluginManager) {
        console.log('[WaterReminder] 🚀 初始化喝水助手插件...');

        // 预检查 @electron/remote 是否可用
        try {
            const remote = getElectronRemote();
            if (!remote || !remote.BrowserWindow) {
                throw new Error('BrowserWindow 不可用');
            }
            console.log('[WaterReminder] ✅ @electron/remote 模块加载成功');
        } catch (error) {
            const msg = `@electron/remote 模块不可用: ${error.message}`;
            console.error(`[WaterReminder] ❌ ${msg}`);
            return { success: false, message: msg };
        }

        const intervalMin = parseFloat(config.interval) || 30;

        const instance = {
            config,
            timer: null,
            _alignTimer: null,
            _reminderWindow: null,
            _reminderShowTime: null,
            _watchdog: null,
        };

        // 启动看门狗
        this._startWatchdog(instance);

        // 启动整点对齐的定时提醒
        this._startAlignedTimer(instance, intervalMin);

        const modeDesc = intervalMin === 60 ? '每小时整点（:00）' : '每半小时整点（:00 和 :30）';
        console.log(`[WaterReminder] ✅ 插件已启动（OS 级置顶窗口模式），${modeDesc}提醒`);
        return instance;
    },

    async destroy(instance) {
        console.log('[WaterReminder] 🔄 销毁喝水助手插件...');

        if (instance._alignTimer) {
            clearTimeout(instance._alignTimer);
            instance._alignTimer = null;
        }

        if (instance.timer) {
            clearInterval(instance.timer);
            instance.timer = null;
        }

        this._stopWatchdog(instance);
        this._hideReminder(instance);

        console.log('[WaterReminder] ✅ 插件已销毁');
    }
};
