"""Home — App-Store-Startseite im GNOME-Software-Stil.

Kuratierte Endnutzer-Apps (core/catalog), nach Kategorie gruppiert, als
klickbare Icon-Tiles. Klick öffnet die Detailansicht (Info + Quellenwahl +
Install). Async geladen.
"""
from __future__ import annotations

import threading

import gi

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

from taninux.core import catalog, pacman
from taninux.gui.pages.appdetail import open_app_detail


def build() -> Gtk.Widget:
    page = Adw.PreferencesPage()
    groups: list[Adw.PreferencesGroup] = []

    intro = Adw.PreferencesGroup(
        title="Recommended apps",
        description="Popular apps for everyday use — click for details.",
    )
    refresh = Gtk.Button(icon_name="view-refresh-symbolic")
    refresh.add_css_class("flat")
    refresh.set_valign(Gtk.Align.CENTER)
    intro.set_header_suffix(refresh)
    page.add(intro)

    def _icon_name(app: catalog.App) -> str:
        theme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default())
        if theme and theme.has_icon(app.icon):
            return app.icon
        return catalog.CATEGORY_ICON.get(app.category, "system-software-install-symbolic")

    def _open(app: catalog.App) -> None:
        open_app_detail(
            page,
            title=app.name,
            icon=app.icon,
            repo_name=app.pkg if app.source == "repo" else None,
            flatpak_id=app.pkg if app.source == "flatpak" else None,
            on_changed=_load,
        )

    def _tile(app: catalog.App) -> Gtk.Widget:
        tile = Gtk.Button()
        tile.add_css_class("card")
        tile.connect("clicked", lambda _b, a=app: _open(a))

        row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=14)
        row.set_margin_top(14)
        row.set_margin_bottom(14)
        row.set_margin_start(14)
        row.set_margin_end(14)
        icon = Gtk.Image.new_from_icon_name(_icon_name(app))
        icon.set_pixel_size(48)
        row.append(icon)
        text = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2, hexpand=True)
        text.set_valign(Gtk.Align.CENTER)
        name = Gtk.Label(label=app.name, xalign=0.0)
        name.add_css_class("title-4")
        summary = Gtk.Label(label=app.summary, xalign=0.0, wrap=True)
        summary.add_css_class("dim-label")
        summary.add_css_class("caption")
        summary.set_lines(2)
        summary.set_ellipsize(3)
        text.append(name)
        text.append(summary)
        row.append(text)
        tile.set_child(row)
        return tile

    def _category_group(category: str, apps: list[catalog.App]) -> Adw.PreferencesGroup:
        group = Adw.PreferencesGroup(title=category)
        flow = Gtk.FlowBox()
        flow.set_selection_mode(Gtk.SelectionMode.NONE)
        flow.set_max_children_per_line(2)
        flow.set_min_children_per_line(1)
        flow.set_column_spacing(12)
        flow.set_row_spacing(12)
        flow.set_homogeneous(True)
        for app in apps:
            flow.append(_tile(app))
        group.add(flow)
        return group

    def _render(apps: list[catalog.App]) -> None:
        for g in groups:
            page.remove(g)
        groups.clear()
        if not apps:
            g = Adw.PreferencesGroup()
            g.add(Adw.StatusPage(
                icon_name="emblem-ok-symbolic",
                title="You're all set",
                description="All recommended apps are already installed.",
            ))
            page.add(g)
            groups.append(g)
            return
        by_cat: dict[str, list[catalog.App]] = {}
        for app in apps:
            by_cat.setdefault(app.category, []).append(app)
        for cat in catalog.CATEGORY_ORDER:
            if cat in by_cat:
                g = _category_group(cat, by_cat[cat])
                page.add(g)
                groups.append(g)

    def _load() -> None:
        def worker() -> None:
            try:
                pac = set(pacman.installed_packages())
                fp = catalog._flatpak_installed_ids()
                apps = catalog.recommended(pac, fp)
            except Exception:  # noqa: BLE001
                apps = []
            GLib.idle_add(lambda: (_render(apps), False)[1])

        threading.Thread(target=worker, daemon=True).start()

    refresh.connect("clicked", lambda _b: (pacman.invalidate(), _load()))
    GLib.idle_add(lambda: (_load(), False)[1])
    return page
