"""CloudFront and Route 53 waste detection for StackSage."""

from typing import Any, Dict, List

from stacksage.pricing import (
    PRICING_CLOUDFRONT_UNUSED_BASELINE_MONTH,
    PRICING_ROUTE53_HOSTED_ZONE_PRIVATE_MONTH,
    PRICING_ROUTE53_HOSTED_ZONE_PUBLIC_MONTH,
)


def detect_unused_cloudfront_distributions(
    inventory: Dict[str, Any],
    cw_avg_fn: Any,
    pricing: Any,
    config: Any,
) -> List[Dict[str, Any]]:
    """Detect CloudFront distributions with zero traffic for 30+ days.

    Detection logic:
    - Query CloudWatch Requests metric (total requests)
    - If effectively zero for 30 days, flag as unused
    - Calculate cost based on distribution pricing class
    - Flag as forgotten CDNs

    Evidence:
    - CloudWatch metrics (30-day average)
    - Distribution status and price class
    - Estimated monthly cost
    """
    findings = []
    distributions = inventory.get("cloudfront_distributions") or []

    for dist in distributions:
        dist_id = dist.get("Id")
        dist_arn = dist.get("ARN", "")
        domain_name = dist.get("DomainName", "")
        status = dist.get("Status", "")
        price_class = dist.get("PriceClass", "PriceClass_All")

        if not dist_id or status != "Deployed":
            continue

        # Query CloudWatch for request activity (30-day lookback)
        # CloudFront metrics are in us-east-1 regardless of distribution edge locations
        requests_avg = cw_avg_fn(
            namespace="AWS/CloudFront",
            metric="Requests",
            dimensions={"DistributionId": dist_id},
            stat="Sum",
            lookback_days=30,
            region="us-east-1",  # CloudFront metrics are always in us-east-1
        )

        # Check if metrics are unavailable or effectively zero
        if requests_avg is None:
            # Can't make confident determination
            continue

        # Threshold: less than 100 requests over 30 days (very conservative)
        threshold = 100.0
        is_unused = requests_avg < threshold

        if not is_unused:
            continue

        # Estimate monthly cost (CloudFront has complex pricing, use conservative estimate)
        monthly_cost = _estimate_cloudfront_cost(price_class)

        # Build evidence
        evidence = {
            "cloudwatch": {
                "metric": "Requests",
                "lookback_days": 30,
                "requests_total": round(requests_avg, 2),
                "threshold": threshold,
            },
            "distribution": {
                "id": dist_id,
                "domain_name": domain_name,
                "status": status,
                "price_class": price_class,
                "arn": dist_arn,
            },
        }

        findings.append(
            {
                "type": "cloudfront_unused_distribution",
                "resource_type": "cloudfront_distribution",
                "id": dist_id,
                "region": "global",  # CloudFront is a global service
                "severity": "low",
                "confidence": 0.9,
                "estimated_monthly_savings_usd": monthly_cost,
                "estimated_monthly_cost_usd": monthly_cost,
                "recommended_action": "disable-cloudfront-distribution",
                "summary": (
                    f"CloudFront distribution '{dist_id}' ({domain_name}) has had "
                    f"zero traffic for 30+ days ({requests_avg:.0f} requests total). "
                    f"Disable unused distribution to save ~${monthly_cost:.2f}/month."
                ),
                "reason_codes": ["cloudfront", "unused", "zero_traffic", "30_days"],
                "evidence": evidence,
                "remediation": {
                    "steps": [
                        f"1. Verify distribution is truly unused: aws cloudfront get-distribution --id {dist_id}",
                        f"2. Disable distribution: aws cloudfront update-distribution --id {dist_id} --if-match <etag> --distribution-config file://disabled-config.json",
                        f"3. After 24h, delete distribution: aws cloudfront delete-distribution --id {dist_id} --if-match <etag>",
                    ],
                    "verification": f"aws cloudfront get-distribution --id {dist_id} | grep Enabled | grep false",
                    "documentation": "https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/HowToDeleteDistribution.html",
                },
            }
        )

    return findings


def detect_unused_route53_hosted_zones(
    inventory: Dict[str, Any],
    cw_avg_fn: Any,
    pricing: Any,
    config: Any,
) -> List[Dict[str, Any]]:
    """Detect Route 53 hosted zones with zero DNS queries for 90+ days.

    Detection logic:
    - Query CloudWatch Query metric (DNS queries)
    - If zero for 90 days, flag as unused
    - Hosted zones cost $0.50/month each (standard) or $50/month (private VPC)
    - Conservative 90-day window to avoid false positives

    Evidence:
    - CloudWatch metrics (90-day average)
    - Hosted zone type (public vs private)
    - Record count
    """
    findings = []
    hosted_zones = inventory.get("route53_hosted_zones") or []

    for zone in hosted_zones:
        zone_id = zone.get("Id", "").split("/")[-1]  # Extract ID from full path
        zone_name = zone.get("Name", "")
        is_private = zone.get("Config", {}).get("PrivateZone", False)
        resource_record_set_count = zone.get("ResourceRecordSetCount", 0)

        if not zone_id:
            continue

        # Query CloudWatch for DNS query activity (90-day lookback)
        # Route 53 metrics are in us-east-1
        queries_avg = cw_avg_fn(
            namespace="AWS/Route53",
            metric="Query",
            dimensions={"HostedZoneId": zone_id},
            stat="Sum",
            lookback_days=90,
            region="us-east-1",  # Route 53 metrics are always in us-east-1
        )

        # Check if metrics are unavailable or effectively zero
        if queries_avg is None:
            # Route 53 metrics might not exist if zone truly has no queries
            # But we need to be conservative - skip if we can't confirm
            continue

        # Threshold: less than 10 queries over 90 days (extremely conservative)
        threshold = 10.0
        is_unused = queries_avg < threshold

        if not is_unused:
            continue

        # Calculate monthly cost
        if is_private:
            monthly_cost = PRICING_ROUTE53_HOSTED_ZONE_PRIVATE_MONTH
        else:
            monthly_cost = PRICING_ROUTE53_HOSTED_ZONE_PUBLIC_MONTH

        # Build evidence
        evidence = {
            "cloudwatch": {
                "metric": "Query",
                "lookback_days": 90,
                "queries_total": round(queries_avg, 2),
                "threshold": threshold,
            },
            "hosted_zone": {
                "id": zone_id,
                "name": zone_name,
                "is_private": is_private,
                "record_count": resource_record_set_count,
            },
        }

        severity = "medium" if is_private else "low"

        findings.append(
            {
                "type": "route53_unused_hosted_zone",
                "resource_type": "route53_hosted_zone",
                "id": zone_id,
                "region": "global",  # Route 53 is a global service
                "severity": severity,
                "confidence": 0.85,
                "estimated_monthly_savings_usd": monthly_cost,
                "estimated_monthly_cost_usd": monthly_cost,
                "recommended_action": "delete-route53-hosted-zone",
                "summary": (
                    f"Route 53 {'private' if is_private else 'public'} hosted zone "
                    f"'{zone_name}' has had zero DNS queries for 90+ days "
                    f"({queries_avg:.0f} queries total). "
                    f"Delete unused zone to save ${monthly_cost:.2f}/month."
                ),
                "reason_codes": ["route53", "unused", "zero_queries", "90_days"],
                "evidence": evidence,
                "remediation": {
                    "steps": [
                        f"1. Verify zone is truly unused: aws route53 get-hosted-zone --id {zone_id}",
                        f"2. List all records: aws route53 list-resource-record-sets --hosted-zone-id {zone_id}",
                        "3. Delete all non-default records (NS and SOA must be last)",
                        f"4. Delete hosted zone: aws route53 delete-hosted-zone --id {zone_id}",
                    ],
                    "verification": f"aws route53 get-hosted-zone --id {zone_id} 2>&1 | grep NoSuchHostedZone",
                    "documentation": "https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DeleteHostedZone.html",
                },
            }
        )

    return findings


def _estimate_cloudfront_cost(price_class: str) -> float:
    """Estimate monthly cost of a CloudFront distribution.

    CloudFront pricing is complex (data transfer out, requests, price class).
    For unused distributions, assume minimal baseline cost.

    Price classes:
    - PriceClass_All: $0-1/month (minimal baseline)
    - PriceClass_200: $0-1/month
    - PriceClass_100: $0-1/month
    """
    # For truly unused distributions, cost is near-zero
    # But we estimate a small baseline to account for any background activity
    return PRICING_CLOUDFRONT_UNUSED_BASELINE_MONTH
