/*! 
  * @name 全豆要[聚合音源] v12智谱版
 * @description 整合ikun、聚合API、长青SVIP、念心SVIP等多源，支持自动回退 
 * @version v12.0 
 * @author 整合自社区开源音源 
 */ 

// --- 常量定义 ---
const CACHE_TTL_MS = 21600000; // 6小时缓存
const CACHE_MAX_SIZE = 500;
const HTTP_URL_REGEX = /^https?:\/\//i;

// API 端点
const IKUN_API_URL = "https://c.wwwweb.top";
const AGGREGATE_API_URL = "https://api.music.lerd.dpdns.org";

// 长青SVIP URL模板
const CHANGQING_URL_TEMPLATES = {
    tx: "http://175.27.166.236/kgqq/qq.php?type=mp3&id={id}&level={level}",
    wy: "http://175.27.166.236/wy/wy.php?type=mp3&id={id}&level={level}",
    kw: "https://musicapi.haitangw.net/music/kw.php?type=mp3&id={id}&level={level}",
    kg: "https://music.haitangw.cc/kgqq/kg.php?type=mp3&id={id}&level={level}",
    mg: "https://music.haitangw.cc/musicapi/mg.php?type=mp3&id={id}&level={level}"
};

// 念心SVIP URL模板
const NIANXIN_URL_TEMPLATES = {
    tx: "https://music.nxinxz.com/kgqq/tx.php?id={id}&level={level}&type=mp3",
    wy: "http://music.nxinxz.com/wy.php?id={id}&level={level}&type=mp3",
    kw: "http://music.nxinxz.com/kw.php?id={id}&level={level}&type=mp3",
    kg: "http://music.nxinxz.com/kgqq/kg.php?id={id}&level={level}&type=mp3",
    mg: "http://music.nxinxz.com/mg.php?id={id}&level={level}&type=mp3"
};

// 各平台支持的音质列表
const PLATFORM_QUALITIES = {
    wy: ["24bit", "flac", "320k", "192k", "128k"],
    tx: ["24bit", "flac", "320k", "192k", "128k"],
    kw: ["24bit", "flac", "320k", "192k", "128k"],
    kg: ["24bit", "flac", "320k", "192k", "128k"],
    mg: ["24bit", "flac", "320k", "192k", "128k"]
};

// 高品质音质集合
const HIRES_QUALITY_SET = new Set(["24bit", "flac", "flac24bit", "hires", "master", "atmos"]);

// URL缓存
const urlCache = new Map();

const { EVENT_NAMES, request, on, send, utils, env, version } = globalThis.lx;

// --- 工具函数 ---

// 发起HTTP请求
function httpRequest(url, options = { method: "GET" }) {
    return new Promise((resolve, reject) => {
        request(url, { timeout: 5000, ...options }, (err, res) => {
            if (err) return reject(new Error("请求错误: " + err.message));
            let body = res?.body;
            if (typeof body === "string") {
                try { body = JSON.parse(body); } catch (e) {}
            }
            resolve({ statusCode: res?.statusCode ?? 0, headers: res?.headers || {}, body: body });
        });
    });
}

// 发起GET请求
async function httpGet(url, params = {}) {
    const queryStr = Object.keys(params)
        .filter(k => params[k] !== undefined && params[k] !== null)
        .map(k => encodeURIComponent(k) + "=" + encodeURIComponent(params[k]))
        .join("&");
    const sep = url.includes("?") ? "&" : "?";
    const fullUrl = url + (queryStr ? sep + queryStr : "");
    const res = await httpRequest(fullUrl, { method: "GET", timeout: 5000 });
    if (res.statusCode >= 400) throw new Error("HTTP错误: " + res.statusCode);
    return res.body;
}

// 发起POST请求
async function httpPost(url, body = {}, timeout = 5000) {
    const res = await httpRequest(url, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: body,
        timeout: timeout
    });
    if (res.statusCode >= 400) throw new Error("HTTP错误: " + res.statusCode);
    return res.body;
}

// 获取歌曲ID
function getSongId(songInfo) {
    return (songInfo?.id || songInfo?.songmid || songInfo?.songId || songInfo?.hash || songInfo?.rid || songInfo?.mid || songInfo?.strMediaMid || songInfo?.mediaId || "").toString();
}

// 获取平台对应的歌曲ID
function getPlatformSongId(platform, songInfo) {
    if (platform === "kg") return songInfo?.hash || songInfo?.songmid || songInfo?.id || songInfo?.rid || songInfo?.mid || null;
    if (platform === "tx") {
        const mid = songInfo?.meta?.qq?.mid || songInfo?.meta?.mid || songInfo?.songmid || (typeof songInfo?.id === "string" && !/^\d+$/.test(songInfo.id) ? songInfo.id : null);
        if (mid) return mid;
        const songid = songInfo?.meta?.qq?.songid || songInfo?.meta?.songid || (typeof songInfo?.id === "number" ? songInfo.id : (typeof songInfo?.id === "string" && /^\d+$/.test(songInfo.id) ? Number(songInfo.id) : null));
        if (songid) return songid;
        return null;
    }
    return songInfo?.songmid || songInfo?.id || songInfo?.songId || songInfo?.rid || songInfo?.hash || null;
}

// 选择最接近的音质
function selectQuality(requestedQuality, supportedQualities) {
    if (requestedQuality === "24bit") return "24bit";
    const qualityList = Array.isArray(supportedQualities) ? supportedQualities : ["128k"];
    const normalized = String(requestedQuality || "128k").toLowerCase();
    if (qualityList.includes(normalized)) return normalized;
    
    const qualityOrder = ["flac24bit", "flac", "320k", "192k", "128k"];
    let idx = qualityOrder.indexOf(normalized);
    if (idx < 0) idx = qualityOrder.length - 1;
    
    for (let i = idx; i < qualityOrder.length; i++) {
        if (qualityList.includes(qualityOrder[i])) return qualityOrder[i];
    }
    for (let i = qualityOrder.length - 1; i >= 0; i--) {
        if (qualityList.includes(qualityOrder[i])) return qualityOrder[i];
    }
    return qualityList[0] || "128k";
}

// 音质转换为通用格式
function qualityToNetease(quality) {
    const q = String(quality || "128k").toLowerCase();
    if (q === "flac" || q === "flac24bit" || q === "hires" || q === "master" || q === "atmos") return "lossless";
    if (q === "320k" || q === "192k") return "exhigh";
    return "standard";
}

// 构建模板URL
function buildTemplateUrl(platform, quality, songInfo, templates, sourceName) {
    const template = templates[platform];
    if (!template) throw new Error(sourceName + "不支持该平台");
    
    const songId = getPlatformSongId(platform, songInfo);
    if (!songId) throw new Error(sourceName + "缺少songId");
    
    const level = qualityToNetease(quality);
    return template
        .replace("{id}", encodeURIComponent(String(songId)))
        .replace("{level}", encodeURIComponent(level));
}

// 构建缓存键
function buildCacheKey(prefix, songInfo, quality = "") {
    const name = songInfo?.name || "";
    const singer = songInfo?.singer || "";
    const album = songInfo?.albumName || songInfo?.album || "";
    return prefix + "_" + name + "_" + singer + "_" + album + "_" + quality;
}

// 从缓存中获取URL
function getCachedUrl(cacheKey) {
    const entry = urlCache.get(cacheKey);
    if (!entry) return null;
    if (Date.now() - entry.timestamp >= CACHE_TTL_MS) {
        urlCache.delete(cacheKey);
        return null;
    }
    return entry.url;
}

// 将URL写入缓存
function setCachedUrl(cacheKey, url) {
    urlCache.set(cacheKey, { url: url, timestamp: Date.now() });
    if (urlCache.size > CACHE_MAX_SIZE) {
        const oldestKey = urlCache.keys().next().value;
        if (oldestKey !== undefined) urlCache.delete(oldestKey);
    }
}

// 验证URL合法性
function validateUrl(url, sourceName) {
    if (!url || typeof url !== "string") throw new Error(sourceName + "返回空URL");
    if (!HTTP_URL_REGEX.test(url.trim())) throw new Error(sourceName + "非法URL格式");
    return url;
}

// --- 音源获取函数 ---

// ikun音源获取URL
async function ikunGetUrl(platform, songId, quality, songInfo) {
    const id = songInfo?.hash ?? songInfo?.songmid;
    if (!id) throw new Error("ikun缺少歌曲ID");
    
    const res = await httpPost(`${IKUN_API_URL}/music/url`, {
        source: platform,
        musicId: id,
        quality: quality
    });
    
    if (!res || isNaN(Number(res.code))) throw new Error("ikun unknow error");
    
    switch (res.code) {
        case 200: return res.url;
        case 403: throw new Error("ikun 鉴权失败");
        case 429: throw new Error("ikun 请求过速");
        case 500: throw new Error("ikun 获取URL失败, " + (res.message || "未知错误"));
        default: throw new Error(res.message || "ikun 未知错误");
    }
}

// 聚合API获取URL
async function aggregateApiGetUrl(platform, songId, quality, songInfo) {
    const res = await httpPost(`${AGGREGATE_API_URL}/${platform}`, {
        musicInfo: songInfo,
        type: quality
    });
    
    if (res.code === 200) return res.data.url;
    else if (res.code === 303) {
        // 处理重定向逻辑
        try {
            const requestData = JSON.parse(JSON.stringify(res.data));
            const requestConfig = requestData.request;
            const responseConfig = requestData.response;
            
            const followRes = await httpRequest(encodeURI(requestConfig.url), requestConfig.options);
            
            let value = responseConfig.check.key.reduce((a, c) => a && a[c], followRes);
            if (value === responseConfig.check.value) {
                const url = responseConfig.url.reduce((a, c) => a && a[c], followRes);
                if (url && url.startsWith("http")) return url;
            }
        } catch (e) {}
        throw new Error("聚合API重定向处理失败");
    } else {
        throw new Error(res.msg || "聚合API请求失败");
    }
}

// 长青SVIP获取URL
async function changqingGetUrl(platform, songId, quality, songInfo) {
    const cacheKey = buildCacheKey("changqing", songInfo, quality);
    const cached = getCachedUrl(cacheKey);
    if (cached) return cached;
    
    const url = buildTemplateUrl(platform, quality, songInfo, CHANGQING_URL_TEMPLATES, "长青SVIP");
    const result = validateUrl(url, "长青SVIP");
    setCachedUrl(cacheKey, result);
    return result;
}

// 念心SVIP获取URL
async function nianxinGetUrl(platform, songId, quality, songInfo) {
    const cacheKey = buildCacheKey("nianxin", songInfo, quality);
    const cached = getCachedUrl(cacheKey);
    if (cached) return cached;
    
    const url = buildTemplateUrl(platform, quality, songInfo, NIANXIN_URL_TEMPLATES, "念心SVIP");
    const result = validateUrl(url, "念心SVIP");
    setCachedUrl(cacheKey, result);
    return result;
}

// --- 音源处理器注册表 ---
const SOURCE_HANDLERS = {
    ikun: { name: "ikun音源", fn: ikunGetUrl },
    aggregate: { name: "聚合API", fn: aggregateApiGetUrl },
    changqingVip: { name: "长青SVIP", fn: changqingGetUrl },
    nianxinVip: { name: "念心SVIP", fn: nianxinGetUrl }
};

// --- 构建音源链 ---
function buildSourceChain(platform, isHires, quality) {
    const chain = [];
    
    // 优先使用模板类音源（长青、念心）
    if (SOURCE_HANDLERS.changqingVip) chain.push(SOURCE_HANDLERS.changqingVip);
    if (SOURCE_HANDLERS.nianxinVip) chain.push(SOURCE_HANDLERS.nianxinVip);
    
    // 然后使用API类音源
    if (SOURCE_HANDLERS.ikun) chain.push(SOURCE_HANDLERS.ikun);
    if (SOURCE_HANDLERS.aggregate) chain.push(SOURCE_HANDLERS.aggregate);
    
    return chain;
}

// --- 带fallback获取URL ---
async function getUrlWithFallback(platform, songInfo, quality) {
    if (!platform || typeof platform !== "string" || !PLATFORM_QUALITIES[platform]) {
        throw new Error("无效的平台参数");
    }
    if (!songInfo || typeof songInfo !== "object") {
        throw new Error("无效的歌曲信息");
    }
    
    const resolvedQuality = quality || "128k";
    const selectedQuality = selectQuality(resolvedQuality, PLATFORM_QUALITIES[platform]);
    const songId = getSongId(songInfo);
    const isHires = HIRES_QUALITY_SET.has(resolvedQuality.toLowerCase());
    const chain = buildSourceChain(platform, isHires, selectedQuality);
    
    if (!chain.length) throw new Error("未找到可用fallback链");
    
    const errors = [];
    
    // 并发尝试前2个源
    try {
        const url = await Promise.any(chain.slice(0, 2).map(async handler => {
            const result = await handler.fn(platform, songId, selectedQuality, songInfo);
            return validateUrl(result, handler.name);
        }));
        if (url) return url;
    } catch (e) {
        if (e.errors) {
            e.errors.forEach(err => errors.push(err.message));
        }
    }
    
    // 顺序尝试剩余源
    for (const handler of chain.slice(2)) {
        try {
            const result = await handler.fn(platform, songId, selectedQuality, songInfo);
            return validateUrl(result, handler.name);
        } catch (e) {
            errors.push(handler.name + ": " + e.message);
            continue;
        }
    }
    
    throw new Error("所有源均失败: " + errors.join("; "));
}

// --- 音源配置与注册 ---
const sourceConfig = {};
const PLATFORM_NAMES = {
    wy: "网易云音乐",
    tx: "QQ音乐",
    kw: "酷我音乐",
    kg: "酷狗音乐",
    mg: "咪咕音乐"
};

Object.keys(PLATFORM_QUALITIES).forEach(platform => {
    sourceConfig[platform] = {
        name: PLATFORM_NAMES[platform],
        type: "music",
        actions: ["musicUrl"],
        qualitys: PLATFORM_QUALITIES[platform]
    };
});

// --- 事件监听 ---
on(EVENT_NAMES.request, ({ action, source, info }) => {
    if (action !== "musicUrl") {
        return Promise.reject(new Error("action not support"));
    }
    if (!info?.musicInfo) {
        return Promise.reject(new Error("请求参数不完整"));
    }
    
    return getUrlWithFallback(source, info.musicInfo, info.type || "128k")
        .then(url => Promise.resolve(url))
        .catch(err => Promise.reject(err));
});

send(EVENT_NAMES.inited, { openDevTools: false, sources: sourceConfig });
console.log("全聚合音源初始化完成");
