"""Command-line interface for branchguard."""

from typing import Annotated, Optional

import typer
from rich.console import Console
from rich.table import Table

from branchguard import __version__
from branchguard.core import (
    delete_branches,
    find_pruneable_branches,
)

app = typer.Typer(
    name="branchguard",
    help="Clean up stale and merged git branches.",
    add_completion=False,
    invoke_without_command=True,
)

console = Console()
err_console = Console(stderr=True)


def version_callback(value: bool) -> None:
    if value:
        console.print(f"branchguard [bold]{__version__}[/bold]")
        raise typer.Exit()


@app.callback(invoke_without_command=True)
def main(
    ctx: typer.Context,
    version: Annotated[
        Optional[bool],
        typer.Option(
            "--version",
            "-V",
            help="Show version and exit.",
            callback=version_callback,
            is_eager=True,
        ),
    ] = None,
) -> None:
    """Clean up stale and merged git branches."""
    if ctx.invoked_subcommand is None:
        ctx.invoke(scan)


def _render_table(branches: list, force: bool) -> None:
    """Render branch results as a rich table."""
    table = Table(title="branchguard", show_header=True, header_style="bold")
    table.add_column("Branch", style="cyan", no_wrap=True)
    table.add_column("Last Commit", style="dim")
    table.add_column("Age (days)", justify="right")
    table.add_column("Merged?", justify="center")
    table.add_column("Status", justify="center")

    status_styles = {
        "merged": "[green]merged[/green]",
        "stale": "[yellow]stale[/yellow]",
        "active": "[dim]active[/dim]",
    }

    for branch in branches:
        merged_display = "[green]yes[/green]" if branch.is_merged else "no"
        remote_prefix = "[dim](remote)[/dim] " if branch.is_remote else ""
        table.add_row(
            f"{remote_prefix}{branch.name}",
            branch.last_commit_date.strftime("%Y-%m-%d"),
            str(branch.age_days),
            merged_display,
            status_styles.get(branch.status, branch.status),
        )

    console.print()
    console.print(table)

    n = len(branches)
    if n == 0:
        console.print("\n[green]No branches to prune. Everything looks clean.[/green]")
    elif force:
        console.print(f"\n[red bold]Deleted {n} branch(es).[/red bold]")
    else:
        s = "es" if n != 1 else ""
        console.print(
            f"\nFound [bold]{n}[/bold] branch{s} to prune."
            " Run with [bold]--force[/bold] to delete."
        )


@app.command()
def scan(
    days: Annotated[
        int,
        typer.Option(
            "--days",
            "-d",
            help="Branches older than this many days are considered stale.",
        ),
    ] = 90,
    merged: Annotated[
        bool,
        typer.Option(
            "--merged",
            "-m",
            help="Only show branches merged into the target branch.",
        ),
    ] = False,
    target: Annotated[
        str,
        typer.Option(
            "--target",
            "-t",
            help="Target branch to check merged status against.",
        ),
    ] = "main",
    remote: Annotated[
        bool,
        typer.Option(
            "--remote",
            "-r",
            help="Include remote branches.",
        ),
    ] = False,
    force: Annotated[
        bool,
        typer.Option(
            "--force",
            "-f",
            help="Actually delete branches (default is dry-run).",
        ),
    ] = False,
    output_json: Annotated[
        bool,
        typer.Option(
            "--json",
            "-j",
            help="Output results as JSON.",
        ),
    ] = False,
) -> None:
    """Scan for stale and merged branches."""
    try:
        result = find_pruneable_branches(
            days=days,
            merged_only=merged,
            target=target,
            include_remote=remote,
        )
    except Exception as exc:
        err_console.print(f"[red]Error:[/red] {exc}")
        raise typer.Exit(code=1) from exc

    if output_json:
        console.print_json(result.to_json())
        return

    if force and result.branches:
        branch_names = [b.name for b in result.branches]
        is_remote_delete = any(b.is_remote for b in result.branches)
        delete_results = delete_branches(
            branch_names,
            remote=is_remote_delete,
            dry_run=False,
        )
        failed = [r for r in delete_results if not r.success]
        if failed:
            for f in failed:
                err_console.print(f"[red]Failed to delete {f.branch}:[/red] {f.error}")

    _render_table(result.branches, force=force)


if __name__ == "__main__":
    app()
