"""antiqa crawl / antiqa graph — discover app routes and view the navigation graph."""

from __future__ import annotations

from pathlib import Path

import typer
from rich.console import Console
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.table import Table
from rich.tree import Tree

from antiqa.config.manager import config_exists, load_config
from antiqa.crawler.crawler import DEFAULT_GRAPH_PATH
from antiqa.crawler.graph import NavigationGraph

console = Console()


def run_crawl(
    max_pages: int = 50,
    max_depth: int = 5,
    start_path: str = "/",
) -> None:
    """Crawl the application and build a navigation graph."""
    if not config_exists():
        console.print("[red]No antiqa.json found. Run [bold]antiqa init[/bold] first.[/red]")
        raise typer.Exit(code=1)

    config = load_config()
    start_url = config.app_url.rstrip("/") + start_path
    console.print(Panel(
        f"[bold cyan]Crawling[/bold cyan] {start_url}\n"
        f"[dim]max_pages={max_pages}  max_depth={max_depth}  browser={config.browser.type}[/dim]",
        expand=False,
    ))

    from antiqa.crawler.crawler import Crawler

    crawler = Crawler(
        base_url=start_url,
        browser_config=config.browser,
        max_pages=max_pages,
        max_depth=max_depth,
    )

    with Progress(
        SpinnerColumn(),
        TextColumn("[progress.description]{task.description}"),
        console=console,
        transient=True,
    ) as progress:
        task = progress.add_task("Crawling...", total=None)

        def progress_callback(url: str, visited: int, queued: int) -> None:
            progress.update(task, description=f"Crawling [{visited}] {url}")

        crawler.on_page = progress_callback
        graph = crawler.crawl_and_save(output_path=DEFAULT_GRAPH_PATH)

    console.print()
    console.print(Panel(
        f"[bold green]Crawl complete![/bold green]\n\n"
        f"  Pages discovered: [cyan]{graph.page_count}[/cyan]\n"
        f"  Transitions found: [cyan]{graph.edge_count}[/cyan]\n"
        f"  Graph saved to: [cyan]{DEFAULT_GRAPH_PATH}[/cyan]",
        expand=False,
    ))


def run_graph_show() -> None:
    """Display the navigation graph in the terminal."""
    path = Path(DEFAULT_GRAPH_PATH)
    if not path.is_file():
        console.print("[red]No navigation graph found. Run [bold]antiqa crawl[/bold] first.[/red]")
        raise typer.Exit(code=1)

    graph = NavigationGraph.load(path)

    # Page table
    table = Table(
        title=f"Navigation Graph — {graph.page_count} pages, {graph.edge_count} transitions",
        show_header=True,
        header_style="bold magenta",
        expand=False,
    )
    table.add_column("Page", style="cyan")
    table.add_column("Title")
    table.add_column("Links", justify="right")
    table.add_column("Forms", justify="right")
    table.add_column("Buttons", justify="right")
    table.add_column("Inputs", justify="right")

    for node in graph.nodes.values():
        table.add_row(
            node.url_pattern,
            node.title or "[dim]—[/dim]",
            str(len(node.links)),
            str(len(node.forms)),
            str(len(node.buttons)),
            str(len(node.inputs)),
        )

    console.print()
    console.print(table)

    # Transition tree
    if graph.edges:
        console.print()
        tree = Tree("[bold]Transitions[/bold]")
        grouped: dict[str, list[str]] = {}
        for edge in graph.edges:
            grouped.setdefault(edge.source, []).append(
                f"--[{edge.action}]--> [cyan]{edge.target}[/cyan]"
            )
        for source, targets in grouped.items():
            branch = tree.add(f"[bold]{source}[/bold]")
            for t in targets:
                branch.add(t)
        console.print(tree)
    console.print()
