"""Modern minimal Rich terminal UI for Oncecheck."""

from __future__ import annotations

from pathlib import Path
from typing import List, Optional, Tuple

import readchar
from rich.console import Console
from rich.panel import Panel
from rich.table import Table

from .. import __version__
from ..engine.runner import Finding, ScanResult

console = Console()

_ACCENT = "#eeef20"
_SUCCESS = "#22c55e"
_WARN = "#eab308"
_DANGER = "#ef4444"
_MUTED = "#a1a1aa"

_SEVERITY_STYLES = {
    "FAIL": f"bold {_DANGER}",
    "WARN": f"bold {_WARN}",
    "INFO": "bold #60a5fa",
}

_SEVERITY_ICONS = {
    "FAIL": "x",
    "WARN": "!",
    "INFO": "i",
}

_STEP_STYLES = {
    "pending": ("o", _MUTED),
    "running": ("~", _ACCENT),
    "done": ("+", _SUCCESS),
    "warn": ("!", _WARN),
    "failed": ("x", _DANGER),
}


def arrow_select(
    title: str,
    options: List[Tuple[str, str]],
    *,
    icons: Optional[List[str]] = None,
) -> str:
    """Render an arrow-key menu and return selected value."""
    selected = 0
    total = len(options)

    while True:
        lines: List[str] = []
        for i, (label, _value) in enumerate(options):
            icon = icons[i] if icons else ""
            if i == selected:
                prefix = f"[bold {_ACCENT}]>[/bold {_ACCENT}]"
                text = f"[bold]{label}[/bold]"
            else:
                prefix = " "
                text = f"[dim]{label}[/dim]"
            if icon:
                lines.append(f"  {prefix} {icon} {text}")
            else:
                lines.append(f"  {prefix} {text}")

        panel = Panel(
            "\n".join(lines) + "\n\n[dim]Use up/down + Enter[/dim]",
            title=f"[bold]{title}[/bold]",
            border_style=_ACCENT,
            expand=False,
            padding=(1, 2),
        )
        console.clear()
        console.print(panel)
        key = readchar.readkey()
        if key == readchar.key.UP:
            selected = (selected - 1) % total
        elif key == readchar.key.DOWN:
            selected = (selected + 1) % total
        elif key in (readchar.key.ENTER, "\r", "\n"):
            console.clear()
            return options[selected][1]
        elif key in ("q", readchar.key.ESC):
            console.clear()
            return options[-1][1]


def print_welcome() -> None:
    """Show a minimal welcome screen."""
    console.clear()
    panel = Panel(
        f"[bold]Oncecheck[/bold] v{__version__}\n"
        "[dim]Scan iOS, Android, and Web projects for compliance risks.[/dim]",
        border_style=_ACCENT,
        expand=False,
        padding=(1, 2),
    )
    console.print(panel)
    console.print("  [dim]Press any key to continue...[/dim]")
    readchar.readkey()


def prompt_main_menu() -> str:
    return arrow_select(
        "Main Menu",
        [
            ("Scan project", "scan"),
            ("Login", "login"),
            ("Subscription status", "status"),
            ("Exit", "exit"),
        ],
    )


def prompt_platform() -> str:
    return arrow_select(
        "Select Platform",
        [
            ("Auto-detect", "auto"),
            ("iOS", "ios"),
            ("Android", "android"),
            ("Web", "web"),
        ],
    )


def prompt_project_path() -> str:
    console.print()
    console.print(
        Panel(
            "[bold]Project path[/bold]\n[dim]Press Enter to use current directory.[/dim]",
            border_style=_ACCENT,
            expand=False,
            padding=(1, 2),
        )
    )
    while True:
        path_str = console.input(f"  [bold {_ACCENT}]>[/bold {_ACCENT}] ").strip()
        if not path_str:
            path_str = "."
        p = Path(path_str).expanduser().resolve()
        if p.is_dir():
            return str(p)
        console.print(f"  [bold {_DANGER}]Invalid directory:[/bold {_DANGER}] {path_str}")


def prompt_post_scan(is_team: bool = False) -> str:
    options = [("Browse findings", "browse")]
    if is_team:
        options.append(("Export results", "export"))
    options.extend([("Back to menu", "menu"), ("Exit", "exit")])
    return arrow_select("Next Action", options)


def prompt_export_format() -> str:
    return arrow_select("Export Format", [("JSON", "json"), ("Text", "text"), ("SARIF", "sarif")])


def prompt_export_location() -> str:
    home = Path.home()
    cwd = Path.cwd()
    options = [
        (f"Current directory ({cwd})", str(cwd)),
        (f"Desktop ({home / 'Desktop'})", str(home / "Desktop")),
        (f"Documents ({home / 'Documents'})", str(home / "Documents")),
        (f"Downloads ({home / 'Downloads'})", str(home / "Downloads")),
    ]
    valid = [(label, val) for label, val in options if Path(val).is_dir()]
    return arrow_select("Save Location", valid)


def print_step_status(
    index: int,
    total: int,
    label: str,
    state: str,
    detail: str = "",
) -> None:
    """Print one step-state line for the scan pipeline."""
    icon, color = _STEP_STYLES.get(state, _STEP_STYLES["pending"])
    suffix = f" [dim]{detail}[/dim]" if detail else ""
    console.print(f"  [dim]{index}/{total}[/dim] [{color}]{icon}[/{color}] {label}{suffix}")


def print_header() -> None:
    console.print(Panel("[bold]Scan Report[/bold]", border_style=_ACCENT, expand=False, padding=(0, 2)))


def print_scan_result(result: ScanResult) -> None:
    console.print()
    console.print(
        f"[bold]{result.platform.value.upper()}[/bold] "
        f"[dim]({result.project_type})[/dim] "
        f"[dim]- {result.scan_time_seconds:.1f}s[/dim]"
    )

    summary = Table(show_header=False, box=None, pad_edge=False)
    summary.add_row(f"[bold {_DANGER}]FAIL[/bold {_DANGER}]", str(result.fail_count))
    summary.add_row(f"[bold {_WARN}]WARN[/bold {_WARN}]", str(result.warn_count))
    summary.add_row("[bold #60a5fa]INFO[/bold #60a5fa]", str(result.info_count))
    console.print(Panel(summary, border_style=_ACCENT, expand=False, title="Summary"))

    if not result.findings:
        console.print(f"  [bold {_SUCCESS}]+ No compliance issues found[/bold {_SUCCESS}]")
        return

    severity_order = {"FAIL": 0, "WARN": 1, "INFO": 2}
    findings = sorted(result.findings, key=lambda f: severity_order.get(f.severity, 3))
    for finding in findings:
        _print_finding(finding)


def _print_finding(finding: Finding) -> None:
    style = _SEVERITY_STYLES.get(finding.severity, "bold")
    icon = _SEVERITY_ICONS.get(finding.severity, "?")
    console.print(f"  [{style}]{icon} {finding.severity}[/{style}] [bold]{finding.rule_id}[/bold] {finding.message}")
    console.print(f"      [dim]Fix: {finding.fix}[/dim]")
    if finding.reference:
        console.print(f"      [dim]Ref: {finding.reference}[/dim]")


def print_footer(results: List[ScanResult]) -> None:
    total_fail = sum(r.fail_count for r in results)
    total_warn = sum(r.warn_count for r in results)
    total_info = sum(r.info_count for r in results)
    console.print()
    console.print(
        f"[dim]Totals ->[/dim] "
        f"[bold {_DANGER}]FAIL {total_fail}[/bold {_DANGER}]  "
        f"[bold {_WARN}]WARN {total_warn}[/bold {_WARN}]  "
        f"[bold #60a5fa]INFO {total_info}[/bold #60a5fa]"
    )
