"""An identity mapping and link-policy model, not an OIDC token verifier.

All authentication and authorization evidence is assigned fixture input.
No browser, issuer, signature, session store or persistent database is tested.
"""
import copy
import json
from pathlib import Path

ISSUER = "https://idp.example/corporate"
SECONDARY = "https://other-idp.example"
PRIMARY_KEY = (ISSUER, "subject-42")
SECONDARY_KEY = (SECONDARY, "subject-99")


def initial():
    return {"identities": {PRIMARY_KEY: "person-a", (SECONDARY, "taken"): "person-b"},
            "memberships": {("person-a", "tenant-a")},
            "approved_connections": {("tenant-a", ISSUER), ("tenant-a", SECONDARY)}}


def resolve(store, issuer, subject, email):
    # Email intentionally does not participate in principal lookup.
    return store["identities"].get((issuer, subject))


def link(store, *, current_person="person-a", tenant="tenant-a",
         primary_fresh=True, secondary_fresh=True, intent_bound=True,
         candidate=SECONDARY_KEY):
    if not primary_fresh:
        return "deny_primary_proof"
    if not secondary_fresh:
        return "deny_secondary_proof"
    if not intent_bound:
        return "deny_intent_binding"
    if (current_person, tenant) not in store["memberships"]:
        return "deny_tenant_membership"
    if (tenant, candidate[0]) not in store["approved_connections"]:
        return "deny_connection_policy"
    existing = store["identities"].get(candidate)
    if existing is not None and existing != current_person:
        return "deny_identity_already_owned"
    if existing == current_person:
        return "already_linked"
    store["identities"][candidate] = current_person
    return "linked"


def run():
    store = initial()
    lookup_inputs = [
        ("original_identity", ISSUER, "subject-42", "old@example.test", "person-a"),
        ("changed_email", ISSUER, "subject-42", "new@example.test", "person-a"),
        ("same_subject_different_issuer", SECONDARY, "subject-42", "old@example.test", None),
        ("same_host_different_issuer_path", "https://idp.example/sales", "subject-42", "old@example.test", None),
        ("same_email_different_subject", ISSUER, "new-subject", "old@example.test", None),
        ("new_pairwise_sector_subject", ISSUER, "pairwise-sector-b", "old@example.test", None),
    ]
    lookups = []
    for case, issuer, subject, email, expected in lookup_inputs:
        actual = resolve(store, issuer, subject, email)
        assert actual == expected
        lookups.append({"case": case, "issuer": issuer, "subject": subject,
                        "email": email, "resolved_person": actual})
    link_inputs = [
        ("both_identities_and_tenant_policy", {}, "linked"),
        ("missing_primary_proof", {"primary_fresh": False}, "deny_primary_proof"),
        ("missing_secondary_proof", {"secondary_fresh": False}, "deny_secondary_proof"),
        ("unbound_link_intent", {"intent_bound": False}, "deny_intent_binding"),
        ("different_tenant", {"tenant": "tenant-b"}, "deny_tenant_membership"),
        ("unapproved_issuer", {"candidate": ("https://unapproved.example", "new")}, "deny_connection_policy"),
        ("secondary_identity_owned_elsewhere", {"candidate": (SECONDARY, "taken")}, "deny_identity_already_owned"),
        ("repeat_same_link", {}, "already_linked"),
    ]
    links = []
    for case, kwargs, expected in link_inputs:
        trial = initial()
        if case == "repeat_same_link":
            assert link(trial) == "linked"
        before = copy.deepcopy(trial)
        actual = link(trial, **kwargs)
        assert actual == expected
        if actual.startswith("deny_") or actual == "already_linked":
            assert trial == before
        if actual == "linked":
            assert trial["identities"][SECONDARY_KEY] == "person-a"
            assert trial["memberships"] == before["memberships"]
        links.append({"case": case, "outcome": actual,
                      "identities_before": len(before["identities"]),
                      "identities_after": len(trial["identities"]),
                      "membership_changed": trial["memberships"] != before["memberships"]})
    assert len(lookups) == 6 and len(links) == 8
    return {"method": "Pure mapping and assigned-policy fixture; no protocol or persistent-store test",
            "summary": {"lookup_cases": 6, "resolved_known_person": 2, "unmapped_identities": 4,
                        "link_cases": 8, "new_links": 1, "idempotent_link_replays": 1,
                        "link_denials": 6, "total_cases": 14},
            "lookups": lookups, "links": links}


if __name__ == "__main__":
    results = run()
    assert results == run()
    Path(__file__).with_name("results.json").write_text(json.dumps(results, indent=2) + "\n")
    print(json.dumps(results["summary"], sort_keys=True))
    print("PASS: six lookups, eight link decisions and repeated-run equality")
