"""Standard-Anwendungen pro Kategorie. UI-frei, user-level (kein root).

Liest/setzt die MIME-Default-Apps über `gio mime` + `xdg-mime`. Anzeigename und
Icon kommen aus den .desktop-Dateien.
"""
from __future__ import annotations

import os
import subprocess
from dataclasses import dataclass
from pathlib import Path

# (Label, repräsentativer MIME-Typ, Fallback-Icon)
CATEGORIES = [
    ("Web browser", "x-scheme-handler/https", "web-browser-symbolic"),
    ("Email", "x-scheme-handler/mailto", "mail-send-symbolic"),
    ("Files", "inode/directory", "folder-symbolic"),
    ("Images", "image/png", "image-x-generic-symbolic"),
    ("Audio", "audio/mpeg", "audio-x-generic-symbolic"),
    ("Video", "video/mp4", "video-x-generic-symbolic"),
    ("PDF documents", "application/pdf", "x-office-document-symbolic"),
]

_DIRS = [
    Path.home() / ".local/share/applications",
    Path.home() / ".local/share/flatpak/exports/share/applications",
    Path("/var/lib/flatpak/exports/share/applications"),
    Path("/usr/share/applications"),
]


@dataclass
class App:
    id: str          # desktop file id, z.B. firefox.desktop
    name: str
    icon: str


def _find_desktop(desktop_id: str) -> Path | None:
    for d in _DIRS:
        p = d / desktop_id
        if p.is_file():
            return p
    return None


def _meta(desktop_id: str) -> App:
    name, icon = desktop_id.removesuffix(".desktop"), ""
    path = _find_desktop(desktop_id)
    if path:
        try:
            in_entry = False
            for line in path.read_text().splitlines():
                s = line.strip()
                if s.startswith("["):
                    in_entry = s == "[Desktop Entry]"
                elif in_entry and s.startswith("Name=") and name == desktop_id.removesuffix(".desktop"):
                    name = s[5:].strip()
                elif in_entry and s.startswith("Icon="):
                    icon = s[5:].strip()
        except OSError:
            pass
    return App(id=desktop_id, name=name, icon=icon)


def _gio_mime(mime: str) -> tuple[str | None, list[str]]:
    env = {**os.environ, "LC_ALL": "C"}
    try:
        r = subprocess.run(["gio", "mime", mime], capture_output=True, text=True,
                           check=False, timeout=8, env=env)
    except (FileNotFoundError, subprocess.TimeoutExpired):
        return None, []
    default: str | None = None
    recommended: list[str] = []
    section = None
    for line in r.stdout.splitlines():
        if line.startswith("Default application"):
            default = line.split(":", 1)[1].strip() or None
        elif line.startswith("Recommended applications"):
            section = "rec"
        elif line.startswith("Registered applications"):
            section = "reg" if not recommended else section
        elif line.startswith("\t") or line.startswith("  "):
            app = line.strip()
            if app.endswith(".desktop") and app not in recommended and section in ("rec", "reg"):
                recommended.append(app)
    return default, recommended


def apps_for(mime: str) -> tuple[App | None, list[App]]:
    """(aktueller Default, verfügbare Apps) für einen MIME-Typ."""
    default_id, ids = _gio_mime(mime)
    apps = [_meta(i) for i in ids]
    current = _meta(default_id) if default_id else None
    return current, apps


def set_default(desktop_id: str, mime: str) -> bool:
    ok = True
    try:
        subprocess.run(["xdg-mime", "default", desktop_id, mime],
                      check=False, timeout=8)
    except (FileNotFoundError, subprocess.TimeoutExpired):
        ok = False
    if mime.startswith("x-scheme-handler/http"):
        # Browser zusätzlich als System-Default registrieren.
        try:
            subprocess.run(["xdg-settings", "set", "default-web-browser", desktop_id],
                          check=False, timeout=8)
        except (FileNotFoundError, subprocess.TimeoutExpired):
            pass
    return ok
