"""
Screen backlight — the ONE real brightness control behind both the in-game
Quick Menu slider and the Display & Power screen. One element, two surfaces.

Standard Linux sysfs:  /sys/class/backlight/<dev>/{brightness,max_brightness}
The backlight device name varies by board, so we SCAN and take the first one.
Reads are world-readable; writes go through `sudo -n` (passwordless `ark`, the
same mechanism the governor uses in powerops). Tolerant: no backlight dir →
None / False (dev box / Mac), so callers keep their demo value and nothing is
written by accident.

Lives in gui.library (not gui.control) because both the launcher and Control
need it, and gui.library is the package both already share.
"""

from __future__ import annotations

import glob
import os
import subprocess
from typing import Optional

# Allow tests / a non-sudo dev box to write directly (AAHEAD_SUDO=0).
_SUDO = [] if os.environ.get("AAHEAD_SUDO") == "0" else ["sudo", "-n"]


# ── pure helpers (testable, no device) ────────────────────────────────

def pct_from_raw(raw, mx) -> Optional[int]:
    """raw backlight value + max → a human 0..100 percent. None if unreadable."""
    try:
        raw_i, mx_i = int(str(raw).strip()), int(str(mx).strip())
    except (TypeError, ValueError):
        return None
    if mx_i <= 0:
        return None
    return max(0, min(100, round(raw_i / mx_i * 100)))


def raw_from_pct(pct, mx) -> Optional[int]:
    """A percent → the raw value to write. Floored at 1 so the slider can never
    drive the panel fully black (you'd lose the screen). None if unusable."""
    try:
        pct_i, mx_i = int(str(pct).strip()), int(str(mx).strip())
    except (TypeError, ValueError):
        return None
    if mx_i <= 0:
        return None
    return max(1, min(mx_i, round(max(0, min(100, pct_i)) / 100 * mx_i)))


# ── tolerant live layer (device; never raises) ───────────────────────

def device_dir() -> Optional[str]:
    """First /sys/class/backlight/* dir, or None when there's no backlight."""
    dirs = sorted(glob.glob("/sys/class/backlight/*"))
    return dirs[0] if dirs else None


def _read_file(path: str) -> Optional[str]:
    try:
        with open(path, encoding="utf-8", errors="replace") as fh:
            return fh.read().strip()
    except OSError:
        return None


def present() -> bool:
    return device_dir() is not None


def read() -> Optional[dict]:
    """Current backlight as {pct, raw, max}, or None when there's no backlight."""
    d = device_dir()
    if not d:
        return None
    mx = _read_file(os.path.join(d, "max_brightness"))
    raw = _read_file(os.path.join(d, "brightness"))
    pct = pct_from_raw(raw, mx)
    if pct is None:
        return None
    return {"pct": pct, "raw": int(raw), "max": int(mx)}


def set_pct(pct: int) -> bool:
    """Write a percentage to the backlight. True on success, False otherwise
    (no backlight, bad value, or the privileged write failed)."""
    d = device_dir()
    if not d:
        return False
    raw = raw_from_pct(pct, _read_file(os.path.join(d, "max_brightness")))
    if raw is None:
        return False
    try:
        r = subprocess.run([*_SUDO, "tee", os.path.join(d, "brightness")],
                           input=f"{raw}\n", capture_output=True, text=True, timeout=5)
        return r.returncode == 0
    except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
        return False
