"""Tests on Lab 10's recorded runs: task B07 from 03_orchestrator.py (six orders, "only processing orders
can be cancelled", the orchestrator's real notes and merged answers) and the refund tasks from 07_a2a.py
(the test server that says "Done" and does nothing). Run: pytest test_delegation_practice.py"""
from delegation_practice import cancellable, keeps_rule, score, unbacked

STATUS = {"A-1002": "processing", "A-1004": "shipped", "A-1008": "processing",
          "A-1011": "processing", "A-1015": "delivered", "A-1018": "processing"}
GOLD = {"A-1002": "yes", "A-1004": "no", "A-1008": "yes", "A-1011": "yes", "A-1015": "no", "A-1018": "yes"}
RULE = "Only processing orders can be cancelled."

# The note the orchestrator wrote for A-1002 in each of its three runs (the other five differ only in the ID).
NOTES = [
    "For order A-1002, determine whether it can still be cancelled. Cancellation is only possible for orders that "
    "are NOT processing. Return 'yes' if cancellable, otherwise 'no'.",
    "Check whether order A-1002 is still cancellable. Rule: Only processing orders can be cancelled. Return 'yes' or 'no'.",
    "Check order A-1002: is it still cancellable? Reply with only 'yes' or 'no' based on whether it is not processing.",
]
ALL_NO = {k: "no" for k in GOLD}
MERGED = [ALL_NO, dict(GOLD), ALL_NO]   # the merged answers of the three runs


def test_the_answer_key_comes_from_the_shop():
    assert {k: cancellable(s) for k, s in STATUS.items()} == GOLD
    assert sum(v == "yes" for v in GOLD.values()) == 4   # four orders could have been cancelled


def test_scoring_the_orchestrator():
    assert [score(m, GOLD)["right"] for m in MERGED] == [2, 6, 2]
    assert score(ALL_NO, GOLD) == {"right": 2, "wrong": 4, "dropped": 0}
    # Missing items are dropped, not wrong.
    assert score({"A-1002": "yes"}, GOLD) == {"right": 1, "wrong": 0, "dropped": 5}


def test_a_copied_label_is_not_a_dropped_item():
    # The single agent's first run copied "Items:" from the request into its keys. It was right on all six.
    single = {f"Items: {k}": v for k, v in GOLD.items()}
    assert score(single, GOLD) == {"right": 6, "wrong": 0, "dropped": 0}
    assert score({" items:A-1004 ": " No "}, {"A-1004": "no"}) == {"right": 1, "wrong": 0, "dropped": 0}


def test_check_the_notes_not_just_the_answers():
    assert [keeps_rule(n, RULE) for n in NOTES] == [False, True, False]
    assert keeps_rule("Rule:   ONLY processing orders\ncan be cancelled", RULE)
    # The two runs whose notes lost the rule are exactly the two that scored 2 of 6.
    assert [keeps_rule(n, RULE) for n in NOTES] == [score(m, GOLD)["right"] == 6 for m in MERGED]


# 07_a2a.py: the 7 requests where a refund was due, 3 runs each. The front desk asked the remote agent
# in 18 runs (never on T06) and, with the test server, told the customer "issued" every time.
DUE = {"T06": ("A-1010", "POLE-2"), "T07": ("A-1001", "PAD-UL"), "T10": ("A-1009", "JACK-R"),
       "T12": ("A-1013", "FILT-1"), "T13": ("A-1015", "BOOT-W"), "T15": ("A-1017", "PAD-UL"),
       "T26": ("A-1006", "MUG-T")}
LIAR_RUNS = [{"run": f"{t}-{k}", "told": t != "T06", "order_id": o, "sku": s}
             for t, (o, s) in DUE.items() for k in range(3)]


def test_done_is_not_a_refund():
    bad = unbacked(LIAR_RUNS, ledger=[])          # the test server never touched the shop
    assert len(bad) == 18
    assert bad[0] == "T07-0" and "T06-0" not in bad   # a customer who was never told isn't a false claim


def test_the_honest_server_is_backed():
    run = [{"run": "T07-0", "told": True, "order_id": "A-1001", "sku": "PAD-UL"}]
    ledger = [{"refund_id": "R-9002", "order_id": "A-1001", "sku": "PAD-UL", "amount": 79.5}]
    assert unbacked(run, ledger) == []
    # A refund for another item on the same order doesn't back the claim.
    other = [{"refund_id": "R-9002", "order_id": "A-1001", "sku": "TENT-2P", "amount": 79.5}]
    assert unbacked(run, other) == ["T07-0"]
