/**
 * 工作日志总结插件
 * 监听当日 IM 中「我参与的」消息（私聊 + @我的群聊），记录到本地，
 * 用户手动触发 AI 总结以生成结构化工作日志。
 * 消息记录和总结结果最多保留 10 天。
 */

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

module.exports = {
    name: '工作日志总结',
    description: '自动收集当日私聊和@我的消息，通过 AI 生成结构化工作日志',
    version: 'dev',
    author: 'zfeng',
    defaultEnabled: false,
    defaultConfig: {},

    // ---- 内部参数 ----
    _settings: {
        apiPath: '/api/ai/work-log',
        maxMessagesPerConversation: 200,
        scanIntervalMs: 5 * 60 * 1000,  // 5 分钟
        cooldownMs: 10 * 1000,  // 30 秒冷却
        oaApiBaseUrl: 'https://oa.epoint.com.cn',
        defaultWorkHours: '8',
        defaultCompletePercent: 100,
        oaRequestTimeoutMs: 10 * 1000,  // OA 接口最大请求时间 10 秒
    },

    // ---- 常量 ----
    NAV_ICON_ID: 'work-log-nav-icon',
    STYLE_ID: 'work-log-styles',
    PANEL_ID: 'work-log-panel',
    SUBMIT_MODAL_ID: 'work-log-submit-modal',
    MAX_DAYS: 30,

    // ======================== 数据管理 ========================

    _getDataDir() {
        try {
            const cacheDir = path.join(__dirname, 'cache');
            if (!fs.existsSync(cacheDir)) {
                fs.mkdirSync(cacheDir, { recursive: true });
            }
            return cacheDir;
        } catch (e) { return null; }
    },

    _getMessageLogPath(dateStr) {
        const dir = this._getDataDir();
        return dir ? path.join(dir, `work-log-${dateStr}.json`) : null;
    },

    _getSummaryPath(dateStr) {
        const dir = this._getDataDir();
        return dir ? path.join(dir, `work-log-summary-${dateStr}.json`) : null;
    },

    _getDateStr(date) {
        const d = date || new Date();
        const pad = n => String(n).padStart(2, '0');
        return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
    },

    _getDateOffset(offset) {
        const d = new Date();
        d.setDate(d.getDate() + offset);
        return this._getDateStr(d);
    },

    _formatDateLabel(dateStr) {
        const today = this._getDateStr();
        const yesterday = this._getDateOffset(-1);
        if (dateStr === today) return `${dateStr}（今天）`;
        if (dateStr === yesterday) return `${dateStr}（昨天）`;
        const d = new Date(dateStr + 'T00:00:00');
        const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
        return `${dateStr}（${weekdays[d.getDay()]}）`;
    },

    _isMessageFromDate(sentTime, dateStr) {
        const d = new Date(sentTime);
        return this._getDateStr(d) === dateStr;
    },

    _loadDayMessages(dateStr) {
        const filePath = this._getMessageLogPath(dateStr);
        if (!filePath) return { date: dateStr, messages: [], stats: {}, lastScanTime: null };
        try {
            if (fs.existsSync(filePath)) {
                return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
            }
        } catch (e) {
            console.error('[WorkLog] 加载消息日志失败:', e);
        }
        return { date: dateStr, messages: [], stats: {}, lastScanTime: null };
    },

    _saveDayMessages(dateStr, data) {
        const filePath = this._getMessageLogPath(dateStr);
        if (!filePath) return;
        try {
            fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
        } catch (e) {
            console.error('[WorkLog] 保存消息日志失败:', e);
        }
    },

    _loadSummary(dateStr) {
        const filePath = this._getSummaryPath(dateStr);
        if (!filePath) return null;
        try {
            if (fs.existsSync(filePath)) {
                return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
            }
        } catch (e) {
            console.error('[WorkLog] 加载总结失败:', e);
        }
        return null;
    },

    _saveSummary(dateStr, summaryObj) {
        const filePath = this._getSummaryPath(dateStr);
        if (!filePath) return;
        try {
            fs.writeFileSync(filePath, JSON.stringify(summaryObj, null, 2), 'utf-8');
        } catch (e) {
            console.error('[WorkLog] 保存总结失败:', e);
        }
    },

    _cleanupOldData() {
        const dir = this._getDataDir();
        if (!dir) return;
        try {
            const cutoff = this._getDateOffset(-this.MAX_DAYS);
            const files = fs.readdirSync(dir);
            files.forEach(file => {
                const match = file.match(/^work-log(?:-summary)?-(\d{4}-\d{2}-\d{2})\.json$/);
                if (match && match[1] < cutoff) {
                    fs.unlinkSync(path.join(dir, file));
                    console.log('[WorkLog] 清理过期文件:', file);
                }
            });
        } catch (e) {
            console.warn('[WorkLog] 清理旧数据失败:', e);
        }
    },

    _calculateStats(messages, myUserId) {
        const convSet = new Set(messages.map(m => `${m.conversationType}_${m.targetId}`));
        return {
            totalMessages: messages.length,
            myMessages: messages.filter(m => m.isMine).length,
            conversations: convSet.size,
        };
    },

    // ======================== 消息收集 ========================

    _getCurrentUserId() {
        try {
            if (window.RongIM && window.RongIM.instance) {
                const auth = window.RongIM.instance.auth;
                if (auth && auth.id) return auth.id;
            }
        } catch (e) { }
        try {
            const client = window.RongIMLib && window.RongIMLib.RongIMClient.getInstance();
            if (client && typeof client.getCurrentUserId === 'function') {
                return client.getCurrentUserId();
            }
        } catch (e) { }
        return null;
    },

    _isAtMe(msg, myUserId) {
        const mentioned = msg.content && msg.content.mentionedInfo;
        if (!mentioned) return false;
        if (mentioned.type === 1) return true;  // @全体
        if (mentioned.type === 2 && mentioned.userIdList && mentioned.userIdList.includes(myUserId)) return true;
        return false;
    },

    _getConversationList() {
        return new Promise((resolve) => {
            try {
                const RongIMClient = window.RongIMLib && window.RongIMLib.RongIMClient;
                if (!RongIMClient) { resolve([]); return; }
                RongIMClient.getInstance().getConversationList({
                    onSuccess(list) { resolve(list || []); },
                    onError(err) {
                        console.warn('[WorkLog] getConversationList 失败:', err);
                        resolve([]);
                    },
                }, [1, 3], 50);
            } catch (e) {
                console.warn('[WorkLog] getConversationList 异常:', e);
                resolve([]);
            }
        });
    },

    _getConversationMessages(convType, targetId, count) {
        count = count || this._settings.maxMessagesPerConversation;
        return new Promise((resolve) => {
            try {
                const RongIMClient = window.RongIMLib && window.RongIMLib.RongIMClient;
                if (!RongIMClient) { resolve([]); return; }
                RongIMClient.getInstance().getHistoryMessages(
                    convType, targetId, 0, count,
                    {
                        onSuccess(list) { resolve(list || []); },
                        onError(err) {
                            // 尝试远程获取
                            RongIMClient.getInstance().getRemoteHistoryMessages(
                                convType, targetId, 0, count,
                                {
                                    onSuccess(list) { resolve(list || []); },
                                    onError() { resolve([]); },
                                }
                            );
                        },
                    }
                );
            } catch (e) { resolve([]); }
        });
    },

    _resolveUserName(userId, instance) {
        if (instance._userNameCache && instance._userNameCache.has(userId)) {
            return Promise.resolve(instance._userNameCache.get(userId));
        }
        return new Promise((resolve) => {
            try {
                const RongIM = window.RongIM;
                if (RongIM && RongIM.dataModel && RongIM.dataModel.User) {
                    RongIM.dataModel.User.get(userId, (err, user) => {
                        const name = (!err && user) ? (user.name || user.alias || userId) : userId;
                        if (instance._userNameCache) instance._userNameCache.set(userId, name);
                        resolve(name);
                    });
                } else { resolve(userId); }
            } catch (e) { resolve(userId); }
        });
    },

    _getConversationName(convType, targetId, instance) {
        const cacheKey = `conv_${convType}_${targetId}`;
        if (instance._userNameCache && instance._userNameCache.has(cacheKey)) {
            return Promise.resolve(instance._userNameCache.get(cacheKey));
        }

        // 单聊：解析用户名
        if (convType === 1) {
            return this._resolveUserName(targetId, instance);
        }

        // 群聊：统一使用"群聊会话"，不再尝试获取群名称以减少服务端压力
        if (convType === 3) {
            const name = '群聊会话';
            if (instance._userNameCache) instance._userNameCache.set(cacheKey, name);
            return Promise.resolve(name);
        }

        return Promise.resolve(targetId);
    },

    async _scanAndCollect(instance, targetDate, progressCallback) {
        if (instance._scanning) return;
        instance._scanning = true;

        try {
            const myUserId = this._getCurrentUserId();
            if (!myUserId) {
                console.warn('[WorkLog] 无法获取当前用户ID，跳过扫描');
                return;
            }
            instance._myUserId = myUserId;

            const scanDate = targetDate || this._getDateStr();
            const dayData = this._loadDayMessages(scanDate);
            const existingIds = new Set(dayData.messages.map(m => m.id));
            let newCount = 0;

            const conversations = await this._getConversationList();
            // 过滤出有效会话，最多遍历 100 个
            const allValid = conversations.filter(c => c.conversationType === 1 || c.conversationType === 3);
            const MAX_SCAN_CONVERSATIONS = 100;
            if (allValid.length > MAX_SCAN_CONVERSATIONS) {
                console.warn(`[WorkLog] 有效会话数 ${allValid.length} 超过上限，仅扫描前 ${MAX_SCAN_CONVERSATIONS} 个`);
            }
            const validConversations = allValid.slice(0, MAX_SCAN_CONVERSATIONS);
            const totalConversations = validConversations.length;
            let scannedConversations = 0;

            console.log(`[WorkLog] 扫描 ${totalConversations} 个会话...`);

            // 初始进度回调
            if (progressCallback) {
                progressCallback({ phase: 'scanning', scannedConversations: 0, totalConversations, totalMessages: dayData.messages.length, newMessages: 0 });
            }

            for (const conv of validConversations) {
                try {
                    const convType = conv.conversationType;
                    const targetId = conv.targetId;

                    const messages = await this._getConversationMessages(convType, targetId);
                    const targetName = await this._getConversationName(convType, targetId, instance);

                    for (const msg of messages) {
                        const msgId = msg.messageUId || `${msg.sentTime}_${msg.senderUserId}`;
                        if (existingIds.has(msgId)) continue;
                        if (!this._isMessageFromDate(msg.sentTime, scanDate)) continue;
                        if (!['TextMessage', 'ReferenceMessage'].includes(msg.messageType)) continue;

                        const isMine = msg.senderUserId === myUserId;
                        const isAtMe = this._isAtMe(msg, myUserId);

                        // 群聊只收集@我的和我发的
                        if (convType === 3 && !isMine && !isAtMe) continue;

                        let content = '';
                        if (msg.messageType === 'TextMessage') {
                            content = (msg.content && msg.content.content) || '';
                        } else if (msg.messageType === 'ReferenceMessage') {
                            content = (msg.content && msg.content.text) || '';
                        }
                        content = content.replace(/<[^>]+>/g, '').trim();
                        if (!content) continue;
                        // 单条消息超过 300 字符时裁剪
                        if (content.length > 300) {
                            content = content.substring(0, 300) + '...';
                        }

                        const senderName = await this._resolveUserName(msg.senderUserId, instance);

                        dayData.messages.push({
                            id: msgId,
                            time: msg.sentTime,
                            timeStr: new Date(msg.sentTime).toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
                            conversationType: convType,
                            targetId: targetId,
                            targetName: targetName,
                            sender: senderName,
                            senderId: msg.senderUserId,
                            content: content,
                            isMine: isMine,
                            isAtMe: isAtMe,
                        });
                        existingIds.add(msgId);
                        newCount++;
                    }
                } catch (e) {
                    console.warn(`[WorkLog] 扫描会话 ${conv.targetId} 失败:`, e);
                }

                scannedConversations++;
                // 实时进度回调
                if (progressCallback) {
                    progressCallback({ phase: 'scanning', scannedConversations, totalConversations, totalMessages: dayData.messages.length, newMessages: newCount });
                }
            }

            // 排序
            dayData.messages.sort((a, b) => a.time - b.time);
            dayData.lastScanTime = new Date().toISOString();
            dayData.stats = this._calculateStats(dayData.messages, myUserId);
            this._saveDayMessages(scanDate, dayData);

            console.log(`[WorkLog] ✅ 扫描完成，新增 ${newCount} 条，总计 ${dayData.messages.length} 条`);
        } catch (e) {
            console.error('[WorkLog] 扫描失败:', e);
            throw e;
        } finally {
            instance._scanning = false;
        }
    },

    // ======================== 构建消息文本（给 AI） ========================

    _buildMessageText(dayData) {
        const grouped = {};
        for (const msg of dayData.messages) {
            // 使用 targetName（群名称）作为分组 key，避免将群 ID 泄漏到发送给 API 的数据中
            const groupName = msg.targetName || (msg.conversationType === 3 ? '群聊会话' : msg.targetId);
            const key = `${msg.conversationType}_${groupName}`;
            if (!grouped[key]) {
                grouped[key] = {
                    type: msg.conversationType,
                    name: groupName,
                    messages: [],
                };
            }
            grouped[key].messages.push(msg);
        }

        const sections = [];
        for (const key of Object.keys(grouped)) {
            const group = grouped[key];
            const label = group.type === 1
                ? `=== 与「${group.name}」的私聊 ===`
                : `=== 群聊「${group.name}」中与我相关的消息 ===`;

            const lines = group.messages.map(m => {
                const prefix = m.isMine ? '我' : m.sender;
                const atTag = m.isAtMe ? '(@我)' : '';
                // 兜底裁剪：防止已缓存的旧长消息超过 300 字符
                let text = m.content || '';
                if (text.length > 300) {
                    text = text.substring(0, 300) + '...';
                }
                return `[${m.timeStr}] ${prefix}${atTag}: ${text}`;
            });

            sections.push(label + '\n' + lines.join('\n'));
        }
        return sections.join('\n\n');
    },



    // ======================== OA 日志提交 ========================

    // 带超时的 fetch 请求（用于 OA 接口）
    _fetchWithTimeout(url, options, timeoutMs) {
        const timeout = timeoutMs || this._settings.oaRequestTimeoutMs;
        const controller = new AbortController();
        const timer = setTimeout(() => controller.abort(), timeout);

        return fetch(url, { ...options, signal: controller.signal })
            .catch(err => {
                if (err.name === 'AbortError') {
                    throw new Error('OA 接口超时，系统响应较慢，请稍后再试');
                }
                throw err;
            })
            .finally(() => clearTimeout(timer));
    },

    // 从 localStorage 获取 OA access_token（与 now-playing 插件相同逻辑）
    _getOaAccessToken() {
        try {
            for (let i = 0; i < localStorage.length; i++) {
                const key = localStorage.key(i);
                if (key && key.includes('tokenname')) {
                    const raw = localStorage.getItem(key);
                    const parsed = JSON.parse(raw);
                    if (parsed && parsed.data && parsed.data.access_token) {
                        return parsed.data.access_token;
                    }
                }
            }
        } catch (e) {
            console.error('[WorkLog] ⚠️ 读取 OA token 失败:', e.message);
        }
        return null;
    },

    // 查询日志信息，获取 rzguid
    async _queryRzInfo(dateStr) {
        const token = this._getOaAccessToken();
        if (!token) throw new Error('未获取到 OA 登录令牌，请确保已登录 OA 系统');

        const url = `${this._settings.oaApiBaseUrl}/epoint-gateway/oaerp_v7/select_rzrelationinfo`;
        const params = JSON.stringify({ rzdate: dateStr, rzguid: '' });

        const response = await this._fetchWithTimeout(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Authorization': `Bearer ${token}`,
            },
            body: `params=${encodeURIComponent(params)}`,
        });

        if (!response.ok) throw new Error(`查询日志信息失败: HTTP ${response.status}`);
        const result = await response.json();

        if (!result.status || result.status.code !== 1) {
            throw new Error(`查询日志信息业务错误: ${result.status?.text || '未知'}`);
        }

        const rzinfo = result.custom?.rzinfo;
        if (!rzinfo || !rzinfo.length || !rzinfo[0].rzguid) {
            throw new Error('未获取到当日日志 rzguid');
        }

        return {
            rzguid: rzinfo[0].rzguid,
            rzdate: rzinfo[0].rzdate,
            status: rzinfo[0].status,
            existingDetails: result.custom?.rzdetail || [],
        };
    },

    // 提交工作日志
    async _submitWorkLogToOa(dateStr, rzguid, content) {
        const token = this._getOaAccessToken();
        if (!token) throw new Error('未获取到 OA 登录令牌');

        const url = `${this._settings.oaApiBaseUrl}/epoint-gateway/oaerp_v7/rz_insert_rzdetailv2`;
        const params = JSON.stringify({
            rzdate: dateStr,
            rzguid: rzguid,
            missionguid: '',
            missionname: '',
            gongzuosj: this._settings.defaultWorkHours,
            completepercent: this._settings.defaultCompletePercent,
            gongzuonr: content,
            contenttype: '02',
            gzdworktype: '0201',
            projectname: '',
            projectguid: '',
            lsrztype: '1',
            lsrztypesm: '',
        });

        const response = await this._fetchWithTimeout(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Authorization': `Bearer ${token}`,
            },
            body: `params=${encodeURIComponent(params)}`,
        });

        if (!response.ok) throw new Error(`提交日志失败: HTTP ${response.status}`);
        const result = await response.json();

        if (!result.status || result.status.code !== 1) {
            throw new Error(`提交日志业务错误: ${result.status?.text || '未知'}`);
        }

        return true;
    },

    // 打开提交确认弹窗
    _openSubmitModal(instance) {
        const dateStr = instance._viewDate || this._getDateStr();
        const summaryData = this._loadSummary(dateStr);

        if (!summaryData || !summaryData.summary) {
            this._showToast(instance, '❌ 暂无 AI 总结内容，请先生成总结', 'error');
            return;
        }

        // 移除已有 modal
        const existing = document.getElementById(this.SUBMIT_MODAL_ID);
        if (existing) existing.remove();

        const modal = document.createElement('div');
        modal.id = this.SUBMIT_MODAL_ID;
        modal.className = 'wl-modal-overlay';
        modal.innerHTML = `
            <div class="wl-modal">
                <div class="wl-modal-header">
                    <span class="wl-modal-title">📤 提交工作日志</span>
                    <button class="wl-modal-close" id="wl-modal-close">✕</button>
                </div>
                <div class="wl-modal-meta">
                    <span class="wl-modal-date">📅 ${this._formatDateLabel(dateStr)}</span>
                    <span class="wl-modal-hint">可在下方编辑内容后提交到 OA 系统</span>
                </div>
                <div class="wl-modal-body">
                    <textarea class="wl-modal-textarea" id="wl-modal-textarea">${this._escapeHtml(summaryData.summary)}</textarea>
                </div>
                <div class="wl-modal-footer">
                    <button class="wl-modal-btn cancel" id="wl-modal-cancel">取消</button>
                    <button class="wl-modal-btn confirm" id="wl-modal-confirm">📤 确认提交</button>
                </div>
            </div>
        `;

        document.body.appendChild(modal);

        // 动画入场
        requestAnimationFrame(() => modal.classList.add('wl-modal-visible'));

        const self = this;
        const closeModal = () => {
            modal.classList.remove('wl-modal-visible');
            setTimeout(() => modal.remove(), 200);
        };

        // 关闭
        modal.querySelector('#wl-modal-close').addEventListener('click', closeModal);
        modal.querySelector('#wl-modal-cancel').addEventListener('click', closeModal);
        modal.addEventListener('click', (e) => {
            if (e.target === modal) closeModal();
        });

        // 确认提交
        modal.querySelector('#wl-modal-confirm').addEventListener('click', async () => {
            const textarea = modal.querySelector('#wl-modal-textarea');
            const content = textarea.value.trim();
            if (!content) {
                self._showToast(instance, '❌ 日志内容不能为空', 'error');
                return;
            }

            const confirmBtn = modal.querySelector('#wl-modal-confirm');
            confirmBtn.disabled = true;
            confirmBtn.textContent = '⏳ 提交中...';

            try {
                // 1. 查询 rzguid
                const rzInfo = await self._queryRzInfo(dateStr);
                if (rzInfo.status === '已提交') {
                    self._showToast(instance, '⚠️ 当日日志已提交，无法重复提交', 'error');
                    confirmBtn.disabled = false;
                    confirmBtn.textContent = '📤 确认提交';
                    return;
                }

                // 2. 提交日志
                await self._submitWorkLogToOa(dateStr, rzInfo.rzguid, content);

                self._showToast(instance, '✅ 工作日志提交成功！', 'success');
                closeModal();
            } catch (e) {
                console.error('[WorkLog] 提交日志失败:', e);
                self._showToast(instance, `❌ 提交失败: ${e.message}`, 'error');
                confirmBtn.disabled = false;
                confirmBtn.textContent = '📤 确认提交';
            }
        });
    },

    // 轻量级 Toast 提示
    _showToast(instance, message, type) {
        const existing = document.querySelector('.wl-toast');
        if (existing) existing.remove();

        const toast = document.createElement('div');
        toast.className = `wl-toast wl-toast-${type || 'info'}`;
        toast.textContent = message;
        document.body.appendChild(toast);

        requestAnimationFrame(() => toast.classList.add('wl-toast-visible'));
        setTimeout(() => {
            toast.classList.remove('wl-toast-visible');
            setTimeout(() => toast.remove(), 300);
        }, 3000);
    },

    // ======================== 服务器通信 ========================

    _getServerUrl() {
        try {
            if (window.PluginManager && typeof window.PluginManager.getServerUrl === 'function') {
                return window.PluginManager.getServerUrl() || null;
            }
        } catch (e) { }
        return null;
    },

    async _requestAISummary(instance, dateStr) {
        const dayData = this._loadDayMessages(dateStr);
        if (!dayData.messages.length) {
            throw new Error('该日期没有收集到消息');
        }



        const rawMessages = this._buildMessageText(dayData);
        const stats = dayData.stats || this._calculateStats(dayData.messages, instance._myUserId);
        const serverUrl = this._getServerUrl();
        if (!serverUrl) {
            throw new Error('服务器地址未配置，请在插件管理中心→设置中配置');
        }

        const apiEndpoint = serverUrl.replace(/\/+$/, '') + this._settings.apiPath;
        console.log('[WorkLog] 请求AI总结:', apiEndpoint);

        const response = await fetch(apiEndpoint, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                ...(instance._myUserId ? { 'X-User-Id': instance._myUserId } : {}),
            },
            body: JSON.stringify({
                date: dateStr,
                rawMessages: rawMessages,
                messageCount: stats.totalMessages,
                conversationCount: stats.conversations,
            }),
        });

        if (!response.ok) {
            throw new Error(`AI接口返回错误: ${response.status} ${response.statusText}`);
        }

        const result = await response.json();
        const summary = result.summary || result.content || result.data?.summary || '';

        return summary;
    },

    // ======================== UI：样式管理 ========================

    _injectStyles() {
        if (document.getElementById(this.STYLE_ID)) return;
        try {
            const cssPath = path.join(__dirname, 'styles.css');
            const cssContent = fs.readFileSync(cssPath, 'utf-8');
            const style = document.createElement('style');
            style.id = this.STYLE_ID;
            style.textContent = cssContent;
            document.head.appendChild(style);
        } catch (e) {
            console.error('[WorkLog] 加载样式失败:', e);
        }
    },

    _removeStyles() {
        const el = document.getElementById(this.STYLE_ID);
        if (el) el.remove();
    },

    // ======================== UI：导航栏图标 ========================

    _getNavIconSvg(color) {
        return `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="${color}"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zM13 9V3.5L18.5 9H13z"/></svg>`;
    },

    _getNavIconBase64(color) {
        return btoa(this._getNavIconSvg(color));
    },

    _registerNavIcon(instance) {
        const CHECK_INTERVAL = 1000;
        const MAX_ATTEMPTS = 60;
        let attempts = 0;
        const self = this;

        const checkAndAddIcon = () => {
            if (document.getElementById(self.NAV_ICON_ID)) return;
            const navTab = document.querySelector('body > div.rong-im > div > div.rong-nav > ul.rong-nav-tab');
            if (!navTab) {
                attempts++;
                if (attempts < MAX_ATTEMPTS) setTimeout(checkAndAddIcon, CHECK_INTERVAL);
                return;
            }

            const navItem = document.createElement('li');
            navItem.id = self.NAV_ICON_ID;
            navItem.className = 'rong-nav-tab-item';
            navItem.style.position = 'relative';
            const iconColor = window.PluginTheme ? window.PluginTheme.getNavIconColor() : '#808CA4';
            navItem.innerHTML = `
                <em class="item-content" style="cursor: pointer;">
                    <span class="rong-nav-icon" style="background-image: url('data:image/svg+xml;base64,${self._getNavIconBase64(iconColor)}');"></span>
                    <span class="rong-nav-icon hover" style="background-image: url('data:image/svg+xml;base64,${self._getNavIconBase64('#3A6EE7')}');"></span>
                    <span class="rong-nav-text">工作日志</span>
                </em>
                <div class="wl-nav-badge"></div>
            `;

            navItem.addEventListener('click', (e) => {
                e.stopPropagation();
                self._togglePanel(instance);
            });

            const pluginNavIcon = document.getElementById('plugin-manager-nav-icon');
            if (pluginNavIcon && pluginNavIcon.nextSibling) {
                navTab.insertBefore(navItem, pluginNavIcon.nextSibling);
            } else {
                navTab.appendChild(navItem);
            }

            instance.navIcon = navItem;
            console.log('[WorkLog] ✅ 导航图标已添加');
        };

        checkAndAddIcon();
    },

    // ======================== UI：面板 ========================

    _createPanel(instance) {
        const panel = document.createElement('div');
        panel.id = this.PANEL_ID;

        panel.innerHTML = `
            <div class="wl-header">
                <div class="wl-header-left">
                    <span class="wl-header-icon">📝</span>
                    <span class="wl-header-title">工作日志</span>
                </div>
                <div class="wl-header-actions">
                    <button class="wl-header-btn" id="wl-close-btn" title="关闭">✕</button>
                </div>
            </div>
            <div class="wl-date-bar">
                <div class="wl-week-header">
                    <button class="wl-cal-nav" id="wl-week-prev" title="上一周">‹</button>
                    <span class="wl-cal-title" id="wl-week-title"></span>
                    <button class="wl-cal-nav" id="wl-week-next" title="下一周">›</button>
                </div>
                <div class="wl-cal-weekdays">
                    <span>日</span><span>一</span><span>二</span><span>三</span><span>四</span><span>五</span><span>六</span>
                </div>
                <div class="wl-week-days" id="wl-week-days"></div>
                <div class="wl-date-display" id="wl-date-display"></div>
            </div>
            <div class="wl-stats-bar" id="wl-stats-bar">
                <div class="wl-stat-item"><span class="wl-stat-value" id="wl-stat-total">0</span><span class="wl-stat-label">消息</span></div>
                <div class="wl-stat-item"><span class="wl-stat-value" id="wl-stat-conv">0</span><span class="wl-stat-label">会话</span></div>
                <div class="wl-stat-item"><span class="wl-stat-value" id="wl-stat-mine">0</span><span class="wl-stat-label">我发送</span></div>
            </div>
            <div class="wl-action-bar">
                <button class="wl-action-btn primary" id="wl-summary-btn">🤖 AI 总结</button>
                <button class="wl-action-btn submit" id="wl-submit-btn" title="提交日志到 OA">📤 提交</button>
                <button class="wl-action-btn secondary" id="wl-copy-btn" title="复制总结" style="flex:0 0 40px;">📋</button>
            </div>
            <div class="wl-tabs">
                <button class="wl-tab active" data-tab="summary">AI 总结</button>
                <button class="wl-tab" data-tab="messages">消息记录</button>
            </div>
            <div class="wl-content" id="wl-content"></div>
            <div class="wl-footer" id="wl-footer"></div>
        `;

        document.body.appendChild(panel);
        instance.panel = panel;
        this._bindPanelEvents(instance);
        return panel;
    },

    _bindPanelEvents(instance) {
        const panel = instance.panel;
        const self = this;

        // 关闭
        panel.querySelector('#wl-close-btn').addEventListener('click', () => {
            self._togglePanel(instance, false);
        });

        // 周导航
        panel.querySelector('#wl-week-prev').addEventListener('click', () => self._navigateWeek(instance, -1));
        panel.querySelector('#wl-week-next').addEventListener('click', () => self._navigateWeek(instance, 1));



        // AI 总结
        panel.querySelector('#wl-summary-btn').addEventListener('click', () => self._onSummaryClick(instance));

        // 提交日志
        panel.querySelector('#wl-submit-btn').addEventListener('click', () => self._openSubmitModal(instance));

        // 复制
        panel.querySelector('#wl-copy-btn').addEventListener('click', () => self._onCopyClick(instance));

        // Tab 切换
        panel.querySelectorAll('.wl-tab').forEach(tab => {
            tab.addEventListener('click', () => {
                panel.querySelectorAll('.wl-tab').forEach(t => t.classList.remove('active'));
                tab.classList.add('active');
                instance._activeTab = tab.dataset.tab;
                self._renderContent(instance);
            });
        });
    },

    _togglePanel(instance, forceState) {
        const panel = instance.panel;
        if (!panel) return;
        const targetState = typeof forceState === 'boolean' ? forceState : !instance.isOpen;
        instance.isOpen = targetState;

        if (targetState) {
            panel.classList.add('wl-visible');
            this._renderPanel(instance);
        } else {
            panel.classList.remove('wl-visible');
        }
    },

    _setupOutsideClick(instance) {
        const self = this;
        const handler = (e) => {
            if (!instance.isOpen) return;
            const panel = instance.panel;
            const navIcon = instance.navIcon;
            // 若点击目标已被重渲染从 DOM 中移除（如周视图重新生成），不视为外部点击
            if (!document.contains(e.target)) return;
            if (panel && !panel.contains(e.target) && navIcon && !navIcon.contains(e.target)) {
                self._togglePanel(instance, false);
            }
        };
        document.addEventListener('click', handler);
        instance._outsideClickHandler = handler;
    },

    // ======================== UI：渲染 ========================

    _renderPanel(instance) {
        const dateStr = instance._viewDate || this._getDateStr();

        // 渲染周日期选择器
        this._renderWeekPicker(instance);

        // 当前选中日期的可读标签
        instance.panel.querySelector('#wl-date-display').innerHTML = this._formatDateLabel(dateStr);

        // AI 总结按钮冷却状态
        this._updateSummaryBtnState(instance);

        // 加载数据
        const dayData = this._loadDayMessages(dateStr);
        const stats = dayData.stats || { totalMessages: 0, myMessages: 0, conversations: 0 };

        // 统计
        instance.panel.querySelector('#wl-stat-total').textContent = stats.totalMessages || 0;
        instance.panel.querySelector('#wl-stat-conv').textContent = stats.conversations || 0;
        instance.panel.querySelector('#wl-stat-mine').textContent = stats.myMessages || 0;

        // 底部
        const footer = instance.panel.querySelector('#wl-footer');
        if (dayData.lastScanTime) {
            const t = new Date(dayData.lastScanTime).toLocaleTimeString('zh-CN');
            footer.textContent = `上次收集: ${t}`;
        } else {
            footer.textContent = '尚未收集消息';
        }

        this._renderContent(instance);
    },

    _renderContent(instance) {
        const dateStr = instance._viewDate || this._getDateStr();
        const tab = instance._activeTab || 'summary';
        const content = instance.panel.querySelector('#wl-content');

        if (tab === 'summary') {
            this._renderSummaryTab(instance, content, dateStr);
        } else {
            this._renderMessagesTab(instance, content, dateStr);
        }
    },

    _renderSummaryTab(instance, container, dateStr) {
        const summaryData = this._loadSummary(dateStr);
        if (!summaryData) {
            container.innerHTML = `
                <div class="wl-empty">
                    <div class="wl-empty-icon">🤖</div>
                    <div class="wl-empty-text">尚未生成 AI 总结</div>
                    <div class="wl-empty-sub">先收集消息，再点击「AI 总结」按钮</div>
                </div>`;
            return;
        }
        const time = summaryData.generatedAt
            ? new Date(summaryData.generatedAt).toLocaleString('zh-CN')
            : '';
        container.innerHTML = `
            <div class="wl-summary-section">
                <div class="wl-summary-time">生成于 ${time}</div>
                ${this._formatSummary(summaryData.summary)}
            </div>`;
    },

    _renderMessagesTab(instance, container, dateStr) {
        const dayData = this._loadDayMessages(dateStr);
        if (!dayData.messages.length) {
            container.innerHTML = `
                <div class="wl-empty">
                    <div class="wl-empty-icon">📭</div>
                    <div class="wl-empty-text">暂无消息记录</div>
                    <div class="wl-empty-sub">点击「收集消息」获取今天的 IM 消息</div>
                </div>`;
            return;
        }

        // 按会话分组
        const grouped = {};
        for (const msg of dayData.messages) {
            const key = `${msg.conversationType}_${msg.targetId}`;
            if (!grouped[key]) {
                grouped[key] = { type: msg.conversationType, name: msg.targetName, messages: [] };
            }
            grouped[key].messages.push(msg);
        }

        let html = '';
        for (const key of Object.keys(grouped)) {
            const g = grouped[key];
            const label = g.type === 1 ? `💬 ${g.name}` : `👥 ${g.name}`;
            html += `<div class="wl-msg-group">`;
            html += `<div class="wl-msg-group-title">${this._escapeHtml(label)}（${g.messages.length} 条）</div>`;
            for (const m of g.messages) {
                const senderClass = m.isMine ? 'mine' : '';
                const senderLabel = m.isMine ? '我' : this._escapeHtml(m.sender);
                html += `<div class="wl-msg-item">
                    <span class="wl-msg-time">${m.timeStr}</span>
                    <span class="wl-msg-sender ${senderClass}">${senderLabel}</span>
                    <span class="wl-msg-text">${this._escapeHtml(m.content)}</span>
                </div>`;
            }
            html += `</div>`;
        }
        container.innerHTML = html;
    },

    // ======================== UI：操作按钮回调 ========================

    // ---- 冷却管理 ----

    _startCooldown(instance) {
        instance._lastSummaryTime = Date.now();
        this._updateSummaryBtnState(instance);

        // 启动倒计时更新
        if (instance._cooldownTimer) clearInterval(instance._cooldownTimer);
        instance._cooldownTimer = setInterval(() => {
            const remaining = this._getCooldownRemaining(instance);
            if (remaining <= 0) {
                clearInterval(instance._cooldownTimer);
                instance._cooldownTimer = null;
            }
            this._updateSummaryBtnState(instance);
        }, 1000);
    },

    _getCooldownRemaining(instance) {
        if (!instance._lastSummaryTime) return 0;
        const elapsed = Date.now() - instance._lastSummaryTime;
        return Math.max(0, this._settings.cooldownMs - elapsed);
    },

    _updateSummaryBtnState(instance) {
        const btn = instance.panel?.querySelector('#wl-summary-btn');
        if (!btn) return;
        const remaining = this._getCooldownRemaining(instance);
        if (remaining > 0 && !instance._summaryRunning) {
            const secs = Math.ceil(remaining / 1000);
            btn.disabled = false;
            btn.classList.add('wl-cooldown');
            btn.textContent = `⏳ ${secs}s 后可用`;
            btn.title = `为减少服务端压力，${secs} 秒后才能再次使用`;
        } else if (!instance._summaryRunning) {
            btn.disabled = false;
            btn.classList.remove('wl-cooldown');
            btn.textContent = '🤖 AI 总结';
            btn.title = '收集消息并生成 AI 工作日志总结';
        }
    },

    async _onSummaryClick(instance) {
        // 检查冷却
        const remaining = this._getCooldownRemaining(instance);
        if (remaining > 0) {
            console.log(`[WorkLog] 冷却中，还需 ${Math.ceil(remaining / 1000)} 秒`);
            // 在按钮上显示提示
            const btn = instance.panel?.querySelector('#wl-summary-btn');
            if (btn) {
                btn.textContent = '😅 稍后再点吧，服务器压力山大了';
                // 2 秒后恢复倒计时显示
                setTimeout(() => this._updateSummaryBtnState(instance), 2000);
            }
            return;
        }

        const dateStr = instance._viewDate || this._getDateStr();
        const btn = instance.panel.querySelector('#wl-summary-btn');
        const content = instance.panel.querySelector('#wl-content');

        // 确保显示总结 tab
        instance._activeTab = 'summary';
        instance.panel.querySelectorAll('.wl-tab').forEach(t => {
            t.classList.toggle('active', t.dataset.tab === 'summary');
        });

        instance._summaryRunning = true;
        btn.disabled = true;

        // ---- 阶段1：收集消息 ----
        btn.textContent = '⏳ 采集中...';
        content.innerHTML = `
            <div class="wl-loading">
                <div class="wl-spinner"></div>
                <div class="wl-loading-text">正在采集消息...</div>
                <div class="wl-progress-info" id="wl-progress-info">
                    <div class="wl-progress-row"><span class="wl-progress-label">会话进度</span><span class="wl-progress-value" id="wl-progress-conv">0 / 0</span></div>
                    <div class="wl-progress-bar-wrap"><div class="wl-progress-bar" id="wl-progress-bar" style="width:0%"></div></div>
                    <div class="wl-progress-row"><span class="wl-progress-label">已采集消息</span><span class="wl-progress-value" id="wl-progress-msg">0</span></div>
                    <div class="wl-progress-row"><span class="wl-progress-label">新增消息</span><span class="wl-progress-value" id="wl-progress-new">0</span></div>
                </div>
            </div>`;

        try {
            // 进度回调：实时更新UI
            const progressCallback = (progress) => {
                const convEl = content.querySelector('#wl-progress-conv');
                const barEl = content.querySelector('#wl-progress-bar');
                const msgEl = content.querySelector('#wl-progress-msg');
                const newEl = content.querySelector('#wl-progress-new');
                if (convEl) convEl.textContent = `${progress.scannedConversations} / ${progress.totalConversations}`;
                if (barEl) {
                    const pct = progress.totalConversations > 0 ? Math.round((progress.scannedConversations / progress.totalConversations) * 100) : 0;
                    barEl.style.width = pct + '%';
                }
                if (msgEl) msgEl.textContent = progress.totalMessages;
                if (newEl) newEl.textContent = progress.newMessages;
            };

            // 删除当天缓存文件，强制重新采集所有消息
            const cacheFile = this._getMessageLogPath(dateStr);
            if (cacheFile && fs.existsSync(cacheFile)) {
                try {
                    fs.unlinkSync(cacheFile);
                    console.log('[WorkLog] 已清除当天缓存，将重新采集');
                } catch (e) {
                    console.warn('[WorkLog] 清除缓存失败:', e);
                }
            }

            await this._scanAndCollect(instance, dateStr, progressCallback);

            // 更新统计
            this._renderPanel(instance);

            // 检查是否有消息可总结
            const dayData = this._loadDayMessages(dateStr);
            if (!dayData.messages.length) {
                content.innerHTML = `
                    <div class="wl-empty">
                        <div class="wl-empty-icon">📭</div>
                        <div class="wl-empty-text">暂无可总结的消息</div>
                        <div class="wl-empty-sub">当前日期没有采集到任何消息记录</div>
                    </div>`;
                return;
            }

            // ---- 阶段2：AI 总结 ----
            btn.textContent = '⏳ AI 总结中...';
            content.innerHTML = `
                <div class="wl-loading">
                    <div class="wl-spinner"></div>
                    <div class="wl-loading-text">正在进行 AI 总结...</div>
                    <div class="wl-loading-sub">已采集 ${dayData.stats?.conversations || 0} 个会话、${dayData.stats?.totalMessages || 0} 条消息，AI 正在分析中</div>
                </div>`;

            const summary = await this._requestAISummary(instance, dateStr);
            const summaryObj = {
                date: dateStr,
                generatedAt: new Date().toISOString(),
                summary: summary,
                messageCount: dayData.stats?.totalMessages || 0,
                conversationCount: dayData.stats?.conversations || 0,
            };
            this._saveSummary(dateStr, summaryObj);
            this._renderContent(instance);

        } catch (e) {
            console.error('[WorkLog] AI 总结失败:', e);
            content.innerHTML = `
                <div class="wl-error">
                    <div class="wl-error-icon">⚠️</div>
                    <div class="wl-error-text">总结失败</div>
                    <div class="wl-error-detail">${this._escapeHtml(e.message || '未知错误')}</div>
                    <button class="wl-retry-btn" id="wl-retry-btn">重试</button>
                </div>`;
            content.querySelector('#wl-retry-btn')?.addEventListener('click', () => {
                this._onSummaryClick(instance);
            });
        } finally {
            instance._summaryRunning = false;
            // 启动冷却
            this._startCooldown(instance);
        }
    },

    _onCopyClick(instance) {
        const dateStr = instance._viewDate || this._getDateStr();
        const summaryData = this._loadSummary(dateStr);
        const btn = instance.panel.querySelector('#wl-copy-btn');

        if (!summaryData || !summaryData.summary) {
            btn.textContent = '❌';
            setTimeout(() => { btn.textContent = '📋'; }, 1000);
            return;
        }

        try {
            const textarea = document.createElement('textarea');
            textarea.value = summaryData.summary;
            textarea.style.position = 'fixed';
            textarea.style.opacity = '0';
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand('copy');
            document.body.removeChild(textarea);

            btn.textContent = '✅';
            setTimeout(() => { btn.textContent = '📋'; }, 1500);
        } catch (e) {
            btn.textContent = '❌';
            setTimeout(() => { btn.textContent = '📋'; }, 1000);
        }
    },

    // ======================== 周日期选择器 ========================

    _getWeekStart(date) {
        const d = new Date(date);
        d.setDate(d.getDate() - d.getDay());
        d.setHours(0, 0, 0, 0);
        return d;
    },

    _getCachedDates() {
        const dir = this._getDataDir();
        const set = new Set();
        if (!dir) return set;
        try {
            const files = fs.readdirSync(dir);
            files.forEach(f => {
                const m = f.match(/^work-log(?:-summary)?-(\d{4}-\d{2}-\d{2})\.json$/);
                if (m) set.add(m[1]);
            });
        } catch (e) { }
        return set;
    },

    _renderWeekPicker(instance) {
        const panel = instance.panel;
        if (!panel) return;

        const weekStart = instance._weekStartDate || this._getWeekStart(new Date());
        instance._weekStartDate = weekStart;

        const todayStr = this._getDateStr();
        const oldestStr = this._getDateOffset(-(this.MAX_DAYS - 1));
        const selectedStr = instance._viewDate || todayStr;
        const cachedDates = this._getCachedDates();

        // 周标题
        const weekEnd = new Date(weekStart);
        weekEnd.setDate(weekEnd.getDate() + 6);
        let titleText = '';
        if (weekStart.getMonth() === weekEnd.getMonth()) {
            titleText = `${weekStart.getFullYear()}年${String(weekStart.getMonth() + 1).padStart(2, '0')}月`;
        } else {
            titleText = `${String(weekStart.getMonth() + 1).padStart(2, '0')}月 - ${String(weekEnd.getMonth() + 1).padStart(2, '0')}月`;
        }
        panel.querySelector('#wl-week-title').textContent = titleText;

        // 7 天单元格
        const daysContainer = panel.querySelector('#wl-week-days');
        let html = '';
        for (let i = 0; i < 7; i++) {
            const d = new Date(weekStart);
            d.setDate(d.getDate() + i);
            const dateStr = this._getDateStr(d);
            const isToday = dateStr === todayStr;
            const isSelected = dateStr === selectedStr;
            const isFuture = dateStr > todayStr;
            const isOutOfRange = dateStr < oldestStr;
            const hasData = cachedDates.has(dateStr);

            let cls = 'wl-cal-day';
            if (isToday) cls += ' wl-cal-day-today';
            if (isSelected) cls += ' wl-cal-day-selected';
            if (isFuture || isOutOfRange) cls += ' wl-cal-day-disabled';

            html += `<span class="${cls}" data-date="${dateStr}">${d.getDate()}${hasData ? '<i class="wl-cal-dot"></i>' : ''}</span>`;
        }
        daysContainer.innerHTML = html;

        // 上/下周按钮可用状态
        const prevWeekEnd = new Date(weekStart);
        prevWeekEnd.setDate(prevWeekEnd.getDate() - 1);
        panel.querySelector('#wl-week-prev').disabled = (this._getDateStr(prevWeekEnd) < oldestStr);
        const nextWeekStart = new Date(weekStart);
        nextWeekStart.setDate(nextWeekStart.getDate() + 7);
        panel.querySelector('#wl-week-next').disabled = (this._getDateStr(nextWeekStart) > todayStr);

        // 绑定点击
        const self = this;
        daysContainer.querySelectorAll('.wl-cal-day[data-date]').forEach(el => {
            if (el.classList.contains('wl-cal-day-disabled')) return;
            el.addEventListener('click', () => {
                instance._viewDate = el.dataset.date;
                self._renderPanel(instance);
            });
        });
    },

    _navigateWeek(instance, direction) {
        const weekStart = instance._weekStartDate || this._getWeekStart(new Date());
        const newStart = new Date(weekStart);
        newStart.setDate(newStart.getDate() + direction * 7);

        const todayStr = this._getDateStr();
        const oldestStr = this._getDateOffset(-(this.MAX_DAYS - 1));
        const newStartStr = this._getDateStr(newStart);
        const newEnd = new Date(newStart);
        newEnd.setDate(newEnd.getDate() + 6);
        const newEndStr = this._getDateStr(newEnd);

        // 越界保护
        if (direction < 0 && newEndStr < oldestStr) return;
        if (direction > 0 && newStartStr > todayStr) return;

        instance._weekStartDate = newStart;
        this._renderWeekPicker(instance);
    },

    // ======================== 工具方法 ========================

    _escapeHtml(text) {
        if (!text) return '';
        return String(text)
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;');
    },

    _formatSummary(summary) {
        if (!summary) return '<p style="color:#999;">暂无总结内容</p>';
        let text = summary
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');

        text = text.replace(/\n{3,}/g, '\n\n').trim();

        let html = text
            .replace(/^([\u{1F300}-\u{1F9FF}].*?)$/gmu, '<div class="wl-section-title">$1</div>')
            .replace(/^(\d+[\.、].*)$/gm, '<div class="wl-numbered-item">$1</div>')
            .replace(/^[-•]\s(.*)$/gm, '<div class="wl-sub-item">· $1</div>')
            .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');

        html = html.replace(/<\/div>\n+<div/g, '</div><div');
        html = html.replace(/\n\n/g, '<div class="wl-paragraph-gap"></div>');
        html = html.replace(/\n/g, '<br>');

        return `<div class="wl-summary-formatted">${html}</div>`;
    },

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

    async init(config, pluginManager) {
        console.log('[WorkLog] 🚀 初始化工作日志总结插件...');

        const instance = {
            config,
            isOpen: false,
            panel: null,
            navIcon: null,
            _viewDate: this._getDateStr(),
            _weekStartDate: this._getWeekStart(new Date()),
            _activeTab: 'summary',
            _scanning: false,
            _scanTimer: null,
            _outsideClickHandler: null,
            _userNameCache: new Map(),
            _myUserId: null,
            _lastSummaryTime: null,
            _cooldownTimer: null,
            _summaryRunning: false,
        };

        const self = this;
        const initDOM = () => {
            self._injectStyles();
            self._createPanel(instance);
            self._registerNavIcon(instance);
            self._setupOutsideClick(instance);

            // 清理旧数据
            self._cleanupOldData();

            console.log('[WorkLog] ✅ 插件已启动（手动触发模式）');
        };

        if (document.body) {
            initDOM();
        } else {
            const onReady = () => { initDOM(); document.removeEventListener('DOMContentLoaded', onReady); };
            document.addEventListener('DOMContentLoaded', onReady);
            setTimeout(() => { if (!instance.panel && document.body) initDOM(); }, 5000);
        }

        return instance;
    },

    async destroy(instance) {
        console.log('[WorkLog] 🔄 销毁工作日志总结插件...');

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

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

        if (instance._outsideClickHandler) {
            document.removeEventListener('click', instance._outsideClickHandler);
        }

        const navIcon = document.getElementById(this.NAV_ICON_ID);
        if (navIcon) navIcon.remove();

        if (instance.panel) instance.panel.remove();

        this._removeStyles();

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