"""Check for updates from GitHub releases.

Queries the public GitHub API for the latest release of
``thebotclub/tribunal`` and compares it with the running version.
"""

from __future__ import annotations

import json
import sys
import urllib.error
import urllib.request
from typing import Any

from launcher import __version__

GITHUB_RELEASES_URL = "https://api.github.com/repos/thebotclub/tribunal/releases/latest"

REQUEST_TIMEOUT_SECONDS = 10


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def _parse_version(version_str: str) -> tuple[int, ...]:
    """Parse a version string like ``'v6.5.3'`` into a comparable tuple."""
    cleaned = version_str.lstrip("vV").strip()
    parts: list[int] = []
    for segment in cleaned.split("."):
        try:
            parts.append(int(segment))
        except ValueError:
            break
    return tuple(parts)


def _gh_token() -> str:
    """Try to get a GitHub token via the gh CLI for private repo access."""
    import shutil
    import subprocess
    if shutil.which("gh"):
        try:
            result = subprocess.run(
                ["gh", "auth", "token"],
                capture_output=True, text=True, timeout=5
            )
            token = result.stdout.strip()
            if token:
                return token
        except Exception:
            pass
    return ""


def _fetch_latest_release() -> dict[str, Any] | None:
    """Fetch the latest release metadata from GitHub.

    Returns ``None`` on network errors so the caller can degrade gracefully.
    """
    headers: dict[str, str] = {"Accept": "application/vnd.github+json", "User-Agent": "TribunalCode"}
    token = _gh_token()
    if token:
        headers["Authorization"] = f"Bearer {token}"
    req = urllib.request.Request(GITHUB_RELEASES_URL, headers=headers)
    try:
        with urllib.request.urlopen(req, timeout=REQUEST_TIMEOUT_SECONDS) as resp:
            data: dict[str, Any] = json.loads(resp.read().decode("utf-8"))
            return data
    except (urllib.error.URLError, urllib.error.HTTPError, OSError, json.JSONDecodeError):
        return None


# ---------------------------------------------------------------------------
# Public API
# ---------------------------------------------------------------------------


def check_for_updates(*, quiet: bool = False) -> bool:
    """Check GitHub for a newer release and inform the user.

    Parameters
    ----------
    quiet:
        When *True*, suppress all output and just return whether an update is
        available.

    Returns
    -------
    bool
        ``True`` if a newer version is available, ``False`` otherwise.
    """
    if not quiet:
        print(f"Current version: v{__version__}")
        print("Checking for updates...")

    release = _fetch_latest_release()
    if release is None:
        if not quiet:
            print("Could not reach GitHub. Please check your connection and try again.")
        return False

    tag: str = release.get("tag_name", "")
    latest = _parse_version(tag)
    current = _parse_version(__version__)

    if not latest:
        if not quiet:
            print("Could not determine the latest version.")
        return False

    if latest > current:
        if not quiet:
            html_url = release.get("html_url", GITHUB_RELEASES_URL)
            print(f"\nA new version is available: {tag}")
            print(f"Release page: {html_url}")
            print("\nTo update, run:")
            print("  pip install --upgrade tribunal")
            print("or download the latest release from the link above.")
        return True

    if not quiet:
        print(f"You are on the latest version (v{__version__}).")
    return False


if __name__ == "__main__":
    has_update = check_for_updates()
    sys.exit(0 if not has_update else 1)
