"""Tests for CLI version check utilities."""

from __future__ import annotations

import json
import time
from unittest.mock import patch


def test_parse_version_simple():
    from terminaluse.lib.cli.utils.version_check import _parse_version

    assert _parse_version("0.25.0") == (0, 25, 0)
    assert _parse_version("1.0.0") == (1, 0, 0)
    assert _parse_version("10.20.30") == (10, 20, 30)


def test_parse_version_prerelease():
    from terminaluse.lib.cli.utils.version_check import _parse_version

    assert _parse_version("0.25.0a1") == (0, 25, 0)
    assert _parse_version("1.0.0b2") == (1, 0, 0)
    assert _parse_version("2.0.0rc1") == (2, 0, 0)


def test_parse_version_invalid():
    from terminaluse.lib.cli.utils.version_check import _parse_version

    assert _parse_version("invalid") == (0, 0, 0)
    assert _parse_version("") == (0, 0, 0)


def test_is_newer():
    from terminaluse.lib.cli.utils.version_check import _is_newer

    assert _is_newer("0.26.0", "0.25.0") is True
    assert _is_newer("1.0.0", "0.99.99") is True
    assert _is_newer("0.25.1", "0.25.0") is True

    assert _is_newer("0.25.0", "0.25.0") is False
    assert _is_newer("0.24.0", "0.25.0") is False
    assert _is_newer("0.25.0", "1.0.0") is False


def test_check_for_updates_uses_cache(tmp_path, monkeypatch):
    """When cache is fresh, should return cached version without network call."""
    from terminaluse.lib.cli.utils import version_check

    cache_file = tmp_path / "version_cache.json"
    monkeypatch.setattr(version_check, "VERSION_CACHE_FILE", cache_file)
    monkeypatch.setattr(version_check, "__version__", "0.25.0")

    # Write fresh cache with newer version
    cache_file.write_text(
        json.dumps(
            {
                "latest_version": "0.26.0",
                "checked_at": time.time(),
            }
        )
    )

    with patch.object(version_check, "_fetch_latest_version") as mock_fetch:
        result = version_check.check_for_updates()

        assert result.available == "0.26.0"
        assert result.checked is True
        mock_fetch.assert_not_called()


def test_check_for_updates_stale_cache_fetches(tmp_path, monkeypatch):
    """When cache is stale, should fetch from PyPI."""
    from terminaluse.lib.cli.utils import version_check

    cache_file = tmp_path / "version_cache.json"
    monkeypatch.setattr(version_check, "VERSION_CACHE_FILE", cache_file)
    monkeypatch.setattr(version_check, "__version__", "0.25.0")

    # Write stale cache (2 hours old)
    cache_file.write_text(
        json.dumps(
            {
                "latest_version": "0.25.0",
                "checked_at": time.time() - 2 * 60 * 60,
            }
        )
    )

    with patch.object(version_check, "_fetch_latest_version", return_value="0.27.0") as mock_fetch:
        result = version_check.check_for_updates()

        assert result.available == "0.27.0"
        assert result.checked is True
        mock_fetch.assert_called_once()


def test_check_for_updates_no_update_available(tmp_path, monkeypatch):
    """When current version is latest, should return no available update."""
    from terminaluse.lib.cli.utils import version_check

    cache_file = tmp_path / "version_cache.json"
    monkeypatch.setattr(version_check, "VERSION_CACHE_FILE", cache_file)
    monkeypatch.setattr(version_check, "__version__", "0.25.0")

    cache_file.write_text(
        json.dumps(
            {
                "latest_version": "0.25.0",
                "checked_at": time.time(),
            }
        )
    )

    result = version_check.check_for_updates()
    assert result.available is None
    assert result.checked is True


def test_check_for_updates_network_failure(tmp_path, monkeypatch):
    """Network failures should set checked=False."""
    from terminaluse.lib.cli.utils import version_check

    cache_file = tmp_path / "version_cache.json"
    monkeypatch.setattr(version_check, "VERSION_CACHE_FILE", cache_file)

    with patch.object(version_check, "_fetch_latest_version", return_value=None):
        result = version_check.check_for_updates()
        assert result.available is None
        assert result.checked is False


def test_check_for_updates_force_bypasses_cache(tmp_path, monkeypatch):
    """When force=True, should fetch from PyPI even if cache is fresh."""
    from terminaluse.lib.cli.utils import version_check

    cache_file = tmp_path / "version_cache.json"
    monkeypatch.setattr(version_check, "VERSION_CACHE_FILE", cache_file)
    monkeypatch.setattr(version_check, "__version__", "0.25.0")

    # Write fresh cache
    cache_file.write_text(
        json.dumps(
            {
                "latest_version": "0.25.0",
                "checked_at": time.time(),
            }
        )
    )

    with patch.object(version_check, "_fetch_latest_version", return_value="0.28.0") as mock_fetch:
        result = version_check.check_for_updates(force=True)

        assert result.available == "0.28.0"
        assert result.checked is True
        mock_fetch.assert_called_once()
