"""Tests for compliance domain entities."""

import pytest

from app.domain.entities.compliance import (
    ComplianceControlEntity,
    ComplianceFrameworkEntity,
    ControlCoverageStatus,
)


# ── Control coverage status ───────────────────────────────────────────────


def test_control_all_techniques_validated_covered():
    """All techniques validated → covered."""
    control = ComplianceControlEntity(
        control_id="AC-2",
        title="Account Management",
        technique_statuses=["validated", "validated"],
    )
    assert control.coverage_status == ControlCoverageStatus.covered


def test_control_all_techniques_partial_covered():
    """All techniques partial → covered."""
    control = ComplianceControlEntity(
        control_id="AC-2",
        title="Account Management",
        technique_statuses=["partial"],
    )
    assert control.coverage_status == ControlCoverageStatus.covered


def test_control_mixed_statuses_partially_covered():
    """Mixed statuses (some validated/partial, some not) → partially_covered."""
    control = ComplianceControlEntity(
        control_id="AC-2",
        title="Account Management",
        technique_statuses=["validated", "not_evaluated"],
    )
    assert control.coverage_status == ControlCoverageStatus.partially_covered


def test_control_no_validated_techniques_not_covered():
    """No validated/partial techniques → not_covered."""
    control = ComplianceControlEntity(
        control_id="AC-2",
        title="Account Management",
        technique_statuses=["not_evaluated", "not_covered"],
    )
    assert control.coverage_status == ControlCoverageStatus.not_covered


def test_control_empty_techniques_not_covered():
    """Empty technique_statuses → not_covered."""
    control = ComplianceControlEntity(
        control_id="AC-2",
        title="Account Management",
        technique_statuses=[],
    )
    assert control.coverage_status == ControlCoverageStatus.not_covered


# ── Framework coverage ─────────────────────────────────────────────────────


def test_framework_coverage_pct_calculation():
    """Framework coverage_pct = (covered_controls / total_controls) * 100."""
    controls = [
        ComplianceControlEntity("AC-1", "Title 1", technique_statuses=["validated"]),
        ComplianceControlEntity("AC-2", "Title 2", technique_statuses=["not_evaluated"]),
        ComplianceControlEntity("AC-3", "Title 3", technique_statuses=["validated", "partial"]),
        ComplianceControlEntity("AC-4", "Title 4", technique_statuses=["partial"]),
        ComplianceControlEntity("AC-5", "Title 5", technique_statuses=[]),
    ]
    framework = ComplianceFrameworkEntity(name="NIST 800-53", controls=controls)
    # AC-1: covered, AC-2: not_covered, AC-3: covered, AC-4: covered, AC-5: not_covered
    assert framework.total_controls == 5
    assert framework.covered_controls == 3
    assert framework.coverage_pct == 60.0


def test_framework_get_gap_controls():
    """get_gap_controls returns only uncovered and partially_covered controls."""
    controls = [
        ComplianceControlEntity("AC-1", "Covered", technique_statuses=["validated"]),
        ComplianceControlEntity("AC-2", "Partial", technique_statuses=["validated", "not_evaluated"]),
        ComplianceControlEntity("AC-3", "Not Covered", technique_statuses=["not_evaluated"]),
        ComplianceControlEntity("AC-4", "Empty", technique_statuses=[]),
    ]
    framework = ComplianceFrameworkEntity(name="Test", controls=controls)
    gaps = framework.get_gap_controls()
    assert len(gaps) == 3
    assert gaps[0].control_id == "AC-2"
    assert gaps[1].control_id == "AC-3"
    assert gaps[2].control_id == "AC-4"


def test_framework_no_controls_coverage_pct_zero():
    """Framework with no controls → coverage_pct is 0."""
    framework = ComplianceFrameworkEntity(name="Empty", controls=[])
    assert framework.total_controls == 0
    assert framework.covered_controls == 0
    assert framework.coverage_pct == 0.0
