"""Hermes Hub — Self-Healing Launcher Bootstrap and Crash Handler.

Responsibilities:
1. Dependency Verification & Self-Healing:
   Checks for required packages (customtkinter, pillow, psutil, pyyaml, requests).
   If any package is missing, attempts non-blocking silent auto-installation into the active Python environment.
2. Pre-UI Crash Logging:
   Ensures all startup lifecycle stages and any early unhandled exceptions are written to
   logs/startup.log with full traceback before GUI initialization.
3. Native User Feedback:
   If a fatal crash occurs before a window can be displayed, shows a native Windows error dialog
   pointing to the exact log file location instead of silent process termination.
"""
from __future__ import annotations

import ctypes
import datetime
import os
import subprocess
import sys
import traceback
from pathlib import Path
from typing import Dict, List, Tuple


def get_startup_log_path() -> Path:
    """Resolve startup.log path safely without external dependencies."""
    try:
        from antigravity_provider import paths
        return paths.get_startup_log_file()
    except Exception:
        local_app = os.environ.get("LOCALAPPDATA", "")
        base = Path(local_app) / "hermes" if local_app else Path.home() / ".hermes"
        return base / "logs" / "startup.log"


def log_startup(msg: str) -> None:
    """Append a timestamped log entry to startup.log."""
    try:
        p = get_startup_log_path()
        p.parent.mkdir(parents=True, exist_ok=True)
        ts = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        with open(p, "a", encoding="utf-8") as f:
            f.write(f"[{ts}] {msg}\n")
    except Exception:
        pass


def show_native_error(title: str, message: str) -> None:
    """Display a native Windows error modal (or fallback to stderr on POSIX)."""
    if sys.platform == "win32":
        try:
            MB_ICONERROR = 0x10
            MB_OK = 0x0
            ctypes.windll.user32.MessageBoxW(0, message, title, MB_ICONERROR | MB_OK)
            return
        except Exception:
            pass
    print(f"[{title}] {message}", file=sys.stderr)


REQUIRED_PACKAGES: Dict[str, str] = {
    "customtkinter": "customtkinter>=6.0.0",
    "PIL": "pillow>=10.0.0",
    "psutil": "psutil>=5.9.0",
    "yaml": "pyyaml>=6.0.1",
}


def check_missing_dependencies() -> List[str]:
    """Check which required UI / system packages are currently unimportable."""
    missing = []
    for mod_name, pkg_spec in REQUIRED_PACKAGES.items():
        try:
            __import__(mod_name)
        except ImportError:
            missing.append(pkg_spec)
    return missing


def self_heal_dependencies(missing_packages: List[str]) -> Tuple[bool, str]:
    """Attempt pip install for missing packages in the current Python executable environment."""
    if not missing_packages:
        return True, "All dependencies present"

    log_startup(f"Missing dependencies detected: {missing_packages}. Starting self-healing...")
    try:
        cmd = [
            sys.executable,
            "-m",
            "pip",
            "install",
            "--no-warn-script-location",
        ] + missing_packages

        res = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=90,
        )
        if res.returncode == 0:
            log_startup("Self-healing successful. Re-verifying package imports...")
            still_missing = check_missing_dependencies()
            if not still_missing:
                log_startup("All packages verified after self-healing.")
                return True, "Self-healing completed successfully"
            else:
                err = f"Packages still missing after install: {still_missing}"
                log_startup(err)
                return False, err
        else:
            err = f"pip install exited with code {res.returncode}: {res.stderr.strip()}"
            log_startup(err)
            return False, err
    except Exception as exc:
        err = f"Self-healing exception: {type(exc).__name__}: {exc}"
        log_startup(err)
        return False, err


def bootstrap_and_launch() -> None:
    """Bootstrap entry point: log startup, verify dependencies, and launch Hermes Hub GUI."""
    log_startup("=== Hermes Hub Launcher Bootstrap initiated ===")
    log_startup(f"Python: {sys.executable} (version {sys.version.split()[0]})")
    log_startup(f"Working Directory: {os.getcwd()}")

    # 1. Dependency verification & self-healing
    missing = check_missing_dependencies()
    if missing:
        log_startup(f"Pre-flight dependency check: missing {missing}")
        ok, detail = self_heal_dependencies(missing)
        if not ok:
            log_path = get_startup_log_path()
            show_native_error(
                "Hermes Hub — Ошибка компонентов",
                "Не удалось автоматически установить необходимые компоненты графического интерфейса (customtkinter / Pillow / psutil).\n\n"
                f"Детали ошибки: {detail}\n\n"
                f"Лог запуска: {log_path}\n\n"
                "Вы можете установить их вручную командой:\n"
                f"{sys.executable} -m pip install customtkinter pillow psutil pyyaml",
            )
            sys.exit(1)

    # 2. Launch GUI with full exception capture
    try:
        log_startup("Importing hermes_hub_app module...")
        from antigravity_provider.router.hermes_hub_app import launch_hub

        log_startup("Executing launch_hub()...")
        launch_hub()
        log_startup("Hermes Hub GUI closed normally.")
    except Exception as exc:
        tb = traceback.format_exc()
        log_startup(f"FATAL EXCEPTION during launch:\n{tb}")
        log_path = get_startup_log_path()
        show_native_error(
            "Hermes Hub — Критическая ошибка при запуске",
            f"Произошла ошибка при запуске интерфейса Hermes Hub:\n\n{exc}\n\n"
            f"Полный текст ошибки записан в лог:\n{log_path}",
        )
        sys.exit(1)


if __name__ == "__main__":
    bootstrap_and_launch()
