"""Tests from the acme-crm-mcp demo's real responses. Run: pytest test_inspector_practice.py"""
import base64
import json

from inspector_practice import decode_claims, how_to_get_a_token, resource_metadata_url, token_problems

MCP = "http://localhost:8787/mcp"
NOW = 1_790_000_000


def b64(obj) -> str:
    return base64.urlsafe_b64encode(json.dumps(obj).encode()).decode().rstrip("=")


def jwt(claims) -> str:
    return f"{b64({'alg': 'RS256', 'kid': 'demo-key-1'})}.{b64(claims)}.not-a-real-signature"


ACME = {"org_id": "acme", "scope": "crm:read crm:write", "client_id": "acme-agent",
        "iss": "http://localhost:8788", "aud": MCP, "sub": "acme-agent", "iat": NOW, "exp": NOW + 3600}


def test_follow_the_401():
    first = 'Bearer resource_metadata="http://localhost:8787/.well-known/oauth-protected-resource"'
    assert resource_metadata_url(first) == "http://localhost:8787/.well-known/oauth-protected-resource"
    expired = first + ', error="invalid_token"'
    assert resource_metadata_url(expired) == "http://localhost:8787/.well-known/oauth-protected-resource"
    assert resource_metadata_url("Basic realm=x") is None


def test_why_the_inspector_found_no_sign_in():
    demo = {"issuer": "http://localhost:8788", "token_endpoint": "http://localhost:8788/token",
            "jwks_uri": "http://localhost:8788/jwks.json", "grant_types_supported": ["client_credentials"],
            "response_types_supported": [], "scopes_supported": ["crm:read", "crm:write"]}
    assert how_to_get_a_token(demo) == "client credentials"
    production = {**demo, "authorization_endpoint": "https://auth.example/authorize",
                  "response_types_supported": ["code"],
                  "grant_types_supported": ["authorization_code", "refresh_token"]}
    assert how_to_get_a_token(production) == "browser sign-in"
    assert how_to_get_a_token({"grant_types_supported": []}) == "none"


def test_decode_reads_anyones_token():
    assert decode_claims(jwt(ACME)) == ACME
    # the signature isn't checked: a forged token decodes just as well
    assert decode_claims(jwt({**ACME, "org_id": "globex"}))["org_id"] == "globex"


def test_what_each_token_gets_wrong():
    assert token_problems(ACME, NOW + 60, MCP, "crm:write") == []          # the demo's token: fine
    readonly = {**ACME, "scope": "crm:read", "client_id": "acme-readonly"}
    assert token_problems(readonly, NOW, MCP, "crm:read") == []
    assert token_problems(readonly, NOW, MCP, "crm:write") == ["missing crm:write"]
    assert token_problems(ACME, NOW + 3600, MCP, "crm:read") == ["expired"]
    other = {**ACME, "aud": "https://other-api.example"}
    assert token_problems(other, NOW, MCP, "crm:read") == ["wrong audience"]
    no_org = {k: v for k, v in ACME.items() if k != "org_id"}
    assert token_problems(no_org, NOW + 7200, "https://x", "crm:delete") == \
        ["no tenant", "wrong audience", "expired", "missing crm:delete"]
