"""Lightweight version checks and upgrade helpers for the CLI."""

from __future__ import annotations

import json
import shutil
import subprocess
from datetime import datetime, timedelta
from urllib.error import URLError
from urllib.request import urlopen

from superpitch import __version__
from superpitch.state import load_config, save_config

_PYPI_URL = "https://pypi.org/pypi/superpitch/json"
_CHECK_INTERVAL = timedelta(hours=12)


def _parse_version(version: str) -> tuple[int, ...]:
    return tuple(int("".join(c for c in p if c.isdigit()) or "0") for p in version.split("."))


def get_update_notice(force: bool = False) -> str | None:
    """Return the latest version string if newer than current, else None."""
    config = load_config()
    now = datetime.now()

    if not force:
        last = (config.get("last_update_check_at") or "").strip()
        if last:
            try:
                if now - datetime.fromisoformat(last) < _CHECK_INTERVAL:
                    cached = (config.get("latest_version_available") or "").strip()
                    if cached and _parse_version(cached) > _parse_version(__version__):
                        return cached
                    return None
            except ValueError:
                pass

    try:
        with urlopen(_PYPI_URL, timeout=1.5) as resp:
            latest = str((json.load(resp).get("info") or {}).get("version") or "").strip()
    except (URLError, TimeoutError, json.JSONDecodeError, OSError):
        latest = ""

    config["last_update_check_at"] = now.isoformat()
    if latest:
        config["latest_version_available"] = latest
    save_config(config)

    if latest and _parse_version(latest) > _parse_version(__version__):
        return latest
    return None


def run_upgrade() -> tuple[bool, str]:
    uv = shutil.which("uv")
    if not uv:
        return False, "uv is not installed. Install it: curl -LsSf https://astral.sh/uv/install.sh | sh"

    try:
        result = subprocess.run([uv, "tool", "upgrade", "superpitch"], capture_output=True, text=True, check=False)
    except OSError as exc:
        return False, str(exc)

    output = "\n".join(p.strip() for p in [result.stdout, result.stderr] if p.strip()).strip()
    if result.returncode == 0:
        return True, output or "Superpitch upgraded."
    return False, output or "Upgrade failed."
