package stereo

import (
	"math"
	"math/cmplx"
	"testing"

	"github.com/jan/fm-rds-tx/internal/audio"
)

func TestSSBSidebandSuppression(t *testing.T) {
	const sampleRate = 228000
	const testFreq = 5000.0 // 5 kHz test tone
	const nSamples = 228000 // 1 second

	for _, mode := range []Mode{ModeDSB, ModeSSB, ModeVSB} {
		enc := NewStereoEncoder(sampleRate)
		enc.SetMode(mode, sampleRate)

		// Generate 1 second of stereo: L=tone, R=-tone → mono=0, diff=tone
		composite := make([]float64, nSamples)
		for i := 0; i < nSamples; i++ {
			phase := 2 * math.Pi * testFreq * float64(i) / sampleRate
			l := audio.Sample(0.5 * math.Sin(phase))
			r := audio.Sample(-0.5 * math.Sin(phase))
			c := enc.Encode(audio.NewFrame(l, r))
			composite[i] = c.Mono + c.Stereo
		}

		// FFT to check spectrum
		n := len(composite)
		buf := make([]complex128, n)
		for i := range buf {
			buf[i] = complex(composite[i], 0)
		}
		// Simple DFT at key frequencies (not full FFT, just spot-check)
		freqBin := func(hz float64) float64 {
			bin := int(hz * float64(n) / sampleRate)
			if bin >= n/2 {
				return 0
			}
			var sum complex128
			for i := 0; i < n; i++ {
				angle := -2 * math.Pi * float64(bin) * float64(i) / float64(n)
				sum += complex(composite[i], 0) * cmplx.Rect(1, angle)
			}
			return cmplx.Abs(sum) / float64(n)
		}

		lsb := freqBin(38000 - testFreq) // 33 kHz — lower sideband
		usb := freqBin(38000 + testFreq) // 43 kHz — upper sideband

		suppression := 0.0
		if usb > 0 && lsb > 0 {
			suppression = 20 * math.Log10(usb/lsb)
		}

		t.Logf("Mode %s: LSB(%.0fHz)=%.4f USB(%.0fHz)=%.4f suppression=%.1f dB",
			mode, 38000-testFreq, lsb, 38000+testFreq, usb, suppression)

		switch mode {
		case ModeDSB:
			// Both sidebands should be roughly equal
			if math.Abs(suppression) > 3 {
				t.Errorf("DSB: sidebands should be balanced, got %.1f dB", suppression)
			}
		case ModeSSB:
			// USB should be suppressed by >20 dB
			if suppression > -20 {
				t.Errorf("SSB: USB suppression only %.1f dB (want >20 dB)", suppression)
			}
		case ModeVSB:
			// 5 kHz tone is above 200 Hz crossover → should behave like SSB
			if suppression > -15 {
				t.Errorf("VSB: USB suppression only %.1f dB at %0.f Hz (want >15 dB)", suppression, testFreq)
			}
		}
	}
}
