"""Parse Pulumi state exports into normalized resource maps."""

from __future__ import annotations

import json
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Optional

from .terraform import _flatten_attributes, _detect_cloud_provider, TerraformResource


@dataclass
class PulumiResource:
    """A resource extracted from Pulumi state."""
    urn: str  # urn:pulumi:stack::project::type::name
    type: str  # e.g. azure-native:resources:ResourceGroup
    name: str  # logical name
    cloud_provider: str  # azure, aws, gcp
    resource_id: str  # cloud resource ID
    parent: Optional[str] = None
    attributes: dict[str, Any] = field(default_factory=dict)
    outputs: dict[str, Any] = field(default_factory=dict)
    dependencies: list[str] = field(default_factory=list)

    @property
    def display_name(self) -> str:
        """Human-readable name."""
        return self.attributes.get("name", self.name)

    @property
    def terraform_type(self) -> str:
        """Map Pulumi type to approximate Terraform resource type for policy matching."""
        type_map: dict[str, str] = {
            "azure-native:resources:ResourceGroup": "azurerm_resource_group",
            "azure-native:storage:StorageAccount": "azurerm_storage_account",
            "azure-native:storage:BlobContainer": "azurerm_storage_container",
            "azure-native:network:NetworkSecurityGroup": "azurerm_network_security_group",
            "azure-native:network:VirtualNetwork": "azurerm_virtual_network",
            "azure-native:compute:VirtualMachine": "azurerm_virtual_machine",
            "azure-native:web:WebApp": "azurerm_app_service",
            "azure-native:sql:Server": "azurerm_mssql_server",
            "azure-native:keyvault:Vault": "azurerm_key_vault",
            "aws:s3/bucket:Bucket": "aws_s3_bucket",
            "aws:ec2/instance:Instance": "aws_instance",
            "aws:ec2/securityGroup:SecurityGroup": "aws_security_group",
            "aws:rds/instance:Instance": "aws_db_instance",
            "aws:iam/role:Role": "aws_iam_role",
            "aws:lambda/function:Function": "aws_lambda_function",
            "gcp:compute/instance:Instance": "google_compute_instance",
            "gcp:storage/bucket:Bucket": "google_storage_bucket",
            "gcp:compute/firewall:Firewall": "google_compute_firewall",
        }
        return type_map.get(self.type, self.type.replace(":", "_").replace("/", "_"))


def _detect_pulumi_provider(resource_type: str) -> str:
    """Detect cloud provider from Pulumi resource type."""
    if resource_type.startswith("azure-native:") or resource_type.startswith("azure:"):
        return "azure"
    if resource_type.startswith("aws:"):
        return "aws"
    if resource_type.startswith("gcp:") or resource_type.startswith("google-native:"):
        return "gcp"
    return "unknown"


class PulumiStateParser:
    """Parse Pulumi stack state exports into normalized resource maps.

    Supports the Pulumi state export format from `pulumi stack export`.
    """

    def __init__(self) -> None:
        self.resources: dict[str, PulumiResource] = {}
        self.stack_name: str = ""
        self.project_name: str = ""
        self.version: int = 0

    def parse_file(self, path: str | Path) -> dict[str, PulumiResource]:
        """Parse a Pulumi state export file.

        Args:
            path: Path to the JSON state export file.

        Returns:
            Dictionary mapping URN to PulumiResource.
        """
        path = Path(path)
        if not path.exists():
            raise FileNotFoundError(f"Pulumi state file not found: {path}")
        with open(path, "r", encoding="utf-8") as f:
            data = json.load(f)
        return self.parse(data)

    def parse(self, state: dict[str, Any]) -> dict[str, PulumiResource]:
        """Parse Pulumi state export data.

        Args:
            state: Parsed JSON from a Pulumi stack export.

        Returns:
            Dictionary mapping URN to PulumiResource.
        """
        self.resources = {}
        self.version = state.get("version", 0)

        deployment = state.get("deployment", {})
        if not deployment:
            raise ValueError("Invalid Pulumi state: missing 'deployment' key")

        resources = deployment.get("resources", [])
        for res in resources:
            res_type = res.get("type", "")
            urn = res.get("urn", "")

            # Skip the stack resource itself
            if res_type == "pulumi:pulumi:Stack":
                # Extract stack/project from URN: urn:pulumi:stack::project::pulumi:pulumi:Stack::name
                parts = urn.split("::")
                if len(parts) >= 2:
                    self.stack_name = parts[0].split(":")[-1] if ":" in parts[0] else ""
                    self.project_name = parts[1] if len(parts) > 1 else ""
                continue

            # Skip provider resources
            if res_type.startswith("pulumi:providers:"):
                continue

            inputs = res.get("inputs", {})
            outputs = res.get("outputs", {})
            cloud_id = outputs.get("id", inputs.get("id", ""))

            # Parse name from URN: ...::type::name
            name = urn.split("::")[-1] if urn else res.get("id", "")

            resource = PulumiResource(
                urn=urn,
                type=res_type,
                name=name,
                cloud_provider=_detect_pulumi_provider(res_type),
                resource_id=cloud_id,
                parent=res.get("parent"),
                attributes=_flatten_attributes(inputs),
                outputs=_flatten_attributes(outputs),
                dependencies=res.get("dependencies", []),
            )
            self.resources[urn] = resource

        return self.resources

    def get_resources_by_provider(self, cloud_provider: str) -> dict[str, PulumiResource]:
        """Filter resources by cloud provider."""
        return {
            urn: res for urn, res in self.resources.items()
            if res.cloud_provider == cloud_provider
        }

    def to_terraform_resources(self) -> dict[str, TerraformResource]:
        """Convert Pulumi resources to TerraformResource format for unified policy checking."""
        result: dict[str, TerraformResource] = {}
        for urn, res in self.resources.items():
            # Merge inputs and outputs, outputs take precedence
            merged = {**res.attributes, **res.outputs}
            tf_res = TerraformResource(
                address=urn,
                type=res.terraform_type,
                name=res.name,
                provider=f"pulumi:{res.type}",
                cloud_provider=res.cloud_provider,
                resource_id=res.resource_id,
                attributes=merged,
                dependencies=res.dependencies,
            )
            result[urn] = tf_res
        return result
