"""DynamoDB waste detection for StackSage."""

from typing import Any, Dict, List, Optional

from stacksage.pricing import (
    PRICING_DYNAMODB_RCU_HOURLY,
    PRICING_DYNAMODB_STORAGE_GB_MONTH,
    PRICING_DYNAMODB_WCU_HOURLY,
)


def detect_unused_dynamodb_tables(
    inventory: Dict[str, Any],
    cw_avg_fn: Any,
    pricing: Any,
    config: Any,
) -> List[Dict[str, Any]]:
    """Detect DynamoDB tables with zero read/write activity for 30+ days.

    Detection logic:
    - Query CloudWatch ConsumedReadCapacityUnits and ConsumedWriteCapacityUnits
    - If both are 0 (or near-0) for 30 days, flag as unused
    - Calculate cost based on provisioned capacity or on-demand usage
    - Conservative threshold to avoid false positives

    Evidence:
    - CloudWatch metrics (30-day average)
    - Table capacity mode (provisioned vs on-demand)
    - Current cost estimate
    """
    findings = []
    tables = inventory.get("dynamodb_tables") or []

    for table in tables:
        table_name = table.get("TableName")
        table_arn = table.get("TableArn", "")
        region = _extract_region_from_arn(table_arn)
        billing_mode = table.get("BillingModeSummary", {}).get(
            "BillingMode", "PROVISIONED"
        )

        if not table_name:
            continue

        # Query CloudWatch for read/write activity (30-day lookback)
        read_capacity_avg = cw_avg_fn(
            namespace="AWS/DynamoDB",
            metric="ConsumedReadCapacityUnits",
            dimensions={"TableName": table_name},
            stat="Sum",
            lookback_days=30,
            region=region,
        )

        write_capacity_avg = cw_avg_fn(
            namespace="AWS/DynamoDB",
            metric="ConsumedWriteCapacityUnits",
            dimensions={"TableName": table_name},
            stat="Sum",
            lookback_days=30,
            region=region,
        )

        # Check if both metrics are unavailable or effectively zero
        if read_capacity_avg is None or write_capacity_avg is None:
            # If metrics are unavailable, we can't make a confident determination
            continue

        # Threshold: less than 1 read/write per day on average (very conservative)
        # Over 30 days, that's <30 total capacity units
        threshold = 30.0
        is_unused = read_capacity_avg < threshold and write_capacity_avg < threshold

        if not is_unused:
            continue

        # Calculate cost estimate
        monthly_cost = _estimate_dynamodb_table_cost(table, pricing, region)

        # Build evidence
        evidence = {
            "cloudwatch": {
                "metric": "ConsumedReadCapacityUnits + ConsumedWriteCapacityUnits",
                "lookback_days": 30,
                "read_capacity_avg": round(read_capacity_avg, 2),
                "write_capacity_avg": round(write_capacity_avg, 2),
                "threshold": threshold,
            },
            "table": {
                "name": table_name,
                "billing_mode": billing_mode,
                "arn": table_arn,
            },
        }

        # Add provisioned capacity details if applicable
        if billing_mode == "PROVISIONED":
            provisioned_throughput = table.get("ProvisionedThroughput", {})
            evidence["table"]["read_capacity_units"] = provisioned_throughput.get(
                "ReadCapacityUnits", 0
            )
            evidence["table"]["write_capacity_units"] = provisioned_throughput.get(
                "WriteCapacityUnits", 0
            )

        findings.append(
            {
                "type": "dynamodb_unused_table",
                "resource_type": "dynamodb_table",
                "id": table_name,
                "region": region,
                "severity": "medium",
                "confidence": 0.95,
                "estimated_monthly_savings_usd": monthly_cost,
                "estimated_monthly_cost_usd": monthly_cost,
                "recommended_action": "delete-or-disable-dynamodb-table",
                "summary": (
                    f"DynamoDB table '{table_name}' has had zero activity for 30+ days "
                    f"(reads: {read_capacity_avg:.1f}, writes: {write_capacity_avg:.1f}). "
                    f"Delete unused table to save ~${monthly_cost:.2f}/month."
                ),
                "reason_codes": ["dynamodb", "unused", "zero_activity", "30_days"],
                "evidence": evidence,
                "remediation": {
                    "steps": [
                        f"1. Verify table is truly unused: aws dynamodb describe-table --table-name {table_name}",
                        f"2. Create on-demand backup if needed: aws dynamodb create-backup --table-name {table_name} --backup-name {table_name}-final-backup",
                        f"3. Delete table: aws dynamodb delete-table --table-name {table_name}",
                    ],
                    "verification": f"aws dynamodb describe-table --table-name {table_name} 2>&1 | grep ResourceNotFoundException",
                },
            }
        )

    return findings


def _estimate_dynamodb_table_cost(
    table: Dict[str, Any], pricing: Any, region: str
) -> float:
    """Estimate monthly cost of a DynamoDB table.

    For PROVISIONED mode: RCU + WCU hourly cost * 730 hours
    For PAY_PER_REQUEST mode: Assume minimal cost (harder to estimate without request volume)
    """
    billing_mode = table.get("BillingModeSummary", {}).get("BillingMode", "PROVISIONED")

    if billing_mode == "PAY_PER_REQUEST":
        # On-demand pricing is harder to estimate without actual request counts
        # Assume a minimal cost for unused tables (storage only)
        table_size_bytes = table.get("TableSizeBytes", 0)
        storage_gb = table_size_bytes / (1024**3)
        return storage_gb * PRICING_DYNAMODB_STORAGE_GB_MONTH

    # PROVISIONED mode
    provisioned_throughput = table.get("ProvisionedThroughput", {})
    read_capacity_units = provisioned_throughput.get("ReadCapacityUnits", 0)
    write_capacity_units = provisioned_throughput.get("WriteCapacityUnits", 0)

    # Use pricing constants from pricing.py
    hours_per_month = 730
    monthly_cost = (
        read_capacity_units * PRICING_DYNAMODB_RCU_HOURLY * hours_per_month
    ) + (write_capacity_units * PRICING_DYNAMODB_WCU_HOURLY * hours_per_month)

    # Add storage cost
    table_size_bytes = table.get("TableSizeBytes", 0)
    storage_gb = table_size_bytes / (1024**3)
    monthly_cost += storage_gb * PRICING_DYNAMODB_STORAGE_GB_MONTH

    return round(monthly_cost, 2)


def _extract_region_from_arn(arn: str) -> Optional[str]:
    """Extract AWS region from ARN.

    Example: arn:aws:dynamodb:us-east-1:123456789012:table/MyTable
    Returns: us-east-1
    """
    if not arn:
        return None
    parts = arn.split(":")
    if len(parts) >= 4:
        return parts[3] if parts[3] else None
    return None
