"""UnlockCalendarRepo round-trip on SQLite — the unlock calendar moved off the single-node JSON file on
the surfer-data PVC into the operational DB (networked, node-agnostic). Same event shape `load_unlock_events`
returns today: [{"sym","cliff_day","n","cat"}]. No network."""
import datetime as dt

from fxhnt.adapters.persistence.unlock_calendar_repo import UnlockCalendarRepo

_EVENTS = [
    {"sym": "AAVE", "cliff_day": 20100, "n": 5.0e7, "cat": "insiders"},
    {"sym": "ARB", "cliff_day": 20150, "n": 1.2e8, "cat": "privateSale"},
]


def test_roundtrip_same_shape():
    repo = UnlockCalendarRepo("sqlite://")
    repo.migrate()
    repo.write_events(_EVENTS)
    got = repo.read_events()
    # same SHAPE (list of dicts with the same keys/values the JSON loader returns)
    assert sorted(got, key=lambda e: e["sym"]) == sorted(_EVENTS, key=lambda e: e["sym"])
    for e in got:
        assert set(e) == {"sym", "cliff_day", "n", "cat"}
        assert isinstance(e["cliff_day"], int) and isinstance(e["n"], float)


def test_empty_table_returns_empty_list():
    repo = UnlockCalendarRepo("sqlite://")
    repo.migrate()
    assert repo.read_events() == []


def test_write_is_idempotent_upsert():
    repo = UnlockCalendarRepo("sqlite://")
    repo.migrate()
    repo.write_events(_EVENTS)
    repo.write_events(_EVENTS)            # re-write same events
    got = repo.read_events()
    assert len(got) == len(_EVENTS)       # upsert, not duplicate

    # an updated `n`/`cat` for an existing (sym, cliff_day) overwrites in place
    repo.write_events([{"sym": "AAVE", "cliff_day": 20100, "n": 9.9e7, "cat": "insiders"}])
    got = repo.read_events()
    assert len(got) == len(_EVENTS)
    aave = next(e for e in got if e["sym"] == "AAVE")
    assert aave["n"] == 9.9e7


def test_migrate_idempotent():
    repo = UnlockCalendarRepo("sqlite://")
    repo.migrate()
    repo.migrate()                        # create-if-not-exists, no error on re-run
    repo.write_events(_EVENTS)
    assert len(repo.read_events()) == len(_EVENTS)


def test_write_empty_is_noop():
    repo = UnlockCalendarRepo("sqlite://")
    repo.migrate()
    repo.write_events(_EVENTS)
    repo.write_events([])                  # empty write must NOT wipe the calendar
    assert len(repo.read_events()) == len(_EVENTS)


def test_src_updated_at_accepted():
    """An explicit `at` timestamp is accepted (mirrors the paper_* repos' src_updated_at)."""
    repo = UnlockCalendarRepo("sqlite://")
    repo.migrate()
    repo.write_events(_EVENTS, at=dt.datetime(2026, 6, 24, tzinfo=dt.UTC))
    assert len(repo.read_events()) == len(_EVENTS)
