//go:build windows

package audio

import (
	"os"

	"github.com/braheezy/shine-mp3/pkg/mp3"
)

// mp3Rate is the encode sample rate. The capture pipeline is 16 kHz, but the
// Shine encoder emits broken "free-format" frames at MPEG-2 rates (16/22/24
// kHz) that most players reject. Encoding at an MPEG-1 rate (we upsample ×2 to
// 32 kHz) produces standard, universally-playable MP3s.
const mp3Rate = sampleRate * 2 // 32000

// writeMP3 encodes 16 kHz mono 16-bit PCM to a standard MP3 file using the
// pure-Go Shine encoder (no CGO). Two quirks are worked around:
//   - 16 kHz (MPEG-2) yields broken free-format frames → upsample ×2 to 32 kHz.
//   - Shine's Write only encodes half the samples for MONO input (its loop
//     advances by samples_per_pass*2). Feeding STEREO interleaved data (the
//     encoder reads samples_per_pass*channels per pass) encodes everything, so
//     we duplicate mono → L=R stereo.
func writeMP3(path string, pcm []byte) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()
	mono32 := upsample2(bytesToInt16(pcm)) // 16 kHz → 32 kHz mono
	stereo := make([]int16, len(mono32)*2) // L=R interleaved
	for i, v := range mono32 {
		stereo[2*i], stereo[2*i+1] = v, v
	}
	// Shine's Write() reads a WHOLE frame (samplesPerPass × channels = 1152 × 2 =
	// 2304 interleaved samples for MPEG-1) per pass via unsafe pointer arithmetic,
	// regardless of how short the trailing chunk is. If the buffer isn't an exact
	// multiple of a frame, the final pass reads past the slice and the process
	// dies with an access violation (0xc0000005) inside windowFilterSubband.
	// Pad with trailing silence to a whole number of frames so no partial pass
	// exists. (~36 ms of silence at most — inaudible.)
	const frameInterleaved = 1152 * 2 // samplesPerPass(MPEG-1) × 2 channels
	if rem := len(stereo) % frameInterleaved; rem != 0 {
		stereo = append(stereo, make([]int16, frameInterleaved-rem)...)
	}
	if len(stereo) == 0 {
		return nil // nothing to encode (empty recording)
	}
	enc := mp3.NewEncoder(mp3Rate, 2)
	return enc.Write(f, stereo)
}

// upsample2 doubles the sample rate with linear interpolation (16 kHz → 32 kHz).
func upsample2(in []int16) []int16 {
	if len(in) == 0 {
		return in
	}
	out := make([]int16, len(in)*2)
	for i := range in {
		out[2*i] = in[i]
		if i+1 < len(in) {
			out[2*i+1] = int16((int32(in[i]) + int32(in[i+1])) / 2)
		} else {
			out[2*i+1] = in[i]
		}
	}
	return out
}
