"""Laufwerke und Belegung. UI-frei. Lesen via lsblk; mount/eject via udisksctl
(user-level, polkit-backed — kein root-Helper nötig)."""
from __future__ import annotations

import json
import subprocess
from dataclasses import dataclass


@dataclass
class Volume:
    dev: str              # /dev/sdX1
    size: int             # bytes
    fstype: str
    label: str
    mountpoint: str
    removable: bool
    used: int             # bytes (0 wenn nicht gemountet)
    use_pct: int          # 0..100


def _lsblk() -> list[dict]:
    try:
        r = subprocess.run(
            ["lsblk", "-J", "-b", "-o",
             "NAME,PATH,SIZE,TYPE,MOUNTPOINT,FSTYPE,LABEL,RM,FSUSED,FSUSE%"],
            capture_output=True, text=True, check=False, timeout=8,
        )
        return json.loads(r.stdout).get("blockdevices", [])
    except (FileNotFoundError, subprocess.TimeoutExpired, json.JSONDecodeError):
        return []


def _walk(node: dict, removable: bool, out: list[Volume]) -> None:
    rm = removable or node.get("rm", False)
    if (node.get("fstype") and node.get("fstype") != "swap"
            and node.get("type") in ("part", "crypt", "lvm", "disk")):
        pct = node.get("fsuse%") or ""
        try:
            use_pct = int(str(pct).rstrip("%")) if pct else 0
        except ValueError:
            use_pct = 0
        out.append(Volume(
            dev=node.get("path", node.get("name", "")),
            size=int(node.get("size") or 0),
            fstype=node.get("fstype", ""),
            label=node.get("label") or "",
            mountpoint=node.get("mountpoint") or "",
            removable=bool(rm),
            used=int(node.get("fsused") or 0),
            use_pct=use_pct,
        ))
    for child in node.get("children", []):
        _walk(child, rm, out)


def volumes() -> list[Volume]:
    out: list[Volume] = []
    for dev in _lsblk():
        _walk(dev, False, out)
    return out


def mount_argv(dev: str) -> list[str]:
    return ["udisksctl", "mount", "-b", dev]


def unmount_argv(dev: str) -> list[str]:
    return ["udisksctl", "unmount", "-b", dev]


def eject_argv(dev: str) -> list[str]:
    return ["udisksctl", "power-off", "-b", dev]
