"""AWS Security Hub cross-validation client.

Contract:
- AWSCrossValidator extends CloudIntelligenceAnalyzer.
- analyze() fetches Security Hub failed findings and cross-validates.
- Never raises — returns success=False with descriptive error on failure.
"""

from __future__ import annotations

import time
from datetime import UTC, datetime
from typing import TYPE_CHECKING

from complyform.core.cloud_intelligence import (
    CloudIntelligenceAnalyzer,
    CloudIntelligenceResult,
)
from complyform.core.cloud_intelligence.cross_validator import (
    CrossValidationResult,
    NativeFinding,
    match_findings,
)
from complyform.core.cloud_intelligence.resource_normalizers import (
    normalize_security_hub_resource,
)

if TYPE_CHECKING:
    from complyform.core.assessor.control_matcher import Finding

__all__ = ["AWSCrossValidator"]


class AWSCrossValidator(CloudIntelligenceAnalyzer):
    """AWS Security Hub GetFindings client.

    Pre-requisite: describe_hub() — InvalidAccessException = not enabled.
    API: get_findings, filter: ComplianceStatus=FAILED, RecordState=ACTIVE,
    ProductName=Security Hub, severity DESC, pageSize 100.
    """

    def __init__(
        self,
        cloud: str,
        project_id: str,
        credentials: object | None = None,
        complyform_findings: list[Finding] | None = None,
    ) -> None:
        super().__init__(cloud, project_id, credentials)
        self.complyform_findings: list[Finding] = complyform_findings or []

    def check_prerequisites(self) -> list[str]:
        """Check Security Hub access."""
        issues: list[str] = []
        try:
            import boto3  # type: ignore  # noqa: F401
        except ImportError:
            issues.append("boto3 not installed: pip install boto3")
        return issues

    def analyze(self) -> CloudIntelligenceResult:
        """Fetch Security Hub findings and cross-validate."""
        start = time.monotonic()
        ts = datetime.now(tz=UTC).isoformat()

        def _result(
            success: bool,
            error: str | None = None,
            **kwargs: object,
        ) -> CrossValidationResult:
            elapsed = int((time.monotonic() - start) * 1000)
            return CrossValidationResult(
                feature="cross_validation",
                cloud=self.cloud,
                success=success,
                error=error,
                duration_ms=elapsed,
                timestamp=ts,
                native_tool="security_hub",
                **kwargs,  # type: ignore[arg-type]
            )

        try:
            import boto3
            from botocore.exceptions import (  # type: ignore
                ClientError,
            )
        except ImportError:
            return _result(False, error="boto3 not installed")

        try:
            session = self.credentials if self.credentials else boto3.Session()
            client = session.client("securityhub")  # type: ignore[union-attr]

            # Pre-req check: is Security Hub enabled?
            try:
                client.describe_hub()
            except ClientError as exc:
                code = exc.response.get("Error", {}).get("Code", "")
                if code == "InvalidAccessException":
                    return _result(False, error="Security Hub not enabled")
                if code == "AccessDeniedException":
                    return _result(
                        False,
                        error="Missing securityhub:GetFindings permission",
                    )
                raise

            # Fetch findings
            native_findings: list[NativeFinding] = []
            paginator = client.get_paginator("get_findings")
            filters = {
                "ComplianceStatus": [{"Value": "FAILED", "Comparison": "EQUALS"}],
                "RecordState": [{"Value": "ACTIVE", "Comparison": "EQUALS"}],
            }
            sort_criteria = {"Field": "SeverityNormalized", "SortOrder": "desc"}

            for page in paginator.paginate(
                Filters=filters,
                SortCriteria=sort_criteria,
                PaginationConfig={"MaxItems": 1000, "PageSize": 100},
            ):
                for f in page.get("Findings", []):
                    resources = f.get("Resources", [{}])
                    resource = resources[0] if resources else {}
                    severity_label = (
                        f.get("Severity", {}).get("Label", "MEDIUM").upper()
                    )
                    native_findings.append(
                        NativeFinding(
                            native_id=f.get("GeneratorId", ""),
                            resource_id=resource.get("Id", ""),
                            resource_type=resource.get("Type", ""),
                            severity=severity_label,
                            title=f.get("Title", ""),
                            status="ACTIVE",
                        )
                    )

        except ClientError as exc:
            code = exc.response.get("Error", {}).get("Code", "")
            if code == "AccessDeniedException":
                return _result(
                    False,
                    error="Missing securityhub:GetFindings permission",
                )
            return _result(False, error=str(exc))
        except Exception as exc:
            return _result(False, error=str(exc))

        def _normalize(resource_id: str, resource_type: str) -> str | None:
            return normalize_security_hub_resource(resource_id, resource_type)

        result = match_findings(self.complyform_findings, native_findings, _normalize)
        return _result(
            success=True,
            total_complyform_findings=result.total_complyform_findings,
            total_native_findings=result.total_native_findings,
            confirmed=result.confirmed,
            complyform_only=result.complyform_only,
            native_only=result.native_only,
            cross_validation_score=result.cross_validation_score,
        )
