export const audioFils = {
  // 激光已校准:
  //   "https://static.shelingxingqiu.com/attachment/2025-10-29/ddupaur1vdkyhzaqdc.mp3",
  胜利: "https://static.shelingxingqiu.com/attachment/2025-09-17/dcuo9yjp0kt5msvmvd.mp3",
  失败: "https://static.shelingxingqiu.com/attachment/2025-09-17/dcuo9yht2sdwhuqygy.mp3",
  请射箭测试距离:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcuvj8avzqyw4hpq7t.mp3",
  距离合格:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutwrda0amn5kqr4j.mp3",
  距离不足:
    "https://static.shelingxingqiu.com/attachment/2025-11-12/de6hr2faw28t0ianh0.mp3",
  轮到你了:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutzdrn4lxcpv8aqr.mp3",
  第一轮:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutyyr9a7m1vz2w13.mp3",
  第二轮:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutyyr9ldnfexjxtw.mp3",
  第三轮:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutyyr97m4ipxaze4.mp3",
  第四轮:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutyyr9x5addohlzf.mp3",
  第五轮:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutyyr9d7lw2gebpv.mp3",
  决金箭轮:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutwrd9zs4oi2kujv.mp3",
  请蓝方射箭:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutzdrxcbe5ll46as.mp3",
  请红方射箭:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutzdrl3re3dhlfjd.mp3",
  中场休息:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutwrd9zdk1xyolst.mp3",
  比赛结束:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutya59b6pu0ur4um.mp3",
  比赛开始:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcuu5z3a3lumkutske.mp3",
  请开始射击:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutzdrl5u0iromqhf.mp3",
  射击无效:
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutya55ufiiw8oo55.mp3",
  未上靶:
    "https://static.shelingxingqiu.com/attachment/2025-11-12/de6n45o3tsm1v4unam.mp3",
  "1环":
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin1aq7gxjih5l.mp3",
  "2环":
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin64tdgx2s4at.mp3",
  "3环":
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxinlmf87vt8z65.mp3",
  "4环":
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxinniv97sx0q9u.mp3",
  "5环":
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin7j01kknpb7k.mp3",
  "6环":
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin4syy1015rtq.mp3",
  "7环":
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin3iz3dvmjdai.mp3",
  "8环":
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxinnjd42lhpfiw.mp3",
  "9环":
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin69nj1xh7yfz.mp3",
  "10环":
    "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxinnvsx0tt7ksa.mp3",
  向上调整:
    "https://static.shelingxingqiu.com/attachment/2025-11-12/de6ellf5pfvu3l8dhr.mp3",
  向右上调整:
    "https://static.shelingxingqiu.com/attachment/2025-11-12/de6ellf45v88pirarr.mp3",
  向右调整:
    "https://static.shelingxingqiu.com/attachment/2025-11-12/de6elleqnhrenggxsb.mp3",
  向右下调整:
    "https://static.shelingxingqiu.com/attachment/2025-11-12/de6elleo6q16qctf6a.mp3",
  向下调整:
    "https://static.shelingxingqiu.com/attachment/2025-11-12/de6ellek2mu2cri2n9.mp3",
  向左下调整:
    "https://static.shelingxingqiu.com/attachment/2025-11-12/de6ellf25yu1pt2k5r.mp3",
  向左调整:
    "https://static.shelingxingqiu.com/attachment/2025-11-12/de6ellen3zoalxcb06.mp3",
  向左上调整:
    "https://static.shelingxingqiu.com/attachment/2025-11-12/de6ellf37a2iw6w4pu.mp3",
  最后30秒:
    "https://static.shelingxingqiu.com/attachment/2025-11-13/de7kzzllq0futwynso.mp3",
  练习开始:
    "https://static.shelingxingqiu.com/attachment/2025-11-14/de88w0lmmt43nnfmoi.mp3",
};

// 版本控制日志函数
function debugLog(...args) {
  // 获取当前环境信息
  const accountInfo = uni.getAccountInfoSync();
  const envVersion = accountInfo.miniProgram.envVersion;

  // 只在体验版打印日志，正式版(release)和开发版(develop)不打印
  if (envVersion === "trial") {
    console.log(...args);
  }
}

class AudioManager {
  constructor() {
    this.audioMap = new Map();
    this.currentPlayingKey = null;
    this.maxRetries = 3;
    // 多轮统一重试：最多重试的轮次与每轮间隔
    this.maxRetryRounds = 10;
    this.retryRoundIntervalMs = 1500;
    // 显式授权播放标记，防止 iOS 在设置 src 后误播
    this.allowPlayMap = new Map();

    // 串行加载相关属性
    this.audioKeys = [];
    this.currentLoadingIndex = 0;
    this.isLoading = false;
    this.loadingPromise = null;

    // 连续播放队列相关属性
    this.sequenceQueue = [];
    this.sequenceIndex = 0;
    this.isSequenceRunning = false;

    // 防重复播放保护
    this.lastPlayKey = null;
    this.lastPlayAt = 0;

    // 静音开关
    this.isMuted = false;
    this.pendingPlayKey = null;
    // 新增：就绪状态映射
    this.readyMap = new Map();
    // 新增：首轮失败的音频集合与重试阶段标识
    this.failedLoadKeys = new Set();
    // 加载代数，用于 reloadAll 时作废旧的加载循环
    this.loadGeneration = 0;
    // 本地路径缓存 Map: { url: localPath }
    this.localFileCache = uni.getStorageSync("audio_local_files") || {};
    // 启动时自动清理过期的缓存文件（URL 已不在 audioFils 中的文件）
    this.cleanObsoleteCache();
    this.initAudios();
  }

  // 清理不再使用的缓存文件
  cleanObsoleteCache() {
    const activeUrls = new Set(Object.values(audioFils));
    const cachedUrls = Object.keys(this.localFileCache);
    let hasChanges = false;

    for (const url of cachedUrls) {
      if (!activeUrls.has(url)) {
        debugLog(`发现废弃音频缓存，正在清理: ${url}`);
        const path = this.localFileCache[url];
        // 移除物理文件
        uni.removeSavedFile({
          filePath: path,
          complete: () => {
            // 忽略移除结果，直接移除记录
          },
        });
        // 移除记录
        delete this.localFileCache[url];
        hasChanges = true;
      }
    }

    if (hasChanges) {
      uni.setStorageSync("audio_local_files", this.localFileCache);
      debugLog("废弃缓存清理完成");
    }
  }

  // 初始化音频（两阶段：首轮串行加载全部，次轮仅串行加载失败项一次）
  initAudios() {
    if (this.isLoading) {
      debugLog("音频正在加载中，跳过重复初始化");
      return this.loadingPromise;
    }
    debugLog("开始串行加载音频...");
    this.isLoading = true;
    this.audioKeys = Object.keys(audioFils);
    this.currentLoadingIndex = 0;
    this.failedLoadKeys.clear();

    // 增加代数，使得旧的加载循环失效
    this.loadGeneration = (this.loadGeneration || 0) + 1;
    const currentGen = this.loadGeneration;

    this.loadingPromise = new Promise((resolve) => {
      const finalize = () => {
        if (currentGen !== this.loadGeneration) return;
        const runRounds = (round) => {
          if (currentGen !== this.loadGeneration) return;
          // 达到最大轮次或没有失败项，收尾
          if (this.failedLoadKeys.size === 0 || round > this.maxRetryRounds) {
            this.isLoading = false;
            resolve();
            return;
          }

          const retryKeys = Array.from(this.failedLoadKeys);
          this.failedLoadKeys.clear();
          debugLog(`开始第 ${round} 轮串行加载，共 ${retryKeys.length} 个`);

          this.loadKeysSequentially(
            retryKeys,
            () => {
              if (currentGen !== this.loadGeneration) return;
              // 如仍有失败项，继续下一轮；否则结束
              if (this.failedLoadKeys.size > 0 && round < this.maxRetryRounds) {
                setTimeout(
                  () => runRounds(round + 1),
                  this.retryRoundIntervalMs
                );
              } else {
                this.isLoading = false;
                resolve();
              }
            },
            currentGen
          );
        };

        // 启动第 1 轮重试（如有失败项）
        runRounds(1);
      };
      this.loadNextAudio(finalize, currentGen);
    });
    return this.loadingPromise;
  }

  // 按自定义列表串行加载音频（避免并发过多）
  loadKeysSequentially(keys, onComplete, gen) {
    if (gen !== undefined && gen !== this.loadGeneration) return;
    let idx = 0;
    const list = Array.from(keys);
    const next = () => {
      if (gen !== undefined && gen !== this.loadGeneration) return;
      if (idx >= list.length) {
        if (onComplete) onComplete();
        return;
      }
      const k = list[idx++];

      // 已就绪的音频不再重载，避免把 ready 状态重置为 false
      if (this.readyMap.get(k)) {
        setTimeout(next, 50);
        return;
      }

      // 未就绪：已存在则重载；不存在则创建
      if (this.audioMap.has(k)) {
        this.retryLoadAudio(k);
        setTimeout(next, 100);
      } else {
        this.createAudio(k, () => {
          setTimeout(next, 100);
        });
        return; // createAudio 内部会触发 next
      }
    };
    next();
  }

  // 串行加载下一个音频（首轮）
  loadNextAudio(onComplete, gen) {
    if (gen !== undefined && gen !== this.loadGeneration) return;
    if (this.currentLoadingIndex >= this.audioKeys.length) {
      debugLog("首轮加载遍历完成", this.currentLoadingIndex);
      if (onComplete) onComplete();
      return;
    }
    const key = this.audioKeys[this.currentLoadingIndex];
    debugLog(
      `开始加载音频 ${this.currentLoadingIndex + 1}/${
        this.audioKeys.length
      }: ${key}`
    );
    this.createAudio(key, () => {
      setTimeout(() => {
        this.loadNextAudio(onComplete, gen);
      }, 100);
    });
  }

  // 创建单个音频实例（支持本地缓存）
  createAudio(key, callback) {
    this.currentLoadingIndex++;
    const src = audioFils[key];

    const setupAudio = (realSrc) => {
      const audio = uni.createInnerAudioContext();
      audio.autoplay = false;
      audio.src = realSrc;
      try {
        if (typeof audio.volume === "number") {
          audio.volume = this.isMuted ? 0 : 1;
        } else if (typeof audio.muted !== "undefined") {
          audio.muted = this.isMuted;
        }
      } catch (_) {}
      this.allowPlayMap.set(key, false);
      audio.onPlay(() => {
        if (!this.allowPlayMap.get(key)) {
          try {
            audio.stop();
          } catch (_) {}
        }
      });

      const loadTimeout = setTimeout(() => {
        debugLog(`音频 ${key} 加载超时`);
        this.recordLoadFailure(key);
        try {
          audio.destroy();
        } catch (_) {}
        if (callback) callback();
      }, 10000);

      audio.onCanplay(() => {
        if (!this.allowPlayMap.get(key)) {
          try {
            audio.pause();
          } catch (_) {}
        }
        clearTimeout(loadTimeout);
        this.readyMap.set(key, true);
        this.failedLoadKeys.delete(key);
        // debugLog(`音频 ${key} 已加载完成`, this.getLoadProgress());
        uni.$emit("audioLoaded", key);
        const loadedAudioKeys = uni.getStorageSync("loadedAudioKeys") || {};
        loadedAudioKeys[key] = true;
        uni.setStorageSync("loadedAudioKeys", loadedAudioKeys);
        if (callback) callback();
      });

      audio.onError((res) => {
        clearTimeout(loadTimeout);
        debugLog(`音频 ${key} 加载失败：`, res.errMsg);
        // 如果是本地文件加载失败，可能是文件损坏，清除缓存以便下次重新下载
        if (realSrc !== src && this.localFileCache[src] === realSrc) {
          debugLog(`本地缓存失效，移除记录: ${key}`);
          delete this.localFileCache[src];
          uni.setStorageSync("audio_local_files", this.localFileCache);
          // 移除文件
          uni.removeSavedFile({ filePath: realSrc });
        }
        this.recordLoadFailure(key);
        this.audioMap.delete(key);
        audio.destroy();
        if (this.readyMap.get(key)) {
          // 这里不要去除，不然检查进度的时候由于没有重新加载而进度卡住，等播放失败的时候会重新加载
          // this.readyMap.set(key, false);
        } else {
          if (callback) callback();
        }
      });

      audio.onEnded(() => {
        if (this.currentPlayingKey === key) {
          this.currentPlayingKey = null;
        }
        this.allowPlayMap.set(key, false);
        this.onAudioEnded(key);
      });

      audio.onStop(() => {
        if (this.currentPlayingKey === key) {
          this.currentPlayingKey = null;
        }
        this.allowPlayMap.set(key, false);
      });

      this.audioMap.set(key, audio);
    };

    // 检查是否有可用的本地缓存
    this.checkLocalFile(src).then((localPath) => {
      if (localPath) {
        debugLog(`命中本地缓存: ${key}`);
        setupAudio(localPath);
      } else {
        console.log("download");
        // 下载并尝试保存
        uni.downloadFile({
          url: src,
          timeout: 20000,
          success: (res) => {
            if (res.tempFilePath) {
              // 尝试保存文件到本地存储（持久化）
              uni.saveFile({
                tempFilePath: res.tempFilePath,
                success: (saveRes) => {
                  const savedPath = saveRes.savedFilePath;
                  this.localFileCache[src] = savedPath;
                  uni.setStorageSync("audio_local_files", this.localFileCache);
                  debugLog(`音频已缓存到本地: ${key}`);
                  setupAudio(savedPath);
                },
                fail: (err) => {
                  debugLog(
                    `保存音频失败(可能空间不足)，使用临时文件: ${key}`,
                    err
                  );
                  setupAudio(res.tempFilePath);
                },
              });
            } else {
              this.recordLoadFailure(key);
              if (callback) callback();
            }
          },
          fail: () => {
            this.recordLoadFailure(key);
            if (callback) callback();
          },
        });
      }
    });
  }

  // 检查本地文件是否有效
  checkLocalFile(url) {
    return new Promise((resolve) => {
      const path = this.localFileCache[url];
      if (!path) {
        resolve(null);
        return;
      }
      // 检查文件是否存在
      uni.getFileSystemManager().getFileInfo({
        filePath: path,
        success: () => {
          resolve(path);
        },
        fail: () => {
          // 文件不存在，清理记录
          delete this.localFileCache[url];
          uni.setStorageSync("audio_local_files", this.localFileCache);
          resolve(null);
        },
      });
    });
  }

  // 新增：记录失败（首轮与次轮都会用到）
  recordLoadFailure(key) {
    this.failedLoadKeys.add(key);
  }

  // 重新加载音频
  retryLoadAudio(key) {
    const oldAudio = this.audioMap.get(key);
    if (oldAudio) oldAudio.destroy();
    this.createAudio(key);
  }

  // 播放指定音频或音频数组（数组则按顺序连续播放）
  play(input, interrupt = true) {
    // 统一规范化为队列
    let queue = [];
    if (Array.isArray(input)) {
      queue = input.filter((k) => !!audioFils[k]);
    } else if (typeof input === "string") {
      queue = !!audioFils[input] ? [input] : [];
    } else {
      debugLog("play 参数类型无效，仅支持字符串或字符串数组");
      return;
    }

    if (queue.length === 0) {
      debugLog("连续播放队列为空或无效");
      return;
    }

    if (interrupt) {
      // 立即打断并启动新的播放序列
      this.stopAll();
      this.isSequenceRunning = false;
      this.sequenceQueue = [];
      this.sequenceIndex = 0;

      this.sequenceQueue = queue;
      this.sequenceIndex = 0;
      this.isSequenceRunning = true;
      this._playSingle(queue[0], false);
      return;
    }

    // 不打断当前播放：把新的队列加入到序列中，等待当前播放结束后衔接
    if (this.currentPlayingKey) {
      if (this.isSequenceRunning) {
        // 已有序列在跑：直接追加
        this.sequenceQueue = this.sequenceQueue.concat(queue);
      } else {
        // 没有序列但当前有正在播放的：以当前为序列的起点
        this.isSequenceRunning = true;
        this.sequenceQueue = [this.currentPlayingKey].concat(queue);
        this.sequenceIndex = 0;
        // 不触发 _playSingle，等待当前音频自然结束后由 onAudioEnded 接管
      }
    } else {
      // 当前没有播放：直接启动新的序列
      this.sequenceQueue = queue;
      this.sequenceIndex = 0;
      this.isSequenceRunning = true;
      this._playSingle(queue[0], false);
    }
  }

  // 内部方法：播放单个 key
  _playSingle(key, forceStopAll = false) {
    // 200ms 内的同 key 重复播放直接忽略，避免“比比赛开始”这类重复首音
    const now = Date.now();
    if (this.lastPlayKey === key && now - this.lastPlayAt < 250) {
      debugLog(`忽略快速重复播放: ${key}`);
      return;
    }

    if (forceStopAll) {
      this.stopAll();
    } else if (this.currentPlayingKey && this.currentPlayingKey !== key) {
      this.stop(this.currentPlayingKey);
    } else if (this.currentPlayingKey === key) {
      // 同一音频正在播放：不重启，避免听到重复开头
      return;
    }

    const audio = this.audioMap.get(key);
    if (audio) {
      // 播放前确保遵循当前静音状态
      try {
        if (typeof audio.volume === "number") {
          audio.volume = this.isMuted ? 0 : 1;
        } else if (typeof audio.muted !== "undefined") {
          audio.muted = this.isMuted;
        }
      } catch (_) {}
      // 同一音频：避免 stop() 触发 onStop 清除授权，使用 pause()+seek(0)
      try {
        audio.pause();
      } catch (_) {}
      try {
        if (typeof audio.seek === "function") {
          audio.seek(0);
        } else {
          audio.startTime = 0;
        }
      } catch (_) {
        audio.startTime = 0;
      }

      // 显式授权播放并立即播放
      this.allowPlayMap.set(key, true);

      audio.play();
      this.currentPlayingKey = key;
      this.lastPlayKey = key;
      this.lastPlayAt = Date.now();
    } else {
      debugLog(`音频 ${key} 不存在，尝试重新加载...`);
      this.retryLoadAudio(key);
      const handler = (loadedKey) => {
        if (loadedKey === key) {
          try {
            uni.$off("audioLoaded", handler);
          } catch (_) {}
          // 再次校验是否存在且就绪
          const a = this.audioMap.get(key);
          if (a && this.readyMap.get(key)) {
            this._playSingle(key, false);
          }
        }
      };
      try {
        uni.$on("audioLoaded", handler);
      } catch (_) {}
    }
  }

  // 连续播放：在某个音频结束后，若处于队列播放状态则继续下一个
  onAudioEnded(key) {
    if (!this.isSequenceRunning) return;
    const currentKey = this.sequenceQueue[this.sequenceIndex];
    if (currentKey !== key) return;

    const nextIndex = this.sequenceIndex + 1;
    if (nextIndex < this.sequenceQueue.length) {
      this.sequenceIndex = nextIndex;
      const nextKey = this.sequenceQueue[nextIndex];
      this._playSingle(nextKey, false);
    } else {
      // 队列播放完成
      this.isSequenceRunning = false;
      this.sequenceQueue = [];
      this.sequenceIndex = 0;
    }
  }

  // 停止指定音频
  stop(key) {
    const audio = this.audioMap.get(key);
    if (audio) {
      audio.stop();
      this.allowPlayMap.set(key, false);
      if (this.currentPlayingKey === key) {
        this.currentPlayingKey = null;
      }
    }
  }

  // 停止所有音频
  stopAll() {
    for (const [k, audio] of this.audioMap.entries()) {
      try {
        audio.stop();
      } catch (_) {}
      this.allowPlayMap.set(k, false);
    }
    this.currentPlayingKey = null;
  }

  // 设置静音开关：true 静音，false 取消静音
  setMuted(muted) {
    this.isMuted = !!muted;
    for (const audio of this.audioMap.values()) {
      try {
        if (typeof audio.volume === "number") {
          audio.volume = this.isMuted ? 0 : 1;
        } else if (typeof audio.muted !== "undefined") {
          audio.muted = this.isMuted;
        }
      } catch (_) {}
    }
    debugLog(`静音状态已设置为: ${this.isMuted}`);
  }

  // 新增：返回音频加载进度（0~1）
  getLoadProgress() {
    const keys = Object.keys(audioFils);
    const total = keys.length;
    if (total === 0) return 0;
    let loaded = 0;
    for (const k of keys) {
      if (this.readyMap.get(k)) loaded++;
    }
    return Number((loaded / total).toFixed(2));
  }

  // 清理本地音频缓存文件
  clearCache() {
    debugLog("开始清理本地音频缓存...");
    const cache = uni.getStorageSync("audio_local_files") || {};
    const paths = Object.values(cache);
    for (const path of paths) {
      uni.removeSavedFile({
        filePath: path,
        complete: (res) => {
          // 无论成功失败都继续
        },
      });
    }
    uni.removeStorageSync("audio_local_files");
    this.localFileCache = {};
    debugLog("本地音频缓存清理完成");
  }

  // 手动重置并重新加载所有音频（用于卡住时恢复）
  reloadAll() {
    debugLog("执行 reloadAll: 重置所有状态并重新加载");

    // 1. 停止所有播放
    this.stopAll();

    // 2. 销毁现有音频实例
    for (const audio of this.audioMap.values()) {
      try {
        audio.destroy();
      } catch (_) {}
    }
    this.audioMap.clear();

    // 3. 重置状态
    this.readyMap.clear();
    this.failedLoadKeys.clear();
    this.allowPlayMap.clear();
    this.currentPlayingKey = null;
    this.sequenceQueue = [];
    this.sequenceIndex = 0;
    this.isSequenceRunning = false;

    // 清理一下可能损坏的缓存（可选，如果用户因为缓存坏了卡住，这一步很有用）
    // 这里选择不自动全清，而是依赖 onError 里的单点清除。如果需要彻底重置，可取消注释：
    // this.clearCache();

    // 4. 强制重置加载锁
    this.isLoading = false;
    this.loadingPromise = null;
    this.currentLoadingIndex = 0;

    // 5. 重新初始化 (initAudios 会自增 loadGeneration，从而终止之前的任何异步循环)
    return this.initAudios();
  }
}

// 导出单例
export default new AudioManager();
