"""SecAgent CLI — powered by Typer."""

from __future__ import annotations

import logging
from pathlib import Path

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

from secagent import __version__
from secagent.models import TokenUsage, _DEFAULT_PRICING, _MODEL_PRICING
from secagent.pipeline import run_fix, run_scan

_FAST_TAG = "fast"
_REASONING_TAG = "reasoning"


def _model_tag(model: str) -> str:
    """Return a short display tag for a model name."""
    if "non-reasoning" in model:
        return _FAST_TAG
    if "reasoning" in model:
        return _REASONING_TAG
    return model.split("-")[-1]


def _load_config() -> None:
    """Load config from the user's system config file.

    On first run (no config file), shows the welcome banner and runs the
    interactive setup wizard to collect and save the Grok API key.
    """
    from secagent.config import apply_config_to_env, is_first_run, load_config, run_setup_wizard

    if is_first_run():
        config = run_setup_wizard(console)
    else:
        config = load_config()
        if config is None:
            console.print(
                "[bold red]Error:[/] SecAgent is not configured.\n"
                "Run [bold cyan]secagent configure[/] to set up your API key."
            )
            raise typer.Exit(code=1)

    apply_config_to_env(config)


app = typer.Typer(
    name="secagent",
    help="Autonomous security agent — scan, verify, fix, report.",
    add_completion=False,
)
console = Console()

_STAGE_ORDER = ["planner", "scanner", "verifier", "fixer", "validator"]


def _configure_logging(verbose: bool) -> None:
    """Set up root logger for CLI output."""
    level = logging.DEBUG if verbose else logging.WARNING
    logging.basicConfig(
        level=level,
        format="%(name)s | %(levelname)s | %(message)s",
    )


def _print_usage_table(
    stage_usage: dict[str, TokenUsage],
    stage_models: dict[str, str],
) -> None:
    """Print a Rich table showing per-stage token counts and estimated cost."""
    if not stage_usage:
        return

    has_reasoning = any(u.reasoning_tokens > 0 for u in stage_usage.values())

    table = Table(title="📊 Token Usage & Estimated Cost")
    table.add_column("Stage", style="cyan")
    table.add_column("Model", style="dim")
    table.add_column("Input", justify="right")
    table.add_column("Output", justify="right")
    if has_reasoning:
        table.add_column("Reasoning", justify="right", style="dim")
    table.add_column("Total", justify="right")
    table.add_column("Calls", justify="right")
    table.add_column("Cost (USD)", justify="right", style="green")

    total_prompt = total_completion = total_reasoning = total_calls = 0
    total_cost = 0.0

    for stage in _STAGE_ORDER:
        if stage not in stage_usage:
            continue
        u = stage_usage[stage]
        model = stage_models.get(stage, "")
        cost = u.cost_usd(model)
        total_prompt += u.prompt_tokens
        total_completion += u.completion_tokens
        total_reasoning += u.reasoning_tokens
        total_calls += u.calls
        total_cost += cost
        row = [
            stage,
            _model_tag(model),
            f"{u.prompt_tokens:,}",
            f"{u.completion_tokens:,}",
        ]
        if has_reasoning:
            row.append(f"{u.reasoning_tokens:,}" if u.reasoning_tokens else "—")
        row += [f"{u.total_tokens:,}", str(u.calls), f"${cost:.4f}"]
        table.add_row(*row)

    table.add_section()
    total_row = [
        "[bold]Total[/]",
        "",
        f"[bold]{total_prompt:,}[/]",
        f"[bold]{total_completion:,}[/]",
    ]
    if has_reasoning:
        total_row.append(f"[bold]{total_reasoning:,}[/]")
    total_row += [
        f"[bold]{total_prompt + total_completion:,}[/]",
        f"[bold]{total_calls}[/]",
        f"[bold green]${total_cost:.4f}[/]",
    ]
    table.add_row(*total_row)

    console.print()
    console.print(table)
    if has_reasoning:
        console.print("[dim]Reasoning tokens are billed as output tokens[/]")


@app.command()
def scan(
    path: str = typer.Argument(..., help="File or directory to scan."),
    verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
) -> None:
    """Scan PATH for vulnerabilities and save results. Does not apply fixes."""
    _configure_logging(verbose)
    _load_config()

    console.print(f"\n[bold magenta]SecAgent[/] [dim]v{__version__}[/]")
    target = Path(path).resolve()

    if not target.exists():
        console.print(f"[bold red]Error:[/] Path does not exist: {target}")
        raise typer.Exit(code=1)

    kind = "file" if target.is_file() else "directory"
    console.print(f"Scanning [cyan]{target}[/] [dim]({kind})[/]")

    result = run_scan(target)

    console.print("[bold magenta]─" * 50)
    console.print(f"[bold]Findings:[/] {result.total_findings}")
    if result.scan_file:
        console.print(f"[dim]Vulnerabilities saved to: {result.scan_file}[/]")

    console.print()


@app.command()
def fix(
    path: str = typer.Argument(..., help="File or directory to fix."),
    verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
) -> None:
    """Verify and fix vulnerabilities in PATH.

    Loads cached scan results if available, otherwise runs a scan first.
    """
    _configure_logging(verbose)
    _load_config()

    console.print(f"\n[bold magenta]SecAgent[/] [dim]v{__version__}[/]")
    target = Path(path).resolve()

    if not target.exists():
        console.print(f"[bold red]Error:[/] Path does not exist: {target}")
        raise typer.Exit(code=1)

    kind = "file" if target.is_file() else "directory"
    console.print(f"Fixing [cyan]{target}[/] [dim]({kind})[/]")

    result = run_fix(target)

    console.print("[bold magenta]─" * 50)
    console.print(
        f"[bold]Findings:[/] {result.total_findings}  "
        f"[bold]TP:[/] {result.true_positives}  "
        f"[bold]FP:[/] {result.false_positives}  "
        f"[bold]Fixed:[/] {result.fixes_applied}"
    )
    if result.report_path:
        console.print(f"\n[bold green]Report generated:[/] {result.report_path}")

    console.print()


@app.command()
def configure() -> None:
    """Set up or re-configure your Grok API key."""
    from secagent.config import run_setup_wizard

    run_setup_wizard(console)


@app.command()
def version() -> None:
    """Print SecAgent version."""
    console.print(f"SecAgent v{__version__}")


def main() -> None:
    """Entry point for ``python -m secagent``."""
    app()


if __name__ == "__main__":
    main()
