package audio

import (
	"bytes"
	"io"
	"sync"
	"sync/atomic"
	"time"

	"github.com/ebitengine/oto/v3"
	"github.com/hajimehoshi/go-mp3"
	"go.uber.org/zap"
)

// PlayMP3Loop 循环播放 MP3(非阻塞)
// 返回 player 和清理函数,调用者负责 defer cleanup()
func PlayMP3Loop(r io.ReadCloser) (*oto.Player, func() error, error) {
	// Read the entire MP3 into memory for seeking support
	data, err := io.ReadAll(r)
	if err != nil {
		r.Close()
		return nil, func() error { return nil }, err
	}
	r.Close()

	dec, err := mp3.NewDecoder(bytes.NewReader(data))
	if err != nil {
		return nil, func() error { return nil }, err
	}

	// 获取采样率信息
	sampleRate := int(dec.SampleRate())

	// 需要重采样（使用 Sinc 高质量重采样）
	var reader io.Reader = dec
	if needsResampling(sampleRate) {
		zap.S().Infof("BGM Sinc 重采样: %d Hz → %d Hz", sampleRate, UniversalSampleRate)
		reader = newSincResampler(dec, sampleRate, UniversalSampleRate, 2)
	}

	otoCtx, err := initContext()
	if err != nil {
		return nil, func() error { return nil }, err
	}

	player := otoCtx.NewPlayer(reader)

	playing := atomic.Bool{}
	playing.Store(true)
	var wg sync.WaitGroup
	wg.Add(1)

	go func() {
		defer wg.Done()
		for playing.Load() {
			player.Play()
			for playing.Load() && player.IsPlaying() {
				time.Sleep(10 * time.Millisecond)
			}
			if playing.Load() {
				// 重置解码器位置
				_, _ = dec.Seek(0, io.SeekStart)
			}
		}
	}()

	cleanup := func() error {
		playing.Store(false)
		wg.Wait()
		player.Close()
		return nil
	}

	return player, cleanup, nil
}
