import shutil
import subprocess
from pathlib import Path
from typing import Annotated

from rich.console import Console
from typer import Option, Typer

cache_app = Typer(no_args_is_help=True)
console = Console()


@cache_app.command()
def clean(
    force: Annotated[
        bool,
        Option(
            "-f",
            "--force",
            help="Skip confirmation prompt and clean immediately.",
        ),
    ] = False,
    dry: Annotated[
        bool,
        Option(
            "--dry",
            help="Show what would be cleaned without actually cleaning.",
        ),
    ] = False,
    no_docker: Annotated[
        bool,
        Option(
            "--no-docker",
            help="Skip Docker image cleanup.",
        ),
    ] = False,
    no_cache_dir: Annotated[
        bool,
        Option(
            "--no-cache-dir",
            help="Skip cache directory cleanup.",
        ),
    ] = False,
):
    """Clean Harbor cache: remove Docker images (alexgshaw/*, hb__*, sb__*) and ~/.cache/harbor folder."""
    cache_dir = Path("~/.cache/harbor").expanduser()

    cache_exists = cache_dir.exists()
    cache_size = None
    if cache_exists and not no_cache_dir:
        total_size = sum(f.stat().st_size for f in cache_dir.rglob("*") if f.is_file())
        cache_size = total_size / (1024 * 1024)

    docker_images = []
    if not no_docker:
        try:
            result = subprocess.run(
                ["docker", "images", "--format", "{{.Repository}}:{{.Tag}}"],
                capture_output=True,
                text=True,
                check=True,
            )
            all_images = result.stdout.strip().split("\n")
            docker_images = [
                img
                for img in all_images
                if img.startswith("alexgshaw/")
                or img.startswith("hb__")
                or img.startswith("sb__")
            ]
        except subprocess.CalledProcessError:
            console.print("[yellow]⚠️  Could not list Docker images[/yellow]")
        except FileNotFoundError:
            console.print(
                "[yellow]⚠️  Docker not found, skipping image cleanup[/yellow]"
            )

    console.print("\n[bold]Harbor Cache Cleanup[/bold]\n")
    if dry:
        console.print("[yellow]DRY RUN - No changes will be made[/yellow]\n")

    if cache_exists and not no_cache_dir:
        console.print(f"[blue]Cache directory:[/blue] {cache_dir}")
        console.print(f"[blue]Cache size:[/blue] {cache_size:.2f} MB\n")
    elif not no_cache_dir:
        console.print(f"[dim]Cache directory not found: {cache_dir}[/dim]\n")

    if docker_images:
        console.print(
            f"[blue]Docker images to remove:[/blue] {len(docker_images)} image(s)"
        )
        for img in docker_images[:10]:
            console.print(f"  • {img}")
        if len(docker_images) > 10:
            console.print(f"  ... and {len(docker_images) - 10} more")
        console.print()
    elif not no_docker:
        console.print("[dim]No matching Docker images found[/dim]\n")

    should_clean_cache = cache_exists and not no_cache_dir
    should_clean_docker = bool(docker_images) and not no_docker

    if not should_clean_cache and not should_clean_docker:
        console.print("[green]✓ Nothing to clean[/green]")
        return

    if dry:
        console.print("[yellow]✓ Dry run completed (no changes made)[/yellow]")
        return

    if not force:
        response = console.input("[yellow]Proceed with cleanup? (y/N):[/yellow] ")
        if response.lower() not in ["y", "yes"]:
            console.print("[dim]Cleanup cancelled[/dim]")
            return

    cleaned = False

    if should_clean_cache:
        try:
            shutil.rmtree(cache_dir)
            console.print(f"[green]✓ Removed cache directory: {cache_dir}[/green]")
            cleaned = True
        except Exception as e:
            console.print(f"[red]❌ Failed to remove cache directory: {e}[/red]")

    if should_clean_docker:
        try:
            subprocess.run(
                ["docker", "rmi", "-f"] + docker_images,
                capture_output=True,
                text=True,
                check=True,
            )
            console.print(
                f"[green]✓ Removed {len(docker_images)} Docker image(s)[/green]"
            )
            cleaned = True
        except subprocess.CalledProcessError as e:
            console.print(f"[red]❌ Failed to remove Docker images: {e.stderr}[/red]")
        except FileNotFoundError:
            console.print(
                "[yellow]⚠️  Docker not found, skipping image cleanup[/yellow]"
            )

    if cleaned:
        console.print("\n[green bold]✓ Cache cleanup completed[/green bold]")
    else:
        console.print("\n[yellow]⚠️  No cleanup was performed[/yellow]")
