"""Resolve desktop app icon paths and scan installed applications."""
from pathlib import Path
from typing import Optional
import configparser

_HOME = Path.home()

ICON_SEARCH_DIRS = [
    _HOME / ".local/share/icons",
    Path("/usr/share/icons"),
    Path("/usr/share/pixmaps"),
    Path("/usr/local/share/icons"),
]

_THEME_ORDER = ["hicolor", "Papirus-Dark", "Papirus", "gnome", "Adwaita", "breeze"]
_ICON_EXTS = [".png", ".svg", ".xpm"]

DESKTOP_DIRS = [
    _HOME / ".local/share/applications",
    Path("/usr/local/share/applications"),
    Path("/usr/share/applications"),
]

_NEXUS_ICONS = _HOME / ".icons" / "NexusOS"


def _icon_stem(icon_name: str) -> str:
    """Return the icon's name for theme lookup.

    Only strips a real image extension (.png/.svg/.xpm). Reverse-DNS icon
    names like ``com.visualstudio.code`` or ``org.gnome.Files`` must be kept
    intact — Path.stem would wrongly treat the final dotted segment as an
    extension and truncate it.
    """
    p = Path(icon_name)
    if p.suffix.lower() in _ICON_EXTS:
        return p.stem
    return p.name


def resolve_icon(icon_name: str, size: int = 128) -> Optional[str]:
    """Return absolute path to an icon file, or None if not found."""
    if not icon_name:
        return None

    # Absolute path — use directly if it exists
    p = Path(icon_name)
    if p.is_absolute() and p.exists():
        return str(p)

    # Strip extension for name-based search
    stem = _icon_stem(icon_name)

    size_dirs = [f"{size}x{size}", f"{size}x{size}@2x", "scalable"]

    for search_root in ICON_SEARCH_DIRS:
        if not search_root.is_dir():
            continue
        for theme in _THEME_ORDER:
            theme_dir = search_root / theme
            if not theme_dir.is_dir():
                continue
            for size_dir in size_dirs:
                for ctx in ("apps", "categories", "places", "status", "actions"):
                    ctx_dir = theme_dir / size_dir / ctx
                    if not ctx_dir.is_dir():
                        continue
                    for ext in _ICON_EXTS:
                        candidate = ctx_dir / f"{stem}{ext}"
                        if candidate.exists():
                            return str(candidate)

    # pixmaps fallback
    for search_root in ICON_SEARCH_DIRS:
        if not search_root.is_dir():
            continue
        if search_root.name == "pixmaps":
            for ext in _ICON_EXTS:
                candidate = search_root / f"{stem}{ext}"
                if candidate.exists():
                    return str(candidate)

    for ext in _ICON_EXTS:
        candidate = Path("/usr/share/pixmaps") / f"{stem}{ext}"
        if candidate.exists():
            return str(candidate)

    return None


def _is_branded(icon_name: str) -> bool:
    """Return True if a NexusOS-branded PNG already exists for this icon name."""
    stem = _icon_stem(icon_name)
    return (_NEXUS_ICONS / "128x128" / "apps" / f"{stem}.png").exists()


def scan_apps() -> list[dict]:
    """Return list of installed apps with resolved icon paths."""
    seen: dict[str, dict] = {}

    for desktop_dir in DESKTOP_DIRS:
        if not desktop_dir.is_dir():
            continue
        for desktop_file in sorted(desktop_dir.glob("*.desktop")):
            cfg = configparser.ConfigParser(interpolation=None, strict=False)
            try:
                cfg.read(str(desktop_file), encoding="utf-8")
            except Exception:
                continue

            if not cfg.has_section("Desktop Entry"):
                continue
            de = cfg["Desktop Entry"]

            if de.get("NoDisplay", "false").lower() == "true":
                continue
            if de.get("Hidden", "false").lower() == "true":
                continue
            if de.get("Type", "") != "Application":
                continue

            name = de.get("Name", desktop_file.stem)
            icon_name = de.get("Icon", "")
            if not icon_name:
                continue

            icon_path = resolve_icon(icon_name)
            already_branded = _is_branded(icon_name)

            key = name.lower()
            if key not in seen:
                seen[key] = {
                    "name": name,
                    "icon_name": _icon_stem(icon_name),
                    "icon_path": icon_path,
                    "already_branded": already_branded,
                    "desktop_file": str(desktop_file),
                }

    return sorted(seen.values(), key=lambda x: x["name"].lower())
