"""Install/update the Linux .desktop entry for taskbar and window icons."""

from __future__ import annotations

import os
import subprocess
import sys
from pathlib import Path

from util.paths import ICON_PATH, PROJECT_ROOT

DESKTOP_ID = "DazedMTLTool"
LAUNCH_SCRIPT = PROJECT_ROOT / "scripts" / "launch.sh"

# Qt logs this on Wayland whenever a dialog tries to steal focus (harmless noise).
_WAYLAND_ACTIVATE_WARNING = "Wayland does not support QWindow::requestActivate()"


def _append_qt_logging_rule(rule: str) -> None:
    category = rule.split("=", 1)[0]
    existing = os.environ.get("QT_LOGGING_RULES", "")
    if category in existing:
        return
    os.environ["QT_LOGGING_RULES"] = f"{existing};{rule}" if existing else rule


def configure_qt_platform() -> None:
    """Apply Linux/Qt environment tweaks before constructing QApplication."""
    if not sys.platform.startswith("linux"):
        return
    _append_qt_logging_rule("qt.qpa.wayland=false")


def install_qt_message_filter() -> None:
    """Drop the noisy Wayland requestActivate warning (QT rules miss some builds)."""
    if not sys.platform.startswith("linux"):
        return
    try:
        from PyQt5.QtCore import QtMsgType, qInstallMessageHandler
    except ImportError:
        return

    def _handler(mode, _context, message):
        if _WAYLAND_ACTIVATE_WARNING in message:
            return
        if mode in (QtMsgType.QtWarningMsg, QtMsgType.QtCriticalMsg, QtMsgType.QtFatalMsg):
            print(message, file=sys.stderr)

    qInstallMessageHandler(_handler)


def installed_desktop_path() -> Path:
    data_home = os.environ.get("XDG_DATA_HOME", "")
    if data_home:
        base = Path(data_home)
    else:
        base = Path.home() / ".local" / "share"
    return base / "applications" / f"{DESKTOP_ID}.desktop"


def _desktop_content(root: Path, icon: Path, launch: Path) -> str:
    return (
        "[Desktop Entry]\n"
        "Type=Application\n"
        f"Name={DESKTOP_ID}\n"
        "GenericName=Translation Tool\n"
        "Comment=AI translation tool for visual novels and RPG games\n"
        f"Exec={launch}\n"
        f"Icon={icon}\n"
        f"Path={root}\n"
        "Terminal=false\n"
        "Categories=Development;Utility;\n"
        f"StartupWMClass={DESKTOP_ID}\n"
    )


def ensure_linux_desktop_entry() -> None:
    """Write ~/.local/share/applications/DazedMTLTool.desktop with absolute paths."""
    if not sys.platform.startswith("linux"):
        return
    if not LAUNCH_SCRIPT.is_file() or not ICON_PATH.is_file():
        return

    desktop_path = installed_desktop_path()
    content = _desktop_content(PROJECT_ROOT, ICON_PATH, LAUNCH_SCRIPT)

    try:
        if desktop_path.is_file() and desktop_path.read_text(encoding="utf-8") == content:
            return
        desktop_path.parent.mkdir(parents=True, exist_ok=True)
        desktop_path.write_text(content, encoding="utf-8")
        desktop_path.chmod(0o755)
    except OSError as exc:
        print(f"Warning: could not install Linux desktop entry ({exc})")
        return

    _refresh_desktop_database(desktop_path.parent)


def _refresh_desktop_database(applications_dir: Path) -> None:
    for cmd in (
        ["update-desktop-database", str(applications_dir)],
        ["kbuildsycoca5", "--noincremental"],
    ):
        try:
            subprocess.run(cmd, check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        except OSError:
            pass
