"""CLI commands for resource lookup."""

import json
from datetime import datetime, timedelta, timezone

import boto3
import typer

from .alarm import build_report as build_alarm_report
from .alarm import delete_alarm
from .ami import build_report as build_ami_report
from .ami import delete_ami
from .ebs import build_report as build_ebs_report
from .ebs import delete_volume
from .lb import build_report as build_lb_report
from .lb import delete_load_balancer
from .lc import build_report as build_lc_report
from .lt import build_report as build_lt_report
from .snap import build_report as build_snap_report
from .snap import delete_snapshot

app = typer.Typer(help="Resource lookup tools")


@app.command("lt")
def lt_report(
    orphaned: bool = typer.Option(
        False, "--orphaned", help="Show only orphaned launch templates"
    ),
    sort: str = typer.Option("name", "-s", "--sort", help="Sort by: name, created"),
    json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
    region: str = typer.Option(None, "-r", "--region", help="AWS region"),
):
    """Launch Template usage report."""
    session = boto3.Session(region_name=region)
    report = build_lt_report(session)

    # Sort
    if sort == "name":
        report.sort(key=lambda r: r.name)
    elif sort == "created":
        report.sort(key=lambda r: r.created)
    else:
        typer.echo(f"Unknown sort column: {sort}. Use 'name' or 'created'.")
        raise typer.Exit(1)

    if orphaned:
        report = [r for r in report if r.is_orphaned]

    if json_output:
        print(json.dumps([r.to_dict() for r in report], indent=2))
    else:
        if not report:
            typer.echo("No launch templates found.")
            return

        # Calculate column widths
        name_width = max(len(r.name) for r in report)
        name_width = max(name_width, len("Launch Template"))

        # Header
        typer.echo(
            f"{'Launch Template':<{name_width}}  {'Created':<12}  {'EC2':>5}  References"
        )
        typer.echo(f"{'-' * name_width}  {'-' * 12}  {'-' * 5}  {'-' * 40}")

        # Rows
        for r in report:
            created_str = r.created.strftime("%Y-%m-%d")
            if r.references:
                refs_str = ", ".join(f"{ref.type}:{ref.name}" for ref in r.references)
            else:
                refs_str = "-"
            typer.echo(
                f"{r.name:<{name_width}}  {created_str:<12}  {r.instance_count:>5}  {refs_str}"
            )

        # Summary
        orphaned_count = sum(1 for r in report if r.is_orphaned)
        typer.echo()
        typer.echo(f"Total: {len(report)} launch templates, {orphaned_count} orphaned")


@app.command("lc")
def lc_report(
    orphaned: bool = typer.Option(
        False, "--orphaned", help="Show only orphaned launch configurations"
    ),
    sort: str = typer.Option("name", "-s", "--sort", help="Sort by: name, created"),
    json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
    region: str = typer.Option(None, "-r", "--region", help="AWS region"),
):
    """Launch Configuration usage report."""
    session = boto3.Session(region_name=region)
    report = build_lc_report(session)

    # Sort
    if sort == "name":
        report.sort(key=lambda r: r.name)
    elif sort == "created":
        report.sort(key=lambda r: r.created)
    else:
        typer.echo(f"Unknown sort column: {sort}. Use 'name' or 'created'.")
        raise typer.Exit(1)

    if orphaned:
        report = [r for r in report if r.is_orphaned]

    if json_output:
        print(json.dumps([r.to_dict() for r in report], indent=2))
    else:
        if not report:
            typer.echo("No launch configurations found.")
            return

        # Calculate column widths
        name_width = max(len(r.name) for r in report)
        name_width = max(name_width, len("Launch Configuration"))

        # Header
        typer.echo(
            f"{'Launch Configuration':<{name_width}}  {'Created':<12}  {'AMI ID':<21}  References"
        )
        typer.echo(f"{'-' * name_width}  {'-' * 12}  {'-' * 21}  {'-' * 40}")

        # Rows
        for r in report:
            created_str = r.created.strftime("%Y-%m-%d")
            refs_str = (
                ", ".join(f"{ref.type}:{ref.name}" for ref in r.references)
                if r.references
                else "-"
            )
            typer.echo(
                f"{r.name:<{name_width}}  {created_str:<12}  {r.ami_id:<21}  {refs_str}"
            )

        # Summary
        orphaned_count = sum(1 for r in report if r.is_orphaned)
        typer.echo()
        typer.echo(
            f"Total: {len(report)} launch configurations, {orphaned_count} orphaned"
        )


@app.command("ami")
def ami_report(
    orphaned: bool = typer.Option(False, "--orphaned", help="Show only orphaned AMIs"),
    delete: bool = typer.Option(
        False, "--delete", help="Interactive deletion (requires --orphaned)"
    ),
    sort: str = typer.Option("name", "-s", "--sort", help="Sort by: name, created"),
    json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
    region: str = typer.Option(None, "-r", "--region", help="AWS region"),
):
    """AMI usage report."""
    if delete and not orphaned:
        typer.echo("--delete requires --orphaned")
        raise typer.Exit(1)

    session = boto3.Session(region_name=region)
    report = build_ami_report(session)

    # Sort
    if sort == "name":
        report.sort(key=lambda r: r.name)
    elif sort == "created":
        report.sort(key=lambda r: r.created)
    else:
        typer.echo(f"Unknown sort column: {sort}. Use 'name' or 'created'.")
        raise typer.Exit(1)

    if orphaned:
        report = [r for r in report if r.is_orphaned]

    if json_output:
        print(json.dumps([r.to_dict() for r in report], indent=2))
    else:
        if not report:
            typer.echo("No AMIs found.")
            return

        # Calculate column widths
        name_width = max(len(r.name) for r in report)
        name_width = max(name_width, len("AMI Name"))

        # Header
        typer.echo(
            f"{'AMI Name':<{name_width}}  {'AMI ID':<21}  {'Created':<12}  {'EC2':>5}  References  Snapshots"
        )
        typer.echo(f"{'-' * name_width}  {'-' * 21}  {'-' * 12}  {'-' * 5}  {'-' * 40}")

        # Rows
        for r in report:
            created_str = r.created.strftime("%Y-%m-%d")
            refs_str = (
                ", ".join(f"{ref.type}:{ref.name}" for ref in r.references)
                if r.references
                else "-"
            )
            snaps_str = ", ".join(r.snapshot_ids) if r.snapshot_ids else "-"
            typer.echo(
                f"{r.name:<{name_width}}  {r.id:<21}  {created_str:<12}  {r.instance_count:>5}  {refs_str}  {snaps_str}"
            )

        # Summary
        orphaned_count = sum(1 for r in report if r.is_orphaned)
        total_snapshots = sum(len(r.snapshot_ids) for r in report)
        typer.echo()
        typer.echo(
            f"Total: {len(report)} AMIs ({total_snapshots} snapshots), {orphaned_count} orphaned"
        )

        # Interactive deletion
        if delete and report:
            typer.echo()
            typer.echo("Starting interactive deletion (y=delete, n=skip, q=quit)")
            typer.echo()

            deleted_amis = 0
            deleted_snaps = 0

            for r in report:
                created_str = r.created.strftime("%Y-%m-%d")
                total_size = sum(s.size_gb for s in r.snapshots)
                typer.echo(f"AMI: {r.name}")
                typer.echo(f"  ID:      {r.id}")
                typer.echo(f"  Created: {created_str}")
                if r.snapshots:
                    typer.echo(f"  Snapshots ({len(r.snapshots)}, {total_size} GB):")
                    for snap in r.snapshots:
                        typer.echo(f"    - {snap.id} ({snap.size_gb} GB)")
                else:
                    typer.echo("  Snapshots: none")

                while True:
                    choice = typer.prompt("Delete?", default="y")
                    if choice.lower() == "y":
                        delete_ami(session, r.id, r.snapshot_ids)
                        deleted_amis += 1
                        deleted_snaps += len(r.snapshot_ids)
                        break
                    elif choice.lower() == "n":
                        typer.echo("  Skipped")
                        break
                    elif choice.lower() == "q":
                        typer.echo()
                        typer.echo(
                            f"Deleted {deleted_amis} AMIs, {deleted_snaps} snapshots"
                        )
                        return
                    else:
                        typer.echo("  Invalid choice. Use y/n/q")

                typer.echo()

            typer.echo(f"Deleted {deleted_amis} AMIs, {deleted_snaps} snapshots")


@app.command("snap")
def snap_report(
    orphaned: bool = typer.Option(
        False, "--orphaned", help="Show only orphaned snapshots"
    ),
    older_than: int = typer.Option(
        None, "--older-than", help="Show only snapshots older than N days"
    ),
    delete: bool = typer.Option(
        False, "--delete", help="Interactive deletion (requires --orphaned)"
    ),
    sort: str = typer.Option("created", "-s", "--sort", help="Sort by: created, size"),
    json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
    region: str = typer.Option(None, "-r", "--region", help="AWS region"),
):
    """Snapshot usage report."""
    if delete and not orphaned:
        typer.echo("--delete requires --orphaned")
        raise typer.Exit(1)

    session = boto3.Session(region_name=region)
    report = build_snap_report(session)

    # Filter by age
    if older_than is not None:
        cutoff = datetime.now(timezone.utc) - timedelta(days=older_than)
        report = [r for r in report if r.created < cutoff]

    # Sort
    if sort == "created":
        report.sort(key=lambda r: r.created)
    elif sort == "size":
        report.sort(key=lambda r: r.size_gb, reverse=True)
    else:
        typer.echo(f"Unknown sort column: {sort}. Use 'created' or 'size'.")
        raise typer.Exit(1)

    if orphaned:
        report = [r for r in report if r.is_orphaned]

    if json_output:
        print(json.dumps([r.to_dict() for r in report], indent=2))
    else:
        if not report:
            typer.echo("No snapshots found.")
            return

        # Calculate column widths
        desc_width = max(len(r.description[:40]) for r in report)
        desc_width = max(desc_width, len("Description"))

        # Header
        typer.echo(
            f"{'Snapshot ID':<22}  {'Size':>6}  {'Created':<12}  {'Type':<6}  {'Description':<{desc_width}}  References"
        )
        typer.echo(
            f"{'-' * 22}  {'-' * 6}  {'-' * 12}  {'-' * 6}  {'-' * desc_width}  {'-' * 30}"
        )

        # Rows
        for r in report:
            created_str = r.created.strftime("%Y-%m-%d")
            desc_str = r.description[:40] if r.description else "-"
            type_str = "AMI" if r.is_ami_created else "Manual"
            refs_str = (
                ", ".join(f"{ref.type}:{ref.name}" for ref in r.references)
                if r.references
                else "-"
            )
            typer.echo(
                f"{r.id:<22}  {r.size_gb:>5}G  {created_str:<12}  {type_str:<6}  {desc_str:<{desc_width}}  {refs_str}"
            )

        # Summary
        orphaned_count = sum(1 for r in report if r.is_orphaned)
        total_size = sum(r.size_gb for r in report)
        typer.echo()
        typer.echo(
            f"Total: {len(report)} snapshots ({total_size} GB), {orphaned_count} orphaned"
        )

        # Interactive deletion
        if delete and report:
            typer.echo()
            typer.echo("Starting interactive deletion (y=delete, n=skip, q=quit)")
            typer.echo()

            deleted_count = 0
            deleted_size = 0

            for r in report:
                created_str = r.created.strftime("%Y-%m-%d")
                type_str = "AMI-created" if r.is_ami_created else "Manual backup"
                typer.echo(f"Snapshot: {r.id}")
                typer.echo(f"  Size:        {r.size_gb} GB")
                typer.echo(f"  Created:     {created_str}")
                typer.echo(f"  Type:        {type_str}")
                typer.echo(f"  Description: {r.description or '-'}")
                if r.volume_id:
                    typer.echo(f"  Volume:      {r.volume_id}")

                while True:
                    choice = typer.prompt("Delete?", default="y")
                    if choice.lower() == "y":
                        delete_snapshot(session, r.id)
                        deleted_count += 1
                        deleted_size += r.size_gb
                        break
                    elif choice.lower() == "n":
                        typer.echo("  Skipped")
                        break
                    elif choice.lower() == "q":
                        typer.echo()
                        typer.echo(
                            f"Deleted {deleted_count} snapshots ({deleted_size} GB)"
                        )
                        return
                    else:
                        typer.echo("  Invalid choice. Use y/n/q")

                typer.echo()

            typer.echo(f"Deleted {deleted_count} snapshots ({deleted_size} GB)")


@app.command("alarm")
def alarm_report(
    orphaned: bool = typer.Option(
        False, "--orphaned", help="Show only orphaned alarms"
    ),
    delete: bool = typer.Option(
        False, "--delete", help="Interactive deletion (requires --orphaned)"
    ),
    sort: str = typer.Option(
        "namespace", "-s", "--sort", help="Sort by: namespace, name, updated"
    ),
    json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
    region: str = typer.Option(None, "-r", "--region", help="AWS region"),
):
    """CloudWatch Alarm usage report."""
    if delete and not orphaned:
        typer.echo("--delete requires --orphaned")
        raise typer.Exit(1)

    session = boto3.Session(region_name=region)
    report = build_alarm_report(session)

    # Sort
    if sort == "namespace":
        report.sort(key=lambda r: (r.namespace, r.name))
    elif sort == "name":
        report.sort(key=lambda r: r.name)
    elif sort == "updated":
        report.sort(key=lambda r: r.updated)
    else:
        typer.echo(f"Unknown sort column: {sort}. Use 'namespace', 'name', or 'updated'.")
        raise typer.Exit(1)

    if orphaned:
        report = [r for r in report if r.is_orphaned]

    if json_output:
        print(json.dumps([r.to_dict() for r in report], indent=2))
    else:
        if not report:
            typer.echo("No alarms found.")
            return

        # Calculate column widths
        name_width = max(len(r.name[:50]) for r in report)
        name_width = max(name_width, len("Alarm Name"))
        ns_width = max(len(r.namespace) for r in report)
        ns_width = max(ns_width, len("Namespace"))

        # Header
        typer.echo(
            f"{'Alarm Name':<{name_width}}  {'Namespace':<{ns_width}}  {'State':<17}  {'Resource':>8}  Dimensions"
        )
        typer.echo(
            f"{'-' * name_width}  {'-' * ns_width}  {'-' * 17}  {'-' * 8}  {'-' * 30}"
        )

        # Rows
        for r in report:
            name_str = r.name[:50]
            if r.resource_exists is None:
                exists_str = "?"
            elif r.resource_exists:
                exists_str = "exists"
            else:
                exists_str = "MISSING"
            dims_str = ", ".join(f"{k}={v}" for k, v in r.dimensions.items())
            typer.echo(
                f"{name_str:<{name_width}}  {r.namespace:<{ns_width}}  {r.state:<17}  {exists_str:>8}  {dims_str}"
            )

        # Summary
        orphaned_count = sum(1 for r in report if r.is_orphaned)
        unknown_count = sum(1 for r in report if r.resource_exists is None)
        typer.echo()
        typer.echo(
            f"Total: {len(report)} alarms, {orphaned_count} orphaned, {unknown_count} unknown"
        )

        # Interactive deletion
        if delete and report:
            typer.echo()
            typer.echo("Starting interactive deletion (y=delete, n=skip, q=quit)")
            typer.echo()

            deleted_count = 0

            for r in report:
                dims_str = ", ".join(f"{k}={v}" for k, v in r.dimensions.items())
                typer.echo(f"Alarm: {r.name}")
                typer.echo(f"  Namespace:  {r.namespace}")
                typer.echo(f"  Metric:     {r.metric_name}")
                typer.echo(f"  Dimensions: {dims_str}")
                typer.echo(f"  State:      {r.state}")

                while True:
                    choice = typer.prompt("Delete?", default="y")
                    if choice.lower() == "y":
                        delete_alarm(session, r.name)
                        deleted_count += 1
                        break
                    elif choice.lower() == "n":
                        typer.echo("  Skipped")
                        break
                    elif choice.lower() == "q":
                        typer.echo()
                        typer.echo(f"Deleted {deleted_count} alarms")
                        return
                    else:
                        typer.echo("  Invalid choice. Use y/n/q")

                typer.echo()

            typer.echo(f"Deleted {deleted_count} alarms")


@app.command("lb")
def lb_report(
    orphaned: bool = typer.Option(
        False, "--orphaned", help="Show only orphaned load balancers"
    ),
    delete: bool = typer.Option(
        False, "--delete", help="Interactive deletion (requires --orphaned)"
    ),
    sort: str = typer.Option(
        "name", "-s", "--sort", help="Sort by: name, type, created"
    ),
    json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
    region: str = typer.Option(None, "-r", "--region", help="AWS region"),
):
    """Load Balancer usage report."""
    if delete and not orphaned:
        typer.echo("--delete requires --orphaned")
        raise typer.Exit(1)

    session = boto3.Session(region_name=region)
    report = build_lb_report(session)

    # Sort
    if sort == "name":
        report.sort(key=lambda r: r.name)
    elif sort == "type":
        report.sort(key=lambda r: (r.type, r.name))
    elif sort == "created":
        report.sort(key=lambda r: r.created)
    else:
        typer.echo(f"Unknown sort column: {sort}. Use 'name', 'type', or 'created'.")
        raise typer.Exit(1)

    if orphaned:
        report = [r for r in report if r.is_orphaned]

    if json_output:
        print(json.dumps([r.to_dict() for r in report], indent=2))
    else:
        if not report:
            typer.echo("No load balancers found.")
            return

        # Calculate column widths
        name_width = max(len(r.name[:40]) for r in report)
        name_width = max(name_width, len("Name"))

        # Header
        typer.echo(
            f"{'Name':<{name_width}}  {'Type':<11}  {'Created':<12}  {'Targets':>7}  Target Groups"
        )
        typer.echo(
            f"{'-' * name_width}  {'-' * 11}  {'-' * 12}  {'-' * 7}  {'-' * 30}"
        )

        # Rows
        for r in report:
            name_str = r.name[:40]
            created_str = r.created.strftime("%Y-%m-%d")
            if r.type == "classic":
                tg_str = f"{r.instance_count} instances"
            elif r.target_groups:
                tg_str = ", ".join(
                    f"{tg.name}({tg.target_count})" for tg in r.target_groups
                )
            else:
                tg_str = "-"
            typer.echo(
                f"{name_str:<{name_width}}  {r.type:<11}  {created_str:<12}  {r.total_targets:>7}  {tg_str}"
            )

        # Summary
        orphaned_count = sum(1 for r in report if r.is_orphaned)
        typer.echo()
        typer.echo(
            f"Total: {len(report)} load balancers, {orphaned_count} orphaned"
        )

        # Interactive deletion
        if delete and report:
            typer.echo()
            typer.echo("Starting interactive deletion (y=delete, n=skip, q=quit)")
            typer.echo()

            deleted_count = 0

            for r in report:
                created_str = r.created.strftime("%Y-%m-%d")
                typer.echo(f"Load Balancer: {r.name}")
                typer.echo(f"  Type:    {r.type}")
                typer.echo(f"  Created: {created_str}")
                typer.echo(f"  DNS:     {r.dns_name}")
                typer.echo(f"  Targets: {r.total_targets}")

                while True:
                    choice = typer.prompt("Delete?", default="y")
                    if choice.lower() == "y":
                        delete_load_balancer(session, r.arn, r.type)
                        deleted_count += 1
                        break
                    elif choice.lower() == "n":
                        typer.echo("  Skipped")
                        break
                    elif choice.lower() == "q":
                        typer.echo()
                        typer.echo(f"Deleted {deleted_count} load balancers")
                        return
                    else:
                        typer.echo("  Invalid choice. Use y/n/q")

                typer.echo()

            typer.echo(f"Deleted {deleted_count} load balancers")


@app.command("ebs")
def ebs_report(
    orphaned: bool = typer.Option(
        False, "--orphaned", help="Show only orphaned (available) volumes"
    ),
    delete: bool = typer.Option(
        False, "--delete", help="Interactive deletion (requires --orphaned)"
    ),
    sort: str = typer.Option(
        "created", "-s", "--sort", help="Sort by: name, size, created"
    ),
    json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
    region: str = typer.Option(None, "-r", "--region", help="AWS region"),
):
    """EBS Volume usage report."""
    if delete and not orphaned:
        typer.echo("--delete requires --orphaned")
        raise typer.Exit(1)

    session = boto3.Session(region_name=region)
    report = build_ebs_report(session)

    # Sort
    if sort == "name":
        report.sort(key=lambda r: r.name)
    elif sort == "size":
        report.sort(key=lambda r: r.size_gb, reverse=True)
    elif sort == "created":
        report.sort(key=lambda r: r.created)
    else:
        typer.echo(f"Unknown sort column: {sort}. Use 'name', 'size', or 'created'.")
        raise typer.Exit(1)

    if orphaned:
        report = [r for r in report if r.is_orphaned]

    if json_output:
        print(json.dumps([r.to_dict() for r in report], indent=2))
    else:
        if not report:
            typer.echo("No EBS volumes found.")
            return

        # Calculate column widths
        name_width = max((len(r.name[:30]) for r in report), default=4)
        name_width = max(name_width, len("Name"))

        # Header
        typer.echo(
            f"{'Volume ID':<21}  {'Name':<{name_width}}  {'Size':>6}  {'Type':<4}  {'State':<9}  {'Created':<12}  AZ"
        )
        typer.echo(
            f"{'-' * 21}  {'-' * name_width}  {'-' * 6}  {'-' * 4}  {'-' * 9}  {'-' * 12}  {'-' * 12}"
        )

        # Rows
        for r in report:
            name_str = r.name[:30] if r.name else "-"
            created_str = r.created.strftime("%Y-%m-%d")
            size_str = f"{r.size_gb}G"
            type_str = r.volume_type
            typer.echo(
                f"{r.id:<21}  {name_str:<{name_width}}  {size_str:>6}  {type_str:<4}  {r.state:<9}  {created_str:<12}  {r.availability_zone}"
            )

        # Summary
        orphaned_count = sum(1 for r in report if r.is_orphaned)
        total_size = sum(r.size_gb for r in report)
        orphaned_size = sum(r.size_gb for r in report if r.is_orphaned)
        typer.echo()
        typer.echo(
            f"Total: {len(report)} volumes ({total_size} GB), {orphaned_count} orphaned ({orphaned_size} GB)"
        )

        # Interactive deletion
        if delete and report:
            typer.echo()
            typer.echo("Starting interactive deletion (y=delete, n=skip, q=quit)")
            typer.echo()

            deleted_count = 0
            deleted_size = 0

            for r in report:
                created_str = r.created.strftime("%Y-%m-%d")
                typer.echo(f"Volume: {r.id}")
                typer.echo(f"  Name:    {r.name or '-'}")
                typer.echo(f"  Size:    {r.size_gb} GB")
                typer.echo(f"  Type:    {r.volume_type}")
                typer.echo(f"  Created: {created_str}")
                typer.echo(f"  AZ:      {r.availability_zone}")

                while True:
                    choice = typer.prompt("Delete?", default="y")
                    if choice.lower() == "y":
                        delete_volume(session, r.id)
                        deleted_count += 1
                        deleted_size += r.size_gb
                        break
                    elif choice.lower() == "n":
                        typer.echo("  Skipped")
                        break
                    elif choice.lower() == "q":
                        typer.echo()
                        typer.echo(f"Deleted {deleted_count} volumes ({deleted_size} GB)")
                        return
                    else:
                        typer.echo("  Invalid choice. Use y/n/q")

                typer.echo()

            typer.echo(f"Deleted {deleted_count} volumes ({deleted_size} GB)")
