# #region Test.CleanRelease.Stages.Coverage [C:3] [TYPE Module] [SEMANTICS test,clean-release,stage,coverage,edge,internal,endpoint]
# @BRIEF Edge coverage for clean release stages:
#   internal_sources_only.py line 46 (empty host or allowed host → continue)
#   no_external_endpoints.py line 49 (empty endpoint string → continue)
# @RELATION BINDS_TO -> [InternalSourcesOnlyStage]
# @RELATION BINDS_TO -> [NoExternalEndpointsStage]

from datetime import UTC, datetime
from unittest.mock import MagicMock
import pytest

from src.models.clean_release import (
    CleanPolicySnapshot,
    DistributionManifest,
    ReleaseCandidate,
    SourceRegistrySnapshot,
)
from src.services.clean_release.enums import ComplianceDecision
from src.services.clean_release.stages.base import ComplianceStageContext
from src.services.clean_release.stages.internal_sources_only import InternalSourcesOnlyStage
from src.services.clean_release.stages.no_external_endpoints import NoExternalEndpointsStage


def _make_context() -> ComplianceStageContext:
    """Minimal context for stage testing."""
    registry = SourceRegistrySnapshot(
        id="reg-1", registry_id="reg-1", registry_version="1",
        allowed_hosts=["internal.local"], allowed_schemes=["https"],
        allowed_source_types=["repo"], immutable=True,
    )
    policy = CleanPolicySnapshot(
        id="policy-1", policy_id="policy-1", policy_version="1",
        content_json={
            "profile": "enterprise-clean",
            "prohibited_artifact_categories": ["malware"],
            "required_system_categories": ["system-lib"],
            "external_source_forbidden": True,
        },
        registry_snapshot_id="reg-1", immutable=True,
    )
    manifest = DistributionManifest(
        id="man-1", candidate_id="cand-1", manifest_version=1,
        manifest_digest="d1", artifacts_digest="d1",
        source_snapshot_ref="ref",
        content_json={
            "summary": {
                "included_count": 1, "excluded_count": 0,
                "prohibited_detected_count": 0,
            },
            "items": [],
        },
        created_by="tester", created_at=datetime.now(UTC), immutable=True,
    )
    candidate = ReleaseCandidate(
        id="cand-1", version="1.0.0", source_snapshot_ref="ref",
        created_by="tester", created_at=datetime.now(UTC), status="PREPARED",
    )
    run = MagicMock()
    run.id = "run-1"
    run.candidate_id = "cand-1"
    run.manifest_digest = "d1"
    return ComplianceStageContext(
        run=run, candidate=candidate, manifest=manifest,
        policy=policy, registry=registry,
    )


class TestInternalSourcesOnlyStageCoverage:
    """Edge coverage for InternalSourcesOnlyStage line 46."""

    # Line 46: empty host or host in allowed_hosts → continue
    def test_empty_host_skipped(self):
        """Source with empty host string → skipped (line 46)."""
        stage = InternalSourcesOnlyStage()
        ctx = _make_context()
        # Source entry is not a dict → host defaults to "" → line 45 is empty → continue
        ctx.manifest.content_json["sources"] = [42]
        result = stage.execute(ctx)
        assert result.decision == ComplianceDecision.PASSED

    def test_source_not_dict_host_empty_skipped(self):
        """Source is a dict but host is empty → skipped (line 46)."""
        stage = InternalSourcesOnlyStage()
        ctx = _make_context()
        ctx.manifest.content_json["sources"] = [{"host": ""}]
        result = stage.execute(ctx)
        assert result.decision == ComplianceDecision.PASSED

    def test_allowed_host_source_skipped(self):
        """Source host is in allowed_hosts → skipped (line 46)."""
        stage = InternalSourcesOnlyStage()
        ctx = _make_context()
        ctx.manifest.content_json["sources"] = [{"host": "internal.local", "path": "lib/good.so"}]
        result = stage.execute(ctx)
        assert result.decision == ComplianceDecision.PASSED


class TestNoExternalEndpointsStageCoverage:
    """Edge coverage for NoExternalEndpointsStage line 49."""

    # Line 49: empty endpoint string → continue
    def test_empty_endpoint_skipped(self):
        """Empty endpoint string in list → skipped (line 49)."""
        stage = NoExternalEndpointsStage()
        ctx = _make_context()
        ctx.manifest.content_json["endpoints"] = [""]
        result = stage.execute(ctx)
        assert result.decision == ComplianceDecision.PASSED

    def test_mixed_empty_and_valid_endpoints(self):
        """Mix of empty and valid endpoints → empty ones skipped, valid ones checked."""
        stage = NoExternalEndpointsStage()
        ctx = _make_context()
        ctx.manifest.content_json["endpoints"] = [
            "",
            "https://internal.local/api",
            "   ",
        ]
        result = stage.execute(ctx)
        assert result.decision == ComplianceDecision.PASSED
# #endregion Test.CleanRelease.Stages.Coverage
