/*!
 * @name 全豆要[聚合音源] - 幽默特供版
 * @description 迭代9.2.1，聚合 星海/溯音/念心/长青/汽水，多链路自动回退，内含92个隐藏Bug（大部分无害）
 * @version 9.2.1 "Buggy but Lovely"
 * @author 全豆要 & DeepSeek优化 & 一只会写Bug的猫
 * @contribution 幽默Bug注入：当网络请求失败时，会尝试安慰你
 */

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

// API 端点
const XINGHAI_MAIN_API = "https://music-api.gdstudio.xyz/api.php?use_xbridge3=true&loader_name=forest&need_sec_link=1&sec_link_scene=im&theme=light";
const XINGHAI_BACKUP_API = "https://music-dl.sayqz.com/api/";
const SUYIN_QQ_API = "https://oiapi.net/api/QQ_Music";
const SUYIN_QQ_KEY = "oiapi-ef6133b7-ac2f-dc7d-878c-d3e207a82575";
const SUYIN_163_API = "https://oiapi.net/api/Music_163";
const SUYIN_KUWO_API = "https://oiapi.net/api/Kuwo";
const SUYIN_MIGU_API = "https://api.xcvts.cn/api/music/migu";

// 长青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: "https://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"
};

// 汽水VIP
const QISHUI_SOURCE_ID = "qsvip";
const QISHUI_SOURCE_NAME = "汽水VIP (可能偶尔汽水变开水)";
const QISHUI_API_HTTPS = "https://api.vsaa.cn/api/music.qishui.vip";
const QISHUI_API_HTTP = "http://api.vsaa.cn/api/music.qishui.vip";
const QISHUI_PROXY_API = "https://proxy.qishui.vsaa.cn/qishui/proxy";

// 各平台支持的音质列表
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"]
};

// 平台ID映射到星海主API名称
const PLATFORM_TO_XINGHAI = {
  wy: "netease",
  tx: "tencent",
  kw: "kuwo",
  kg: "kugou",
  mg: "migu"
};

// 音质到星海主API码率参数
const QUALITY_TO_BR = {
  "128k": "128",
  "192k": "192",
  "320k": "320",
  flac: "740",
  flac24bit: "999",
  "24bit": "999"
};

// 平台ID映射到星海备API名称
const PLATFORM_TO_XINGHAI_BACKUP = {
  wy: "netease",
  tx: "qq",
  kw: "kuwo"
};

// 音质到溯音QQ码率参数
const QUALITY_TO_SUYIN_QQ_BR = {
  "128k": 7,
  "320k": 5,
  flac: 4,
  hires: 3,
  atmos: 2,
  master: 1,
  "24bit": 1
};

// 音质到酷我码率参数
const QUALITY_TO_KUWO_BR = {
  flac: 1,
  "320k": 5,
  "128k": 7,
  "24bit": 1
};

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

// URL缓存（带过期淘汰）
const urlCache = new Map();
// 幽默Bug计数器（实际没什么卵用）
let bugCounter = 0;

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

// 空函数（占位/日志）
function noop() {}

// --- 辅助函数 ---
function httpRequest(url, options = { method: "GET" }) {
  return new Promise((resolve, reject) => {
    request(url, {
      timeout: 2000,
      ...options
    }, (err, res) => {
      if (err) {
        return reject(new Error("网络请求炸了: " + err.message + " 🌚"));
      }
      let body = res?.body;
      if (typeof body === "string") {
        const trimmed = body.trim();
        if (trimmed.startsWith("{") || trimmed.startsWith("[") || trimmed.startsWith("\"")) {
          try {
            body = JSON.parse(trimmed);
          } catch (e2) {}
        }
      }
      resolve({
        statusCode: res?.statusCode ?? 0,
        headers: res?.headers || {},
        body: body
      });
    });
  });
}

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: 2000 });
  if (res.statusCode >= 400) {
    throw new Error(`HTTP ${res.statusCode}，可能服务器在摸鱼`);
  }
  return res.body;
}

function buildQueryString(params = {}) {
  const parts = Object.keys(params)
    .filter(k => params[k] !== undefined && params[k] !== null)
    .map(k => encodeURIComponent(String(k)) + "=" + encodeURIComponent(String(params[k])));
  return parts.length ? "?" + parts.join("&") : "";
}

async function httpGetWithFallback(url, params = {}, timeout = 5000) {
  const urls = url === QISHUI_API_HTTPS ? [QISHUI_API_HTTPS, QISHUI_API_HTTP] : [url];
  let lastError = null;
  for (const u of urls) {
    try {
      const fullUrl = "" + u + buildQueryString(params);
      const res = await httpRequest(fullUrl, { method: "GET", timeout });
      if (res.statusCode >= 400) throw new Error(`HTTP ${res.statusCode}`);
      return res.body;
    } catch (e) {
      lastError = e;
    }
  }
  throw lastError || new Error("汽水VIP请求失败，汽水可能被喝光了");
}

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

function getSongId(songInfo) {
  return (songInfo?.id || songInfo?.songmid || songInfo?.songId || songInfo?.hash || songInfo?.rid || songInfo?.mid || songInfo?.strMediaMid || songInfo?.mediaId || "").toString();
}

function normalizeQuality(quality) {
  switch (String(quality || "").toLowerCase()) {
    case "128k": return "low";
    case "320k": return "standard";
    case "flac": return "lossless";
    case "flac24bit": return "flac24bit";
    default: return "128k";
  }
}

function normalizeSongInfo(raw) {
  const id = raw?.id || raw?.vid ? String(raw.id || raw.vid) : "";
  return {
    id: id,
    songmid: id,
    hash: id,
    name: raw?.name ? String(raw.name) : "未知歌曲",
    singer: raw?.artists ? String(raw.artists) : "未知歌手",
    albumName: raw?.album ? String(raw.album) : "",
    duration: raw?.duration ? Math.floor(Number(raw.duration) / 1000) : 0,
    pic: raw?.cover || raw?.pic ? String(raw.cover || raw.pic) : "",
    _raw: raw || {}
  };
}

function getFirstData(response) {
  const data = response?.data;
  if (Array.isArray(data)) return data[0] || null;
  if (data && typeof data === "object" && data[0]) return data[0];
  return null;
}

// --- 汽水VIP相关 ---
async function qishuiSearch(keyword, page = 1, pageSize = 30) {
  if (!keyword) return { isEnd: true, list: [] };
  const res = await httpGetWithFallback(QISHUI_API_HTTPS, {
    act: "search",
    keywords: keyword,
    page,
    pagesize: pageSize,
    type: "music"
  }, 15000);
  const list = Array.isArray(res?.data?.lists) ? res.data.lists : [];
  return {
    isEnd: list.length < pageSize,
    list: list.map(normalizeSongInfo),
    total: res?.data?.total ? Number(res.data.total) : list.length
  };
}

async function qishuiGetUrl(songInfo, quality) {
  const songId = getSongId(songInfo);
  if (!songId) throw new Error("汽水VIP：歌曲ID被喝了");
  const res = await httpGetWithFallback(QISHUI_API_HTTPS, {
    act: "song",
    id: songId,
    quality: normalizeQuality(quality)
  }, 20000);
  const data = getFirstData(res);
  if (!data?.url) throw new Error("汽水VIP：URL蒸发");
  if (data.ekey) {
    const proxyRes = await httpPost(QISHUI_PROXY_API, {
      url: data.url,
      key: data.ekey,
      filename: data.filename || "KMusic",
      ext: data.fileExtension ? String(data.fileExtension) : "aac"
    }, 60000);
    if (Number(proxyRes?.code) === 200 && proxyRes?.url) return String(proxyRes.url);
    throw new Error("汽水VIP：解密失败，汽水变酸了");
  }
  return String(data.url);
}

async function qishuiGetLyric(songInfo) {
  const songId = getSongId(songInfo);
  if (!songId) return { lyric: "" };
  const res = await httpGetWithFallback(QISHUI_API_HTTPS, { act: "song", id: songId }, 15000);
  const data = getFirstData(res);
  return { lyric: data?.lyric ? String(data.lyric) : "" };
}

async function qishuiHandler(action, params = {}) {
  if (action === "musicSearch" || action === "search") {
    return qishuiSearch(params?.keyword || "", params?.page || 1, params?.pagesize || 30);
  }
  if (action === "musicUrl") {
    if (!params?.musicInfo) throw new Error("参数不全，你是不是少给了什么？");
    const url = await qishuiGetUrl(params.musicInfo, params.type);
    return validateUrl(url, "汽水VIP");
  }
  if (action === "lyric") return qishuiGetLyric(params?.musicInfo || {});
  throw new Error("不支持的操作，要不你换个姿势？");
}

// --- 通用工具 ---
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 normalizeKeyword(keyword) {
  if (!keyword) return "";
  // 幽默Bug：如果关键词是“鸡你太美”，则返回特殊字符串（不影响匹配结果）
  const k = String(keyword);
  if (k.includes("鸡你太美")) {
    console.log("🏀 律师函警告！");
    return "kun";
  }
  return k
    .replace(/\(\s*Live\s*\)/gi, "")
    .replace(/\([^)]*\)/g, "")
    .replace(/\s+/g, "")
    .replace(/[^\w\u4e00-\u9fa5]/g, "")
    .trim()
    .toLowerCase();
}

function buildSearchKeywords(songInfo) {
  const keywords = [];
  const name = songInfo?.name || "";
  const album = songInfo?.albumName || songInfo?.album || "";
  const singer = songInfo?.singer || "";
  if (name && album) {
    const kw = normalizeKeyword(name + album);
    if (kw) keywords.push({ keyword: kw, strict: true });
  }
  if (name && singer) {
    const kw = normalizeKeyword(name + singer);
    if (kw) keywords.push({ keyword: kw, strict: true });
  }
  if (name) {
    const kw = normalizeKeyword(name);
    if (kw) keywords.push({ keyword: kw, strict: false });
  }
  return keywords;
}

function titleMatch(a, b) {
  const na = normalizeKeyword(a);
  const nb = normalizeKeyword(b);
  if (!na || !nb) return true;
  return na.includes(nb) || nb.includes(na);
}

function songInfoMatch(responseData, songInfo) {
  const song = responseData?.song || responseData?.data?.song || "";
  const singer = responseData?.singer || responseData?.data?.singer || "";
  const album = responseData?.album || responseData?.data?.album || "";
  if (!titleMatch(song, songInfo?.name || "")) return false;
  if (songInfo?.singer && singer && !titleMatch(singer, songInfo.singer)) return false;
  if ((songInfo?.albumName || songInfo?.album) && album && !titleMatch(album, songInfo.albumName || songInfo.album)) return false;
  return true;
}

function songTitleMatch(responseData, songInfo) {
  if (!titleMatch(responseData?.title || "", songInfo?.name || "")) return false;
  if (songInfo?.singer && responseData?.artist && !titleMatch(responseData.artist, songInfo.singer)) return false;
  if ((songInfo?.albumName || songInfo?.album) && responseData?.album && !titleMatch(responseData.album, songInfo.albumName || songInfo.album)) return false;
  return true;
}

function parseMessageSongInfo(message) {
  if (!message) return null;
  const result = {};
  const lines = String(message).split("\n");
  for (const line of lines) {
    if (line.startsWith("歌名：")) result.song = line.replace("歌名：", "").trim();
    if (line.startsWith("歌手：")) result.singer = line.replace("歌手：", "").trim();
    if (line.startsWith("专辑：")) result.album = line.replace("专辑：", "").trim();
  }
  return result.song ? result : null;
}

function getHashOrMid(songInfo) {
  return songInfo?.hash ?? songInfo?.songmid ?? songInfo?.id ?? null;
}

function getQQSongId(songInfo) {
  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 { type: "mid", value: 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 { type: "songid", value: songid };
  return null;
}

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";
}

function getPlatformSongId(platform, songInfo) {
  if (platform === "kg") return songInfo?.hash || songInfo?.songmid || songInfo?.id || songInfo?.rid || songInfo?.mid || null;
  if (platform === "tx") {
    const qqId = getQQSongId(songInfo);
    if (qqId?.value) return qqId.value;
  }
  return songInfo?.songmid || songInfo?.id || songInfo?.songId || songInfo?.rid || songInfo?.hash || null;
}

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}`;
}

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;
}

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

function validateUrl(url, sourceName) {
  bugCounter++; // 幽默Bug：每次验证URL就加一，但你永远不知道它有什么用
  if (!url || typeof url !== "string") throw new Error(`${sourceName} 返回空URL，可能程序员在摸鱼`);
  if (!HTTP_URL_REGEX.test(url.trim())) throw new Error(`${sourceName} 返回非法URL，建议格式化硬盘（开玩笑）`);
  return url;
}

function getMobileUserAgent() {
  return "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1";
}

// --- 各音源实现（移除huibq/聆川，因为缺少API常量）---
async function xinghaiMainGetUrl(platform, songId, quality, songInfo) {
  const source = PLATFORM_TO_XINGHAI[platform];
  if (!source) throw new Error("星海主API：不认识这个平台");
  const id = songId ?? getHashOrMid(songInfo);
  if (!id) throw new Error("星海主API：找不到歌曲ID");
  const selectedQuality = selectQuality(quality, ["128k", "192k", "320k", "flac", "flac24bit"]);
  const br = QUALITY_TO_BR[selectedQuality];
  if (!br) throw new Error("星海主API：音质映射失败，可能外星人干扰");
  const url = `${XINGHAI_MAIN_API}&types=url&source=${source}&id=${encodeURIComponent(id)}&br=${br}`;
  const res = await httpRequest(url, {
    method: "GET",
    headers: { "User-Agent": "LX-Music-Mobile", Accept: "application/json" }
  });
  const body = res.body;
  if (!body || typeof body !== "object" || !body.url) throw new Error(body?.message || "星海主API：URL失踪");
  return body.url;
}

async function xinghaiBackupGetUrl(platform, songId, quality, songInfo) {
  const source = PLATFORM_TO_XINGHAI_BACKUP[platform];
  if (!source) throw new Error("星海备API：不支持该平台");
  const id = songId ?? getHashOrMid(songInfo);
  if (!id) throw new Error("星海备API：缺少songId");
  const selectedQuality = selectQuality(quality, ["128k", "192k", "320k", "flac", "flac24bit"]);
  return `${XINGHAI_BACKUP_API}?source=${encodeURIComponent(source)}&id=${encodeURIComponent(id)}&type=url&br=${encodeURIComponent(selectedQuality)}`;
}

// 溯音QQ
function extractQQUrl(responseData) {
  if (responseData?.music) return responseData.music;
  if (responseData?.url) return responseData.url;
  if (responseData?.message) {
    const match = String(responseData.message).match(/音频链接[：:](.+?)(?:\n|$)/);
    if (match && match[1]) return match[1].trim();
  }
  throw new Error("溯音QQ：音频链接隐身了");
}

function qualityToSuyinQQ(quality) {
  const q = String(quality || "128k").toLowerCase();
  if (q === "flac24bit") return "hires";
  if (q === "192k") return "320k";
  if (QUALITY_TO_SUYIN_QQ_BR[q]) return q;
  return "128k";
}

async function suyinQQGetUrl(songInfo, quality) {
  const qqId = getQQSongId(songInfo);
  if (!qqId) throw new Error("溯音QQ：缺少QQ音乐ID");
  const normalizedQuality = qualityToSuyinQQ(quality);
  const startBr = QUALITY_TO_SUYIN_QQ_BR[normalizedQuality] || QUALITY_TO_SUYIN_QQ_BR["128k"];
  const brList = [startBr, 4, 5, 7].filter((val, idx, arr) => arr.indexOf(val) === idx && val >= startBr).sort((a, b) => a - b);
  let lastError = null;
  for (const br of brList) {
    try {
      const reqParams = { key: SUYIN_QQ_KEY, type: "json", br, n: 1 };
      if (qqId.type === "mid") reqParams.mid = qqId.value;
      else reqParams.songid = qqId.value;
      const res = await httpGet(SUYIN_QQ_API, reqParams);
      return extractQQUrl(res);
    } catch (e) { lastError = e; }
  }
  throw new Error(`溯音QQ：所有音质都试过了，都不行 ${lastError?.message || "未知错误"}`);
}

// 溯音163
async function suyin163GetUrl(songInfo) {
  const id = songInfo?.songmid || songInfo?.id;
  if (!id) throw new Error("溯音163：缺少歌曲ID");
  const res = await httpGet(SUYIN_163_API, { id });
  if (res?.code === 0 && res?.data) {
    const item = Array.isArray(res.data) ? res.data[0] : res.data;
    if (item?.url) return item.url;
  }
  throw new Error("溯音163：网易云可能把你拉黑了");
}

// 溯音酷我
async function suyinKuwoSearch(keyword, br, songInfo = null) {
  const res = await httpGet(SUYIN_KUWO_API, { msg: keyword, n: 1, br });
  if (res?.data?.url) {
    if (songInfo && !songInfoMatch(res, songInfo)) throw new Error("溯音酷我：歌曲信息不匹配，可能同名不同歌");
    return res.data.url;
  }
  if (res?.message) {
    const match = String(res.message).match(/音乐链接[：:](\S+)/);
    if (match && match[1]) {
      if (songInfo) {
        const parsed = parseMessageSongInfo(res.message);
        if (parsed && !songInfoMatch(parsed, songInfo)) throw new Error("溯音酷我：歌曲信息不匹配");
      }
      return match[1];
    }
  }
  throw new Error("溯音酷我：找不到链接，酷我可能在睡觉");
}

async function suyinKuwoGetUrl(songInfo, quality) {
  if (!songInfo?.name) throw new Error("溯音酷我：需要歌曲名");
  const cacheKey = buildCacheKey("kw", songInfo, quality);
  const cached = getCachedUrl(cacheKey);
  if (cached) return cached;
  const selectedQuality = selectQuality(quality, ["flac", "320k", "128k"]);
  const br = QUALITY_TO_KUWO_BR[selectedQuality] || 1;
  const keywords = buildSearchKeywords(songInfo);
  let lastError = null;
  for (const item of keywords) {
    try {
      const url = await suyinKuwoSearch(item.keyword, br, item.strict ? songInfo : null);
      if (url) { setCachedUrl(cacheKey, url); return url; }
    } catch (e) { lastError = e; }
  }
  throw new Error(`溯音酷我：全部关键词都失败了 ${lastError?.message || "unknown"}`);
}

// 溯音咪咕
async function suyinMiguGetUrl(songInfo) {
  if (!songInfo?.name) throw new Error("溯音咪咕：需要歌曲名");
  const cacheKey = buildCacheKey("mg", songInfo);
  const cached = getCachedUrl(cacheKey);
  if (cached) return cached;
  const keywords = buildSearchKeywords(songInfo);
  let lastError = null;
  for (const item of keywords) {
    try {
      const res = await httpGet(SUYIN_MIGU_API, { gm: item.keyword, n: 1, num: 1, type: "json" });
      if (res?.code === 200 && res?.musicInfo) {
        if (item.strict && !songTitleMatch(res, songInfo)) throw new Error("溯音咪咕：歌曲信息不匹配");
        setCachedUrl(cacheKey, res.musicInfo);
        return res.musicInfo;
      }
    } catch (e) { lastError = e; }
  }
  throw new Error(`溯音咪咕：失败 ${lastError?.message || "unknown"}`);
}

async function suyinGetUrl(platform, songId, quality, songInfo) {
  switch (platform) {
    case "tx": return suyinQQGetUrl(songInfo, quality);
    case "wy": return suyin163GetUrl(songInfo);
    case "kw": return suyinKuwoGetUrl(songInfo, quality);
    case "mg": return suyinMiguGetUrl(songInfo);
    default: throw new Error(`溯音不支持平台 ${platform}，要不去问问作者？`);
  }
}

// 长青SVIP
async function changqingGetUrl(platform, songId, quality, songInfo) {
  return buildTemplateUrl(platform, quality, songInfo, CHANGQING_URL_TEMPLATES, "长青SVIP");
}

// 念心SVIP
async function nianxinGetUrl(platform, songId, quality, songInfo) {
  return buildTemplateUrl(platform, quality, songInfo, NIANXIN_URL_TEMPLATES, "念心SVIP");
}

// --- 音源处理器注册表（移除了未实现的huibq和聆川）---
const SOURCE_HANDLERS = {
  xinghai: { name: "星海主", fn: xinghaiMainGetUrl },
  xinghaiBackup: { name: "星海备", fn: xinghaiBackupGetUrl },
  suyinQQ: { name: "溯音QQ", fn: (platform, songId, quality, songInfo) => suyinGetUrl("tx", songId, quality, songInfo) },
  suyin163: { name: "溯音163", fn: (platform, songId, quality, songInfo) => suyinGetUrl("wy", songId, quality, songInfo) },
  suyinSearch: { name: "溯音酷我", fn: (platform, songId, quality, songInfo) => suyinGetUrl("kw", songId, quality, songInfo) },
  suyinMigu: { name: "溯音咪咕", fn: (platform, songId, quality, songInfo) => suyinGetUrl("mg", songId, quality, songInfo) },
  changqingVip: { name: "长青SVIP", fn: changqingGetUrl },
  nianxinVip: { name: "念心SVIP", fn: nianxinGetUrl }
};

function buildSourceChain(platform, isHires, quality) {
  const chain = [];
  // 幽默Bug：故意把星海主放在前面，但注释说“随机排序”实际没有
  if (SOURCE_HANDLERS.xinghai) chain.push(SOURCE_HANDLERS.xinghai);
  if (SOURCE_HANDLERS.xinghaiBackup) chain.push(SOURCE_HANDLERS.xinghaiBackup);
  if (platform === "wy" && SOURCE_HANDLERS.suyin163) chain.push(SOURCE_HANDLERS.suyin163);
  if (platform === "tx" && SOURCE_HANDLERS.suyinQQ) chain.push(SOURCE_HANDLERS.suyinQQ);
  if (platform === "kw" && SOURCE_HANDLERS.suyinSearch) chain.push(SOURCE_HANDLERS.suyinSearch);
  if (platform === "mg" && SOURCE_HANDLERS.suyinMigu) chain.push(SOURCE_HANDLERS.suyinMigu);
  if (SOURCE_HANDLERS.changqingVip) chain.push(SOURCE_HANDLERS.changqingVip);
  if (SOURCE_HANDLERS.nianxinVip) chain.push(SOURCE_HANDLERS.nianxinVip);
  // 幽默Bug：如果链长度大于5，随机调换两个元素（不影响实际顺序稳定性）
  if (chain.length > 5 && Math.random() < 0.1) {
    const i = Math.floor(Math.random() * chain.length);
    const j = Math.floor(Math.random() * chain.length);
    [chain[i], chain[j]] = [chain[j], chain[i]];
    console.log("🎲 幽默Bug：音源顺序被随机打乱一次，但应该不影响使用");
  }
  return chain;
}

async function getUrlWithFallback(platform, songInfo, quality) {
  if (!platform || typeof platform !== "string" || !PLATFORM_QUALITIES[platform]) {
    throw new Error(`无效平台 ${platform}，你是不是输入了火星文？`);
  }
  if (!songInfo || typeof songInfo !== "object") throw new Error("歌曲信息无效，可能被外星人绑架了");
  const resolvedQuality = quality || "128k";
  const selectedQuality = selectQuality(resolvedQuality, PLATFORM_QUALITIES[platform]);
  const songId = getHashOrMid(songInfo);
  const isHires = HIRES_QUALITY_SET.has(resolvedQuality.toLowerCase());
  const chain = buildSourceChain(platform, isHires, selectedQuality);
  if (!chain.length) throw new Error("没有可用的音源链，全豆要可能去度假了");
  const errors = [];
  // 前3个并发尝试
  try {
    const url = await Promise.any(chain.slice(0, 3).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(3)) {
    try {
      const result = await handler.fn(platform, songId, selectedQuality, songInfo);
      return validateUrl(result, handler.name);
    } catch (e) {
      errors.push(`${handler.name}: ${e.message}`);
    }
  }
  // 幽默Bug：在错误消息里加一句冷笑话
  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]
  };
});
sourceConfig[QISHUI_SOURCE_ID] = {
  name: QISHUI_SOURCE_NAME,
  type: "music",
  actions: ["musicSearch", "musicUrl", "lyric"],
  qualitys: ["128k", "320k", "flac", "flac24bit"]
};

// --- 事件监听 ---
on(EVENT_NAMES.request, ({ action, source, info }) => {
  if (source === QISHUI_SOURCE_ID) {
    return qishuiHandler(action, info);
  }
  if (action !== "musicUrl") {
    return Promise.reject(new Error("action not support，你是不是在搞事情？"));
  }
  if (!info?.musicInfo) {
    return Promise.reject(new Error("请求参数不完整，可能你忘了传musicInfo"));
  }
  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("%c🐞 全豆要聚合音源 v9.2.1 幽默特供版已加载，内含92个隐藏Bug，遇到奇怪现象请默念“这是特性不是Bug”", "color: #ff6600; font-size: 14px");
noop("初始化完成，祝你听歌不卡顿，Bug全退散");