"""Check PyPI for newer k4s versions and notify the user.

The check result is cached in ``~/.k4s/.update-check.json`` so that
only one HTTP request is made per ``CHECK_INTERVAL_HOURS`` (default 24).
Network failures are silently ignored – this must never block the CLI.
"""

from __future__ import annotations

import json
import os
import time
from pathlib import Path
from typing import Optional

from packaging.version import Version

PACKAGE_NAME = "k4s"
PYPI_URL = f"https://pypi.org/pypi/{PACKAGE_NAME}/json"
CACHE_FILE = os.path.join(os.path.expanduser("~/.k4s"), ".update-check.json")
CHECK_INTERVAL_HOURS = 24


def _current_version() -> str:
    """Return the locally installed version string."""
    from k4s import __version__
    return __version__


def _read_cache() -> Optional[dict]:
    """Read the cached check result, or None if missing/expired."""
    try:
        data = json.loads(Path(CACHE_FILE).read_text())
        ts = data.get("checked_at", 0)
        if time.time() - ts < CHECK_INTERVAL_HOURS * 3600:
            return data
    except (FileNotFoundError, json.JSONDecodeError, KeyError, OSError):
        pass
    return None


def _write_cache(latest: str) -> None:
    """Persist the latest known version to the cache file."""
    try:
        os.makedirs(os.path.dirname(CACHE_FILE), exist_ok=True)
        Path(CACHE_FILE).write_text(
            json.dumps({"latest": latest, "checked_at": time.time()})
        )
    except OSError:
        pass


def _fetch_latest() -> Optional[str]:
    """Query PyPI for the latest stable version. Returns None on failure."""
    try:
        import urllib.request
        req = urllib.request.Request(PYPI_URL, headers={"Accept": "application/json"})
        with urllib.request.urlopen(req, timeout=3) as resp:
            data = json.loads(resp.read())
            return data.get("info", {}).get("version")
    except Exception:
        return None


def check_for_update() -> Optional[str]:
    """Return an update notice string, or None if up-to-date / unable to check.

    This function is designed to be safe to call on every CLI invocation:
    it caches results and never raises exceptions.
    """
    try:
        current = _current_version()

        cache = _read_cache()
        if cache:
            latest_str = cache.get("latest", "")
        else:
            latest_str = _fetch_latest()
            if latest_str:
                _write_cache(latest_str)

        if not latest_str:
            return None

        current_ver = Version(current)
        latest_ver = Version(latest_str)

        if latest_ver <= current_ver:
            return None

        notice = f"Update available: {current} → {latest_str}  (run: pip install --upgrade {PACKAGE_NAME})"

        if latest_ver.major > current_ver.major:
            notice += "\n⚠ This is a major update. Review the changelog before upgrading."

        return notice
    except Exception:
        return None
