const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const os = require('os');

/**
 * 正在听歌插件
 * 
 * 跨平台支持:
 *   macOS:   launchd → bridge.sh → media-control → now-playing.json → 读取更新
 *   Windows: PowerShell → Windows SMTC API → JSON → 读取更新
 * 
 * macOS 依赖安装: bash bridge.sh install
 * Windows 无需额外安装，开箱即用（需 Windows 10+）
 */
module.exports = {
    name: "正在听歌",
    description: "读取系统当前播放的歌曲并更新到个人状态（支持 macOS / Windows 10+）",
    version: "dev",
    author: "assist",
    defaultEnabled: false,

    // 内部默认值（不暴露给用户配置）
    DEFAULT_FORMAT: "🎵 正在听: {title} - {artist}",
    DEFAULT_POLL_INTERVAL: 5,
    DEFAULT_API_BASE_URL: "https://oa.epoint.com.cn",

    defaultConfig: {},

    AGENT_LABEL: 'com.assist.nowplaying',

    async init(config, pluginManager) {
        console.log("[NowPlaying] 🚀 初始化正在听歌插件...");

        const platform = process.platform; // 'win32' | 'darwin' | 'linux'
        console.log(`[NowPlaying] 📌 当前平台: ${platform}`);

        const cacheDir = path.join(__dirname, 'cache');
        if (!fs.existsSync(cacheDir)) {
            fs.mkdirSync(cacheDir, { recursive: true });
        }

        const instance = {
            config,
            platform,
            timer: null,
            lastSong: "",
            dataFile: path.join(cacheDir, 'now-playing.json'),
        };

        try {
            if (platform === 'win32') {
                await this.initWindows(instance);
            } else if (platform === 'darwin') {
                await this.initMacOS(instance);
            } else {
                const msg = `不支持的平台: ${platform}，目前仅支持 macOS 和 Windows`;
                console.error(`[NowPlaying] ❌ ${msg}`);
                return { success: false, message: msg };
            }
        } catch (error) {
            console.error("[NowPlaying] ⚠️ 初始化失败:", error.message);
            return { success: false, message: error.message };
        }

        console.log("[NowPlaying] ✅ 插件启动完成");
        return instance;
    },

    // ===== Windows 初始化 =====
    async initWindows(instance) {
        // 生成 SMTC PowerShell 脚本到 cache 目录
        instance.smtcScriptPath = path.join(__dirname, 'cache', 'smtc_reader.ps1');
        this.createSmtcScript(instance.smtcScriptPath, instance.dataFile);
        console.log("[NowPlaying] 📝 已生成 SMTC 读取脚本");

        // 首次执行验证 SMTC 可用
        try {
            this.execSmtcScript(instance);
            console.log("[NowPlaying] ✅ Windows SMTC 可用");
        } catch (e) {
            throw new Error(`Windows SMTC 不可用: ${e.message}<br><br>请确认系统为 Windows 10 及以上版本`);
        }

        // 开始轮询
        instance.timer = setInterval(() => {
            try {
                this.execSmtcScript(instance);
            } catch (e) {
                console.warn("[NowPlaying] ⚠️ SMTC 轮询执行失败:", e.message);
            }
            this.readNowPlaying(instance);
        }, this.DEFAULT_POLL_INTERVAL * 1000);

        // 立即读取一次
        this.readNowPlaying(instance);
    },

    // 生成 Windows SMTC 读取脚本
    createSmtcScript(scriptPath, outputPath) {
        const outputPathEscaped = outputPath.replace(/\\/g, '\\\\');
        const script = `
Add-Type -AssemblyName System.Runtime.WindowsRuntime

$null = [Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager, Windows.Media.Control, ContentType = WindowsRuntime]
$asyncOp = [Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager]::RequestAsync()
$null = [System.Reflection.Assembly]::LoadWithPartialName('System.Runtime.WindowsRuntime')

$asTaskMethods = [System.WindowsRuntimeSystemExtensions].GetMethods() | Where-Object {
    $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation\`1'
}
$asTask = $asTaskMethods[0]

$closedMethod = $asTask.MakeGenericMethod([Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager])
$task = $closedMethod.Invoke($null, @($asyncOp))
$task.Wait()
$mgr = $task.Result

$session = $mgr.GetCurrentSession()

$result = '{"title":"","artist":"","album":"","playing":false,"source":""}'

if ($null -ne $session) {
    $propsOp = $session.TryGetMediaPropertiesAsync()
    $closedMethod2 = $asTask.MakeGenericMethod([Windows.Media.Control.GlobalSystemMediaTransportControlsSessionMediaProperties])
    $task2 = $closedMethod2.Invoke($null, @($propsOp))
    $task2.Wait()
    $props = $task2.Result

    $info = $session.GetPlaybackInfo()

    $src = $session.SourceAppUserModelId
    $ttl = $props.Title
    $art = $props.Artist
    $alb = $props.AlbumTitle
    $sts = $info.PlaybackStatus.ToString()
    $playing = if ($sts -eq 'Playing') { 'true' } else { 'false' }

    # 转义 JSON 特殊字符
    $ttl = $ttl -replace '\\\\', '\\\\\\\\' -replace '"', '\\\\"'
    $art = $art -replace '\\\\', '\\\\\\\\' -replace '"', '\\\\"'
    $alb = $alb -replace '\\\\', '\\\\\\\\' -replace '"', '\\\\"'
    $src = $src -replace '\\\\', '\\\\\\\\' -replace '"', '\\\\"'

    $result = '{"title":"' + $ttl + '","artist":"' + $art + '","album":"' + $alb + '","playing":' + $playing + ',"source":"' + $src + '"}'
}

[System.IO.File]::WriteAllText("${outputPathEscaped}", $result, (New-Object System.Text.UTF8Encoding $false))
`;
        fs.writeFileSync(scriptPath, script, 'utf-8');
    },

    // 执行 SMTC 脚本
    execSmtcScript(instance) {
        execSync(
            `powershell -NoProfile -ExecutionPolicy Bypass -File "${instance.smtcScriptPath}"`,
            { timeout: 8000, stdio: 'pipe', windowsHide: true }
        );
    },

    // ===== macOS 初始化 =====
    async initMacOS(instance) {
        instance.bridgePath = path.join(__dirname, 'bridge.sh');
        instance.plistPath = path.join(
            process.env.HOME, 'Library', 'LaunchAgents', 'com.assist.nowplaying.plist'
        );

        if (!fs.existsSync(instance.bridgePath)) {
            const installCmd = `bash "${instance.bridgePath}" install`;
            throw new Error(`中间件脚本不存在: ${instance.bridgePath}<br><br>请在终端中执行以下命令安装依赖：<code>${installCmd}</code>`);
        }

        // 安装并启动 LaunchAgent
        this.installLaunchAgent(instance);

        // 等待首次数据生成
        await this.waitForData(instance.dataFile, 5000);

        // 开始轮询读取
        instance.timer = setInterval(() => this.readNowPlaying(instance), this.DEFAULT_POLL_INTERVAL * 1000);
        this.readNowPlaying(instance);
    },

    // 安装 LaunchAgent，让 launchd 定期执行 bridge.sh
    installLaunchAgent(instance) {
        // 先卸载旧的
        this.uninstallLaunchAgent(instance);

        const interval = this.DEFAULT_POLL_INTERVAL;
        const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>${this.AGENT_LABEL}</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>${instance.bridgePath}</string>
    </array>
    <key>StartInterval</key>
    <integer>${interval}</integer>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>/tmp/nowplaying-bridge-err.log</string>
</dict>
</plist>`;

        // 确保 LaunchAgents 目录存在
        const launchAgentsDir = path.dirname(instance.plistPath);
        if (!fs.existsSync(launchAgentsDir)) {
            fs.mkdirSync(launchAgentsDir, { recursive: true });
        }

        // 写入 plist
        fs.writeFileSync(instance.plistPath, plistContent, 'utf-8');
        console.log(`[NowPlaying] 📝 已写入 LaunchAgent: ${instance.plistPath}`);

        // 加载 LaunchAgent
        try {
            execSync(`launchctl load "${instance.plistPath}"`, { stdio: 'pipe' });
            console.log("[NowPlaying] ✅ LaunchAgent 已加载");
        } catch (e) {
            throw new Error(`LaunchAgent 加载失败: ${e.message}`);
        }
    },

    // 卸载 LaunchAgent
    uninstallLaunchAgent(instance) {
        if (!instance.plistPath) return;
        try {
            execSync(`launchctl unload "${instance.plistPath}" 2>/dev/null`, { stdio: 'pipe' });
        } catch (e) {
            // 忽略，可能未加载
        }
        try {
            fs.unlinkSync(instance.plistPath);
        } catch (e) {
            // 忽略
        }
    },

    // 等待数据文件生成 (macOS)
    // 注意: media-control 没有播放内容时输出 "null"，也是有效响应
    waitForData(dataFile, timeoutMs) {
        return new Promise((resolve, reject) => {
            const startTime = Date.now();
            const check = () => {
                if (fs.existsSync(dataFile)) {
                    const content = fs.readFileSync(dataFile, 'utf-8').trim();
                    // 接受 JSON 对象或 "null"（无播放内容）作为有效数据
                    if (content && (content.startsWith('{') || content === 'null')) {
                        resolve();
                        return;
                    }
                }
                if (Date.now() - startTime > timeoutMs) {
                    const installCmd = `bash "${path.join(__dirname, 'bridge.sh')}" install`;
                    reject(new Error(`media-control 未安装或 LaunchAgent 启动超时。<br><br>请先在终端中执行以下命令安装依赖：<code>${installCmd}</code>`));
                } else {
                    setTimeout(check, 500);
                }
            };
            check();
        });
    },

    // ===== 通用: 读取播放状态文件 (macOS/Windows 共用) =====
    readNowPlaying(instance) {
        try {
            if (!fs.existsSync(instance.dataFile)) return;

            let content = fs.readFileSync(instance.dataFile, 'utf-8');
            // 去除可能的 BOM 标记
            content = content.replace(/^\uFEFF/, '').trim();
            // media-control 无播放内容时输出 "null"，视为无播放
            if (!content || content === 'null' || !content.startsWith('{')) return;

            const info = JSON.parse(content);
            const { title, artist, playing } = info;

            if (playing && title) {
                const songInfo = `${title} ${artist ? '- ' + artist : ''}`.trim();
                if (songInfo !== instance.lastSong) {
                    console.log(`[NowPlaying] 🎵 正在播放: ${songInfo}`);
                    instance.lastSong = songInfo;
                    this.updateStatus(title, artist || "", instance.config);
                }
            } else {
                if (instance.lastSong) {
                    console.log(`[NowPlaying] ⏸️ 播放已停止 (上一首: ${instance.lastSong})`);
                    instance.lastSong = "";
                    this.updateStatus("", "", instance.config);
                }
            }
        } catch (e) {
            console.warn("[NowPlaying] ⚠️ 读取播放信息失败:", e.message);
        }
    },

    // ===== API 对接 =====

    // 从 localStorage 获取 access_token
    // key 格式类似 "ik1qhwwyj5r3ptokenname"，包含 "tokenname"
    getAccessToken() {
        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("[NowPlaying] ⚠️ 读取 token 失败:", e.message);
        }
        return null;
    },

    // 获取 API base URL
    getBaseUrl() {
        return this.DEFAULT_API_BASE_URL;
    },

    // 构建请求头
    buildHeaders() {
        const token = this.getAccessToken();
        if (!token) {
            console.warn("[NowPlaying] ⚠️ 未获取到 access_token，无法调用 API");
            return null;
        }
        return {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/x-www-form-urlencoded'
        };
    },

    // 查询状态列表
    async listStatus() {
        const headers = this.buildHeaders();
        if (!headers) return [];
        const baseUrl = this.getBaseUrl();

        try {
            const response = await fetch(`${baseUrl}/950soa/rest/frame/list_personal_status_v8`, {
                method: 'POST',
                headers
            });
            const result = await response.json();
            if (result && result.status && result.status.code === 1 && result.custom) {
                return result.custom.statuslist || [];
            }
        } catch (e) {
            console.error("[NowPlaying] ⚠️ 查询状态列表失败:", e.message);
        }
        return [];
    },

    // 保存状态（新增或更新）
    async saveStatus(params) {
        const headers = this.buildHeaders();
        if (!headers) return false;
        const baseUrl = this.getBaseUrl();

        try {
            const body = `params=${encodeURIComponent(JSON.stringify(params))}`;
            const response = await fetch(`${baseUrl}/950soa/rest/frame/save_personal_status_v8`, {
                method: 'POST',
                headers,
                body
            });
            const result = await response.json();
            return result && result.status && result.status.code === 1;
        } catch (e) {
            console.error("[NowPlaying] ⚠️ 保存状态失败:", e.message);
            return false;
        }
    },

    // 删除状态
    async deleteStatus(statusid) {
        const headers = this.buildHeaders();
        if (!headers) return false;
        const baseUrl = this.getBaseUrl();

        try {
            const body = `params=${encodeURIComponent(JSON.stringify({ statusid }))}`;
            const response = await fetch(`${baseUrl}/950soa/rest/frame/delete_personal_status_v8`, {
                method: 'POST',
                headers,
                body
            });
            const result = await response.json();
            return result && result.status && result.status.code === 1;
        } catch (e) {
            console.error("[NowPlaying] ⚠️ 删除状态失败:", e.message);
            return false;
        }
    },

    // 更新用户当前状态（激活某个 statusid）
    async setCurrentStatus(statusid) {
        const headers = this.buildHeaders();
        if (!headers) return false;
        const baseUrl = this.getBaseUrl();

        try {
            const body = `params=${encodeURIComponent(JSON.stringify({ statusid }))}`;
            const response = await fetch(`${baseUrl}/950soa/rest/frame/set_current_status_v8`, {
                method: 'POST',
                headers,
                body
            });
            const result = await response.json();
            return result && result.status && result.status.code === 1;
        } catch (e) {
            console.error("[NowPlaying] ⚠️ 设置当前状态失败:", e.message);
            return false;
        }
    },

    // 控制状态文本长度不超过 maxLen 个字符
    // 策略: 超长时先去掉歌手名，仍超长则截取歌曲名并加 "..."
    truncateStatusText(title, artist, format, maxLen = 30) {
        // 先尝试完整格式
        let text = format.replace('{title}', title).replace('{artist}', artist || '未知歌手');
        if (text.length <= maxLen) return text;

        // 超长: 去掉歌手，只保留歌曲名
        text = format.replace('{title}', title).replace(' - {artist}', '').replace('- {artist}', '').replace('{artist}', '');
        if (text.length <= maxLen) return text;

        // 仍然超长: 截取歌曲名
        const prefix = format.split('{title}')[0] || '';  // 如 "🎵 正在听: "
        const maxTitleLen = maxLen - prefix.length - 3;    // 留 3 个字符给 "..."
        if (maxTitleLen > 0) {
            return prefix + title.substring(0, maxTitleLen) + '...';
        }
        return text.substring(0, maxLen);
    },

    // 更新 IM 状态（核心逻辑）
    async updateStatus(title, artist, config) {
        // 停止播放时，删除"正在听"状态
        if (!title) {
            console.log("[NowPlaying] 🔄 停止播放，尝试删除听歌状态...");
            const statusList = await this.listStatus();
            const nowPlayingStatus = statusList.find(s => s.statusname && s.statusname.startsWith('🎵'));
            if (nowPlayingStatus) {
                const ok = await this.deleteStatus(nowPlayingStatus.statusid);
                console.log(ok
                    ? `[NowPlaying] ✅ 已删除听歌状态: ${nowPlayingStatus.statusname}`
                    : `[NowPlaying] ❌ 删除听歌状态失败`
                );
            }
            return;
        }

        // 生成状态文本（控制在 30 字符内）
        const statusText = this.truncateStatusText(title, artist, this.DEFAULT_FORMAT, 30);
        console.log(`[NowPlaying] 🔄 更新状态为: ${statusText} (${statusText.length}字)`);

        // 查询现有状态列表，查找是否已有"🎵"开头的状态
        const statusList = await this.listStatus();
        const existingStatus = statusList.find(s => s.statusname && s.statusname.startsWith('🎵'));

        let statusid = null;

        if (existingStatus) {
            // 已有听歌状态 → 更新
            const params = {
                statusid: existingStatus.statusid,
                replies: existingStatus.replies || [],
                replyselectedid: existingStatus.replyselectedid || "null",
                isnodisturb: existingStatus.isnodisturb || false,
                statusname: statusText,
                statusicon: existingStatus.statusicon || "status-default",
                belongtype: existingStatus.belongtype || "user",
                isSingle: true
            };
            const ok = await this.saveStatus(params);
            if (ok) {
                statusid = existingStatus.statusid;
                console.log(`[NowPlaying] ✅ 已更新状态: ${statusText}`);
            } else {
                console.log(`[NowPlaying] ❌ 更新状态失败`);
            }
        } else {
            // 无听歌状态 → 新增
            const params = {
                statusname: statusText,
                isnodisturb: false
            };
            const ok = await this.saveStatus(params);
            if (ok) {
                // 新增后重新查询获取 statusid
                const updatedList = await this.listStatus();
                const newStatus = updatedList.find(s => s.statusname === statusText);
                if (newStatus) statusid = newStatus.statusid;
                console.log(`[NowPlaying] ✅ 已新增状态: ${statusText}`);
            } else {
                console.log(`[NowPlaying] ❌ 新增状态失败`);
            }
        }

        // 激活该状态为当前状态
        if (statusid) {
            const setOk = await this.setCurrentStatus(statusid);
            console.log(setOk
                ? `[NowPlaying] ✅ 已设置为当前状态`
                : `[NowPlaying] ❌ 设置当前状态失败`
            );
        }
    },

    async destroy(instance) {
        console.log("[NowPlaying] 🔄 销毁插件中...");

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

        // 删除听歌状态
        try {
            const statusList = await this.listStatus();
            const nowPlayingStatus = statusList.find(s => s.statusname && s.statusname.startsWith('🎵'));
            if (nowPlayingStatus) {
                await this.deleteStatus(nowPlayingStatus.statusid);
                console.log("[NowPlaying] 🧹 已清理听歌状态");
            }
        } catch (e) { }

        // 平台特定清理
        if (instance.platform === 'darwin') {
            this.uninstallLaunchAgent(instance);
        }
        if (instance.platform === 'win32' && instance.smtcScriptPath) {
            try { fs.unlinkSync(instance.smtcScriptPath); } catch (e) { }
        }

        // 清理数据文件
        try { fs.unlinkSync(instance.dataFile); } catch (e) { }

        console.log("[NowPlaying] ✅ 插件已完全清理");
    }
};
