from __future__ import annotations

import json
from pathlib import Path
from types import SimpleNamespace

from worai import update


def test_installer_and_upgrade_command_and_cache_path() -> None:
    assert update.detect_installer(env={"PIPX_HOME": "/x"}, python_executable="/usr/bin/python") == "pipx"
    assert update.detect_installer(env={}, python_executable="/pipx/venvs/worai/bin/python") == "pipx"
    assert update.detect_installer(env={}, python_executable="/usr/bin/python") == "pip"

    assert update.build_upgrade_command("pipx") == ["pipx", "upgrade", "worai"]
    pip_cmd = update.build_upgrade_command("pip", python_executable="python3")
    assert pip_cmd[:3] == ["python3", "-m", "pip"]

    assert str(update.get_cache_path({"XDG_CACHE_HOME": "/tmp/cache"})).endswith("/tmp/cache/worai/update-check.json")


def test_parse_read_cache_and_fetch_latest(monkeypatch, tmp_path: Path) -> None:
    assert update._parse_version("1.2.3") == (1, 2, 3)
    assert update._parse_version("") is None
    assert update._parse_version("1.a") is None

    cache = tmp_path / "cache.json"
    cache.write_text(json.dumps({"checked_at": 100.0, "latest_version": "3.2.1"}), encoding="utf-8")
    assert update._read_cached_latest(cache, 120.0) == "3.2.1"
    assert update._read_cached_latest(cache, 100.0 + update.CACHE_TTL_SECONDS + 1) is None

    cache.write_text("{}", encoding="utf-8")
    assert update._read_cached_latest(cache, 120.0) is None

    class _Ctx:
        def __enter__(self):
            return self

        def __exit__(self, *_args):
            return None

    monkeypatch.setattr(update.request, "urlopen", lambda *_a, **_k: _Ctx())
    monkeypatch.setattr(update.json, "load", lambda _r: {"info": {"version": "9.9.9"}})
    assert update.fetch_latest_version(0.1) == "9.9.9"

    monkeypatch.setattr(update.json, "load", lambda _r: {"info": {"version": ""}})
    assert update.fetch_latest_version(0.1) is None


def test_write_cache_and_run_upgrade_command(monkeypatch, tmp_path: Path) -> None:
    cache = tmp_path / "d" / "cache.json"
    update._write_cache(cache, 10.0, "3.3.3")
    assert json.loads(cache.read_text(encoding="utf-8"))["latest_version"] == "3.3.3"

    monkeypatch.setattr(update.subprocess, "run", lambda *_a, **_k: SimpleNamespace(returncode=5))
    assert update.run_upgrade_command(["x"]) == 5

    def _raise(*_a, **_k):
        raise FileNotFoundError()

    monkeypatch.setattr(update.subprocess, "run", _raise)
    assert update.run_upgrade_command(["x"]) == 127
