# [DEF:__tests__/test_policy_engine:Module]
# @RELATION: VERIFIES -> ../policy_engine.py
# @PURPOSE: Contract testing for CleanPolicyEngine
# [/DEF:__tests__/test_policy_engine:Module]

import pytest
from datetime import datetime
from src.models.clean_release import (
    CleanProfilePolicy, 
    ResourceSourceRegistry, 
    ResourceSourceEntry, 
    ProfileType, 
    RegistryStatus
)
from src.services.clean_release.policy_engine import CleanPolicyEngine

# @TEST_FIXTURE: policy_enterprise_clean
@pytest.fixture
def enterprise_clean_setup():
    policy = CleanProfilePolicy(
        policy_id="POL-1",
        policy_version="1",
        active=True,
        prohibited_artifact_categories=["demo", "test"],
        required_system_categories=["core"],
        internal_source_registry_ref="REG-1",
        effective_from=datetime.now(),
        profile=ProfileType.ENTERPRISE_CLEAN
    )
    registry = ResourceSourceRegistry(
        registry_id="REG-1",
        name="Internal Registry",
        entries=[
            ResourceSourceEntry(source_id="S1", host="internal.com", protocol="https", purpose="p1", enabled=True)
        ],
        updated_at=datetime.now(),
        updated_by="admin",
        status=RegistryStatus.ACTIVE
    )
    return policy, registry

# @TEST_SCENARIO: policy_valid
def test_policy_valid(enterprise_clean_setup):
    policy, registry = enterprise_clean_setup
    engine = CleanPolicyEngine(policy, registry)
    result = engine.validate_policy()
    assert result.ok is True
    assert not result.blocking_reasons

# @TEST_EDGE: missing_registry_ref
def test_missing_registry_ref(enterprise_clean_setup):
    policy, registry = enterprise_clean_setup
    policy.internal_source_registry_ref = "  "
    engine = CleanPolicyEngine(policy, registry)
    result = engine.validate_policy()
    assert result.ok is False
    assert "Policy missing internal_source_registry_ref" in result.blocking_reasons

# @TEST_EDGE: conflicting_registry
def test_conflicting_registry(enterprise_clean_setup):
    policy, registry = enterprise_clean_setup
    registry.registry_id = "WRONG-REG"
    engine = CleanPolicyEngine(policy, registry)
    result = engine.validate_policy()
    assert result.ok is False
    assert "Policy registry ref does not match provided registry" in result.blocking_reasons

# @TEST_INVARIANT: deterministic_classification
def test_classify_artifact(enterprise_clean_setup):
    policy, registry = enterprise_clean_setup
    engine = CleanPolicyEngine(policy, registry)
    
    # Required
    assert engine.classify_artifact({"category": "core", "path": "p1"}) == "required-system"
    # Prohibited
    assert engine.classify_artifact({"category": "demo", "path": "p2"}) == "excluded-prohibited"
    # Allowed
    assert engine.classify_artifact({"category": "others", "path": "p3"}) == "allowed"

# @TEST_EDGE: external_endpoint
def test_validate_resource_source(enterprise_clean_setup):
    policy, registry = enterprise_clean_setup
    engine = CleanPolicyEngine(policy, registry)
    
    # Internal (OK)
    res_ok = engine.validate_resource_source("internal.com")
    assert res_ok.ok is True
    
    # External (Blocked)
    res_fail = engine.validate_resource_source("external.evil")
    assert res_fail.ok is False
    assert res_fail.violation["category"] == "external-source"
    assert res_fail.violation["blocked_release"] is True

def test_evaluate_candidate(enterprise_clean_setup):
    policy, registry = enterprise_clean_setup
    engine = CleanPolicyEngine(policy, registry)
    
    artifacts = [
        {"path": "core.js", "category": "core"},
        {"path": "demo.sql", "category": "demo"}
    ]
    sources = ["internal.com", "google.com"]
    
    classified, violations = engine.evaluate_candidate(artifacts, sources)
    
    assert len(classified) == 2
    assert classified[0]["classification"] == "required-system"
    assert classified[1]["classification"] == "excluded-prohibited"
    
    # 1 violation for demo artifact + 1 for google.com source
    assert len(violations) == 2
    assert violations[0]["category"] == "data-purity"
    assert violations[1]["category"] == "external-source"
