package lookup

import (
	"context"
	"path/filepath"
	"testing"

	"hamlog/internal/db"
)

func testCache(t *testing.T) *Cache {
	t.Helper()
	conn, err := db.Open(filepath.Join(t.TempDir(), "c.db"))
	if err != nil {
		t.Fatalf("open: %v", err)
	}
	t.Cleanup(func() { conn.Close() })
	return NewCache(conn, 0)
}

// Adding a field to the cache leaves every row already in it without that field,
// and the cache lasts thirty days. So a callsign looked up before the change
// would go a MONTH without its island reference — which is exactly what the
// first test of the feature ran into: a QRZ record plainly carrying
// <iota>EU-048</iota>, and no IOTA on the entry.
//
// A row that predates the column is therefore treated as stale and refetched
// once. NULL and "" mean different things here, and that is the whole mechanism.
func TestCacheRefetchesRowsWrittenBeforeTheIOTAColumn(t *testing.T) {
	c := testCache(t)
	ctx := context.Background()

	// An operator with an island: stored and returned.
	if err := c.Put(ctx, Result{Callsign: "F5IRH", Name: "Max", IOTA: "EU-048", Source: "qrz"}); err != nil {
		t.Fatalf("put: %v", err)
	}
	got, ok := c.Get(ctx, "F5IRH")
	if !ok || got.IOTA != "EU-048" {
		t.Fatalf("Get = (%+v,%v), want the island back", got, ok)
	}

	// An operator with NO island: an empty string is stored, and the row stays
	// usable. If this wrote NULL, every ordinary callsign would refetch for ever.
	if err := c.Put(ctx, Result{Callsign: "M0ABC", Name: "Ann", Source: "qrz"}); err != nil {
		t.Fatalf("put: %v", err)
	}
	got, ok = c.Get(ctx, "M0ABC")
	if !ok {
		t.Fatal("a callsign with no island was treated as stale — every lookup would repeat for ever")
	}
	if got.IOTA != "" {
		t.Errorf("IOTA = %q for an operator with no island", got.IOTA)
	}
}
