"""Panel & Dock — steuert die eww-Bar + das Dock über panel.json + dock-pins.

Schreibt ausschließlich Config-Dateien (core.panel); eww zieht live nach. Fasst
~/eww NIE direkt an. Vertrag: docs/eww-panel-dock-integration.md.
"""
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.core import panel

_MODULE_LABELS = {
    "music": "Now playing",
    "sys": "System (CPU / RAM)",
    "updates": "Updates",
    "net": "Network",
    "bt": "Bluetooth",
    "vol": "Volume",
}


def build() -> Gtk.Widget:
    page = Adw.PreferencesPage()
    cfg = panel.load()
    state = {"ready": False}

    def persist() -> None:
        if state["ready"]:
            panel.save(cfg)

    page.add(_topbar_group(cfg, persist))
    page.add(_dock_group(cfg, persist))
    page.add(_pins_group())

    state["ready"] = True
    return page


# -- Top bar --------------------------------------------------------------

def _topbar_group(cfg: dict, persist) -> Adw.PreferencesGroup:
    group = Adw.PreferencesGroup(
        title="Top bar",
        description="Which modules the eww bar shows, and the clock format.",
    )

    clock = Adw.EntryRow(title="Clock format")
    clock.set_text(cfg["bar"]["clock_format"])
    clock.set_show_apply_button(True)

    def on_clock(_e: Adw.EntryRow) -> None:
        cfg["bar"]["clock_format"] = clock.get_text()
        persist()

    clock.connect("apply", on_clock)
    group.add(clock)

    mods = cfg["bar"]["modules"]
    for key in panel.MODULES:
        row = Adw.SwitchRow(title=_MODULE_LABELS.get(key, key))
        row.set_active(bool(mods.get(key, True)))

        def on_toggle(r: Adw.SwitchRow, _p, k: str = key) -> None:
            cfg["bar"]["modules"][k] = r.get_active()
            persist()

        row.connect("notify::active", on_toggle)
        group.add(row)

    return group


# -- Dock -----------------------------------------------------------------

def _dock_group(cfg: dict, persist) -> Adw.PreferencesGroup:
    group = Adw.PreferencesGroup(
        title="Dock",
        description="Auto-hide, icon size and hide delay. Applies live.",
    )
    dock = cfg["dock"]

    autohide = Adw.SwitchRow(
        title="Auto-hide",
        subtitle="Hide the dock until you reach the screen edge",
    )
    autohide.set_active(bool(dock.get("autohide", True)))

    def on_autohide(r: Adw.SwitchRow, _p) -> None:
        dock["autohide"] = r.get_active()
        persist()

    autohide.connect("notify::active", on_autohide)
    group.add(autohide)

    size = Adw.SpinRow.new_with_range(24, 64, 1)
    size.set_title("Icon size")
    size.set_subtitle("Pixels (24–64)")
    size.set_value(int(dock.get("icon_size", 42)))

    def on_size(r: Adw.SpinRow, _p) -> None:
        dock["icon_size"] = int(r.get_value())
        persist()

    size.connect("notify::value", on_size)
    group.add(size)

    delay_adj = Gtk.Adjustment(value=float(dock.get("hide_delay", 1.2)),
                               lower=0.2, upper=5.0,
                               step_increment=0.1, page_increment=0.5)
    delay = Adw.SpinRow(title="Hide delay", adjustment=delay_adj, digits=1)
    delay.set_subtitle("Seconds before the dock hides (0.2–5.0)")

    def on_delay(r: Adw.SpinRow, _p) -> None:
        dock["hide_delay"] = round(r.get_value(), 1)
        persist()

    delay.connect("notify::value", on_delay)
    group.add(delay)

    return group


# -- Pinned apps (dock-pins) ----------------------------------------------

def _pins_group() -> Adw.PreferencesGroup:
    group = Adw.PreferencesGroup(
        title="Pinned apps",
        description="Apps pinned to the dock (exec · class · icon).",
    )

    pins = panel.load_pins()
    rows: list[Gtk.Widget] = []

    def _save() -> None:
        panel.save_pins(pins)

    def _refresh() -> None:
        for r in rows:
            group.remove(r)
        rows.clear()
        for i, pin in enumerate(pins):
            row = Adw.ActionRow(title=pin.wmclass or pin.exec, subtitle=pin.exec)
            row.add_prefix(Gtk.Image.new_from_icon_name(pin.icon or "application-x-executable"))
            rm = Gtk.Button(icon_name="user-trash-symbolic")
            rm.add_css_class("flat")
            rm.set_valign(Gtk.Align.CENTER)
            rm.connect("clicked", lambda _b, idx=i: (_remove(idx)))
            row.add_suffix(rm)
            group.add(row)
            rows.append(row)
        group.add(_add_row)
        rows.append(_add_row)

    def _remove(idx: int) -> None:
        if 0 <= idx < len(pins):
            del pins[idx]
            _save()
            _refresh()

    # -- Add-Zeile (Expander mit 3 Feldern) --
    _add_row = Adw.ExpanderRow(title="Add app", subtitle="exec · class · icon")
    e_exec = Adw.EntryRow(title="Exec (command)")
    e_class = Adw.EntryRow(title="Window class (app_id / WM_CLASS)")
    e_icon = Adw.EntryRow(title="Icon name (Papirus)")
    _add_row.add_row(e_exec)
    _add_row.add_row(e_class)
    _add_row.add_row(e_icon)
    add_btn_row = Adw.ActionRow()
    add_btn = Gtk.Button(label="Add to dock")
    add_btn.add_css_class("suggested-action")
    add_btn.add_css_class("pill")
    add_btn.set_halign(Gtk.Align.START)
    add_btn.set_margin_top(4)
    add_btn.set_margin_bottom(4)
    add_btn_row.set_child(add_btn)
    _add_row.add_row(add_btn_row)

    def _on_add(_b: Gtk.Button) -> None:
        ex = e_exec.get_text().strip()
        cl = e_class.get_text().strip() or ex
        ic = e_icon.get_text().strip() or ex
        if not ex:
            return
        pins.append(panel.Pin(ex, cl, ic))
        e_exec.set_text("")
        e_class.set_text("")
        e_icon.set_text("")
        _add_row.set_expanded(False)
        _save()
        _refresh()

    add_btn.connect("clicked", _on_add)

    _refresh()
    return group
