"""Storage — Laufwerke, Belegung, Wechseldatenträger (udisksctl)."""
from __future__ import annotations

import gi

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

from taninux.core import storage
from taninux.gui.process import ProcessRunner


def _gib(b: int) -> str:
    if b >= 1024**3:
        return f"{b / 1024**3:.0f} GiB"
    return f"{b / 1024**2:.0f} MiB" if b else "—"


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

    def _row(vol: storage.Volume) -> Adw.ActionRow:
        title = vol.label or vol.dev.split("/")[-1]
        sub = vol.mountpoint or "Not mounted"
        row = Adw.ActionRow(title=title, subtitle=f"{sub}  ·  {_gib(vol.size)} · {vol.fstype}")
        if vol.mountpoint and vol.use_pct:
            level = Gtk.LevelBar.new_for_interval(0, 100)
            level.set_value(vol.use_pct)
            level.set_size_request(120, -1)
            level.set_valign(Gtk.Align.CENTER)
            row.add_suffix(level)
            pct = Gtk.Label(label=f"{vol.use_pct}%")
            pct.add_css_class("dim-label")
            pct.add_css_class("numeric")
            row.add_suffix(pct)
        if vol.removable:
            if vol.mountpoint:
                row.add_suffix(_btn("Eject", lambda: runner.run(storage.eject_argv(vol.dev))))
            else:
                row.add_suffix(_btn("Mount", lambda: runner.run(storage.mount_argv(vol.dev))))
        return row

    def _render() -> None:
        for g in groups:
            page.remove(g)
        groups.clear()
        vols = storage.volumes()
        internal = [v for v in vols if not v.removable]
        removable = [v for v in vols if v.removable]

        g_int = Adw.PreferencesGroup(title="This device")
        if internal:
            for v in internal:
                g_int.add(_row(v))
        else:
            g_int.add(Adw.ActionRow(title="No filesystems found"))
        page.add(g_int)
        groups.append(g_int)

        if removable:
            g_rm = Adw.PreferencesGroup(title="Removable")
            for v in removable:
                g_rm.add(_row(v))
            page.add(g_rm)
            groups.append(g_rm)

    runner.connect("done", lambda _r, _c: _render())
    GLib.idle_add(lambda: (_render(), False)[1])
    return page


def _btn(label: str, cb) -> Gtk.Button:
    b = Gtk.Button(label=label)
    b.add_css_class("flat")
    b.set_valign(Gtk.Align.CENTER)
    b.connect("clicked", lambda _b: cb())
    return b
