"""Suggest-Pillar — system-aware Paket-Empfehlungen."""
from __future__ import annotations

import subprocess

from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import VerticalScroll
from textual.widgets import DataTable, Static

from taninux.core import pacman as pac
from taninux.core import theme as T
from taninux.core.confirm import ConfirmModal
from taninux.core.runner import Command, run_interactive
from taninux.suggest.rules import Suggestion, all_suggestions


CATEGORY_GLYPH = {
    "gpu":   ("▣", T.UME),
    "dev":   ("◆", T.SHINKAI),
    "shell": ("●", T.TAKE),
    "audio": ("◐", T.CHIKYU),
}


class SuggestView(VerticalScroll):
    DEFAULT_CSS = f"""
    SuggestView {{
        background: {T.YORU};
        padding: 1 2;
        scrollbar-color: {T.BASE2} {T.YORU};
        scrollbar-background: {T.YORU};
        scrollbar-corner-color: {T.YORU};
        scrollbar-size-vertical: 1;
    }}
    SuggestView Static {{
        background: {T.YORU};
        margin-bottom: 1;
    }}
    SuggestView #s-table {{
        height: auto;
        background: {T.YORU};
        color: {T.FG_ALT};
        border: none;
        overflow-x: hidden;
    }}
    SuggestView #s-table:focus {{
        border: none;
    }}
    SuggestView DataTable > .datatable--header {{
        background: {T.YORU};
        color: {T.SHINKAI};
    }}
    SuggestView DataTable > .datatable--cursor {{
        background: {T.BASE1};
        color: {T.YUKI};
    }}
    SuggestView DataTable > .datatable--even-row {{
        background: {T.YORU};
    }}
    SuggestView DataTable > .datatable--odd-row {{
        background: {T.YORU};
    }}
    """

    BINDINGS = [
        Binding("r", "rescan", "rescan"),
        Binding("i", "install", "installieren"),
        Binding("j", "cursor_down", "down", show=False),
        Binding("k", "cursor_up", "up", show=False),
    ]

    def __init__(self, **kwargs) -> None:
        super().__init__(**kwargs)
        self.suggestions: list[Suggestion] = []

    def compose(self) -> ComposeResult:
        yield Static("", id="s-intro", markup=True)
        yield DataTable(id="s-table", cursor_type="row", zebra_stripes=False)
        yield Static("", id="s-flash", markup=True)

    def on_mount(self) -> None:
        table = self.query_one("#s-table", DataTable)
        table.add_column("", width=2, key="glyph")
        table.add_column("kat", width=8, key="cat")
        table.add_column("anlass", key="reason")
        table.add_column("pakete", key="pkgs")
        table.add_column("pri", width=4, key="pri")
        self.action_rescan()

    def action_rescan(self) -> None:
        self._flash("scanne …")
        pac.invalidate()
        installed = set(pac.installed_packages())
        self.suggestions = sorted(
            all_suggestions(installed),
            key=lambda s: (s.priority, s.category),
        )
        self._refresh_view()
        self._flash(f"{len(self.suggestions)} empfehlungen")

    def action_install(self) -> None:
        cur = self._current()
        if cur is None:
            self._flash("nichts ausgewählt", color=T.BASE4)
            return
        body = (
            f"folgende pakete via paru -S installieren?\n\n"
            f"  {', '.join(cur.packages)}\n\n"
            f"grund: {cur.reason}"
        )
        self.app.push_screen(
            ConfirmModal("installieren?", body, danger=False),
            lambda ok: self._after_install(ok, cur),
        )

    def _after_install(self, confirmed: bool | None, s: Suggestion) -> None:
        if not confirmed:
            self._flash("abgebrochen")
            return
        from taninux.core import sysinfo
        helper = "paru" if sysinfo.has_binary("paru") else (
            "yay" if sysinfo.has_binary("yay") else "sudo pacman"
        )
        argv = helper.split() + ["-S", *s.packages]
        codes = run_interactive(
            self.app,
            [Command(label=f"install {len(s.packages)} pakete", argv=argv)],
        )
        ok = codes and codes[0] == 0
        pac.invalidate()
        self._flash(
            "installation ok — rescan…" if ok else "installation fehlgeschlagen",
            color=T.TAKE if ok else T.RED,
        )
        self.action_rescan()

    def action_cursor_down(self) -> None:
        self.query_one("#s-table", DataTable).action_cursor_down()

    def action_cursor_up(self) -> None:
        self.query_one("#s-table", DataTable).action_cursor_up()

    def _current(self) -> Suggestion | None:
        t = self.query_one("#s-table", DataTable)
        r = t.cursor_row
        if r is None or r < 0 or r >= len(self.suggestions):
            return None
        return self.suggestions[r]

    def _flash(self, msg: str, color: str | None = None) -> None:
        color = color or T.BASE4
        self.query_one("#s-flash", Static).update(f"[{color}]{msg}[/]")

    def _refresh_view(self) -> None:
        intro = (
            f"[{T.UME}]✦ suggest[/]\n"
            f"[{T.BASE5}]system-aware empfehlungen — `i` installiert die ausgewählte zeile via paru[/]"
        )
        self.query_one("#s-intro", Static).update(intro)

        table = self.query_one("#s-table", DataTable)
        table.clear()
        for s in self.suggestions:
            glyph, color = CATEGORY_GLYPH.get(s.category, ("·", T.BASE4))
            pri_color = {1: T.RED, 2: T.CHIKYU, 3: T.BASE5}.get(s.priority, T.BASE5)
            pri_label = {1: "hoch", 2: "mittel", 3: "nice"}.get(s.priority, str(s.priority))
            pkg_count = len(s.packages)
            pkgs_str = ", ".join(s.packages[:4]) + (f" +{pkg_count - 4}" if pkg_count > 4 else "")
            table.add_row(
                f"[{color}]{glyph}[/]",
                f"[{color}]{s.category}[/]",
                f"[{T.YUKI}]{s.reason}[/]",
                f"[{T.BASE5}]{pkgs_str}[/]",
                f"[{pri_color}]{pri_label}[/]",
            )
