"""Rich console output for yaml-doctor scan results."""

from __future__ import annotations

from rich import box
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

from ..models import FileType, LintResult, ScanResult, Severity
from ..utils import grade_color, score_bar, severity_icon, truncate

console = Console()

# ─── Colours ───────────────────────────────────────────────────────────
SEV_STYLE = {
    Severity.CRITICAL: "bold red",
    Severity.HIGH: "red",
    Severity.MEDIUM: "yellow",
    Severity.LOW: "cyan",
    Severity.INFO: "dim",
}

TYPE_STYLE = {
    FileType.KUBERNETES: "bold blue",
    FileType.HELM: "bold magenta",
    FileType.DOCKER_COMPOSE: "bold cyan",
    FileType.GITHUB_ACTIONS: "bold green",
    FileType.GITLAB_CI: "bold yellow",
    FileType.GENERIC_YAML: "white",
    FileType.UNKNOWN: "dim",
}


def render_file_result(result: LintResult) -> None:
    """Render a single file's lint result."""
    if not result.valid_yaml:
        console.print(
            Panel(
                f"[bold red]YAML Parse Error[/]\n{result.parse_error}",
                title=f"[red]✗ {result.file_path}[/]",
                border_style="red",
            )
        )
        return

    # Header
    g_col = grade_color(result.grade)
    ft_style = TYPE_STYLE.get(result.file_type, "white")
    header = Text()
    header.append(f"  {result.grade.value}", style=f"bold {g_col}")
    header.append(f"  {result.score}/100", style=g_col)
    header.append(f"  │  {result.file_type.value}", style=ft_style)
    header.append(f"  │  {result.documents} doc(s)")
    console.print(
        Panel(
            header,
            title=f"[bold]{result.file_path}[/]",
            subtitle=score_bar(result.score),
            border_style=g_col,
            padding=(0, 1),
        )
    )

    if not result.findings:
        console.print("  [green]✓ No issues found — perfect![/]\n")
        return

    # Findings table
    table = Table(box=box.SIMPLE_HEAVY, show_edge=False, pad_edge=False, expand=True)
    table.add_column("", width=2)
    table.add_column("Rule", style="bold", width=8)
    table.add_column("Severity", width=10)
    table.add_column("Line", justify="right", width=5)
    table.add_column("Message", ratio=1)
    table.add_column("Fix", ratio=1, style="dim green")

    for f in result.findings:
        icon = severity_icon(f.rule.severity)
        sev_style = SEV_STYLE.get(f.rule.severity, "white")
        table.add_row(
            icon,
            f.rule.rule_id,
            Text(f.rule.severity.value.upper(), style=sev_style),
            str(f.line) if f.line else "–",
            truncate(f.message, 60),
            truncate(f.rule.fix, 50),
        )

    console.print(table)

    # Summary line
    parts = []
    if result.critical_count:
        parts.append(f"[bold red]{result.critical_count} critical[/]")
    if result.high_count:
        parts.append(f"[red]{result.high_count} high[/]")
    if result.medium_count:
        parts.append(f"[yellow]{result.medium_count} medium[/]")
    if result.low_count:
        parts.append(f"[cyan]{result.low_count} low[/]")
    if result.info_count:
        parts.append(f"[dim]{result.info_count} info[/]")
    console.print(f"  {' · '.join(parts)}\n")


def render_scan_result(scan: ScanResult) -> None:
    """Render directory scan results."""
    console.print()
    console.print(
        Panel(
            "[bold]yaml-doctor[/] — YAML Linter & Security Scanner",
            style="bold blue",
            padding=(0, 2),
        )
    )

    if not scan.files:
        console.print("[yellow]No YAML files found.[/]")
        return

    # Print each file
    for result in scan.files:
        render_file_result(result)

    # Summary panel
    _render_summary(scan)


def _render_summary(scan: ScanResult) -> None:
    """Render scan summary panel."""
    g_col = grade_color(scan.overall_grade)

    # Grade distribution
    grade_dist: dict[str, int] = {}
    for f in scan.files:
        gv = f.grade.value
        grade_dist[gv] = grade_dist.get(gv, 0) + 1

    summary = Table(box=box.SIMPLE, show_header=False, padding=(0, 2))
    summary.add_column("Key", style="bold")
    summary.add_column("Value")

    summary.add_row("Files scanned", str(scan.total_files))
    summary.add_row("Total findings", str(scan.total_findings))
    summary.add_row("Passed (A/A+)", f"[green]{scan.passed_files}[/]")
    summary.add_row("Failed (D/F)", f"[red]{scan.failed_files}[/]")
    summary.add_row("Overall grade", f"[bold {g_col}]{scan.overall_grade.value}[/]")
    summary.add_row("Overall score", f"[{g_col}]{scan.overall_score}/100[/]")

    # Severity totals
    summary.add_row("Critical issues", f"[bold red]{scan.critical_total}[/]")
    summary.add_row("High issues", f"[red]{scan.high_total}[/]")

    # Grade distribution
    dist_parts = [f"{g}: {c}" for g, c in sorted(grade_dist.items())]
    summary.add_row("Grade distribution", " │ ".join(dist_parts))

    console.print(
        Panel(
            summary,
            title="[bold]Scan Summary[/]",
            subtitle=score_bar(scan.overall_score),
            border_style=g_col,
        )
    )
    console.print()


def render_rules(rules: list) -> None:
    """Render all available lint rules."""
    table = Table(
        title="[bold]yaml-doctor — All Lint Rules[/]",
        box=box.ROUNDED,
        show_lines=False,
        expand=True,
    )
    table.add_column("#", width=3, justify="right")
    table.add_column("Rule ID", style="bold", width=8)
    table.add_column("Severity", width=10)
    table.add_column("Category", width=18)
    table.add_column("Description", ratio=1)

    for i, r in enumerate(rules, 1):
        sev_style = SEV_STYLE.get(r.severity, "white")
        table.add_row(
            str(i),
            r.rule_id,
            Text(r.severity.value.upper(), style=sev_style),
            r.category,
            r.description,
        )

    console.print(table)
    console.print(f"\n  [bold]{len(rules)}[/] rules available\n")
