"""AWS Control Tower landing zone detection.

Contract:
- detect_aws_landing_zone() detects Control Tower via Organizations API.
- Never raises — returns LandingZoneContext(detected=False) on error.
"""

from __future__ import annotations

import sys

from complyform.core.scanner.landing_zone import LandingZoneContext

__all__ = ["detect_aws_landing_zone"]


def detect_aws_landing_zone(
    project_id: str,
    credentials: object | None,
) -> LandingZoneContext:
    """Detect Control Tower via Organizations API.

    describe_organization() -> list OUs -> pattern match
    (Security OU + Sandbox OU = Control Tower)
    -> list_policies_for_target(Filter="SERVICE_CONTROL_POLICY")
    """
    try:
        import boto3  # type: ignore
        from botocore.exceptions import ClientError  # type: ignore
    except ImportError:
        print(
            "Warning: boto3 not installed, skipping AWS LZ detection",
            file=sys.stderr,
        )
        return LandingZoneContext(cloud="aws", detected=False, type=None)

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

        # Check if Organizations is in use
        try:
            org = org_client.describe_organization()
        except ClientError as exc:
            code = exc.response.get("Error", {}).get("Code", "")
            if code == "AWSOrganizationsNotInUseException":
                return LandingZoneContext(cloud="aws", detected=False, type=None)
            if code == "AccessDeniedException":
                print(
                    "Warning: no Organizations access for LZ detection",
                    file=sys.stderr,
                )
                return LandingZoneContext(cloud="aws", detected=False, type=None)
            raise

        # List OUs to detect Control Tower pattern
        root_id = ""
        roots = org_client.list_roots()
        for root in roots.get("Roots", []):
            root_id = root.get("Id", "")
            break

        if not root_id:
            return LandingZoneContext(cloud="aws", detected=False, type=None)

        ous = org_client.list_organizational_units_for_parent(ParentId=root_id)
        ou_names = {
            ou.get("Name", "").lower() for ou in ous.get("OrganizationalUnits", [])
        }

        # Control Tower pattern: Security OU + Sandbox OU
        is_control_tower = "security" in ou_names and "sandbox" in ou_names

        if not is_control_tower:
            return LandingZoneContext(cloud="aws", detected=False, type=None)

        # Get SCPs
        inherited_policies: list[str] = []
        try:
            policies = org_client.list_policies_for_target(
                TargetId=root_id,
                Filter="SERVICE_CONTROL_POLICY",
            )
            for policy in policies.get("Policies", []):
                name = policy.get("Name", "")
                if name:
                    inherited_policies.append(name)
        except Exception as exc:
            print(
                f"Warning: could not list SCPs: {exc}",
                file=sys.stderr,
            )

        # Build hierarchy
        hierarchy = [
            org.get("Organization", {}).get("Id", ""),
            root_id,
        ]

        return LandingZoneContext(
            cloud="aws",
            detected=True,
            type="control_tower",
            inherited_policies=inherited_policies,
            hierarchy_path=hierarchy,
        )

    except Exception as exc:
        print(
            f"Warning: AWS landing zone detection failed: {exc}",
            file=sys.stderr,
        )
        return LandingZoneContext(cloud="aws", detected=False, type=None)
