"""Tests for the paid checker dynamic loader."""

import json
import pytest
from pathlib import Path
from unittest.mock import patch

from stablestack.checkers.loader import (
    load_paid_checkers,
    get_paid_checkers_dir,
    invalidate_cache,
)


@pytest.fixture(autouse=True)
def reset_cache():
    """Reset the loader cache before each test."""
    invalidate_cache()
    yield
    invalidate_cache()


@pytest.fixture
def checkers_dir(tmp_path):
    """Create a temporary checkers directory."""
    d = tmp_path / "checkers"
    d.mkdir()
    return d


class TestGetPaidCheckersDir:
    def test_returns_expected_path(self):
        result = get_paid_checkers_dir()
        assert result == Path.home() / ".stablestack" / "checkers"


class TestLoadPaidCheckers:
    def test_empty_dir_returns_empty_list(self, checkers_dir):
        with patch(
            "stablestack.checkers.loader.get_paid_checkers_dir",
            return_value=checkers_dir,
        ):
            result = load_paid_checkers()
            assert result == []

    def test_missing_dir_returns_empty_list(self, tmp_path):
        missing = tmp_path / "nonexistent"
        with patch(
            "stablestack.checkers.loader.get_paid_checkers_dir",
            return_value=missing,
        ):
            result = load_paid_checkers()
            assert result == []

    def test_corrupt_manifest_returns_empty_list(self, checkers_dir):
        (checkers_dir / "manifest.json").write_text("not valid json{{{")
        with patch(
            "stablestack.checkers.loader.get_paid_checkers_dir",
            return_value=checkers_dir,
        ):
            result = load_paid_checkers()
            assert result == []

    def test_version_mismatch_returns_empty_list(self, checkers_dir):
        manifest = {
            "stablestack_version": "99.99.0",
            "checkers": [],
        }
        (checkers_dir / "manifest.json").write_text(json.dumps(manifest))
        with patch(
            "stablestack.checkers.loader.get_paid_checkers_dir",
            return_value=checkers_dir,
        ):
            result = load_paid_checkers()
            assert result == []

    def test_valid_manifest_no_modules_returns_empty(self, checkers_dir):
        from stablestack import __version__
        major_minor = ".".join(__version__.split(".")[:2])
        manifest = {
            "stablestack_version": f"{major_minor}.0",
            "checkers": [
                {
                    "module": "nonexistent_module",
                    "class_name": "FakeChecker",
                }
            ],
        }
        (checkers_dir / "manifest.json").write_text(json.dumps(manifest))
        with patch(
            "stablestack.checkers.loader.get_paid_checkers_dir",
            return_value=checkers_dir,
        ):
            result = load_paid_checkers()
            assert result == []

    def test_caching_returns_same_list(self, checkers_dir):
        (checkers_dir / "manifest.json").write_text(
            json.dumps({"stablestack_version": "0.0.0", "checkers": []})
        )
        with patch(
            "stablestack.checkers.loader.get_paid_checkers_dir",
            return_value=checkers_dir,
        ):
            first = load_paid_checkers()
            second = load_paid_checkers()
            # Both should be empty lists but same content
            assert first == second == []

    def test_invalidate_cache_forces_reload(self, checkers_dir):
        (checkers_dir / "manifest.json").write_text(
            json.dumps({"stablestack_version": "0.0.0", "checkers": []})
        )
        with patch(
            "stablestack.checkers.loader.get_paid_checkers_dir",
            return_value=checkers_dir,
        ):
            load_paid_checkers()
            invalidate_cache()
            # After invalidation, the next call should re-scan
            result = load_paid_checkers()
            assert result == []
