package main

import (
	"testing"

	"hamlog/internal/sat"
)

// The dial arithmetic has to be the exact inverse of the correction, or every
// touch of the knob would nudge the nominal frequency a little further off and
// the uplink would walk across the passband over a pass.
func TestSatNominalFromDialRoundTrip(t *testing.T) {
	// A range of range rates: hard approach, drifting, hard recession. ±8 km/s
	// covers a low orbit overhead.
	for _, rate := range []float64{-8, -3.2, -0.4, 0, 0.4, 3.2, 8} {
		p := sat.Position{RangeRate: rate}
		for _, nominal := range []int64{29_450_000, 145_900_000, 435_850_000, 10_489_675_000} {
			sh := sat.Doppler(p, nominal, 0)
			factor := -rate / satLightKmS
			got := satNominalFromDial(sh.DownHz, factor)
			if diff := got - nominal; diff > 1 || diff < -1 {
				t.Errorf("rate %.1f km/s, %d Hz: heard %d, came back as %d (%+d)",
					rate, nominal, sh.DownHz, got, diff)
			}
		}
	}
}

// SAT_MODE is what goes on a QSL card, and the letters are the uplink's then
// the downlink's — the order operators write and the order ADIF wants.
func TestSatModeLetters(t *testing.T) {
	for _, tc := range []struct {
		name     string
		up, down int64
		want     string
	}{
		{"FO-29: 2 m up, 70 cm down", 145_950_000, 435_850_000, "V/U"},
		{"AO-91: 70 cm up, 2 m down", 435_250_000, 145_960_000, "U/V"},
		{"AO-7 mode A: 2 m up, 10 m down", 145_900_000, 29_450_000, "V/A"},
		{"QO-100: 13 cm up, 3 cm down", 2_400_175_000, 10_489_675_000, "S/X"},
		{"receive only", 0, 145_800_000, ""},
	} {
		if got := satModeLetters(tc.up, tc.down); got != tc.want {
			t.Errorf("%s: got %q, wanted %q", tc.name, got, tc.want)
		}
	}
}
