"""CLI principal do abyss-cli."""

from pathlib import Path
from typing import Optional

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

from abyss import __version__
from abyss.scanners import dependencies, secrets

app = typer.Typer(
    name="abyss",
    help="Escaneia repositórios em busca de secrets vazados e dependências vulneráveis.",
    no_args_is_help=False,
    invoke_without_command=True,
)
console = Console()


def _version_callback(value: bool):
    if value:
        console.print(f"abyss-cli v{__version__}")
        raise typer.Exit()


@app.callback(invoke_without_command=True)
def main(
    ctx: typer.Context,
    version: Optional[bool] = typer.Option(
        None, "--version", callback=_version_callback, is_eager=True,
        help="Mostra a versão e sai.",
    ),
):
    """Sem subcomando -> abre o menu interativo."""
    if ctx.invoked_subcommand is None:
        from abyss.ui.menu import run_interactive

        run_interactive()
        raise typer.Exit()


@app.command()
def scan(
    path: str = typer.Argument(".", help="Caminho do repositório a escanear."),
    secrets_only: bool = typer.Option(False, "--secrets-only", help="Roda só o scan de secrets."),
    deps_only: bool = typer.Option(False, "--deps-only", help="Roda só o scan de dependências."),
    json_output: Optional[Path] = typer.Option(None, "--json", help="Salva resultado em JSON no caminho informado."),
):
    """Escaneia um repositório local em busca de secrets e dependências vulneráveis."""
    from abyss.ui.banner import show_banner

    show_banner()

    repo_path = str(Path(path).resolve())
    if not Path(repo_path).exists():
        console.print(f"[red]Erro:[/red] caminho não encontrado: {repo_path}")
        raise typer.Exit(code=1)

    console.print(f"[bold cyan]abyss[/bold cyan] escaneando [bold]{repo_path}[/bold]\n")

    secret_findings = []
    dep_findings = []

    if not deps_only:
        with console.status("[cyan]Procurando secrets vazados...[/cyan]"):
            secret_findings = secrets.scan_repo(repo_path, progress_callback=console.print)
        _print_secret_findings(secret_findings)

    if not secrets_only:
        with console.status("[cyan]Auditando dependências...[/cyan]"):
            dep_findings = dependencies.scan_repo(repo_path)
        _print_dependency_findings(dep_findings)

    total = len(secret_findings) + len(dep_findings)
    if total == 0:
        console.print("\n[bold green]✓ Nenhum problema encontrado.[/bold green]")
    else:
        console.print(
            f"\n[bold yellow]⚠ {total} problema(s) encontrado(s)[/bold yellow] "
            f"({len(secret_findings)} secret(s), {len(dep_findings)} dependência(s) vulnerável(is))"
        )

    if json_output:
        _write_json(json_output, secret_findings, dep_findings, repo_path)
        console.print(f"[dim]Relatório salvo em {json_output}[/dim]")

    if total > 0:
        raise typer.Exit(code=1)


def _print_secret_findings(findings):
    if not findings:
        console.print("[green]✓[/green] Nenhum secret encontrado.\n")
        return

    table = Table(title="Secrets encontrados")
    table.add_column("Arquivo", style="cyan")
    table.add_column("Linha")
    table.add_column("Regra", style="yellow")
    table.add_column("Secret (redigido)", style="red")

    for f in findings:
        table.add_row(f.file, str(f.line_number), f.rule_id, f.redacted_secret)

    console.print(table)
    console.print()


def _print_dependency_findings(findings):
    if not findings:
        console.print("[green]✓[/green] Nenhuma dependência vulnerável encontrada.\n")
        return

    table = Table(title="Dependências vulneráveis")
    table.add_column("Pacote", style="cyan")
    table.add_column("Versão instalada")
    table.add_column("Vulnerabilidade", style="yellow")
    table.add_column("Severidade")
    table.add_column("Correção", style="green")
    table.add_column("Ecossistema")

    for f in findings:
        table.add_row(
            f.package, f.installed_version, f.vulnerability_id,
            f.severity, f.fix_version or "-", f.ecosystem,
        )

    console.print(table)
    console.print()


def _write_json(output_path: Path, secret_findings, dep_findings, repo_path: str):
    import json as json_lib
    from dataclasses import asdict

    report = {
        "repo": repo_path,
        "secrets": [asdict(f) for f in secret_findings],
        "dependencies": [asdict(f) for f in dep_findings],
    }
    output_path.write_text(json_lib.dumps(report, indent=2, ensure_ascii=False), encoding="utf-8")


if __name__ == "__main__":
    app()