"""Tests for remediate command cloud intelligence integration."""

from __future__ import annotations

from complyform.core.cloud_intelligence.cost_estimator import (
    CostImpactEstimate,
    CostLineItem,
)
from complyform.core.cloud_intelligence.iam_analyzer import (
    IAMFinding,
    generate_iam_patches,
)


def _make_iam_finding(**overrides: object) -> IAMFinding:
    defaults: dict[str, object] = {
        "cloud": "gcp",
        "principal": "sa@proj.iam.gserviceaccount.com",
        "principal_type": "service_account",
        "current_role": "roles/editor",
        "recommended_role": "roles/viewer",
        "unused_permissions": ["storage.buckets.delete"],
        "last_activity": "2025-01-01T00:00:00Z",
        "risk_level": "HIGH",
        "framework_controls": [{"framework": "soc2", "control_id": "CC6.1"}],
        "remediation_terraform": None,
        "source_api": "iam_recommender",
    }
    defaults.update(overrides)
    return IAMFinding(**defaults)  # type: ignore[arg-type]


class TestIAMPatches:
    """remediate --iam-analysis produces iam_ prefixed patches."""

    def test_iam_patches_have_iam_prefix(self) -> None:
        findings = [_make_iam_finding()]
        patches = generate_iam_patches(findings, "gcp")
        assert len(patches) == 1
        assert patches[0].filename.startswith("iam_")
        assert patches[0].filename.endswith(".tf")

    def test_iam_patches_aws(self) -> None:
        findings = [_make_iam_finding(cloud="aws", current_role="AdministratorAccess")]
        patches = generate_iam_patches(findings, "aws")
        assert len(patches) == 1
        assert patches[0].filename.startswith("iam_")
        assert "aws_iam_role_policy_attachment" in patches[0].content

    def test_iam_patches_azure(self) -> None:
        findings = [_make_iam_finding(cloud="azure", current_role="Owner")]
        patches = generate_iam_patches(findings, "azure")
        assert len(patches) == 1
        assert patches[0].filename.startswith("iam_")
        assert "azurerm_role_assignment" in patches[0].content

    def test_multiple_iam_findings(self) -> None:
        findings = [
            _make_iam_finding(principal="sa1@proj.iam.gserviceaccount.com"),
            _make_iam_finding(principal="sa2@proj.iam.gserviceaccount.com"),
        ]
        patches = generate_iam_patches(findings, "gcp")
        assert len(patches) == 2
        filenames = {p.filename for p in patches}
        assert len(filenames) == 2  # Distinct filenames


class TestCostEstimation:
    """remediate --estimate-cost produces cost summary."""

    def test_cost_result_has_totals(self) -> None:
        result = CostImpactEstimate(
            feature="cost_impact",
            cloud="gcp",
            success=True,
            error=None,
            duration_ms=100,
            timestamp="2025-01-01T00:00:00Z",
            total_monthly_delta=42.0,
            total_annual_delta=504.0,
            confidence="estimated",
            breakdown=[
                CostLineItem(
                    category="encryption",
                    description="KMS keys",
                    monthly_cost=12.0,
                    resource_count=2,
                    source="estimate",
                ),
                CostLineItem(
                    category="logging",
                    description="Log sinks",
                    monthly_cost=30.0,
                    resource_count=3,
                    source="estimate",
                ),
            ],
        )
        assert result.total_monthly_delta == 42.0
        assert result.total_annual_delta == 504.0
        assert result.confidence == "estimated"
        assert len(result.breakdown) == 2

    def test_cost_result_failure_still_returns(self) -> None:
        result = CostImpactEstimate(
            feature="cost_impact",
            cloud="gcp",
            success=False,
            error="Infracost not available",
            duration_ms=10,
            timestamp="2025-01-01T00:00:00Z",
        )
        assert not result.success
        assert result.total_monthly_delta == 0.0


class TestBothFlags:
    """Both --iam-analysis and --estimate-cost together."""

    def test_iam_patches_and_cost_both_present(self) -> None:
        # IAM patches
        findings = [_make_iam_finding()]
        patches = generate_iam_patches(findings, "gcp")
        assert len(patches) >= 1

        # Cost result
        cost = CostImpactEstimate(
            feature="cost_impact",
            cloud="gcp",
            success=True,
            error=None,
            duration_ms=100,
            timestamp="2025-01-01T00:00:00Z",
            total_monthly_delta=25.0,
            total_annual_delta=300.0,
            confidence="estimated",
        )
        assert cost.success

        # Both present
        assert patches[0].filename.startswith("iam_")
        assert cost.total_monthly_delta == 25.0
