#!/usr/bin/env python3
"""Exercice local fictif, sans réseau ni compte Amazon.

Les dictionnaires ci-dessous sont un modèle pédagogique interne normalisé,
pas des réponses SP-API à copier dans une intégration. Le contrat de l'API
réelle doit être vérifié séparément.
"""
from decimal import Decimal

PAGES = {
    None: {
        "cases": [
            {"id": "C101", "status": "PENDING_MERCHANT_ACTION", "proof": False},
            {"id": "C102", "status": "PENDING_AMAZON_ACTION", "proof": False},
        ],
        "nextToken": "page-2",
    },
    "page-2": {"cases": [], "nextToken": "page-3"},
    "page-3": {
        "cases": [
            {"id": "C103", "status": "RESOLVED", "proof": False, "blocked_skus": 8},
            {"id": "C104", "status": "TRANSFERRED", "proof": False},
            {"id": "C105", "status": "RESOLVED", "proof": True},
            {"id": "C106", "status": "RESOLVED", "proof": False,
             "expected": Decimal("50"), "observed": Decimal("30")},
        ],
        "nextToken": None,
    },
}
CONTACTS = [
    {"id": "E1", "channel": "PHONE", "status": "EXPIRED"},
    {"id": "E2", "channel": "EMAIL", "status": "VALID",
     "content": "Réponse fictive : contrôle de l'offre à poursuivre."},
]


def collect(pages):
    """Poursuivre même après une page vide, sans accepter un jeton cyclique."""
    token, seen, cases, page_count = None, set(), {}, 0
    while True:
        if token in seen:
            raise ValueError("Parcours incomplet : jeton déjà rencontré")
        seen.add(token)
        page = pages[token]  # Une page absente fait échouer l'exercice.
        page_count += 1
        for case in page["cases"]:
            cases[case["id"]] = case
        token = page["nextToken"]
        if token is None:
            return cases, page_count


def contact_view(contact):
    """Préserver une ligne pour un échange dont le contenu est indisponible."""
    available = contact["status"] == "VALID" and "content" in contact
    return {"id": contact["id"], "channel": contact["channel"],
            "content_available": available,
            "content": contact.get("content") if available else None}


def main():
    cases, page_count = collect(PAGES)
    amazon_resolved = [c for c in cases.values() if c["status"] == "RESOLVED"]
    closed = [c["id"] for c in amazon_resolved if c["proof"]]
    remaining = [c["id"] for c in cases.values() if c["id"] not in closed]
    contacts = [contact_view(c) for c in CONTACTS]
    missing = [c for c in contacts if not c["content_available"]]
    gap = cases["C106"]["expected"] - cases["C106"]["observed"]
    checks = [
        len(cases) == 6,
        page_count == 3,
        len(amazon_resolved) == 3,
        closed == ["C105"],
        len(remaining) == 5,
        gap == Decimal("20"),
        len(contacts) == 2,
        len(missing) == 1 and missing[0]["id"] == "E1" and missing[0]["content"] is None,
    ]
    if not all(checks):
        raise AssertionError(f"Contrôles en échec : {[i + 1 for i, ok in enumerate(checks) if not ok]}")
    print("6 cas collectés ; 3 résolus Amazon ; 1 clôture interne ; 5 suivis ouverts")
    print("2 contacts conservés ; 1 contenu indisponible")
    print("8 contrôles locaux réussis")


if __name__ == "__main__":
    main()
