/**
 * qix_audio.js
 * (404エラーで停止しない修正版)
 */
class AudioManager {
    constructor() {
        const AudioContext = window.AudioContext || window.webkitAudioContext;
        this.ctx = new AudioContext();
        this.buffers = {};
        this.isMuted = false;

        this.bgmSource = null;
        this.bgmGainNode = null;
        this.currentBgmName = null;
        this.currentBgmVolume = 0.5;
        this.bgmStartTime = 0;
        this.bgmPausedAt = 0;
        this.voiceSource = null;

        // 現バージョン互換用
        this.bgmVolume = 0.6;
        this.sfxVolume = 0.7;
        this._bgmPlaying = false;
    }

    resume() {
        if (this.ctx.state === 'suspended') this.ctx.resume();
    }

    setBgmVolume(v) {
        this.bgmVolume = v / 100;
        if (this.bgmGainNode) this.bgmGainNode.gain.value = this.bgmVolume;
    }

    setSfxVolume(v) {
        this.sfxVolume = v / 100;
    }

    async loadAll() {
        const soundFiles = [
            { key: 'se_claim',   ext: 'wav' },
            { key: 'se_destroy', ext: 'wav' },
            { key: 'se_shot',    ext: 'wav' },
            { key: 'se_boost',   ext: 'wav' },
            { key: 'se_damage',  ext: 'wav' },
            { key: 'se_trail',   ext: 'wav' },
            { key: 'bgm_main',   ext: 'wav' }
        ];

        const promises = soundFiles.map(async (file) => {
            try {
                const path = `sounds/${file.key}.${file.ext}`;
                const res = await fetch(path);
                if (!res.ok) throw new Error(res.status);
                const arrayBuffer = await res.arrayBuffer();
                this.buffers[file.key] = await this.ctx.decodeAudioData(arrayBuffer);
            } catch (e) {
                console.warn(`[Audio] Failed to load: ${file.key}`, e);
            }
        });

        await Promise.all(promises);
    }

    play(name, volume = 1.0, loop = false) {
        if (this.isMuted || !this.buffers[name]) return null;
        if (this.ctx.state === 'suspended') this.ctx.resume();

        try {
            const source = this.ctx.createBufferSource();
            source.buffer = this.buffers[name];
            source.loop = loop;
            const gainNode = this.ctx.createGain();
            gainNode.gain.value = volume * this.sfxVolume;
            source.connect(gainNode);
            gainNode.connect(this.ctx.destination);
            source.start(0);
            return source;
        } catch(e) {
            console.warn("Audio play error", e);
            return null;
        }
    }

    playBGM(name, volume = 0.5, offset = 0) {
        if (this.isMuted) return;
        if (this.currentBgmName === name && this.bgmSource) {
            if (this.ctx.state === 'suspended') this.ctx.resume();
            return;
        }
        this.stopBGM(false);
        if (!this.buffers[name]) return;
        if (this.ctx.state === 'suspended') this.ctx.resume();

        try {
            const source = this.ctx.createBufferSource();
            source.buffer = this.buffers[name];
            source.loop = true;
            const gainNode = this.ctx.createGain();
            gainNode.gain.value = volume * this.bgmVolume;
            source.connect(gainNode);
            gainNode.connect(this.ctx.destination);
            const safeOffset = offset % source.buffer.duration;
            source.start(0, safeOffset);

            this.bgmSource = source;
            this.bgmGainNode = gainNode;
            this.currentBgmName = name;
            this.currentBgmVolume = volume;
            this.bgmStartTime = this.ctx.currentTime - safeOffset;
            this.bgmPausedAt = 0;
            this._bgmPlaying = true;
        } catch(e) {
            console.warn("BGM play error", e);
        }
    }

    stopBGM(resetInfo = true) {
        if (this.bgmSource) {
            try { this.bgmSource.stop(); } catch(e){}
            this.bgmSource = null;
        }
        if (resetInfo) {
            this.currentBgmName = null;
            this.bgmPausedAt = 0;
            this.bgmStartTime = 0;
            this._bgmPlaying = false;
        }
    }

    // 現バージョン互換エイリアス
    startBgm() { this.playBGM('bgm_main', 0.6); }
    stopBgm()  { this.stopBGM(); }

    pauseBGM() {
        if (!this.bgmSource) return;
        this.bgmPausedAt = this.ctx.currentTime - this.bgmStartTime;
        try { this.bgmSource.stop(); } catch(e){}
        this.bgmSource = null;
        this._bgmPlaying = false;
    }

    resumeBGM() {
        if (this.currentBgmName && this.bgmPausedAt > 0) {
            this.playBGM(this.currentBgmName, this.currentBgmVolume, this.bgmPausedAt);
        }
    }

    setBGMPitch(rate) {
        if (this.bgmSource && this.bgmSource.playbackRate) {
            try { this.bgmSource.playbackRate.setTargetAtTime(rate, this.ctx.currentTime, 0.1); } catch(e){}
        }
    }

    // 現バージョン互換 (procedural SFX は WAV に置き換え)
    playDeath()       { this.play('se_destroy', 0.8); }
    playClaim()       { this.play('se_claim', 1.0); }
    playBoost()       { this.play('se_boost', 0.5); }
    playGameOver()    { this.play('se_destroy', 0.6); }
    playSparks()      { this.play('se_boost', 0.6); }
    playMineExplode() { this.play('se_damage', 0.8); }
    playTrailStart()  { /* trail loop は updateTrailSound で管理 */ }
    playSlowOn()      { this.setBGMPitch(0.5); }
    playSlowOff()     { this.setBGMPitch(1.0); }
}
