"""History command for viewing scan history."""

from pathlib import Path
from typing import Annotated

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

from apiposture_pro.features.historical_tracking.store import HistoryStore
from apiposture_pro.licensing.manager import ProLicenseManager

app = typer.Typer(help="History commands")
console = Console()


@app.command("list")
def list_scans(
    project: Annotated[
        Path | None,
        typer.Option(
            "--project",
            "-p",
            help="Filter by project path",
        ),
    ] = None,
    limit: Annotated[
        int,
        typer.Option(
            "--limit",
            "-n",
            help="Maximum number of scans to show",
        ),
    ] = 50,
) -> None:
    """List historical scans."""
    # Validate license
    license_manager = ProLicenseManager()
    if not license_manager.is_valid():
        console.print("[red]✗[/red] No valid license found")
        raise typer.Exit(1)

    try:
        store = HistoryStore()
        project_str = str(project.absolute()) if project else None
        scans = store.list_scans(project_path=project_str, limit=limit)

        if not scans:
            console.print("[yellow]No scans found in history[/yellow]")
            return

        # Create table
        table = Table(title=f"Scan History ({len(scans)} scans)", show_header=True)
        table.add_column("ID", style="cyan")
        table.add_column("Time", style="dim")
        table.add_column("Project", style="magenta")
        table.add_column("Findings", style="yellow")
        table.add_column("Risk", style="red")
        table.add_column("Git", style="blue")

        for scan in scans:
            # Format time
            time_str = scan.scan_time.strftime("%Y-%m-%d %H:%M") if scan.scan_time else "N/A"

            # Format project path (show only last 2 parts)
            project_parts = Path(scan.project_path).parts
            project_short = "/".join(project_parts[-2:]) if len(project_parts) >= 2 else scan.project_path

            # Format findings with severity colors
            findings_str = f"{scan.total_findings}"
            if scan.critical_count > 0 or scan.high_count > 0:
                findings_str = f"[red]{findings_str}[/red]"

            # Format risk score
            risk_str = str(scan.risk_score) if scan.risk_score > 0 else "-"

            # Format git info
            git_str = ""
            if scan.git_branch:
                git_str = scan.git_branch
                if scan.git_is_dirty:
                    git_str += " [red]*[/red]"
            else:
                git_str = "-"

            table.add_row(
                str(scan.id),
                time_str,
                project_short,
                findings_str,
                risk_str,
                git_str,
            )

        console.print(table)

    except Exception as e:
        console.print(f"[red]✗[/red] Failed to list scans: {e}")
        raise typer.Exit(1) from e


@app.command("show")
def show_scan(
    scan_id: Annotated[
        int,
        typer.Argument(help="Scan ID to show"),
    ],
) -> None:
    """Show details of a specific scan."""
    # Validate license
    license_manager = ProLicenseManager()
    if not license_manager.is_valid():
        console.print("[red]✗[/red] No valid license found")
        raise typer.Exit(1)

    try:
        store = HistoryStore()
        scan = store.get_scan(scan_id)

        if not scan:
            console.print(f"[red]✗[/red] Scan ID {scan_id} not found")
            raise typer.Exit(1)

        # Display scan details
        console.print(f"\n[bold]Scan #{scan.id}[/bold]")
        console.print(f"[dim]{'=' * 60}[/dim]")
        console.print(f"Project: {scan.project_path}")
        console.print(
            f"Time: {scan.scan_time.strftime('%Y-%m-%d %H:%M:%S') if scan.scan_time else 'N/A'}"
        )
        console.print(f"Duration: {scan.scan_duration_ms}ms")
        console.print()

        console.print("[bold]Results:[/bold]")
        console.print(f"  Endpoints: {scan.total_endpoints}")
        console.print(f"  Findings: {scan.total_findings}")
        console.print(f"  Risk Score: {scan.risk_score}")
        console.print()

        console.print("[bold]Severity Breakdown:[/bold]")
        console.print(f"  {scan.severity_breakdown}")
        console.print()

        if scan.git_commit or scan.git_branch:
            console.print("[bold]Git Information:[/bold]")
            if scan.git_branch:
                console.print(f"  Branch: {scan.git_branch}")
            if scan.git_commit:
                console.print(f"  Commit: {scan.git_commit[:8]}")
            if scan.git_is_dirty:
                console.print("  [yellow]Working directory was dirty[/yellow]")

    except Exception as e:
        console.print(f"[red]✗[/red] Failed to show scan: {e}")
        raise typer.Exit(1) from e


@app.command("trend")
def show_trend(
    project: Annotated[
        Path,
        typer.Option(
            "--project",
            "-p",
            help="Project path to analyze",
        ),
    ] = Path("."),
    days: Annotated[
        int,
        typer.Option(
            "--days",
            "-d",
            help="Number of days to analyze",
        ),
    ] = 30,
) -> None:
    """Show trend analysis for a project."""
    # Validate license
    license_manager = ProLicenseManager()
    if not license_manager.is_valid():
        console.print("[red]✗[/red] No valid license found")
        raise typer.Exit(1)

    try:
        store = HistoryStore()
        project_str = str(project.absolute())
        trend_data = store.get_trend(project_str, days=days)

        if not trend_data:
            console.print(f"[yellow]No trend data found for the last {days} days[/yellow]")
            return

        console.print(f"\n[bold]Trend Analysis: {project.name}[/bold]")
        console.print(f"[dim]Last {days} days ({len(trend_data)} scans)[/dim]\n")

        # Calculate statistics
        findings_values = [count for _, count, _ in trend_data]
        risk_values = [risk for _, _, risk in trend_data if risk > 0]

        avg_findings = sum(findings_values) / len(findings_values)
        avg_risk = sum(risk_values) / len(risk_values) if risk_values else 0

        first_findings = trend_data[0][1]
        last_findings = trend_data[-1][1]
        findings_change = last_findings - first_findings

        console.print(f"Average findings: {avg_findings:.1f}")
        console.print(f"Average risk score: {avg_risk:.1f}")
        console.print()

        # Show trend direction
        if findings_change > 0:
            console.print(
                f"[red]↑[/red] Findings increased by {findings_change} "
                f"({first_findings} → {last_findings})"
            )
        elif findings_change < 0:
            console.print(
                f"[green]↓[/green] Findings decreased by {-findings_change} "
                f"({first_findings} → {last_findings})"
            )
        else:
            console.print("[blue]→[/blue] Findings unchanged")

        console.print()

        # Show recent scans
        console.print("[bold]Recent Scans:[/bold]")
        for scan_time, findings, risk in trend_data[-5:]:
            time_str = scan_time.strftime("%Y-%m-%d %H:%M")
            console.print(f"  {time_str}: {findings} findings (risk: {risk})")

    except Exception as e:
        console.print(f"[red]✗[/red] Failed to show trend: {e}")
        raise typer.Exit(1) from e


@app.command("cleanup")
def cleanup_old_scans(
    days: Annotated[
        int,
        typer.Option(
            "--days",
            "-d",
            help="Delete scans older than this many days",
        ),
    ] = 90,
    force: Annotated[
        bool,
        typer.Option(
            "--force",
            "-f",
            help="Skip confirmation prompt",
        ),
    ] = False,
) -> None:
    """Clean up old scan records."""
    # Validate license
    license_manager = ProLicenseManager()
    if not license_manager.is_valid():
        console.print("[red]✗[/red] No valid license found")
        raise typer.Exit(1)

    if not force:
        confirm = typer.confirm(
            f"Delete all scans older than {days} days?", default=False
        )
        if not confirm:
            console.print("Cancelled")
            raise typer.Exit(0)

    try:
        store = HistoryStore()
        deleted = store.cleanup(days=days)

        console.print(f"[green]✓[/green] Deleted {deleted} old scan record(s)")

    except Exception as e:
        console.print(f"[red]✗[/red] Failed to cleanup: {e}")
        raise typer.Exit(1) from e
