"""
CLI commands for working with large codebases

Specialized commands to handle massive projects without context rot.
"""

import sys
from pathlib import Path
from typing import Optional

import click
from rich.console import Console
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.table import Table

from groknroll.agents.agent_manager import AgentManager
from groknroll.core.large_codebase import LargeCodebaseHandler
from groknroll.storage.database import Database

console = Console()


@click.group()
def large():
    """Commands for working with large codebases"""
    pass


@large.command()
@click.option("--path", type=click.Path(exists=True), help="Project path")
def map_codebase(path: Optional[str]):
    """
    Create hierarchical map of large codebase

    This command chunks your codebase intelligently and creates
    a dependency graph for efficient navigation.
    """
    project_path = Path(path) if path else Path.cwd()

    try:
        with Progress(
            SpinnerColumn(), TextColumn("[progress.description]{task.description}"), console=console
        ) as progress:
            task = progress.add_task("Mapping codebase...", total=None)

            db = Database()
            handler = LargeCodebaseHandler(project_path, db)
            codebase_map = handler.chunk_codebase()

            progress.update(task, completed=True)

        # Display results
        console.print()
        console.print(
            Panel.fit(
                f"[bold green]✓ Codebase mapped successfully![/bold green]\n\n"
                f"[cyan]Total Files:[/cyan] {codebase_map.total_files:,}\n"
                f"[cyan]Total Lines:[/cyan] {codebase_map.total_lines:,}\n"
                f"[cyan]Total Chunks:[/cyan] {len(codebase_map.chunks):,}\n"
                f"[cyan]Modules:[/cyan] {len(codebase_map.modules):,}",
                title="[bold]Codebase Map[/bold]",
                border_style="green",
            )
        )

        # Language breakdown
        overview = handler.get_codebase_overview()

        if overview["languages"]:
            console.print()
            lang_table = Table(title="Language Distribution", show_header=True)
            lang_table.add_column("Language", style="cyan")
            lang_table.add_column("Files", justify="right", style="green")
            lang_table.add_column("Lines", justify="right", style="blue")
            lang_table.add_column("% of Total", justify="right", style="magenta")

            total_lines = overview["total_lines"]
            for lang, stats in sorted(
                overview["languages"].items(), key=lambda x: x[1]["lines"], reverse=True
            ):
                percentage = (stats["lines"] / total_lines * 100) if total_lines > 0 else 0
                lang_table.add_row(
                    lang, f"{stats['files']:,}", f"{stats['lines']:,}", f"{percentage:.1f}%"
                )

            console.print(lang_table)

        # Top modules
        if overview["top_modules"]:
            console.print()
            mod_table = Table(title="Largest Modules", show_header=True)
            mod_table.add_column("Module", style="cyan")
            mod_table.add_column("Lines", justify="right", style="blue")

            for mod in overview["top_modules"][:10]:
                mod_table.add_row(mod["module"], f"{mod['lines']:,}")

            console.print(mod_table)

        console.print(
            f"\n[dim]Map saved to: {project_path}/.groknroll/cache/codebase_map.json[/dim]"
        )

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        import traceback

        traceback.print_exc()
        sys.exit(1)


@large.command()
@click.option("--path", type=click.Path(exists=True), help="Project path")
def overview(path: Optional[str]):
    """Show high-level overview of large codebase"""
    project_path = Path(path) if path else Path.cwd()

    try:
        db = Database()
        handler = LargeCodebaseHandler(project_path, db)
        overview = handler.get_codebase_overview()

        # Display overview
        console.print()
        console.print(
            Panel.fit(
                f"[bold cyan]Project:[/bold cyan] {project_path.name}\n"
                f"[cyan]Files:[/cyan] {overview['total_files']:,}\n"
                f"[cyan]Lines of Code:[/cyan] {overview['total_lines']:,}\n"
                f"[cyan]Modules:[/cyan] {overview['total_modules']:,}\n"
                f"[cyan]Chunks:[/cyan] {overview['total_chunks']:,}",
                title="[bold]Codebase Overview[/bold]",
                border_style="cyan",
            )
        )

        # Languages
        console.print()
        lang_table = Table(title="Languages", show_header=True)
        lang_table.add_column("Language", style="cyan")
        lang_table.add_column("Files", justify="right", style="green")
        lang_table.add_column("Lines", justify="right", style="blue")

        for lang, stats in sorted(
            overview["languages"].items(), key=lambda x: x[1]["lines"], reverse=True
        ):
            lang_table.add_row(lang, f"{stats['files']:,}", f"{stats['lines']:,}")

        console.print(lang_table)

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


@large.command()
@click.argument("module_path")
@click.option("--path", type=click.Path(exists=True), help="Project path")
def inspect_module(module_path: str, path: Optional[str]):
    """Inspect a specific module (directory) in detail"""
    project_path = Path(path) if path else Path.cwd()

    try:
        db = Database()
        handler = LargeCodebaseHandler(project_path, db)
        summary = handler.get_module_summary(module_path)

        if "error" in summary:
            console.print(f"[bold red]Error:[/bold red] {summary['error']}")

            if "available_modules" in summary:
                console.print("\n[yellow]Available modules:[/yellow]")
                for mod in summary["available_modules"]:
                    console.print(f"  • {mod}")

            sys.exit(1)

        # Display module summary
        console.print()
        console.print(
            Panel.fit(
                f"[bold cyan]Module:[/bold cyan] {summary['module']}\n"
                f"[cyan]Files:[/cyan] {summary['files']}\n"
                f"[cyan]Total Lines:[/cyan] {summary['total_lines']:,}",
                title="[bold]Module Summary[/bold]",
                border_style="cyan",
            )
        )

        # Languages in module
        if summary["languages"]:
            console.print()
            lang_table = Table(title="Languages in Module", show_header=True)
            lang_table.add_column("Language", style="cyan")
            lang_table.add_column("Files", justify="right", style="green")
            lang_table.add_column("Lines", justify="right", style="blue")

            for lang, stats in sorted(
                summary["languages"].items(), key=lambda x: x[1]["lines"], reverse=True
            ):
                lang_table.add_row(lang, str(stats["files"]), f"{stats['lines']:,}")

            console.print(lang_table)

        # Files in module
        if summary["chunks"]:
            console.print()
            file_table = Table(title="Files", show_header=True)
            file_table.add_column("File", style="cyan")
            file_table.add_column("Language", style="green")
            file_table.add_column("Lines", justify="right", style="blue")

            for chunk in sorted(summary["chunks"], key=lambda x: x["lines"], reverse=True)[:20]:
                file_table.add_row(chunk["file"], chunk["language"], f"{chunk['lines']:,}")

            console.print(file_table)

            if len(summary["chunks"]) > 20:
                console.print(f"\n[dim]Showing 20 of {len(summary['chunks'])} files[/dim]")

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


@large.command()
@click.argument("symbol")
@click.option("--path", type=click.Path(exists=True), help="Project path")
def find_symbol(symbol: str, path: Optional[str]):
    """Find definition of a symbol across entire codebase"""
    project_path = Path(path) if path else Path.cwd()

    try:
        with console.status(f"[bold cyan]Searching for '{symbol}'..."):
            db = Database()
            handler = LargeCodebaseHandler(project_path, db)
            results = handler.navigate_to_definition(symbol)

        if not results:
            console.print(f"[yellow]No definitions found for '{symbol}'[/yellow]")
            return

        # Display results
        console.print()
        table = Table(title=f"Definitions of '{symbol}'", show_header=True)
        table.add_column("File", style="cyan")
        table.add_column("Line", justify="right", style="green")
        table.add_column("Code", style="white")

        for result in results[:20]:
            table.add_row(result["file"], str(result["line"]), result["snippet"][:80])

        console.print(table)

        if len(results) > 20:
            console.print(f"\n[dim]Showing 20 of {len(results)} results[/dim]")

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


@large.command()
@click.option("--path", type=click.Path(exists=True), help="Project path")
def check_changes(path: Optional[str]):
    """Check which files have changed since last analysis (incremental)"""
    project_path = Path(path) if path else Path.cwd()

    try:
        with console.status("[bold cyan]Checking for changes..."):
            db = Database()
            handler = LargeCodebaseHandler(project_path, db)
            changed = handler.get_changed_chunks()

        if not changed:
            console.print("[bold green]✓ No changes detected[/bold green]")
            console.print("\n[dim]All files are up to date with last analysis[/dim]")
            return

        # Display changed files
        console.print()
        console.print(f"[bold yellow]⚠ {len(changed)} file(s) changed[/bold yellow]\n")

        table = Table(title="Changed Files", show_header=True)
        table.add_column("File", style="cyan")
        table.add_column("Language", style="green")
        table.add_column("Lines", justify="right", style="blue")

        for chunk in changed[:50]:
            relative_path = chunk.path.relative_to(project_path)
            table.add_row(str(relative_path), chunk.language, f"{chunk.size:,}")

        console.print(table)

        if len(changed) > 50:
            console.print(f"\n[dim]Showing 50 of {len(changed)} changed files[/dim]")

        console.print(
            "\n[dim]Tip: Use 'groknroll large analyze-changes' to analyze these changes with RLM[/dim]"
        )

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


@large.command()
@click.argument("task")
@click.option("--path", type=click.Path(exists=True), help="Project path")
@click.option("--max-context", type=int, default=50, help="Max chunks to include in context")
def smart_task(task: str, path: Optional[str], max_context: int):
    """
    Execute task with smart context selection (no context rot!)

    Uses intelligent chunking to only load relevant parts of codebase.
    Perfect for massive projects with 100K+ lines.
    """
    project_path = Path(path) if path else Path.cwd()

    try:
        # Get relevant context
        with console.status("[bold cyan]Finding relevant code..."):
            db = Database()
            handler = LargeCodebaseHandler(project_path, db)
            relevant_chunks = handler.get_relevant_context(task, max_chunks=max_context)

        console.print()
        console.print(
            Panel(
                f"[cyan]Found {len(relevant_chunks)} relevant code chunks[/cyan]\n"
                f"[dim]Total context: ~{sum(c.size for c in relevant_chunks):,} lines[/dim]",
                title="[bold]Smart Context Selection[/bold]",
                border_style="cyan",
            )
        )

        # Show what's being analyzed
        console.print("\n[bold]Analyzing:[/bold]")
        for chunk in relevant_chunks[:10]:
            relative_path = chunk.path.relative_to(project_path)
            console.print(f"  • {relative_path} ({chunk.size} lines)")

        if len(relevant_chunks) > 10:
            console.print(f"  • ... and {len(relevant_chunks) - 10} more files")

        # Execute with build agent
        console.print()
        with console.status("[bold cyan]Build agent working..."):
            manager = AgentManager(project_path)

            # Add relevant files to context
            context = {
                "relevant_files": [
                    {
                        "path": str(c.path.relative_to(project_path)),
                        "lines": c.size,
                        "language": c.language,
                    }
                    for c in relevant_chunks
                ],
                "total_context_lines": sum(c.size for c in relevant_chunks),
            }

            response = manager.execute(task, agent="build", context=context)

        # Display response
        console.print()
        if response.success:
            from rich.markdown import Markdown

            console.print(
                Panel(
                    Markdown(response.message),
                    title="[bold green]✓ Build Agent[/bold green]",
                    border_style="green",
                )
            )

            console.print(
                f"\n[dim]Completed in {response.time:.1f}s (cost: ${response.cost:.4f})[/dim]"
            )
        else:
            console.print(
                Panel(
                    response.message,
                    title="[bold red]✗ Build Agent Failed[/bold red]",
                    border_style="red",
                )
            )

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        import traceback

        traceback.print_exc()
        sys.exit(1)


if __name__ == "__main__":
    large()
