"""Unit tests for cache module."""

from __future__ import annotations

import asyncio
from pathlib import Path

from cascache_lib import LocalCache, compute_cache_key


class TestCacheKey:
    """Tests for compute_cache_key function."""

    def test_same_inputs_same_key(self, tmp_path: Path):
        """Test that identical inputs produce same key."""
        file = tmp_path / "test.txt"
        file.write_text("content")

        key1 = compute_cache_key("op1", [file], {"param": "value"})
        key2 = compute_cache_key("op1", [file], {"param": "value"})

        assert key1 == key2

    def test_different_operation_different_key(self, tmp_path: Path):
        """Test that different operations produce different keys."""
        file = tmp_path / "test.txt"
        file.write_text("content")

        key1 = compute_cache_key("op1", [file], {})
        key2 = compute_cache_key("op2", [file], {})

        assert key1 != key2

    def test_different_params_different_key(self, tmp_path: Path):
        """Test that different parameters produce different keys."""
        file = tmp_path / "test.txt"
        file.write_text("content")

        key1 = compute_cache_key("op1", [file], {"param": "value1"})
        key2 = compute_cache_key("op1", [file], {"param": "value2"})

        assert key1 != key2

    def test_different_content_different_key(self, tmp_path: Path):
        """Test that different file content produces different keys."""
        file = tmp_path / "test.txt"

        file.write_text("content1")
        key1 = compute_cache_key("op1", [file], {})

        file.write_text("content2")
        key2 = compute_cache_key("op1", [file], {})

        assert key1 != key2

    def test_param_order_independent(self, tmp_path: Path):
        """Test that parameter order doesn't affect key."""
        file = tmp_path / "test.txt"
        file.write_text("content")

        key1 = compute_cache_key("op1", [file], {"a": "1", "b": "2"})
        key2 = compute_cache_key("op1", [file], {"b": "2", "a": "1"})

        assert key1 == key2


class TestLocalCache:
    """Tests for LocalCache."""

    def test_create_cache(self, tmp_path: Path):
        """Test cache creation."""
        cache_dir = tmp_path / "cache"
        cache = LocalCache(cache_dir)

        assert cache.cache_dir.exists()
        assert cache.cache_dir == cache_dir

    def test_exists_false_for_nonexistent(self, tmp_path: Path):
        """Test exists returns False for non-existent key."""
        cache = LocalCache(tmp_path / "cache")
        assert not asyncio.run(cache.exists("nonexistent_key"))

    def test_put_and_get(self, tmp_path: Path):
        """Test storing and retrieving cached files."""
        cache_dir = tmp_path / "cache"
        cache = LocalCache(cache_dir)

        # Create test file
        source = tmp_path / "source"
        source.mkdir()
        test_file = source / "test.txt"
        test_file.write_text("test content")

        # Store in cache
        cache_key = "test_key_123"
        success = asyncio.run(cache.put(cache_key, [test_file]))
        assert success

        # Verify exists
        assert asyncio.run(cache.exists(cache_key))

        # Remove original
        test_file.unlink()
        assert not test_file.exists()

        # Restore from cache
        success = asyncio.run(cache.get(cache_key, [test_file]))
        assert success
        assert test_file.exists()
        assert test_file.read_text() == "test content"

    def test_put_multiple_files(self, tmp_path: Path):
        """Test caching multiple files."""
        cache = LocalCache(tmp_path / "cache")

        # Create test files
        source = tmp_path / "source"
        source.mkdir()
        file1 = source / "file1.txt"
        file2 = source / "file2.txt"
        file1.write_text("content1")
        file2.write_text("content2")

        # Cache them
        cache_key = "multi_file_key"
        success = asyncio.run(cache.put(cache_key, [file1, file2]))
        assert success

        # Remove originals
        file1.unlink()
        file2.unlink()

        # Restore from cache
        success = asyncio.run(cache.get(cache_key, [file1, file2]))
        assert success
        assert file1.read_text() == "content1"
        assert file2.read_text() == "content2"

    def test_clear(self, tmp_path: Path):
        """Test clearing cache."""
        cache = LocalCache(tmp_path / "cache")

        # Add entry
        test_file = tmp_path / "test.txt"
        test_file.write_text("content")
        asyncio.run(cache.put("key1", [test_file]))

        assert asyncio.run(cache.exists("key1"))

        # Clear cache
        asyncio.run(cache.clear())

        assert not asyncio.run(cache.exists("key1"))
        assert cache.cache_dir.exists()  # Directory still exists, just empty

    def test_get_nonexistent_returns_false(self, tmp_path: Path):
        """Test that getting non-existent key returns False."""
        cache = LocalCache(tmp_path / "cache")
        test_file = tmp_path / "test.txt"

        success = asyncio.run(cache.get("nonexistent", [test_file]))
        assert not success
