package audio

import (
	"io"

	resampling "github.com/tphakala/go-audio-resampler"
	"go.uber.org/zap"
)

// minProcessSamples 是 FIR 滤波器产生可靠输出所需的最小输入样本数
const minProcessSamples = 64

// needsResampling 检查是否需要重采样
func needsResampling(sourceRate int) bool {
	return sourceRate != UniversalSampleRate
}

// sincResampler 基于 go-audio-resampler 的高质量重采样器
// 使用 Windowed Sinc + Polyphase FIR 算法，专业级音质
type sincResampler struct {
	decoder    io.Reader
	resampler  resampling.Resampler
	inputBuf   []float64 // 输入缓冲区：int16→float64 转换后暂存
	outputBuf  []float64 // 输出缓冲区：Process/Flush 产出但未消费的样本
	inputBytes []byte    // 复用的字节读取缓冲区
	flushed    bool      // 是否已完成 Flush
	eof        bool      // 上游是否已返回 EOF
}

// newSincResampler 创建高质量 Sinc 重采样器
// 使用场景：大广场音效、高保真音乐
func newSincResampler(src io.Reader, inRate, outRate, channels int) io.Reader {
	if inRate == outRate {
		return src
	}

	config := &resampling.Config{
		InputRate:  float64(inRate),
		OutputRate: float64(outRate),
		Channels:   channels,
		Quality: resampling.QualitySpec{
			Preset: resampling.QualityVeryHigh,
		},
	}

	r, err := resampling.New(config)
	if err != nil {
		zap.S().Warnf("Sinc 重采样器创建失败，降级为透传: %v", err)
		return src
	}

	return &sincResampler{
		decoder:    src,
		resampler:  r,
		inputBuf:   make([]float64, 0, 4096),
		outputBuf:  make([]float64, 0, 4096),
		inputBytes: make([]byte, 1024),
	}
}

func (r *sincResampler) Read(p []byte) (int, error) {
	if len(p) < 2 {
		return 0, io.ErrShortBuffer
	}
	maxSamples := len(p) / 2

	// 主循环：直到有足够输出数据或 EOF
	for len(r.outputBuf) < maxSamples {
		// 阶段1：从上游读取数据，累积到 inputBuf
		for len(r.inputBuf) < minProcessSamples && !r.eof {
			nn, readErr := r.decoder.Read(r.inputBytes)
			if readErr != nil && readErr != io.EOF {
				return 0, readErr
			}
			if readErr == io.EOF || nn == 0 {
				r.eof = true
				break
			}

			sampleCount := nn / 2
			for i := range sampleCount {
				sample := int16(r.inputBytes[i*2]) | int16(r.inputBytes[i*2+1])<<8
				r.inputBuf = append(r.inputBuf, float64(sample)/32768.0)
			}
		}

		// 阶段2：处理输入数据
		if len(r.inputBuf) > 0 {
			output, err := r.resampler.Process(r.inputBuf)
			if err != nil {
				return 0, err
			}
			r.inputBuf = r.inputBuf[:0]
			if len(output) > 0 {
				r.outputBuf = append(r.outputBuf, output...)
			}
			continue
		}

		// 阶段3：EOF 且 inputBuf 为空，调用 Flush 获取尾部残留
		if r.eof && !r.flushed {
			r.flushed = true
			flushed, err := r.resampler.Flush()
			if err != nil {
				return 0, err
			}
			if len(flushed) > 0 {
				r.outputBuf = append(r.outputBuf, flushed...)
			}
			continue
		}

		// 无更多数据可获取
		break
	}

	if len(r.outputBuf) == 0 {
		return 0, io.EOF
	}

	// 写入输出
	n := min(len(r.outputBuf), maxSamples)
	writeFloat64ToLE16(p, r.outputBuf[:n])
	if n < len(r.outputBuf) {
		r.outputBuf = r.outputBuf[n:]
	} else {
		r.outputBuf = r.outputBuf[:0]
	}

	return n * 2, nil
}

// writeFloat64ToLE16 将 float64 样本转换为 int16 LE 写入 buf
func writeFloat64ToLE16(buf []byte, samples []float64) {
	for i, s := range samples {
		if s > 1.0 {
			s = 1.0
		} else if s < -1.0 {
			s = -1.0
		}
		v := int32(s * 32768.0)
		if v > 32767 {
			v = 32767
		}
		buf[i*2] = byte(v)
		buf[i*2+1] = byte(v >> 8)
	}
}
