import { ref } from 'vue'

/**
 * 语音播放全局互斥
 *
 * 模块级单例：同一时刻最多只有一条语音在播；新点的语音停掉旧的
 * 三处入口共享同一播放态：
 * - MessageBubble：气泡点击 toggle 当前条
 * - MessagePanel：切会话 stop()
 * - MessageHistory / MessageMergeDetailDialog：关闭时 stop()
 *
 * key 由 MessageBubble 在 setup 里 Symbol() 生成实例级唯一身份；不同来源（主面板 / 历史抽屉 /
 * 合并详情）的同一条语音 url 在不同气泡里也是不同 key，避免一处卸载误停另一处仍可见的播放。
 */
export type VoiceKey = symbol

interface VoiceTask {
  key: VoiceKey
  url: string
  audio: HTMLAudioElement
}

const currentTask = ref<null | VoiceTask>(null)

/**
 * 显式停止
 *
 * - 不传 key：强停（切会话 / 关弹窗用）
 * - 传 key：仅当当前 task 是该 key 时才停（气泡卸载兜底用，避免误停别人）
 */
function stop(key?: VoiceKey) {
  const task = currentTask.value
  if (!task) {
    return
  }
  if (key !== undefined && task.key !== key) {
    return
  }
  task.audio.pause()
  // removeAttribute('src') + load() 是 W3C 推荐的释放姿势：不会触发空 src 加载导致的 error 事件，
  // 也能让浏览器立即释放底层 decoder buffer，比 audio.src = '' 更干净
  task.audio.removeAttribute('src')
  task.audio.load()
  currentTask.value = null
}

/**
 * 切换播放
 *
 * - 同 key 再点：停掉
 * - 切到新 key：停旧起新
 */
function play(key: VoiceKey, url: string) {
  if (!url) {
    return
  }
  if (currentTask.value?.key === key) {
    stop(key)
    return
  }
  stop()
  const audio = new Audio(url)
  const task: VoiceTask = { key, url, audio }
  /** 播放结束 / 异常清栈；只清当前任务，避免被后续新任务的回调误清 */
  const finalize = () => {
    if (currentTask.value === task) {
      currentTask.value = null
    }
  }
  audio.addEventListener('ended', finalize, { once: true })
  audio.addEventListener('error', finalize, { once: true })
  currentTask.value = task
  audio.play().catch(finalize)
}

export function useVoicePlayer() {
  /** 指定 key 是否正在播放 */
  function isPlaying(key: VoiceKey): boolean {
    return currentTask.value?.key === key
  }
  return { isPlaying, play, stop }
}
