"""Version drift detection for heartbeat monitoring."""

from __future__ import annotations

import logging
import subprocess
import sys
from pathlib import Path

logger = logging.getLogger("health-heartbeat")


def detect_hotfix_files(site_pkg: Path) -> list[str]:
    """Detect .py files scp'd to site-packages after wheel install.

    Compares mtime of .py files in the opendeviationbar package against
    the dist-info METADATA (written at wheel install time). Files with
    mtime > METADATA mtime were patched post-install (hotfix).

    Returns list of relative file paths that were hotfixed, empty if none.
    """
    dist_info = list(site_pkg.glob("opendeviationbar-*.dist-info"))
    if not dist_info:
        return []
    metadata = dist_info[0] / "METADATA"
    if not metadata.exists():
        return []

    install_mtime = metadata.stat().st_mtime
    pkg_dir = site_pkg / "opendeviationbar"
    if not pkg_dir.is_dir():
        return []

    # Compare .py files — 60s tolerance for filesystem jitter
    hotfixed = []
    for py_file in pkg_dir.rglob("*.py"):
        if py_file.stat().st_mtime > install_mtime + 60:
            hotfixed.append(str(py_file.relative_to(pkg_dir)))
    return sorted(hotfixed)


def check_version_drift(results: dict[str, bool | str]) -> None:
    """Check if installed version matches latest GitHub release tag.

    Uses `gh` CLI for authenticated access to private repo.
    On probe failure, reports the failure to Telegram (never silently skips).
    Issue #250: prevents stale binary deployment from going undetected.
    """
    # Detect editable install shadowing (the recurring root cause).
    site_pkg = (
        Path(sys.prefix)
        / "lib"
        / f"python{sys.version_info.major}.{sys.version_info.minor}"
        / "site-packages"
    )
    pth_file = site_pkg / "opendeviationbar.pth"
    if pth_file.exists():
        import json as _json

        def _is_non_editable_wheel(dist_info: Path) -> bool:
            if not (dist_info / "WHEEL").exists():
                return False
            du = dist_info / "direct_url.json"
            if du.exists():
                try:
                    info = _json.loads(du.read_text())
                    if info.get("dir_info", {}).get("editable"):
                        return False  # editable install
                except Exception:
                    pass
            return True

        wheel_dist_infos = list(site_pkg.glob("opendeviationbar-*.dist-info"))
        wheel_present = any(_is_non_editable_wheel(d) for d in wheel_dist_infos)
        if wheel_present:
            try:
                pth_file.unlink()
                logger.info(
                    "auto-heal: removed editable .pth at %s (wheel is active now)",
                    pth_file,
                )
                results["auto_healed_pth"] = str(pth_file)
            except OSError as e:
                logger.warning("auto-heal: failed to remove .pth: %s", e)
                results["version_drift"] = False
                results["version_drift_detail"] = (
                    f"editable .pth shadowing wheel (auto-heal failed: {e})! "
                    "Fix: uv pip uninstall opendeviationbar && "
                    "uv pip install opendeviationbar=={version}"
                )
                return
        else:
            results["version_drift"] = False
            results["version_drift_detail"] = (
                "editable .pth shadowing wheel (no wheel dist-info found)! "
                "Fix: uv pip uninstall opendeviationbar && "
                "uv pip install opendeviationbar=={version}"
            )
            return

    # Get installed version
    try:
        from opendeviationbar import __version__ as installed

        results["version_installed"] = installed
    except ImportError:
        results["version_drift"] = False
        results["version_drift_detail"] = "opendeviationbar not importable"
        return

    # Get latest GitHub release tag via gh CLI (authenticated for private repo)
    try:
        r = subprocess.run(
            [
                "gh",
                "api",
                "repos/terrylica/opendeviationbar-py/releases/latest",
                "--jq",
                ".tag_name",
            ],
            capture_output=True,
            text=True,
            timeout=10,
            check=False,
        )
        if r.returncode != 0:
            stderr = r.stderr.strip()[:120]
            results["version_drift"] = False
            results["version_drift_detail"] = f"gh probe failed: {stderr}"
            return

        gh_tag = r.stdout.strip().lstrip("v")  # "v13.1.0" → "13.1.0"
        if not gh_tag:
            results["version_drift"] = False
            results["version_drift_detail"] = "empty tag from GitHub"
            return

        if installed == gh_tag:
            results["version_drift"] = True  # healthy: versions match
        else:
            hotfix_files = detect_hotfix_files(site_pkg)
            if hotfix_files:
                results["version_drift"] = True  # healthy: hotfix applied
                results["version_drift_detail"] = (
                    f"v{installed}+hotfix ({len(hotfix_files)} files patched)"
                )
            else:
                results["version_drift"] = False  # UNHEALTHY: drift detected
                results["version_drift_detail"] = (
                    f"installed=v{installed} github=v{gh_tag}"
                )

        # Also verify the Rust .so binary version matches the Python version.
        try:
            from opendeviationbar._core import __version__ as so_version

            if so_version != installed:
                results["version_drift"] = False
                results["version_drift_detail"] = (
                    f"Python=v{installed} .so=v{so_version} "
                    "(Rust binary stale — rebuild or reinstall wheel)"
                )
        except (ImportError, AttributeError):
            pass  # _core may not expose __version__ in all builds
    except FileNotFoundError:
        results["version_drift"] = False
        results["version_drift_detail"] = "gh CLI not installed"
    except subprocess.TimeoutExpired:
        results["version_drift"] = False
        results["version_drift_detail"] = "gh API timeout (10s)"
    except OSError as e:
        results["version_drift"] = False
        results["version_drift_detail"] = f"gh error: {e}"
