#!/usr/bin/env python3
"""Non-destructive installation check for KOPR Live beta, revision 10.12."""
from __future__ import annotations
import argparse
import importlib
import os
import shutil
import subprocess
import sys
from pathlib import Path

REQUIRED_MODULES = [
    ("PyQt5", "PyQt5"), ("matplotlib", "matplotlib"), ("numpy", "numpy"),
    ("astropy", "astropy"), ("requests", "requests"), ("jplephem", "jplephem"),
    ("ExifRead", "exifread"), ("rawpy", "rawpy"), ("scipy", "scipy"),
    ("urllib3", "urllib3"),
]


def line(level: str, message: str) -> None:
    print(f"[{level}] {message}")


def wsl_prefix(wsl: str) -> list[str]:
    prefix = [wsl]
    distro = (os.environ.get("KOPR_WSL_DISTRIBUTION") or "").strip()
    if distro:
        prefix += ["--distribution", distro]
    return prefix + ["--exec"]


def resolve_solver() -> tuple[bool, str]:
    native = shutil.which("solve-field")
    if native:
        return True, f"native solve-field ({native})"
    if os.name != "nt":
        return False, "solve-field was not found in PATH; install the Astrometry.net command-line package."
    wsl = shutil.which("wsl.exe") or shutil.which("wsl")
    if not wsl:
        return False, "neither native solve-field nor wsl.exe was found"
    try:
        proc = subprocess.run(
            wsl_prefix(wsl) + ["sh", "-lc", "command -v solve-field"],
            capture_output=True, text=True, encoding="utf-8", errors="replace",
            timeout=15, check=False,
            creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
        )
    except Exception as exc:
        return False, f"WSL probe failed: {exc}"
    lines = (proc.stdout or proc.stderr or "").strip().splitlines()
    path = lines[-1].strip() if lines else ""
    if proc.returncode == 0 and path:
        distro = (os.environ.get("KOPR_WSL_DISTRIBUTION") or "default distribution").strip()
        return True, f"WSL solve-field ({path}; {distro})"
    return False, "WSL is available, but solve-field was not found in the selected distribution"


def main() -> int:
    parser = argparse.ArgumentParser(description="Check a KOPR source installation without starting the GUI.")
    parser.add_argument("kopr_dir", nargs="?", default=".", help="directory containing kopr.py")
    args = parser.parse_args()
    root = Path(args.kopr_dir).expanduser().resolve()
    failures = 0

    if sys.version_info < (3, 10):
        line("FAIL", f"Python {sys.version.split()[0]} is too old; this source uses Python 3.10 syntax.")
        failures += 1
    else:
        line("PASS", f"Python {sys.version.split()[0]}")

    for label, module_name in REQUIRED_MODULES:
        try:
            module = importlib.import_module(module_name)
            line("PASS", f"{label}: {getattr(module, '__version__', 'version not reported')}")
        except Exception as exc:
            line("FAIL", f"{label}: {exc}")
            failures += 1

    try:
        module = importlib.import_module("astroquery")
        line("PASS", f"astroquery (optional JPL helper): {getattr(module, '__version__', 'version not reported')}")
    except Exception as exc:
        line("WARN", f"astroquery not installed; JPL Horizons helper unavailable, offline/internal ephemeris remains usable ({exc})")

    ok, detail = resolve_solver()
    line("PASS" if ok else "FAIL", f"Astrometry solver backend: {detail}")
    failures += 0 if ok else 1

    required = ["kopr.py", "datavar.py", "koprhand.py", "wstack.py", "wstack_functions.py", "wstack_common.py", "alb3.py", "data/de440s.bsp"]
    missing = [name for name in required if not (root / name).exists()]
    if missing:
        line("FAIL", "KOPR directory is incomplete or incorrect: " + ", ".join(missing)); failures += 1
    else:
        line("PASS", f"KOPR source root: {root}")

    if root.exists() and os.access(root, os.W_OK):
        line("PASS", "KOPR source root is writable (needed for first-start data and local astrometry indexes).")
    else:
        line("FAIL", "KOPR source root is not writable."); failures += 1

    family_counts = {}
    for family, pattern in (("4100", "index-41*.fits"), ("4200", "index-42*.fits")):
        index_dir = root / "astrometry-index" / family
        family_counts[family] = len(list(index_dir.glob(pattern))) if index_dir.is_dir() else 0
    if family_counts["4200"]:
        line("PASS", f"Local Astrometry.net 4200 index files found: {family_counts['4200']}")
    else:
        line("WARN", "No local 42xx indexes found. After solver preflight succeeds, WStack can download series 4206–4214.")
    if family_counts["4100"]:
        line("PASS", f"Optional Tycho-2 4100 index files found: {family_counts['4100']}")
    else:
        line("WARN", "Optional 4100 family not found; this does not block the established 4200 workflow.")

    if failures:
        line("RESULT", f"Installation check failed with {failures} required item(s) missing."); return 1
    line("RESULT", "Required installation checks passed."); return 0


if __name__ == "__main__":
    raise SystemExit(main())
