package offline

import (
	"testing"
	"time"

	cfgpkg "github.com/jan/fm-rds-tx/internal/config"
	"github.com/jan/fm-rds-tx/internal/dsp"
)

func extractComposite(g *Generator, duration time.Duration) ([]float64, float64) {
	cfg := g.cfg
	cfg.FM.FMModulationEnabled = false
	gen := NewGenerator(cfg)
	frame := gen.GenerateFrame(duration)
	samples := make([]float64, len(frame.Samples))
	for i, s := range frame.Samples {
		samples[i] = float64(s.I)
	}
	return samples, frame.SampleRateHz
}

func TestCompositeHasPilotAt19kHz(t *testing.T) {
	cfg := cfgpkg.Default()
	cfg.FM.FMModulationEnabled = false
	cfg.FM.StereoEnabled = true
	samples, rate := extractComposite(NewGenerator(cfg), 200*time.Millisecond)
	pilotEnergy := dsp.BandEnergy(samples, rate, 19000, 500)
	noiseEnergy := dsp.BandEnergy(samples, rate, 12000, 500)
	if pilotEnergy < noiseEnergy*10 {
		t.Fatalf("missing 19 kHz pilot: pilot=%.6f noise=%.6f", pilotEnergy, noiseEnergy)
	}
}

func TestCompositeHasStereoAt38kHz(t *testing.T) {
	cfg := cfgpkg.Default()
	cfg.FM.FMModulationEnabled = false
	cfg.FM.StereoEnabled = true
	cfg.Audio.ToneLeftHz = 1000
	cfg.Audio.ToneRightHz = 1600 // different L/R -> stereo energy
	samples, rate := extractComposite(NewGenerator(cfg), 200*time.Millisecond)
	stereoEnergy := dsp.BandEnergy(samples, rate, 38000, 3000)
	noiseEnergy := dsp.BandEnergy(samples, rate, 80000, 500)
	if stereoEnergy < noiseEnergy*1 {
		t.Fatalf("missing 38 kHz stereo energy: stereo=%.6f noise=%.6f", stereoEnergy, noiseEnergy)
	}
}

func TestCompositeHasRDSAt57kHz(t *testing.T) {
	cfg := cfgpkg.Default()
	cfg.FM.FMModulationEnabled = false
	cfg.RDS.Enabled = true
	samples, rate := extractComposite(NewGenerator(cfg), 200*time.Millisecond)
	rdsEnergy := dsp.BandEnergy(samples, rate, 57000, 3000)
	noiseEnergy := dsp.BandEnergy(samples, rate, 45000, 500)
	if rdsEnergy < noiseEnergy*5 {
		t.Fatalf("missing 57 kHz RDS energy: rds=%.6f noise=%.6f", rdsEnergy, noiseEnergy)
	}
}

func TestCompositeNoStereoWhenDisabled(t *testing.T) {
	cfg := cfgpkg.Default()
	cfg.FM.FMModulationEnabled = false
	cfg.FM.StereoEnabled = false
	samples, rate := extractComposite(NewGenerator(cfg), 200*time.Millisecond)
	pilotEnergy := dsp.BandEnergy(samples, rate, 19000, 500)
	// Should be near-zero compared to mono energy
	monoEnergy := dsp.BandEnergy(samples, rate, 1000, 500)
	if monoEnergy > 0 && pilotEnergy > monoEnergy*0.01 {
		t.Fatalf("pilot should be suppressed: pilot=%.6f mono=%.6f", pilotEnergy, monoEnergy)
	}
}

func TestCompositeNoRDSWhenDisabled(t *testing.T) {
	cfg := cfgpkg.Default()
	cfg.FM.FMModulationEnabled = false
	cfg.RDS.Enabled = false
	samples, rate := extractComposite(NewGenerator(cfg), 200*time.Millisecond)
	rdsEnergy := dsp.BandEnergy(samples, rate, 57000, 3000)
	monoEnergy := dsp.BandEnergy(samples, rate, 1000, 500)
	if monoEnergy > 0 && rdsEnergy > monoEnergy*0.001 {
		t.Fatalf("RDS should be suppressed: rds=%.6f mono=%.6f", rdsEnergy, monoEnergy)
	}
}
