package config

import (
	"os"
	"path/filepath"
	"testing"
)

func TestDefaultValidate(t *testing.T) {
	if err := Default().Validate(); err != nil { t.Fatalf("default invalid: %v", err) }
}

func TestLoadAndValidate(t *testing.T) {
	dir := t.TempDir()
	path := filepath.Join(dir, "config.json")
	os.WriteFile(path, []byte(`{"audio":{"toneLeftHz":900,"toneRightHz":1700,"toneAmplitude":0.3},"fm":{"frequencyMHz":99.9},"backend":{"kind":"file","outputPath":"out.f32"},"control":{"listenAddress":"127.0.0.1:8088"}}`), 0o644)
	cfg, err := Load(path)
	if err != nil { t.Fatalf("load: %v", err) }
	if cfg.Audio.ToneLeftHz != 900 { t.Fatalf("unexpected left tone: %v", cfg.Audio.ToneLeftHz) }
}

func TestValidateRejectsBadFrequency(t *testing.T) {
	cfg := Default(); cfg.FM.FrequencyMHz = 200
	if err := cfg.Validate(); err == nil { t.Fatal("expected error") }
}

func TestValidateRejectsBadPreEmphasis(t *testing.T) {
	cfg := Default(); cfg.FM.PreEmphasisTauUS = 150
	if err := cfg.Validate(); err == nil { t.Fatal("expected error") }
}

func TestDefaultPreEmphasis(t *testing.T) {
	if Default().FM.PreEmphasisTauUS != 50 { t.Fatal("expected 50") }
}

func TestDefaultFMModulation(t *testing.T) {
	cfg := Default()
	if !cfg.FM.FMModulationEnabled { t.Fatal("expected true") }
	if cfg.FM.MaxDeviationHz != 75000 { t.Fatal("expected 75000") }
}

func TestParsePI(t *testing.T) {
	tests := []struct{ in string; want uint16; ok bool }{
		{"1234", 0x1234, true}, {"0xBEEF", 0xBEEF, true}, {"0XCAFE", 0xCAFE, true},
		{" 0x2345 ", 0x2345, true}, {"", 0, false}, {"nope", 0, false},
	}
	for _, tt := range tests {
		got, err := ParsePI(tt.in)
		if tt.ok && err != nil { t.Fatalf("ParsePI(%q): %v", tt.in, err) }
		if !tt.ok && err == nil { t.Fatalf("ParsePI(%q): expected error", tt.in) }
		if tt.ok && got != tt.want { t.Fatalf("ParsePI(%q): got %x want %x", tt.in, got, tt.want) }
	}
}

func TestValidateRejectsInvalidPI(t *testing.T) {
	cfg := Default(); cfg.RDS.PI = "nope"
	if err := cfg.Validate(); err == nil { t.Fatal("expected error") }
}

func TestValidateRejectsEmptyPI(t *testing.T) {
	cfg := Default(); cfg.RDS.PI = ""
	if err := cfg.Validate(); err == nil { t.Fatal("expected error") }
}

func TestEffectiveDeviceRate(t *testing.T) {
	cfg := Default()
	if cfg.EffectiveDeviceRate() != float64(cfg.FM.CompositeRateHz) { t.Fatal("expected composite rate") }
	cfg.Backend.DeviceSampleRateHz = 912000
	if cfg.EffectiveDeviceRate() != 912000 { t.Fatal("expected 912000") }
}
