"""System diagnostics — dependency checking, capability testing, and reporting."""

import platform
import sys
import time
import json
from dataclasses import dataclass, asdict
from typing import Dict, List

from djhud import __version__
from djhud.platform import IS_WINDOWS, IS_MAC, IS_LINUX, PLATFORM


@dataclass
class DiagnosticResult:
    name: str
    status: str     # "ok", "warning", "error"
    message: str
    detail: str = ""


# ─── Import tracking ────────────────────────────────────────────────────────

_import_errors: Dict[str, str] = {}


def probe_import(name: str):
    """Try importing a module, track failures."""
    try:
        mod = __import__(name)
        return mod
    except ImportError as e:
        _import_errors[name] = str(e)
        return None


def get_import_errors() -> Dict[str, str]:
    return dict(_import_errors)


# ═══════════════════════════════════════════════════════════════════════════════
# DIAGNOSTICS ENGINE
# ═══════════════════════════════════════════════════════════════════════════════

class SystemDiagnostics:
    """Checks all dependencies and platform capabilities."""

    REQUIRED_DEPS = {
        "tkinter": "GUI framework (built-in with Python)",
        "numpy": "Array processing for video frames",
        "PIL": "Image processing (Pillow)",
        "mss": "Screen capture",
        "cv2": "Webcam capture and image processing (opencv-python)",
        "pyvirtualcam": "Virtual camera output",
    }

    OPTIONAL_DEPS = {"pyvirtualcam"}

    INSTALL_HINTS = {
        "numpy": "pip install numpy",
        "PIL": "pip install Pillow",
        "mss": "pip install mss",
        "cv2": "pip install opencv-python",
        "pyvirtualcam": "pip install pyvirtualcam  (+ OBS Virtual Camera driver on Windows)",
    }

    def __init__(self):
        self.results: List[DiagnosticResult] = []

    def run_all(self) -> List[DiagnosticResult]:
        self.results = []
        self._check_platform()
        self._check_python_version()
        self._check_dependencies()
        self._check_screen_capture()
        self._check_macos_permissions()
        self._check_webcam()
        self._check_virtual_camera()
        return self.results

    def _add(self, name: str, status: str, message: str, detail: str = ""):
        self.results.append(DiagnosticResult(name, status, message, detail))

    def _check_platform(self):
        info = f"{platform.system()} {platform.release()} ({platform.machine()})"
        if IS_WINDOWS:
            self._add("Platform", "ok", f"Windows — {info}", "Full support")
        elif IS_MAC:
            self._add("Platform", "ok", f"macOS — {info}",
                       "Screen capture via mss. Window capture requires pyobjc.")
        elif IS_LINUX:
            self._add("Platform", "ok", f"Linux — {info}",
                       "Screen capture via mss. Window listing requires wmctrl.")
        else:
            self._add("Platform", "warning", f"Unknown: {info}", "Some features may not work")

    def _check_python_version(self):
        ver = sys.version.split()[0]
        major, minor = sys.version_info[:2]
        if major >= 3 and minor >= 9:
            self._add("Python", "ok", f"Python {ver}", "")
        elif major >= 3 and minor >= 7:
            self._add("Python", "warning", f"Python {ver}", "Python 3.9+ recommended")
        else:
            self._add("Python", "error", f"Python {ver}", "Python 3.9+ required")

    def _check_dependencies(self):
        for mod_name, description in self.REQUIRED_DEPS.items():
            if mod_name == "tkinter":
                self._add(f"Dep: tkinter", "ok", "tkinter available", description)
                continue
            if mod_name in _import_errors:
                is_optional = mod_name in self.OPTIONAL_DEPS
                status = "warning" if is_optional else "error"
                hint = self.INSTALL_HINTS.get(mod_name, f"pip install {mod_name}")
                self._add(f"Dep: {mod_name}", status, f"{mod_name} not found",
                          f"{description}. Install: {hint}")
            else:
                version = self._get_version(mod_name)
                ver_str = f" v{version}" if version else ""
                self._add(f"Dep: {mod_name}", "ok", f"{mod_name}{ver_str}", description)

    def _get_version(self, mod_name: str) -> str:
        try:
            if mod_name == "PIL":
                import PIL
                return getattr(PIL, "__version__", "")
            mod = sys.modules.get(mod_name)
            if mod:
                return getattr(mod, "__version__", getattr(mod, "VERSION", ""))
        except Exception:
            pass
        return ""

    def _check_screen_capture(self):
        try:
            import mss as _mss
            sct = _mss.mss()
            monitors = sct.monitors
            count = len(monitors) - 1
            if count > 0:
                details = "; ".join(
                    f'Monitor {i}: {m["width"]}x{m["height"]}'
                    for i, m in enumerate(monitors[1:], 1)
                )
                self._add("Screen capture", "ok", f"{count} monitor(s) detected", details)
            else:
                self._add("Screen capture", "warning", "No monitors detected via mss", "")
        except ImportError:
            self._add("Screen capture", "error", "mss not available", "pip install mss")
        except Exception as e:
            self._add("Screen capture", "error", f"Screen capture failed: {e}", "")

    def _check_macos_permissions(self):
        if not IS_MAC:
            return
        from djhud.platform import check_macos_screen_permission
        result = check_macos_screen_permission()
        if result is True:
            self._add("macOS permissions", "ok", "Screen capture permission granted", "")
        elif result is False:
            self._add("macOS permissions", "error",
                       "Screen capture permission denied",
                       "Open System Settings → Privacy & Security → Screen Recording → "
                       "enable your terminal app. Then restart DJ HUD.")
        else:
            self._add("macOS permissions", "warning",
                       "Could not check screen capture permission",
                       "Install pyobjc-framework-Quartz for permission detection: "
                       "pip install djhud[mac]")

    def _check_webcam(self):
        try:
            import cv2
        except ImportError:
            self._add("Webcam", "warning", "OpenCV not available", "Webcam capture disabled")
            return
        try:
            cap = cv2.VideoCapture(0)
            if cap is not None and cap.isOpened():
                ok, frame = cap.read()
                if ok and frame is not None:
                    h, w = frame.shape[:2]
                    self._add("Webcam", "ok", f"Default webcam works ({w}x{h})", "")
                else:
                    self._add("Webcam", "warning", "Webcam opened but no frame", "Camera may be in use")
                cap.release()
            else:
                self._add("Webcam", "warning", "No webcam at index 0", "Connect a webcam or select another device")
        except Exception as e:
            self._add("Webcam", "warning", f"Webcam check failed: {e}", "")

    def _check_virtual_camera(self):
        try:
            import pyvirtualcam
            self._add("Virtual camera", "ok", "pyvirtualcam available",
                       f"Version: {getattr(pyvirtualcam, '__version__', 'unknown')}")
        except ImportError:
            hint = "pip install djhud[virtualcam]"
            if IS_WINDOWS:
                hint += " (also install OBS Virtual Camera driver)"
            self._add("Virtual camera", "warning", "pyvirtualcam not installed", hint)

    def to_dict(self) -> dict:
        return {
            "app_version": __version__,
            "platform": PLATFORM,
            "python": sys.version,
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
            "results": [asdict(r) for r in self.results],
        }

    def to_json(self) -> str:
        return json.dumps(self.to_dict(), indent=2)
