#!/usr/bin/env python3
"""Regression tests for the empty-My-Packs FIFA 17 compatibility workaround (bug 6c).

Pins the behavior store_catalog() now depends on:
- unopenedPackIds == []  -> exactly one synthetic active `mypacks` placeholder id 65534
- unopenedPackIds == [70] -> no synthetic placeholder; the genuine owned pack is shown
- synthetic id 65534 stays economy-safe (non-resolvable, non-openable, non-granting)
- normal store packs (1/5/6/7) are untouched by the empty-state behavior

See docs/evidence/STORE_TILE_6C.md and FIFA17_EMPTY_MYPACKS_CLIENT_CONTRACT.md.
Standalone unit test in the project style: `python3 test_empty_mypacks.py`.
"""
import importlib
import os
import sys
import tempfile

TOOLS = os.path.dirname(os.path.abspath(__file__))
if TOOLS not in sys.path:
    sys.path.insert(0, TOOLS)

SENTINEL_ID = 65534


def _set_unopened(fut_store, ids):
    """Deterministically set the active profile's owned unopened packs."""
    p = fut_store.STORE.load()
    p["unopenedPackIds"] = list(ids)
    fut_store.STORE._save()


def _mypacks(catalog):
    return [p for p in catalog["purchase"]
            if (p.get("displayGroup") or {}).get("value") == "mypacks"]


def _fake_request(command, body):
    class _H:
        pass
    h = _H()
    h.command = command
    h._body = body
    return h


def main():
    with tempfile.TemporaryDirectory() as state:
        os.environ["FUT_ACCOUNT_PATH"] = os.path.join(state, "active_account.json")
        os.environ["FUT_PROFILE_ROOT"] = os.path.join(state, "accounts")
        os.environ.pop("FUT_PROFILE", None)

        import fut_account
        import fut_store
        import fut_accounts
        import utas_server
        importlib.reload(fut_account)
        importlib.reload(fut_store)
        importlib.reload(fut_accounts)
        importlib.reload(utas_server)

        fut_accounts.activate({"personaId": 111001, "personaName": "TEST_A"})
        catalog_ids = [p["id"] for p in fut_store.PACK_CATALOG]

        # ---- A. Empty unopened packs -> one active synthetic 65534 placeholder ----
        _set_unopened(fut_store, [])
        utas_server._OPENED_PACK_GRACE.clear()
        status, cat = utas_server.store_catalog(None)
        assert status == 200
        myp = _mypacks(cat)
        assert len(myp) == 1, "expected exactly one mypacks entry, got %r" % myp
        s = myp[0]
        assert s["id"] == SENTINEL_ID, s
        assert s["state"] == "active", s              # the P2 fix: active, not inactive
        assert (s.get("displayGroup") or {}).get("value") == "mypacks", s
        assert SENTINEL_ID not in catalog_ids, "65534 must not be in PACK_CATALOG"
        assert fut_store.pack_by_id(SENTINEL_ID) is None
        print("A empty-state active placeholder: PASS")

        # ---- D (empty half). Normal packs untouched in empty state ----
        norm = {p["id"]: p for p in cat["purchase"] if p["id"] in (1, 5, 6, 7)}
        assert set(norm) == {1, 5, 6, 7}, sorted(norm)
        assert all(norm[i]["state"] == "active" for i in norm), norm
        assert norm[1]["packType"] == "BRONZE" and norm[1]["description"] == "Bronze Pack"

        # ---- B. Non-empty unopened packs -> NO synthetic; genuine owned pack shown ----
        _set_unopened(fut_store, [70])
        utas_server._OPENED_PACK_GRACE.clear()
        status, cat = utas_server.store_catalog(None)
        assert status == 200
        ids = [p["id"] for p in cat["purchase"]]
        assert SENTINEL_ID not in ids, "synthetic placeholder must be suppressed when a pack exists"
        myp = _mypacks(cat)
        assert len(myp) == 1 and myp[0]["id"] == 70, myp
        assert myp[0]["state"] == "active" and myp[0]["unopened"] is True, myp[0]
        # normal packs still intact alongside the owned pack
        assert {1, 5, 6, 7}.issubset(set(ids)), sorted(ids)
        print("B non-empty-state genuine pack: PASS")

        # ---- C. Economy safety of the synthetic placeholder ----
        _set_unopened(fut_store, [])
        utas_server._OPENED_PACK_GRACE.clear()
        coins0 = fut_store.STORE.coins()
        items0 = len(fut_store.STORE.items())
        next0 = fut_store.STORE.load()["nextItemId"]

        assert fut_store.pack_by_id(SENTINEL_ID) is None

        # store_buy: a confirmed-buy transaction for 65534 must be a no-op {}
        status, body = utas_server.store_buy(
            _fake_request("PUT", b'{"packId":65534,"state":"TRANSACTIONCREATED"}'))
        assert status == 200 and body == {}, (status, body)

        # purchased_items: POST buy for 65534 must not open/grant anything
        status, body = utas_server.purchased_items(
            _fake_request("POST", b'{"packId":65534,"useCredits":1,"usePreOrder":0,"currency":"COINS"}'))
        assert status == 200, (status, body)
        assert "createPackResponse" not in body, body

        # 65534 cannot enter the owned-pack pile (not a catalog pack)
        assert fut_store.STORE.grant_unopened_pack(SENTINEL_ID) is False
        assert SENTINEL_ID not in fut_store.STORE.unopened_packs()

        # nothing mutated
        assert fut_store.STORE.coins() == coins0, (fut_store.STORE.coins(), coins0)
        assert len(fut_store.STORE.items()) == items0
        assert fut_store.STORE.load()["nextItemId"] == next0
        assert not any(i.get("id") == SENTINEL_ID or i.get("resourceId") == SENTINEL_ID
                       for i in fut_store.STORE.items())
        print("C economy safety (65534 non-openable / non-granting): PASS")

    print("empty My Packs compatibility: PASS")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
