"""Tests for autodebug/upgrade.py — PyPI version check and auto-update."""

from __future__ import annotations

import json
import time
from pathlib import Path
from unittest.mock import MagicMock, patch

import pytest

from autodebug.upgrade import (
    CACHE_FILE,
    CHECK_INTERVAL,
    _is_newer,
    check_for_upgrade,
)


@pytest.fixture(autouse=True)
def _clean_cache(tmp_path, monkeypatch):
    """Use a temp cache file for each test."""
    cache = tmp_path / "version_cache.json"
    monkeypatch.setattr("autodebug.upgrade.CACHE_FILE", cache)
    yield
    if cache.exists():
        cache.unlink()


def test_is_newer():
    """_is_newer correctly compares version strings."""
    assert _is_newer("2.0.0", "1.0.0") is True
    assert _is_newer("1.0.0", "2.0.0") is False
    assert _is_newer("1.0.0", "1.0.0") is False
    assert _is_newer("1.1.0", "1.0.0") is True
    assert _is_newer("1.0.1", "1.0.0") is True


def test_check_for_upgrade_no_newer_version():
    """Returns None when PyPI version matches current."""
    mock_resp = MagicMock()
    mock_resp.ok = True
    mock_resp.json.return_value = {"info": {"version": "1.0.0"}}
    with patch("requests.get", return_value=mock_resp):
        result = check_for_upgrade("1.0.0")
    assert result is None


def test_check_for_upgrade_newer_available():
    """Returns new version string when PyPI has a newer version."""
    mock_resp = MagicMock()
    mock_resp.ok = True
    mock_resp.json.return_value = {"info": {"version": "2.0.0"}}
    with patch("requests.get", return_value=mock_resp):
        result = check_for_upgrade("1.0.0")
    assert result == "2.0.0"


def test_check_for_upgrade_cache_hit(tmp_path, monkeypatch):
    """Uses cached result within CHECK_INTERVAL."""
    cache = tmp_path / "version_cache.json"
    monkeypatch.setattr("autodebug.upgrade.CACHE_FILE", cache)
    cache.write_text(json.dumps({
        "latest": "1.5.0",
        "checked_at": time.time(),
    }))
    # Should return the cached version without calling PyPI
    result = check_for_upgrade("1.0.0")
    assert result == "1.5.0"


def test_check_for_upgrade_network_failure():
    """Returns None on network failure (silent fail)."""
    with patch("requests.get", side_effect=Exception("network")):
        result = check_for_upgrade("1.0.0")
    assert result is None
