#!/usr/bin/env python3
"""
Check CloudSmith for the latest cyborgdb-core version and determine if it's newer than baseline.

Usage:
    python check_cloudsmith_version.py

Environment variables:
    PIP_EXTRA_INDEX_URL: CloudSmith PyPI URL for the dev repository
    LAST_TESTED_CORE_VERSION: (optional) The last successfully-built core version,
        typically set from the GitHub Actions cache. Falls back to "0.15.0" if not set.

Outputs (via GITHUB_OUTPUT):
    new_core: true/false - whether a newer core version exists than the baseline
    core_version: the latest version string
    version_date: the date portion of the dev version (YYYYMMDD)
"""

import os
import re
import subprocess
import sys
from packaging.version import Version, InvalidVersion

# Default baseline version - used when no cached version is available
DEFAULT_BASELINE_VERSION = "0.15.0.dev0"

# Read baseline from env (set by GitHub Actions cache), fall back to default
_cached = os.environ.get("LAST_TESTED_CORE_VERSION", "").strip()
if _cached:
    BASELINE_VERSION = _cached
    _BASELINE_SOURCE = "cache"
else:
    BASELINE_VERSION = DEFAULT_BASELINE_VERSION
    _BASELINE_SOURCE = "default"


def get_latest_version(extra_index_url: str) -> str | None:
    """Query pip for the latest available version of cyborgdb-core."""
    try:
        result = subprocess.run(
            [
                sys.executable,
                "-m",
                "pip",
                "index",
                "versions",
                "cyborgdb-core",
                "--extra-index-url",
                extra_index_url,
            ],
            capture_output=True,
            text=True,
            timeout=60,
        )

        output = result.stdout + result.stderr

        # Parse "Available versions: X.X.X, Y.Y.Y, ..."
        match = re.search(r"Available versions:\s*([^\n]+)", output)
        if match:
            versions = match.group(1).split(",")
            if versions:
                return versions[0].strip()

        # Alternative parsing for different pip output formats
        match = re.search(r"cyborgdb-core \(([^)]+)\)", output)
        if match:
            return match.group(1)

        print(f"Could not parse version from output: {output}", file=sys.stderr)
        return None

    except subprocess.TimeoutExpired:
        print("Timeout querying pip index", file=sys.stderr)
        return None
    except Exception as e:
        print(f"Error querying pip: {e}", file=sys.stderr)
        return None


def extract_date_from_version(version: str) -> str | None:
    """
    Extract date from dev version string.

    Examples:
        0.15.0.dev20251211T142206 -> 20251211
        0.15.0.dev2025.12.11 -> 20251211
        0.15.0 -> None (not a dev version)
    """
    # Pattern for dev versions with timestamp: X.X.X.devYYYYMMDDTHHMMSS
    match = re.search(r"\.dev(\d{8})", version)
    if match:
        return match.group(1)

    # Pattern for dev versions with dotted date: X.X.X.devYYYY.MM.DD
    match = re.search(r"\.dev(\d{4})\.(\d{2})\.(\d{2})", version)
    if match:
        return f"{match.group(1)}{match.group(2)}{match.group(3)}"

    return None


def write_github_output(key: str, value: str) -> None:
    """Write a key-value pair to GITHUB_OUTPUT."""
    github_output = os.environ.get("GITHUB_OUTPUT")
    if github_output:
        with open(github_output, "a") as f:
            f.write(f"{key}={value}\n")
    else:
        # For local testing, just print
        print(f"{key}={value}")


def is_newer_than_baseline(version_str: str) -> bool:
    """Check if the given version is newer than the baseline version."""
    try:
        current = Version(version_str)
        baseline = Version(BASELINE_VERSION)
        return current > baseline
    except InvalidVersion as e:
        print(f"Warning: Could not parse version '{version_str}': {e}")
        return False


def main() -> int:
    extra_index_url = os.environ.get("PIP_EXTRA_INDEX_URL")
    if not extra_index_url:
        print("Error: PIP_EXTRA_INDEX_URL environment variable is required")
        return 1

    print("Checking CloudSmith for latest cyborgdb-core version...")
    print(f"Baseline version: {BASELINE_VERSION} (source: {_BASELINE_SOURCE})")

    latest_version = get_latest_version(extra_index_url)
    if not latest_version:
        print("Failed to get latest version")
        write_github_output("new_core", "false")
        write_github_output("core_version", "")
        write_github_output("version_date", "")
        return 1

    print(f"Latest version: {latest_version}")
    write_github_output("core_version", latest_version)

    # Check if version is newer than baseline
    is_new = is_newer_than_baseline(latest_version)
    print(f"Is newer than {BASELINE_VERSION}: {is_new}")

    # Extract date if it's a dev version (for informational purposes)
    version_date = extract_date_from_version(latest_version)
    if version_date:
        write_github_output("version_date", version_date)
        print(f"Version date: {version_date}")
    else:
        write_github_output("version_date", "")

    write_github_output("new_core", "true" if is_new else "false")

    return 0


if __name__ == "__main__":
    sys.exit(main())
