package wav

import (
	"fmt"
	"os"

	"valhallir-deconvolver/pkg/convolve"

	"github.com/go-audio/audio"
	"github.com/go-audio/wav"
)

// WAVData represents the PCM data and metadata from a WAV file
type WAVData struct {
	SampleRate int
	BitDepth   int
	Channels   int
	PCMData    []float64
}

// toMono averages all channels to mono
func toMono(data []float64, channels int) []float64 {
	if channels == 1 {
		return data
	}
	mono := make([]float64, len(data)/channels)
	for i := 0; i < len(mono); i++ {
		sum := 0.0
		for c := 0; c < channels; c++ {
			sum += data[i*channels+c]
		}
		mono[i] = sum / float64(channels)
	}
	return mono
}

// ReadWAVFile reads a WAV file and returns its PCM data as float64 (resampled to 96kHz mono)
func ReadWAVFile(filePath string) (*WAVData, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return nil, fmt.Errorf("failed to open file %s: %w", filePath, err)
	}
	defer file.Close()

	decoder := wav.NewDecoder(file)
	if !decoder.IsValidFile() {
		return nil, fmt.Errorf("file %s is not a valid WAV file", filePath)
	}

	// Read all PCM data
	var pcmData []int32
	buf := &audio.IntBuffer{Data: make([]int, 4096), Format: &audio.Format{SampleRate: int(decoder.SampleRate), NumChannels: int(decoder.NumChans)}}

	for {
		n, err := decoder.PCMBuffer(buf)
		if err != nil {
			break
		}
		if n == 0 {
			break
		}

		// Convert int samples to float64
		for i := 0; i < n; i++ {
			pcmData = append(pcmData, int32(buf.Data[i]))
		}
	}

	// Convert int32 to float64 (-1.0 to 1.0 range, scale by bit depth)
	floatData := make([]float64, len(pcmData))
	var norm float64
	if decoder.BitDepth == 16 {
		norm = float64(1 << 15)
	} else if decoder.BitDepth == 24 {
		norm = float64(1 << 23)
	} else if decoder.BitDepth == 32 {
		norm = float64(1 << 31)
	} else {
		norm = float64(1 << 23) // fallback
	}
	for i, sample := range pcmData {
		floatData[i] = float64(sample) / norm
	}

	// Convert to mono if needed
	channels := int(decoder.NumChans)
	if channels > 1 {
		floatData = toMono(floatData, channels)
		channels = 1
	}

	// Resample to 96kHz if needed
	inSampleRate := int(decoder.SampleRate)
	if inSampleRate != 96000 {
		floatData = convolve.Resample(floatData, inSampleRate, 96000)
	}

	return &WAVData{
		SampleRate: 96000,
		BitDepth:   int(decoder.BitDepth), // original bit depth
		Channels:   1,
		PCMData:    floatData,
	}, nil
}
