"""CLI interface for DepRaptor."""

import logging
from pathlib import Path
from typing import Optional

import typer
from rich.console import Console
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.table import Table

from ..scanner.dependency_parser import DependencyParser
from ..scanner.confusion_checker import ConfusionChecker
from ..poc.poc_generator import PoCGenerator
from ..report.report_writer import ReportWriter
from ..utils.banner import display_banner
from ..utils.config import get_working_dirs
from ..utils.filesystem import ensure_directories
from ..utils.github import is_github_url, clone_repository

app = typer.Typer(add_completion=False, help="DepRaptor - Dependency Confusion Scanner")
console = Console()


def setup_logging(output_dir: Path, verbose: bool = False) -> None:
    """Setup logging configuration."""
    log_file = output_dir / "logs" / "depraptor.log"
    log_file.parent.mkdir(parents=True, exist_ok=True)
    
    level = logging.DEBUG if verbose else logging.INFO
    
    logging.basicConfig(
        level=level,
        format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
        handlers=[
            logging.FileHandler(log_file),
            logging.StreamHandler() if verbose else logging.NullHandler(),
        ],
    )



@app.command()
def scan(
    target: str = typer.Argument(..., help="Path to project or GitHub URL"),
    threads: int = typer.Option(10, "--threads", "-t", help="Number of threads for registry checks"),
    output: Optional[str] = typer.Option(None, "--output", "-o", help="Output directory"),
    repo_dir: Optional[str] = typer.Option(None, "--repo-dir", help="Repository clone directory"),
    verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose logging"),
) -> None:
    """Scan a project for dependency confusion vulnerabilities."""
    display_banner()
    
    # Setup working directories
    working_dirs = get_working_dirs()
    output_dir = Path(output) if output else working_dirs["results"]
    repos_dir = Path(repo_dir) if repo_dir else working_dirs["repos"]
    
    ensure_directories([output_dir, repos_dir, output_dir / "pocs", output_dir / "logs"])
    setup_logging(output_dir, verbose)
    
    logger = logging.getLogger(__name__)
    logger.info(f"Starting DepRaptor scan on: {target}")
    
    # Determine target path
    if is_github_url(target):
        console.print(f"[cyan]Cloning repository:[/cyan] {target}")
        with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
            progress.add_task("Cloning...", total=None)
            project_path = clone_repository(target, repos_dir)
        
        if not project_path:
            console.print("[red]Failed to clone repository[/red]")
            raise typer.Exit(1)
        console.print(f"[green]✓[/green] Cloned to {project_path}")
    else:
        project_path = Path(target).resolve()
        if not project_path.exists():
            console.print(f"[red]Error:[/red] Path does not exist: {target}")
            raise typer.Exit(1)
    
    # Parse dependencies
    console.print("\n[cyan]Parsing dependencies...[/cyan]")
    with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
        progress.add_task("Scanning files...", total=None)
        parser = DependencyParser(project_path)
        dependencies = parser.parse_all()
    
    console.print(f"[green]✓[/green] Found {len(dependencies)} dependencies")
    
    if not dependencies:
        console.print("[yellow]No dependencies found. Exiting.[/yellow]")
        return
    
    # Check for vulnerabilities
    console.print("\n[cyan]Checking for dependency confusion vulnerabilities...[/cyan]")
    with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
        progress.add_task(f"Checking with {threads} threads...", total=None)
        checker = ConfusionChecker(dependencies, max_threads=threads)
        vulnerabilities = checker.check_all()
    
    console.print(f"[green]✓[/green] Found {len(vulnerabilities)} vulnerable dependencies")
    
    # Generate PoCs
    poc_paths = []
    if vulnerabilities:
        console.print("\n[cyan]Generating PoC packages...[/cyan]")
        with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
            progress.add_task("Creating PoCs...", total=None)
            generator = PoCGenerator(output_dir / "pocs")
            poc_paths = generator.generate_all(vulnerabilities)
        console.print(f"[green]✓[/green] Generated {len(poc_paths)} PoC packages")
    
    # Generate reports
    console.print("\n[cyan]Generating reports...[/cyan]")
    with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
        progress.add_task("Writing reports...", total=None)
        writer = ReportWriter(output_dir)
        writer.generate_all(str(project_path), dependencies, vulnerabilities, poc_paths)
    console.print(f"[green]✓[/green] Reports saved to {output_dir}")
    
    # Display summary
    display_summary(dependencies, vulnerabilities, poc_paths, output_dir)


def display_summary(dependencies, vulnerabilities, poc_paths, output_dir) -> None:
    """Display scan summary."""
    console.print("\n[bold cyan]═══ Scan Summary ═══[/bold cyan]\n")
    
    table = Table(show_header=False, box=None)
    table.add_column("Metric", style="cyan")
    table.add_column("Value", style="yellow")
    
    table.add_row("Total Dependencies", str(len(dependencies)))
    table.add_row("Vulnerable Dependencies", str(len(vulnerabilities)))
    table.add_row("Generated PoC Packages", str(len(poc_paths)))
    table.add_row("Output Directory", str(output_dir))
    
    console.print(table)
    
    if vulnerabilities:
        console.print("\n[bold yellow]⚠ Vulnerabilities Detected:[/bold yellow]\n")
        vuln_table = Table()
        vuln_table.add_column("Package", style="red")
        vuln_table.add_column("Ecosystem", style="cyan")
        vuln_table.add_column("Source", style="dim")
        
        for vuln in vulnerabilities[:10]:  # Show first 10
            vuln_table.add_row(
                vuln.dependency.name,
                vuln.dependency.ecosystem,
                vuln.dependency.source,
            )
        
        console.print(vuln_table)
        
        if len(vulnerabilities) > 10:
            console.print(f"\n[dim]... and {len(vulnerabilities) - 10} more (see report.md)[/dim]")
    else:
        console.print("\n[green]✓ No vulnerabilities detected[/green]")
    
    console.print(f"\n[dim]Full report: {output_dir / 'report.md'}[/dim]")


if __name__ == "__main__":
    app()
