"""Bundles — deklarative Paket-Sets über bundles.loader.

Pro Bundle eine ExpanderRow mit installiert/fehlend-Status pro Paket und einem
„Install missing"-Button (pacman -S --needed via Helper). Status wird hier
selbst berechnet (kein Import aus der Textual-screen.py). Nach jedem Lauf wird
neu berechnet.
"""
from __future__ import annotations

import gi

gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1")
from gi.repository import Adw, Gtk  # noqa: E402

from taninux.bundles.loader import all_bundles
from taninux.core import pacman
from taninux.gui import confirm
from taninux.gui.console import LogConsole, log_expander
from taninux.gui.process import ProcessRunner
from taninux.suggest import rules


def build() -> Gtk.Widget:
    page = Adw.PreferencesPage()

    console = LogConsole()
    runner = ProcessRunner()
    runner.connect("line", lambda _r, ln: console.append_line(ln))

    g_rec = Adw.PreferencesGroup(
        title="Recommended",
        description="System-aware suggestions for your hardware and tools.",
    )
    page.add(g_rec)

    g = Adw.PreferencesGroup(title="Bundles")
    page.add(g)

    rows: list[Gtk.Widget] = []
    rec_rows: list[Gtk.Widget] = []

    def _clear() -> None:
        for r in rows:
            g.remove(r)
        rows.clear()

    def _install_pkgs(pkgs: list[str], parent: Gtk.Widget, title: str) -> None:
        def do() -> None:
            console.clear()
            runner.run(["pacman", "-S", "--needed", "--noconfirm", *pkgs], privileged=True)

        confirm.confirm(
            parent, f"Install {title}",
            "Install via pacman: " + ", ".join(pkgs), do,
        )

    def _install_one(pkg: str, parent: Gtk.Widget) -> None:
        _install_pkgs([pkg], parent, pkg)

    def _render() -> None:
        _clear()
        inst = pacman.installed_packages()
        for b in all_bundles():
            n_inst = sum(1 for p in b.packages if p in inst)
            total = len(b.packages)
            complete = n_inst == total

            row = Adw.ExpanderRow(title=b.label, subtitle=b.tagline)

            # Count-Badge als Suffix (statt "Install missing"-Button).
            badge = Gtk.Label(label=f"{n_inst}/{total}")
            badge.add_css_class("numeric")
            badge.add_css_class("success" if complete else "dim-label")
            badge.add_css_class("caption-heading")
            badge.set_valign(Gtk.Align.CENTER)
            row.add_suffix(badge)

            # Pro Paket eine Zeile: installiert = dim-Tag, fehlend = Install-Button.
            for pkg in b.packages:
                pr = Adw.ActionRow(title=pkg)
                if pkg in inst:
                    tag = Gtk.Label(label="installed")
                    tag.add_css_class("dim-label")
                    tag.add_css_class("caption")
                    tag.set_valign(Gtk.Align.CENTER)
                    pr.add_suffix(tag)
                else:
                    ib = Gtk.Button(label="Install")
                    ib.add_css_class("suggested-action")
                    ib.set_valign(Gtk.Align.CENTER)
                    ib.connect("clicked", lambda _b, p=pkg: _install_one(p, _b))
                    pr.add_suffix(ib)
                row.add_row(pr)

            g.add(row)
            rows.append(row)

    def _render_rec() -> None:
        for r in rec_rows:
            g_rec.remove(r)
        rec_rows.clear()
        sugg = rules.all_suggestions(set(pacman.installed_packages()))
        if not sugg:
            row = Adw.ActionRow(title="Nothing recommended",
                                subtitle="Your system looks complete.")
            g_rec.add(row)
            rec_rows.append(row)
            return
        for s in sorted(sugg, key=lambda x: x.priority):
            row = Adw.ActionRow(title=s.title or s.reason, subtitle=s.reason)
            btn = Gtk.Button(label="Install")
            btn.add_css_class("suggested-action")
            btn.set_valign(Gtk.Align.CENTER)
            btn.set_tooltip_text(", ".join(s.packages))
            btn.connect(
                "clicked",
                lambda _b, p=list(s.packages), t=s.title or "packages":
                    _install_pkgs(p, _b, t),
            )
            row.add_suffix(btn)
            g_rec.add(row)
            rec_rows.append(row)

    def _refresh() -> None:
        _render_rec()
        _render()

    def on_done(_r: ProcessRunner, code: int) -> None:
        console.append_line("✔ done" if code == 0 else f"✘ exit {code}")
        pacman.installed_packages.cache_clear()
        _refresh()

    runner.connect("done", on_done)

    # -- Log ----------------------------------------------------------
    page.add(log_expander(console))

    _refresh()
    return page
