"""Scan command for Pro version."""

import time
from pathlib import Path
from typing import Annotated

import typer
from rich.console import Console

from apiposture_pro.analysis.pro_analyzer import ProAnalyzer
from apiposture_pro.cli.output.json_formatter import JsonFormatter
from apiposture_pro.cli.output.markdown_formatter import MarkdownFormatter
from apiposture_pro.cli.output.terminal_formatter import TerminalFormatter
from apiposture_pro.features.historical_tracking.store import HistoryStore
from apiposture_pro.licensing.manager import ProLicenseManager
from apiposture_pro.licensing.models import (
    LicenseErrorCode,
    LicenseFeature,
    LicenseValidationResult,
)

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


@app.command("scan")
def scan(
    path: Annotated[
        Path,
        typer.Argument(
            help="Path to Python project to scan",
            exists=True,
            file_okay=False,
            dir_okay=True,
        ),
    ] = Path("."),
    output: Annotated[
        str,
        typer.Option(
            "--output",
            "-o",
            help="Output format (text, json, markdown)",
        ),
    ] = "text",
    output_file: Annotated[
        Path | None,
        typer.Option(
            "--file",
            "-f",
            help="Output file path",
        ),
    ] = None,
    with_history: Annotated[
        bool,
        typer.Option(
            "--with-history",
            help="Save scan to history database",
        ),
    ] = False,
    show_risk_score: Annotated[
        bool,
        typer.Option(
            "--risk-score/--no-risk-score",
            help="Show risk score calculation",
        ),
    ] = True,
    tag: Annotated[
        list[str] | None,
        typer.Option(
            "--tag",
            "-t",
            help="Tag for this scan (repeatable)",
        ),
    ] = None,
) -> None:
    """
    Scan a Python project for security issues.

    Requires valid Pro license.
    """
    # Validate license
    license_manager = ProLicenseManager()
    validation = license_manager.validate()
    if not validation.is_valid:
        _print_license_error(validation)
        raise typer.Exit(1)

    context = validation.context
    if not context:
        console.print("[red]✗[/red] Could not retrieve license context")
        raise typer.Exit(1)

    # Show license info
    console.print(
        f"[dim]Scanning with {context.tier.upper()} license ({context.customer_name})[/dim]\n"
    )

    # Create analyzer
    analyzer = ProAnalyzer()

    # Run scan
    try:
        console.print(f"[cyan]Scanning:[/cyan] {path.absolute()}")
        console.print("[dim]Loading Pro rules...[/dim]")

        start_time = time.time()
        result = analyzer.analyze(path)
        duration_ms = int((time.time() - start_time) * 1000)

        # Render rich TUI output
        risk = (
            getattr(result, "risk_details", None)
            if show_risk_score and license_manager.has_feature(LicenseFeature.RISK_SCORING)
            else None
        )
        TerminalFormatter(console).render(result, duration_ms=duration_ms, risk=risk)

        # Severity counts needed for exit-code logic below
        from collections import Counter

        severity_counts = Counter(
            (f.severity.name if hasattr(f.severity, "name") else str(f.severity)).upper()
            for f in result.findings
        )

        # Save to history if requested
        if with_history:
            console.print("\n[dim]Saving to history database...[/dim]")
            try:
                store = HistoryStore()
                scan_id = store.save_scan(
                    result,
                    duration_ms=duration_ms,
                    risk_score=getattr(result, "risk_score", 0),
                    tags=tag,
                )
                console.print(f"[green]✓[/green] Saved as scan #{scan_id}")
            except Exception as e:
                console.print(f"[yellow]![/yellow] Failed to save to history: {e}")

        # Export results if requested
        if output_file:
            console.print(f"\n[dim]Writing results to {output_file}...[/dim]")
            if output == "json":
                content = JsonFormatter().format(result, duration_ms)
            elif output == "markdown":
                content = MarkdownFormatter().format(result, duration_ms)
            else:
                console.print(f"[yellow]![/yellow] Format '{output}' cannot be written to file (use json or markdown)")
                content = None
            if content is not None:
                output_file.write_text(content, encoding="utf-8")
                console.print(f"[green]✓[/green] Written to {output_file}")

        # Exit with code 1 if critical or high findings
        critical_high_count = (
            severity_counts.get("CRITICAL", 0) + severity_counts.get("HIGH", 0)
        )
        if critical_high_count > 0:
            console.print(
                f"\n[yellow]![/yellow] Found {critical_high_count} critical/high severity issues"
            )
            raise typer.Exit(1)

    except Exception as e:
        console.print(f"\n[red]✗[/red] Scan failed: {e}")
        raise typer.Exit(1) from e


def _print_license_error(result: LicenseValidationResult) -> None:
    """Print error-code-specific license error message."""
    messages = {
        LicenseErrorCode.EXPIRED: f"[red]✗[/red] Your license has expired. {result.error_message}",
        LicenseErrorCode.MACHINE_MISMATCH: "[red]✗[/red] License is bound to a different machine. Re-activate or contact support.",
        LicenseErrorCode.REVOKED: "[red]✗[/red] Your license has been revoked. Contact support for assistance.",
        LicenseErrorCode.TOO_MANY_ACTIVATIONS: "[red]✗[/red] Too many activations for this license key.",
        LicenseErrorCode.NETWORK_ERROR: "[red]✗[/red] License could not be validated offline. Connect to the internet to re-validate.",
        LicenseErrorCode.GRACE_PERIOD_EXPIRED: "[red]✗[/red] License expired and grace period has ended. Renew your license.",
        LicenseErrorCode.INVALID_SIGNATURE: "[red]✗[/red] License key has an invalid signature.",
    }

    msg = messages.get(result.error_code, f"[red]✗[/red] No valid license found. {result.error_message}")
    console.print(msg)
    console.print("\nActivate your license with: apiposture-pro activate <key>")
    console.print("Or set environment variable: APIPOSTURE_LICENSE_KEY")
