"""CLI commands for AWS tag management."""

from pathlib import Path

import pandas as pd
import typer

from .resources import Resources, TAG_COLUMNS
from .changeset import Changeset
from .getter import get_tags

cli = typer.Typer(help="AWS Tags Management Tools")

DEFAULT_TAGS = ",".join(TAG_COLUMNS)


def parse_tags(value: str) -> list[str]:
    return [t.strip() for t in value.split(",")]


@cli.command("get")
def command_tags_get(
    output: Path = typer.Option(
        Path("tags.xlsx"),
        "--output",
        "-o",
        help="Output XLSX file path",
    ),
    billable: bool = typer.Option(
        False,
        "--billable",
        help="Only include billable resources (exclude free resources like VPCs, subnets)",
    ),
    tags: str = typer.Option(
        DEFAULT_TAGS,
        "--tags",
        metavar="TAGS",
        help="Comma-separated list of tag keys to include",
    ),
):
    """Export AWS resource tags to XLSX spreadsheet."""
    resources = Resources.get()
    df = Resources.to_dataframe(resources, billable, parse_tags(tags))
    df.to_excel(output, index=False, sheet_name="Resources")
    typer.echo(f"Exported {len(df)} resources to {output}")


@cli.command("set")
def command_tags_set(
    input_file: Path = typer.Option(
        ...,
        "--input",
        "-i",
        help="Input XLSX file path",
    ),
    apply: bool = typer.Option(
        False,
        "--apply",
        help="Actually apply changes (default is dry-run)",
    ),
    tags: str = typer.Option(
        DEFAULT_TAGS,
        "--tags",
        metavar="TAGS",
        help="Comma-separated list of tag keys to compare",
    ),
):
    """Import tags from XLSX spreadsheet to AWS resources."""
    tag_keys = parse_tags(tags)

    # 1. Read XLSX
    typer.echo(f"Reading {input_file}...")
    df = pd.read_excel(input_file)
    typer.echo(f"Found {len(df)} resources in file")

    if df.empty:
        typer.echo("No resources in file.")
        return

    # 2. Validate tag columns exist
    missing = [t for t in tag_keys if f"tag:{t}" not in df.columns]
    if missing:
        raise typer.BadParameter(
            f"Missing tag columns in file: {', '.join(missing)}"
        )

    # 3. Fetch current resources to check which still exist
    typer.echo("Fetching current resources...")
    resources = Resources.get()
    # Apply same filter as export (taggable + cost-relevant)
    existing_arns = {
        r["Arn"]
        for r in resources
        if (opts := Resources.OPTIONS.get(r["ResourceType"]))
        and opts.taggable
        and opts.tracked
    }

    # 4. Find resources in XLSX that no longer exist
    xlsx_arns = set(df["resource_arn"])
    missing_arns = xlsx_arns - existing_arns
    if missing_arns:
        typer.echo(f"\nSkipping {len(missing_arns)} resources that no longer exist:")
        for arn in sorted(missing_arns):
            typer.echo(f"  - {arn}")
        df = df[~df["resource_arn"].isin(missing_arns)]
        typer.echo()

    if df.empty:
        typer.echo("No existing resources to update.")
        return

    # 5. Fetch current tags for existing resources
    typer.echo("Fetching current tags...")
    by_arn = {row["resource_arn"]: row["resource_type"] for _, row in df.iterrows()}
    current_tags = get_tags(by_arn, 100)

    # 6. Compute diff
    changes = Changeset.get(df, current_tags, tag_keys)

    # 7. Display changes
    if not changes:
        typer.echo("No changes needed.")
        return

    typer.echo(f"\nPlanned changes ({len(changes)} resources):")
    for change in changes:
        typer.echo(f"\n  {change.arn}")
        for key, value in change.tags.items():
            current = current_tags.get(change.arn, {}).get(key, "")
            if current:
                typer.echo(f"    ~ {key}: {current} -> {value}")
            else:
                typer.echo(f"    + {key}: {value}")

    total_tags = sum(len(c.tags) for c in changes)
    typer.echo(f"\nTotal: {total_tags} tags on {len(changes)} resources")

    # 8. Apply if requested
    if apply:
        confirm = typer.confirm(
            f"\nApply {total_tags} tag changes to {len(changes)} resources?"
        )
        if not confirm:
            typer.echo("Aborted.")
            raise typer.Exit(1)

        typer.echo("Applying changes...")
        result = Changeset.set(changes)
        typer.echo(f"Done: {len(result.success)} success, {len(result.failed)} failed")
        for arn, error in result.failed.items():
            typer.echo(f"  FAILED {arn}: {error}")
    else:
        typer.echo("\nDry run. Use --apply to execute changes.")
