"""Cost impact estimation orchestrator.

Contract:
- CostImpactEstimate extends CloudIntelligenceResult with breakdown,
  confidence, and totals.
- Orchestrates Infracost subprocess + cloud pricing API fallbacks.
- All failures non-fatal — always returns a result.
"""

from __future__ import annotations

import sys
import time
from dataclasses import dataclass, field
from datetime import UTC, datetime

from complyform.core.cloud_intelligence import CloudIntelligenceResult

__all__ = [
    "CostImpactEstimate",
    "CostLineItem",
    "estimate_cost_impact",
]


@dataclass
class CostLineItem:
    """Single cost line item in the breakdown."""

    # "encryption" | "logging" | "networking"
    # | "monitoring" | "compute" | "storage"
    category: str
    description: str
    monthly_cost: float
    resource_count: int
    source: str  # "infracost" | "pricing_api" | "estimate"
    controls: list[str] = field(default_factory=list)


@dataclass
class CostImpactEstimate(CloudIntelligenceResult):
    """Result of cost impact estimation."""

    currency: str = "USD"
    total_monthly_delta: float = 0.0
    total_annual_delta: float = 0.0
    breakdown: list[CostLineItem] = field(default_factory=list)
    confidence: str = "estimated"  # "high" | "medium" | "estimated"
    infracost_available: bool = False


def estimate_cost_impact(
    cloud: str,
    tf_path: str | None = None,
    region: str = "us-east-1",
) -> CostImpactEstimate:
    """Estimate compliance cost impact.

    Orchestration:
    1. Try Infracost diff (via infracost_runner)
    2. If unavailable/failed -> fall back to pricing APIs only
    3. Run supplemental pricing for non-Terraform costs
    4. Merge results into breakdown
    5. Compute totals + confidence
    """
    start = time.monotonic()
    ts = datetime.now(tz=UTC).isoformat()

    breakdown: list[CostLineItem] = []
    infracost_available = False
    infracost_items: list[CostLineItem] = []

    # Step 1: Try Infracost
    if tf_path:
        from complyform.core.cloud_intelligence.infracost_runner import (
            run_infracost_breakdown,
        )

        infracost_result = run_infracost_breakdown(tf_path)
        if infracost_result is not None:
            infracost_available = True
            # Parse Infracost JSON output
            for project in infracost_result.get("projects", []):
                for diff in project.get("breakdown", {}).get("resources", []):
                    monthly = diff.get("monthlyCost")
                    if monthly is not None:
                        infracost_items.append(
                            CostLineItem(
                                category=_categorize_resource(diff.get("name", "")),
                                description=diff.get("name", "unknown"),
                                monthly_cost=float(monthly),
                                resource_count=1,
                                source="infracost",
                            )
                        )
            breakdown.extend(infracost_items)

    # Step 2: Supplemental pricing APIs
    supplemental: list[CostLineItem] = []
    try:
        if cloud == "gcp":
            from complyform.core.cloud_intelligence.pricing_gcp import (
                get_gcp_supplemental_costs,
            )

            supplemental = get_gcp_supplemental_costs(region)
        elif cloud == "aws":
            from complyform.core.cloud_intelligence.pricing_aws import (
                get_aws_supplemental_costs,
            )

            supplemental = get_aws_supplemental_costs(region)
        elif cloud == "azure":
            from complyform.core.cloud_intelligence.pricing_azure import (
                get_azure_supplemental_costs,
            )

            supplemental = get_azure_supplemental_costs(region)
    except Exception as exc:
        print(f"Warning: pricing API failed: {exc}", file=sys.stderr)

    breakdown.extend(supplemental)

    # Step 3: Compute totals + confidence
    total_monthly = sum(item.monthly_cost for item in breakdown)
    total_annual = total_monthly * 12

    if infracost_available and not supplemental:
        confidence = "high"
    elif infracost_available and supplemental:
        confidence = "medium"
    else:
        confidence = "estimated"

    elapsed = int((time.monotonic() - start) * 1000)

    return CostImpactEstimate(
        feature="cost_impact",
        cloud=cloud,
        success=True,
        error=None,
        duration_ms=elapsed,
        timestamp=ts,
        currency="USD",
        total_monthly_delta=total_monthly,
        total_annual_delta=total_annual,
        breakdown=breakdown,
        confidence=confidence,
        infracost_available=infracost_available,
    )


def _categorize_resource(name: str) -> str:
    """Categorize a resource name into a cost category."""
    lower = name.lower()
    if any(k in lower for k in ("kms", "encrypt", "key")):
        return "encryption"
    if any(k in lower for k in ("log", "monitor", "watch", "metric")):
        return "logging"
    if any(k in lower for k in ("vpc", "network", "firewall", "endpoint", "nat")):
        return "networking"
    if any(k in lower for k in ("alarm", "alert", "dashboard")):
        return "monitoring"
    if any(k in lower for k in ("instance", "vm", "compute", "lambda", "function")):
        return "compute"
    if any(k in lower for k in ("bucket", "storage", "disk", "volume", "s3")):
        return "storage"
    return "compute"
