//
//  AudioPlayer.swift
//  ylgamehall
//
//  本地音频播放（srcIsloop 支撑）：背景音循环 + 单次按钮音。
//
//  契约：docs/H5-Native-Contract.md §3.1 ［3］srcIsloop
//  Design：§8.1 AudioKit
//

import AVFoundation
import os.log

/// 本地音频播放器（@MainActor 隔离的状态机）。
///
/// 三类音频通道：
///   - `background`：循环背景音，记录 backgroundType 用于 isloop=-1 时同名停止
///   - `button`：单次按钮音（短促音效），互不抢占（每次调 playOnce 新建 player）
///
/// 与原 msext NewRootVC 的 `buttunPlayer` / `backgroundPlayer` /
/// `backgroundType` 静态变量等价，封装到实例避免全局可变状态。
@MainActor
public final class AudioPlayer {

    public static let shared = AudioPlayer()

    private static let log = Logger(subsystem: "ylgamehall", category: "AudioPlayer")

    private var backgroundPlayer: AVAudioPlayer?
    private var backgroundType: String?
    /// 单次按钮音的 player 保活池：同时点多个按钮也不会互相打断
    private var buttonPlayers: [AVAudioPlayer] = []

    public init() {}

    // MARK: - srcIsloop 入口

    /// 单次按钮音播放（msext `isloop == 0`）。
    public func playOnce(_ url: URL) {
        do {
            let player = try AVAudioPlayer(contentsOf: url)
            player.numberOfLoops = 0
            player.prepareToPlay()
            player.play()
            buttonPlayers.append(player)
            // 短促音播放完就清理（依靠 AVAudioPlayer 自身的 duration + delay 释放）
            let duration = player.duration
            Task { @MainActor [weak self] in
                try? await Task.sleep(nanoseconds: UInt64((duration + 0.5) * 1_000_000_000))
                self?.buttonPlayers.removeAll { $0 === player }
            }
            Self.log.debug("playOnce \(url.lastPathComponent, privacy: .public) duration=\(duration, privacy: .public)s")
        } catch {
            Self.log.error("playOnce failed: \(error.localizedDescription, privacy: .public) url=\(url.path, privacy: .public)")
        }
    }

    /// 循环背景音（msext `isloop == 1`）。同名再次启动会替换上一份。
    public func loopBackground(_ url: URL, type: String) {
        do {
            let player = try AVAudioPlayer(contentsOf: url)
            player.numberOfLoops = -1   // 无限循环
            player.prepareToPlay()
            player.play()
            backgroundPlayer?.stop()
            backgroundPlayer = player
            backgroundType = type
            Self.log.debug("loopBackground type=\(type, privacy: .public) url=\(url.lastPathComponent, privacy: .public)")
        } catch {
            Self.log.error("loopBackground failed: \(error.localizedDescription, privacy: .public) url=\(url.path, privacy: .public)")
        }
    }

    /// 停止同名背景音（msext `isloop == -1`）。仅 type 与当前 backgroundType 匹配时停止。
    public func stopBackground(type: String) {
        guard backgroundType == type else {
            Self.log.debug("stopBackground noop: requested type=\(type, privacy: .public) but current=\(self.backgroundType ?? "nil", privacy: .public)")
            return
        }
        backgroundPlayer?.stop()
        backgroundPlayer = nil
        backgroundType = nil
        Self.log.debug("stopBackground done type=\(type, privacy: .public)")
    }

    /// 无条件停止当前背景音。子游戏 `backgameData` 退出时统一调一次
    /// （msext gameController.m:693-697 行为：不看 type，直接 stop + nil）。
    public func stopAllBackground() {
        guard backgroundPlayer != nil else { return }
        let oldType = backgroundType ?? "nil"
        backgroundPlayer?.stop()
        backgroundPlayer = nil
        backgroundType = nil
        Self.log.debug("stopAllBackground done (was type=\(oldType, privacy: .public))")
    }
}
