import boy5 from '@/assets/audio/boy-5s.mp3'
import system10 from '@/assets/audio/boy-10s.mp3'

export type AudioType = 'start' | 'tick10' | 'flip' | 'boy5'

export class AudioController {
  private static audioContext: AudioContext | null = null
  private soundFiles: Record<string, string> = {}
  private audioCache: Record<string, HTMLAudioElement> = {}

  constructor(soundFiles: Record<string, string> = {}) {
    this.soundFiles = {
      tick10: system10,
      boy5,
      ...soundFiles,
    }
    // 预加载关键音频
    this.preload(['tick10', 'boy5'])
  }

  private initAudioContext() {
    if (!AudioController.audioContext) {
      const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext
      if (AudioContextClass) {
        AudioController.audioContext = new AudioContextClass()
      }
    }
    // 尝试恢复上下文（如果被挂起）
    if (AudioController.audioContext?.state === 'suspended') {
      AudioController.audioContext.resume().catch(() => {})
    }
  }

  /**
   * 预加载音频文件
   */
  preload(types: AudioType[]) {
    types.forEach((type) => {
      const url = this.soundFiles[type]
      if (url && !this.audioCache[type]) {
        const audio = new Audio(url)
        audio.preload = 'auto'
        this.audioCache[type] = audio
      }
    })
  }

  /**
   * 播放指定类型的音效
   * 优先使用预设的音频文件，如果没有配置或加载失败，则使用 Web Audio API 合成音效
   */
  async play(type: AudioType) {
    // 确保音频上下文已初始化
    this.initAudioContext()

    // 尝试播放音频文件
    if (this.soundFiles[type]) {
      try {
        await this.playFile(type)
        return
      }
      catch (error) {
        console.warn(`Failed to play audio file for ${type}, falling back to synth.`, error)
      }
    }

    // 回退到合成音效
    this.playSynth(type)
  }

  private playFile(type: string): Promise<void> {
    return new Promise((resolve, reject) => {
      const url = this.soundFiles[type]
      if (!url) {
        reject(new Error('No file url'))
        return
      }

      // 使用缓存的 Audio 对象
      if (!this.audioCache[type]) {
        this.audioCache[type] = new Audio(url)
      }

      const audio = this.audioCache[type]
      audio.currentTime = 0
      audio.play()
        .then(() => resolve())
        .catch(e => reject(e))
    })
  }

  private playSynth(type: AudioType) {
    if (!AudioController.audioContext)
      return

    const ctx = AudioController.audioContext
    const ctxTime = ctx.currentTime
    const gain = ctx.createGain()
    gain.connect(ctx.destination)

    switch (type) {
      case 'start':
        this.playStartSound(ctx, gain, ctxTime)
        break
      case 'tick10':
      case 'boy5':
        this.playTickSound(ctx, gain, ctxTime)
        break
      case 'flip':
        this.playFlipSound(ctx, gain, ctxTime)
        break
    }
  }

  private playStartSound(ctx: AudioContext, gain: GainNode, time: number) {
    const osc = ctx.createOscillator()
    osc.connect(gain)
    // 开始音效：高音短促提示
    osc.type = 'sine'
    osc.frequency.setValueAtTime(880, time)
    osc.frequency.exponentialRampToValueAtTime(440, time + 0.3)
    gain.gain.setValueAtTime(0.5, time)
    gain.gain.exponentialRampToValueAtTime(0.01, time + 0.3)
    osc.start(time)
    osc.stop(time + 0.3)
  }

  private playTickSound(ctx: AudioContext, gain: GainNode, time: number) {
    const osc = ctx.createOscillator()
    osc.connect(gain)
    // 倒计时音效：急促的滴答声
    osc.type = 'triangle'
    osc.frequency.setValueAtTime(600, time)
    gain.gain.setValueAtTime(0.3, time)
    gain.gain.exponentialRampToValueAtTime(0.01, time + 0.1)
    osc.start(time)
    osc.stop(time + 0.1)
  }

  private playFlipSound(ctx: AudioContext, gain: GainNode, time: number) {
    // 翻书音效：使用白噪声模拟纸张摩擦
    const bufferSize = ctx.sampleRate * 0.5 // 0.5秒缓冲
    const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate)
    const data = buffer.getChannelData(0)

    // 生成白噪声
    for (let i = 0; i < bufferSize; i++) {
      data[i] = Math.random() * 2 - 1
    }

    const noise = ctx.createBufferSource()
    noise.buffer = buffer

    // 滤波器：低通滤波器，模拟纸张的闷声
    const filter = ctx.createBiquadFilter()
    filter.type = 'lowpass'
    filter.frequency.setValueAtTime(400, time)
    filter.frequency.exponentialRampToValueAtTime(3000, time + 0.1) // 频率快速扫过，模拟快速翻动

    noise.connect(filter)
    filter.connect(gain)

    // 音量包络：快速淡入淡出
    gain.gain.setValueAtTime(0, time)
    gain.gain.linearRampToValueAtTime(0.8, time + 0.05)
    gain.gain.exponentialRampToValueAtTime(0.01, time + 0.3)

    noise.start(time)
    noise.stop(time + 0.3)
  }
}
