import pytest
from governor.resolver import resolve
from governor.models import (
    Domain, AuthorityClass, LensStatus, ContinuationPathway, 
    SpeechAct, ResolutionMode, UserClass, GovernorPolicy, 
    ForensicObligation, ExposureLevel
)

def test_ask_status_no_side_door():
    """ASK status must stay ASK. No sly answering through the side door."""
    domains = [Domain.GENERAL, Domain.MEDICAL, Domain.LEGAL, Domain.FINANCE, Domain.RESEARCH]
    
    for domain in domains:
        policy = resolve(domain, AuthorityClass.GP, LensStatus.ASK)
        
        # EFFECTIVE CORRIDOR CHECK:
        # 1. Commitment MUST be closed
        assert policy.commitment_closed is True
        
        # 2. Ensure only non-substantive speech acts are allowed
        allowed_acts = policy.allowed_speech_acts
        substantive_acts = {
            SpeechAct.PROVIDE_SUBSTANTIVE_ANSWER,
            SpeechAct.INFER_ANSWER,
            SpeechAct.SUGGEST_PROBABLE_RESOLUTION,
            SpeechAct.SOFTEN_INTO_ADVICE,
            SpeechAct.NARRATIVE_COMPLETION,
            SpeechAct.COMPARATIVE_RANKING
        }
        for act in allowed_acts:
            assert act not in substantive_acts, f"Forbidden act '{act}' in ASK status for {domain}"

def test_no_fake_moustache_invariant():
    """Invariant: commitment_closed=True forbids substantive speech acts."""
    with pytest.raises(ValueError, match="Governor must not assert, imply, recommend, rank, compare, or narratively complete"):
        GovernorPolicy(
            domain=Domain.GENERAL,
            authority_class=AuthorityClass.GP,
            lens_status=LensStatus.REFUSE,
            commitment_closed=True,
            allowed_speech_acts=[SpeechAct.PROVIDE_SUBSTANTIVE_ANSWER]
        )

def test_implied_ranking_leakage_prohibited():
    """Invariant: commitment_closed=True forbids comparative ranking acts (defined by effect)."""
    # Comparative ranking acts like "better suited" are defined by decision effect.
    with pytest.raises(ValueError, match="Governor must not assert, imply, recommend, rank, compare, or narratively complete"):
        GovernorPolicy(
            domain=Domain.FINANCE,
            authority_class=AuthorityClass.GP,
            lens_status=LensStatus.REFUSE,
            commitment_closed=True,
            allowed_speech_acts=[SpeechAct.COMPARATIVE_RANKING]
        )

def test_no_epistemic_widening_invariant():
    """Invariant: Governor cannot widen commitment relative to Lens."""
    # REFUSE must have commitment_closed=True
    with pytest.raises(ValueError, match="Epistemic widening violation"):
        GovernorPolicy(
            domain=Domain.GENERAL,
            authority_class=AuthorityClass.GP,
            lens_status=LensStatus.REFUSE,
            commitment_closed=False
        )

def test_user_type_corridor_alteration():
    """Auditor should see forensic exposure in STOP state."""
    # General user STOP
    policy_gen = resolve(Domain.GENERAL, AuthorityClass.GP, LensStatus.STOP, user_class=UserClass.GENERAL)
    assert SpeechAct.EXPOSE_AUDIT_BASIS not in policy_gen.allowed_speech_acts
    assert policy_gen.exposure_level == ExposureLevel.MINIMAL
    assert ForensicObligation.EMIT_FORENSIC_ENVELOPE in policy_gen.forensic_obligations
    
    # Auditor STOP
    policy_aud = resolve(Domain.GENERAL, AuthorityClass.GP, LensStatus.STOP, user_class=UserClass.AUDITOR)
    assert SpeechAct.EXPOSE_AUDIT_BASIS in policy_aud.allowed_speech_acts
    assert policy_aud.exposure_level == ExposureLevel.FULL
    assert ForensicObligation.ATTACH_PEF_SNAPSHOT in policy_aud.forensic_obligations
    assert policy_aud.resolution_mode == ResolutionMode.EXACT

def test_auditor_corridor_hardening():
    """Auditor status may ONLY increase forensic visibility; it NEVER widens substantive authority."""
    # Auditor in medical REFUSE state should not have wider answer rights than general user
    policy_gen = resolve(Domain.MEDICAL, AuthorityClass.GP, LensStatus.REFUSE, user_class=UserClass.GENERAL)
    policy_aud = resolve(Domain.MEDICAL, AuthorityClass.GP, LensStatus.REFUSE, user_class=UserClass.AUDITOR)
    
    # EFFECTIVE CORRIDOR CHECK:
    # Substantive authority (commitment_closed) must be identical
    assert policy_gen.commitment_closed == policy_aud.commitment_closed == True
    
    # Allowed substantive speech acts must be identical
    visibility_acts = {SpeechAct.EXPOSE_AUDIT_BASIS}
    substantive_gen = set(policy_gen.allowed_speech_acts) - visibility_acts
    substantive_aud = set(policy_aud.allowed_speech_acts) - visibility_acts
    
    assert substantive_gen == substantive_aud, "Auditor has wider substantive latitude than general user in restricted domain."

def test_fallback_resolution_tracking():
    """Resolver should correctly report resolution mode."""
    # finance:DA:ADMIT is now a direct matrix entry — resolution is exact.
    policy = resolve(Domain.FINANCE, AuthorityClass.DA, LensStatus.ADMIT)
    assert policy.resolution_mode == ResolutionMode.EXACT

    # Domain fallback: research:DA:STOP has no entry; resolver collapses to GP.
    policy_gen = resolve(Domain.RESEARCH, AuthorityClass.DA, LensStatus.STOP)
    assert policy_gen.resolution_mode == ResolutionMode.AUTHORITY_FALLBACK  # Collapsed to GP

def test_medical_gp_asymmetry():
    """GP cannot provide substantive answers in Medical domain even if ADMIT."""
    policy = resolve(Domain.MEDICAL, AuthorityClass.GP, LensStatus.ADMIT)
    
    # EFFECTIVE CORRIDOR CHECK:
    # 1. Lens ADMIT != Institutional permission (commitment_closed must be True)
    assert policy.commitment_closed is True
    
    # 2. No substantive answers allowed
    assert SpeechAct.PROVIDE_SUBSTANTIVE_ANSWER not in policy.allowed_speech_acts
    assert SpeechAct.PROVIDE_GENERAL_INFORMATION in policy.allowed_speech_acts