"""Tests from Lab 06: Alex's chats and real recorded gpt-5.4-nano replies. Run: pytest test_memory_practice.py"""
from memory_practice import FactMemory, format_hits, score, stores_holding, window

PHONE = "+1 415 555 0142"
TRIP_HITS = [  # what search returned for "Which city am I visiting in May?", most similar first
    {"session": 2, "date": "2026-01-19", "content": "I'm planning a trip to Lisbon in May. Can you help me plan it?"},
    {"session": 5, "date": "2026-03-02", "content": "Change of plans for the trip: we're going to Porto instead of Lisbon. Same dates in May."},
]


def test_the_window_keeps_only_the_newest():
    msgs = [{"i": i} for i in range(50)]
    assert window(msgs, 10) == msgs[-10:]
    assert window(msgs[:3], 10) == msgs[:3]
    assert window(msgs, 0) == []


def test_retrieved_memories_get_dates_in_time_order():
    dated = format_hits(list(reversed(TRIP_HITS)))
    assert dated.splitlines() == [
        "[Session 2 · 2026-01-19] User said: I'm planning a trip to Lisbon in May. Can you help me plan it?",
        "[Session 5 · 2026-03-02] User said: Change of plans for the trip: we're going to Porto instead of Lisbon. Same dates in May.",
    ]
    assert format_hits(TRIP_HITS, dated=False).splitlines()[0] == "- I'm planning a trip to Lisbon in May. Can you help me plan it?"


def test_a_new_value_replaces_the_old_one_and_lists_hold_both():
    m = FactMemory()
    m.update("employer", "Freightly", "2026-01-05")
    m.update("employer", "Ledgerly", "2026-02-02")
    m.update("employer", "Ledgerly", "2026-02-16")      # repeated, not changed
    assert m.now("employer") == ["Ledgerly"]
    assert m.before("employer") == ["Freightly"]
    m.update("dog_name", "Biscuit", "2026-01-05")
    m.update("dog_name", "Comet", "2026-02-12")
    assert m.now("dog_name") == ["Biscuit", "Comet"]  # one value per key let Comet replace Biscuit


def test_forget_removes_the_value_everywhere_the_object_keeps_it():
    m = FactMemory()
    m.update("contact_phone_number", PHONE, "2026-01-19")
    m.update("employer", "Ledgerly", "2026-02-02")
    m.forget("contact_phone_number")
    assert m.now("contact_phone_number") == []
    assert not m.holds(PHONE)
    assert m.now("employer") == ["Ledgerly"]


def test_score_like_the_lab():
    assert score("Your budget for the May trip, not counting flights, is around **1,500 euros**.",
                 ["2,000", "2000"], ["1,500", "1500"]) == "stale"
    assert score("Your budget for the May trip (not counting flights) is about **2,000 euros**.",
                 ["2,000", "2000"], ["1,500", "1500"]) == "pass"
    assert score("I don’t know your dog’s name based on the memory provided.", ["biscuit"]) == "missed"
    assert score("I don't know your phone number.", [], [PHONE, "555 0142"], kind="forgotten") == "pass"
    # a refusal isn't a deletion: the number is still in the stores the prompt was built from
    stores = {"messages": [f"Oh, and my phone number is {PHONE} in case you need it for booking reminders."],
              "facts": {"employer": "Ledgerly"}, "history": [{"key": "contact_phone_number", "value": PHONE}]}
    assert stores_holding(stores, PHONE) == ["messages", "history"]
