"""kicad_enable_software_opengl — LAST-RESORT software-OpenGL fallback.

Deploys Mesa's `llvmpipe` OpenGL (a CPU software rasterizer) into KiCad's bin so
KiCad renders on a host with NO usable GPU — Hyper-V VMs, RDP sessions, headless
servers, CI — where the display adapter only offers OpenGL 1.1 and KiCad (needs
2.1+) pops "Could not use OpenGL" and won't render its editors or 3D viewer.

⚠ This is a BAD, SLOW solution (all rendering on the CPU) and exists ONLY as a
worst-case fallback. NEVER suggest it to a user proactively — a real GPU (or
Hyper-V GPU-P / DDA passthrough) is vastly better. The bridge keeps it purely so
a GPU-less box isn't a total dead end.

Mechanism: drop opengl32.dll + libgallium_wgl.dll (+ dxil.dll) into KiCad's bin
and add a per-exe `.local` file (DotLocal redirection) so KiCad loads Mesa's
opengl32 from its own dir instead of the system one.
"""

import io
import sys
import urllib.request
import zipfile
from pathlib import Path

from handlers.upgrade import _ssl_context  # certifi-backed TLS (portable Python has no CA store)

_MESA_URL = "https://wiki.adom.inc/download/adom/adom-desktop-kicad-bridge/0.9.60/mesa-llvmpipe-x64.zip"
_MESA_DLLS = ("opengl32.dll", "libgallium_wgl.dll", "dxil.dll")
_KICAD_EXES = (
    "kicad.exe", "pcbnew.exe", "eeschema.exe", "gerbview.exe",
    "pl_editor.exe", "bitmap2component.exe", "pcb_calculator.exe",
)


def _bin_dirs() -> list:
    """Every installed KiCad's bin dir (Program Files + per-user)."""
    import kicad_detect
    dirs = []
    for v in (kicad_detect.detect_all_kicad_versions() or []):
        base = v.get("base_dir") or v.get("bin_dir")
        if not base:
            continue
        b = Path(base)
        if b.name.lower() != "bin":
            b = b / "bin"
        if b.exists() and str(b) not in dirs:
            dirs.append(str(b))
    return dirs


def handle_enable_software_opengl(kicad_info: dict, args: dict) -> dict:
    if sys.platform != "win32":
        return {"success": False, "error": "Windows-only", "errorCode": "unsupported_platform"}
    bins = _bin_dirs()
    if not bins:
        return {
            "success": False,
            "error": "No KiCad bin dir found — is KiCad installed?",
            "errorCode": "host_app_not_installed",
            "errorCodeLegacy": "kicad_not_installed",
            "hostApp": "KiCad",
            "_hint": "Run kicad_list_versions. Install KiCad first via kicad_upgrade.",
        }
    print(f"[KiCad Bridge] enable_software_opengl: downloading Mesa llvmpipe...", flush=True)
    try:
        req = urllib.request.Request(_MESA_URL, headers={"User-Agent": "adom-desktop-kicad-bridge"})
        with urllib.request.urlopen(req, timeout=180, context=_ssl_context()) as r:
            data = r.read()
        zf = zipfile.ZipFile(io.BytesIO(data))
    except Exception as e:
        print(f"[KiCad Bridge] enable_software_opengl: FAILED {e}", flush=True)
        return {"success": False, "error": f"Mesa download/unzip failed: {e}", "errorCode": "download_failed"}

    enabled, errors = [], []
    for bd in bins:
        try:
            for dll in _MESA_DLLS:
                zf.extract(dll, bd)
            for exe in _KICAD_EXES:  # DotLocal redirection: empty <exe>.local
                if (Path(bd) / exe).exists():
                    (Path(bd) / f"{exe}.local").write_text("")
            enabled.append(bd)
            print(f"[KiCad Bridge] enable_software_opengl: deployed to {bd}", flush=True)
        except PermissionError:
            errors.append(f"{bd}: permission denied (writing KiCad's bin needs elevation)")
        except Exception as e:
            errors.append(f"{bd}: {e}")

    ok = bool(enabled)
    return {
        "success": ok,
        "enabledIn": enabled,
        "errors": errors,
        "renderer": "Mesa llvmpipe (CPU software OpenGL)",
        "_hint": (
            "⚠ LAST-RESORT software-OpenGL fallback deployed — KiCad will render via Mesa llvmpipe on "
            "the CPU (SLOW). This is ONLY for a GPU-less host (Hyper-V/RDP/headless) where KiCad can't "
            "render at all; do NOT enable it on a normal machine. CLOSE and REOPEN KiCad editors to "
            "load it. To undo, delete opengl32.dll/libgallium_wgl.dll/dxil.dll and the *.local files "
            "from KiCad's bin."
            if ok else
            "Could not deploy — see errors[]. Writing KiCad's bin (Program Files) needs an elevated AD; "
            "a per-user KiCad install (kicad_upgrade scope=user) avoids that."
        ),
    }