"""CLI self-update — installer detection, PyPI version check, upgrade."""

from __future__ import annotations

import subprocess
import sys
from enum import StrEnum
from pathlib import Path


class Installer(StrEnum):
    """How ievo was installed — determines the upgrade strategy.

    UVX:     ephemeral (``uvx ievo``), no persistent install to upgrade.
    UV_TOOL: persistent (``uv tool install ievo``), upgraded via ``uv tool upgrade``.
    PIP:     classic pip install, upgraded via ``pip install --upgrade``.
    """

    UVX = "uvx"
    UV_TOOL = "uv tool"
    PIP = "pip"


def detect_installer() -> Installer:
    """Detect how ievo was installed by inspecting ``sys.argv[0]``.

    Heuristic based on resolved path:
    - Contains ``.cache/uv/`` or ``uvx`` → UVX (ephemeral cache run)
    - Contains ``.local/share/uv/tools/ievo/`` → UV_TOOL (persistent)
    - Everything else → PIP (fallback)

    Returns PIP on any path-resolution error as the safest default.
    """
    try:
        argv0 = sys.argv[0] if sys.argv else ""
        path = str(Path(argv0).resolve()) if argv0 else ""
    except (OSError, ValueError):
        return Installer.PIP

    if ".cache/uv/" in path or "uvx" in path:
        return Installer.UVX
    if ".local/share/uv/tools/ievo/" in path:
        return Installer.UV_TOOL
    return Installer.PIP


def get_current_version() -> str:
    """Return the currently installed ievo version."""
    from ievo import __version__

    return __version__


async def fetch_latest_version() -> str:
    """Fetch the latest version of ievo from PyPI.

    Raises httpx.HTTPError on failure.
    """
    import httpx

    async with httpx.AsyncClient() as client:
        response = await client.get("https://pypi.org/pypi/ievo/json", timeout=10.0)
        response.raise_for_status()
        return response.json()["info"]["version"]


def run_upgrade(installer: Installer) -> subprocess.CompletedProcess[str]:
    """Run the appropriate upgrade command.

    Raises ValueError for UVX (no persistent install to upgrade).
    Raises FileNotFoundError if binary missing.
    """
    if installer == Installer.UVX:
        msg = "UVX does not support upgrade — it auto-fetches latest"
        raise ValueError(msg)

    if installer == Installer.UV_TOOL:
        return subprocess.run(
            ["uv", "tool", "upgrade", "ievo"],
            check=True,
            capture_output=True,
            text=True,
        )

    return subprocess.run(
        ["pip", "install", "--upgrade", "ievo"],
        check=True,
        capture_output=True,
        text=True,
    )
