package rds

import (
	"math"
	"strings"
	"testing"
)

func TestCRC10KnownVector(t *testing.T) {
	c := crc10(0x1234)
	if c > 0x3FF { t.Fatalf("CRC exceeds 10 bits: %x", c) }
}

func TestEncodeBlockProduces26Bits(t *testing.T) {
	block := encodeBlock(0x1234, 'A')
	if block>>26 != 0 { t.Fatalf("block exceeds 26 bits: %x", block) }
	if uint16(block>>10) != 0x1234 { t.Fatalf("data mismatch") }
}

func TestBuildGroup0A(t *testing.T) {
	g := buildGroup0A(0x1234, 0, false, false, 0, "TESTFM")
	if g[0] != 0x1234 { t.Fatalf("block A not PI: %x", g[0]) }
	if byte(g[3]>>8) != 'T' || byte(g[3]&0xFF) != 'E' { t.Fatal("wrong PS chars") }
}

func TestBuildGroup2A(t *testing.T) {
	g := buildGroup2A(0x1234, 0, false, false, 0, "Hello World")
	if g[0] != 0x1234 { t.Fatal("block A not PI") }
	if (g[1]>>12)&0x0F != 2 { t.Fatal("wrong group type") }
}

func TestBuildGroupUsesConfiguredPI(t *testing.T) {
	if buildGroup0A(0xBEEF, 0, false, false, 0, "TEST")[0] != 0xBEEF { t.Fatal("PI mismatch 0A") }
	if buildGroup2A(0xCAFE, 0, false, false, 0, "Hello")[0] != 0xCAFE { t.Fatal("PI mismatch 2A") }
}

func TestEncoderGenerate(t *testing.T) {
	cfg := DefaultConfig(); cfg.SampleRate = 228000
	enc, err := NewEncoder(cfg)
	if err != nil { t.Fatal(err) }
	samples := enc.Generate(1024)
	if len(samples) != 1024 { t.Fatal("wrong length") }
	var energy, maxAbs float64
	for _, s := range samples {
		energy += s * s
		if math.Abs(s) > maxAbs { maxAbs = math.Abs(s) }
	}
	if energy == 0 { t.Fatal("zero energy") }
	// Unity output: peak should be close to 1.0
	if maxAbs > 3.0 { t.Fatalf("exceeds unity: %.6f", maxAbs) }
}

func TestEncoderNextSample(t *testing.T) {
	cfg := DefaultConfig(); cfg.SampleRate = 228000
	enc, _ := NewEncoder(cfg)
	s := enc.NextSample()
	// Should not panic and should produce a value
	if math.IsNaN(s) { t.Fatal("NaN") }
}

func TestEncoderReset(t *testing.T) {
	cfg := DefaultConfig(); cfg.SampleRate = 228000
	enc, _ := NewEncoder(cfg)
	a := enc.NextSample()
	for i := 0; i < 100; i++ { enc.NextSample() }
	enc.Reset()
	b := enc.NextSample()
	if math.Abs(a-b) > 1e-9 { t.Fatalf("reset failed: %v vs %v", a, b) }
}

func TestGroupSchedulerCycles(t *testing.T) {
	cfg := DefaultConfig(); cfg.PS = "TESTPS"; cfg.RT = "short"
	gs := newGroupScheduler(cfg)
	for i := 0; i < 40; i++ { _ = gs.NextGroup() }
}

func TestNormalizePS(t *testing.T) {
	if normalizePS("radiox") != "RADIOX  " { t.Fatal("wrong PS") }
}

func TestNormalizeRT(t *testing.T) {
	if len(normalizeRT(strings.Repeat("a", 80))) != 64 { t.Fatal("wrong RT length") }
}


func TestRTSegmentCount(t *testing.T) {
	if rtSegmentCount("Hi") != 1 { t.Fatal("expected 1") }
	if rtSegmentCount("Hello World!") != 3 { t.Fatal("expected 3") }
	if rtSegmentCount(strings.Repeat("x", 64)) != 16 { t.Fatal("expected 16") }
}
