"""Tests for complyform.core.assessor.coverage."""

from __future__ import annotations

import pytest

from complyform.core.assessor.control_matcher import Finding
from complyform.core.assessor.coverage import ResourceCoverageClassifier
from complyform.core.scanner.state_parser import ResourceRecord


def _make_resource(resource_type: str, address: str | None = None) -> ResourceRecord:
    """Create a minimal ResourceRecord for testing."""
    return ResourceRecord(
        provider="aws",
        resource_type=resource_type,
        name="test",
        address=address or f"{resource_type}.test",
        attributes={},
        module=None,
        source_state="test-state",
    )


@pytest.fixture
def classifier() -> ResourceCoverageClassifier:
    return ResourceCoverageClassifier(
        applicable_types=frozenset({"aws_s3_bucket", "aws_iam_role"}),
        not_applicable_types=frozenset(
            {"aws_route53_zone", "aws_cloudwatch_log_group"}
        ),
    )


class TestClassify:
    def test_mapped_resource_type(self, classifier: ResourceCoverageClassifier) -> None:
        resource = _make_resource("aws_s3_bucket")
        assert classifier.classify(resource) == "mapped"

    def test_not_applicable_resource(
        self, classifier: ResourceCoverageClassifier
    ) -> None:
        resource = _make_resource("aws_route53_zone")
        assert classifier.classify(resource) == "not_applicable"

    def test_unknown_resource_is_not_assessed(
        self, classifier: ResourceCoverageClassifier
    ) -> None:
        resource = _make_resource("aws_lambda_function")
        assert classifier.classify(resource) == "not_assessed"


class TestGenerateNotAssessedFindings:
    def test_findings_have_correct_structure(
        self, classifier: ResourceCoverageClassifier
    ) -> None:
        resources = [_make_resource("aws_lambda_function", "aws_lambda_function.my_fn")]
        findings = classifier.generate_not_assessed_findings(resources, "soc2")

        assert len(findings) == 1
        f = findings[0]
        assert isinstance(f, Finding)
        assert f.status == "NOT_ASSESSED"
        assert f.severity == "LOW"
        assert f.not_assessed_reason == "no_mapping"
        assert f.control_id == "N/A"
        assert f.framework == "soc2"
        assert f.resource_address == "aws_lambda_function.my_fn"
        assert f.resource_type == "aws_lambda_function"
        assert f.confidence == "inferred"
        assert f.checkov_id is None
        assert f.cross_mappings is None
        assert f.native_ids is None
        assert "aws_lambda_function" in f.finding

    def test_only_not_assessed_resources_generate_findings(
        self, classifier: ResourceCoverageClassifier
    ) -> None:
        resources = [
            _make_resource("aws_s3_bucket"),  # mapped
            _make_resource("aws_route53_zone"),  # not_applicable
            _make_resource("aws_lambda_function"),  # not_assessed
            _make_resource("aws_iam_role"),  # mapped
            _make_resource("aws_eks_cluster"),  # not_assessed
        ]
        findings = classifier.generate_not_assessed_findings(resources, "nist-800-53")

        assert len(findings) == 2
        types = {f.resource_type for f in findings}
        assert types == {"aws_lambda_function", "aws_eks_cluster"}
        for f in findings:
            assert f.status == "NOT_ASSESSED"
            assert f.framework == "nist-800-53"
