package main

import (
	"testing"
	"time"

	"hamlog/internal/qso"
)

func at(s string) time.Time {
	t, err := time.Parse("2006-01-02 15:04", s)
	if err != nil {
		panic(err)
	}
	return t
}

// The number is the contact's rank in the WHOLE log, not its position in what
// the grid happens to be showing. Ranking inside the result would renumber
// every contact the moment a filter is applied, and QSO #1 would change
// identity as the operator typed.
func TestQSONumberIsGlobalNotPerPage(t *testing.T) {
	a := &App{}
	// The log, oldest first: ids are deliberately NOT in date order, which is
	// exactly what an imported ADIF produces.
	a.qsoNumbers = map[int64]int{
		770: 1, // oldest, imported last so it has the highest id
		101: 2,
		102: 3,
		103: 4,
	}

	// A filtered page holding only two of them, newest first as the grid asks.
	page := []qso.QSO{{ID: 103}, {ID: 770}}
	a.stampQSONumbers(page)

	if page[0].Number != 4 {
		t.Errorf("id 103 numbered %d, want 4", page[0].Number)
	}
	if page[1].Number != 1 {
		t.Errorf("id 770 numbered %d, want 1 — the oldest contact, whatever its id", page[1].Number)
	}
}

// A contact logged now is the newest, so it takes the next number without
// rereading the log — a full scan per QSO would be felt in a contest run.
func TestNewQSOTakesTheNextNumber(t *testing.T) {
	a := &App{}
	a.qsoNumbers = map[int64]int{1: 1, 2: 2, 3: 3}
	a.qsoNumMax = at("2026-08-13 10:00")

	a.noteQSONumbered(9, at("2026-08-13 11:00"))
	if got := a.qsoNumbers[9]; got != 4 {
		t.Errorf("new QSO numbered %d, want 4", got)
	}
	if !a.qsoNumMax.Equal(at("2026-08-13 11:00")) {
		t.Error("the newest date was not carried forward")
	}
}

// A contact entered with an OLDER date belongs in the middle of the order.
// Appending it would number it last, which is wrong — so the map is dropped and
// rebuilt correctly instead.
func TestBackdatedQSOForcesARebuild(t *testing.T) {
	a := &App{}
	a.qsoNumbers = map[int64]int{1: 1, 2: 2, 3: 3}
	a.qsoNumMax = at("2026-08-13 10:00")

	a.noteQSONumbered(9, at("2020-01-01 09:00"))
	if a.qsoNumbers != nil {
		t.Errorf("a back-dated QSO was appended as the newest: %v", a.qsoNumbers)
	}
}

// Nothing built yet: the lazy build will see the new contact anyway, so this
// must not create a one-entry map that then numbers the whole log wrongly.
func TestNoteBeforeAnyBuildDoesNothing(t *testing.T) {
	a := &App{}
	a.noteQSONumbered(9, at("2026-08-13 11:00"))
	if a.qsoNumbers != nil {
		t.Errorf("built a map from a single contact: %v", a.qsoNumbers)
	}
}

// With no index available the column is simply empty — never wrong.
func TestStampWithoutIndexLeavesZero(t *testing.T) {
	a := &App{} // no qso repo, so the index cannot be built
	page := []qso.QSO{{ID: 1}, {ID: 2}}
	a.stampQSONumbers(page)
	for _, q := range page {
		if q.Number != 0 {
			t.Errorf("invented a number without an index: %d", q.Number)
		}
	}
}
