//go:build windows

package audio

import (
	"encoding/binary"
	"fmt"
	"os"
)

// The DVK/recorder pipeline uses a single fixed PCM format end-to-end: 16 kHz
// mono 16-bit. That's plenty for SSB voice (3 kHz audio bandwidth), keeps files
// tiny (~32 KB/s), and — fed through WASAPI's AUTOCONVERTPCM — plays/records on
// any device regardless of its native mix format.
const (
	sampleRate    = 16000

	channels      = 1
	bitsPerSample = 16
	blockAlign    = channels * bitsPerSample / 8 // bytes per frame (=2)
	bytesPerSec   = sampleRate * blockAlign      // =32000
)

// writeWAV writes 16-bit PCM as a canonical RIFF/WAVE file.
func writeWAV(path string, pcm []byte) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()
	dataLen := len(pcm)
	put := func(v any) { _ = binary.Write(f, binary.LittleEndian, v) }
	f.WriteString("RIFF")
	put(uint32(36 + dataLen))
	f.WriteString("WAVE")
	f.WriteString("fmt ")
	put(uint32(16))            // PCM fmt chunk size
	put(uint16(1))             // WAVE_FORMAT_PCM
	put(uint16(channels))      //
	put(uint32(sampleRate))    //
	put(uint32(bytesPerSec))   // byte rate
	put(uint16(blockAlign))    //
	put(uint16(bitsPerSample)) //
	f.WriteString("data")
	put(uint32(dataLen))
	_, err = f.Write(pcm)
	return err
}

// readWAV reads a PCM WAV and returns the raw sample bytes plus its format.
// Handles arbitrary chunk ordering (walks the RIFF chunk list).
func readWAV(path string) (pcm []byte, rate, ch, bits int, err error) {
	b, err := os.ReadFile(path)
	if err != nil {
		return nil, 0, 0, 0, err
	}
	if len(b) < 12 || string(b[0:4]) != "RIFF" || string(b[8:12]) != "WAVE" {
		return nil, 0, 0, 0, fmt.Errorf("not a WAVE file")
	}
	i := 12
	for i+8 <= len(b) {
		id := string(b[i : i+4])
		size := int(binary.LittleEndian.Uint32(b[i+4 : i+8]))
		body := i + 8
		if body+size > len(b) {
			size = len(b) - body
		}
		switch id {
		case "fmt ":
			if size >= 16 {
				ch = int(binary.LittleEndian.Uint16(b[body+2 : body+4]))
				rate = int(binary.LittleEndian.Uint32(b[body+4 : body+8]))
				bits = int(binary.LittleEndian.Uint16(b[body+14 : body+16]))
			}
		case "data":
			pcm = b[body : body+size]
		}
		i = body + size
		if size%2 == 1 {
			i++ // chunks are word-aligned
		}
	}
	if pcm == nil || rate == 0 {
		return nil, 0, 0, 0, fmt.Errorf("WAV missing fmt/data")
	}
	return pcm, rate, ch, bits, nil
}
