from datetime import UTC, datetime, timedelta
from scopewrit.inspect import inspect_manifest
from scopewrit.models import ScopeManifest

def manifest(resource='https://example.com/api/**', **rule_changes):
    now=datetime(2026,9,5,tzinfo=UTC)
    return ScopeManifest(mandate_id='mandate-001',run_id='run-001',principal='principal-001',agent_id='agent-001',objective='Inspect one bounded API action',issued_at=now,not_before=now,expires_at=now+timedelta(hours=1),nonce='a'*24,claim_boundary='Only actions through guarded adapters are governed.',rules=[dict(rule_id='rule-001',effect='allow',action='network.http',resource=resource,methods=['GET'],max_uses=1,**rule_changes)])

def test_inspection_is_deterministic_and_grants_nothing():
    now=datetime(2026,9,5,tzinfo=UTC)
    result=inspect_manifest(manifest(),at=now)
    assert result==inspect_manifest(manifest(),at=now)
    assert result['valid'] and not result['authority_granted']
    assert result['findings']==[]

def test_invalid_resource_is_found_before_signing():
    result=inspect_manifest(manifest('https://example.com/a/../b'),at=datetime(2026,9,5,tzinfo=UTC))
    assert not result['valid']
    assert 'invalid_resource' in [f['code'] for f in result['findings']]

def test_expiry_is_not_conflated_with_signature_validity():
    result=inspect_manifest(manifest(),at=datetime(2026,9,6,tzinfo=UTC))
    assert not result['valid']
    assert result['findings'][0]['code']=='expired'

def test_broad_authority_gets_specific_findings():
    m=manifest(); data=m.model_dump(mode='json'); data['rules'][0].update(methods=[],max_uses=None,allow_private_network=True)
    result=inspect_manifest(ScopeManifest.model_validate(data),at=datetime(2026,9,5,tzinfo=UTC))
    assert result['valid']
    assert {f['code'] for f in result['findings']}=={'unrestricted_methods','unbounded_rule_uses','private_network'}
