"""Tests for cloud abstraction layer.

Run with: pytest suno_utils/tests/test_cloud_abstraction.py
"""

import pytest
from unittest.mock import Mock, patch
import os

from suno_utils.cloud.backend import InferenceBackend, get_backend, set_backend_provider
from suno_utils.cloud.factory import CloudProvider, CloudBackendFactory
from suno_utils.cloud.chirp_backend import ChirpInferenceBackend


class TestQueueBackend:
    """Test queue backend abstraction."""

    def test_modal_queue_adapter(self):
        """Test Modal queue adapter initialization."""
        backend = InferenceBackend(CloudProvider.MODAL)
        queue = backend.get_queue("test-queue")

        assert queue is not None
        assert hasattr(queue, "put")
        assert hasattr(queue, "get")
        assert hasattr(queue, "iterate")
        assert hasattr(queue, "iterate_async")

    def test_queue_caching(self):
        """Test that queues are cached."""
        backend = InferenceBackend(CloudProvider.MODAL)
        queue1 = backend.get_queue("test-queue")
        queue2 = backend.get_queue("test-queue")

        assert queue1 is queue2  # Same instance


class TestVolumeBackend:
    """Test volume backend abstraction."""

    def test_modal_volume_adapter(self):
        """Test Modal volume adapter initialization."""
        backend = InferenceBackend(CloudProvider.MODAL)
        volume = backend.get_volume("test-volume", "/test/path")

        assert volume is not None
        assert hasattr(volume, "get_mount_path")
        assert hasattr(volume, "exists")
        assert hasattr(volume, "list_files")
        assert volume.get_mount_path() == "/test/path"


class TestKVStoreBackend:
    """Test key-value store backend abstraction."""

    def test_modal_kv_adapter(self):
        """Test Modal KV adapter initialization."""
        backend = InferenceBackend(CloudProvider.MODAL)
        kv = backend.get_kv_store("test-kv")

        assert kv is not None
        assert hasattr(kv, "get")
        assert hasattr(kv, "put")
        assert hasattr(kv, "delete")
        assert hasattr(kv, "contains")


class TestSecretsBackend:
    """Test secrets backend abstraction."""

    def test_modal_secrets_adapter(self):
        """Test Modal secrets adapter initialization."""
        backend = InferenceBackend(CloudProvider.MODAL)
        secrets = backend.get_secrets()

        assert secrets is not None
        assert hasattr(secrets, "get_secret")


class TestBackendFactory:
    """Test backend factory."""

    def test_factory_creates_modal_backend(self):
        """Test factory creates Modal backend by default."""
        factory = CloudBackendFactory(CloudProvider.MODAL)
        queue = factory.create_queue("test-queue")

        assert queue is not None

    def test_global_backend(self):
        """Test global backend singleton."""
        backend = get_backend()
        assert backend is not None
        assert isinstance(backend, InferenceBackend)


class TestChirpBackend:
    """Test Chirp-specific backend helper."""

    def test_chirp_backend_initialization(self):
        """Test Chirp backend initializes all components."""
        chirp = ChirpInferenceBackend("dev")

        # Check queues
        assert chirp.mp3_chunk_queue is not None
        assert chirp.webm_chunk_queue is not None
        assert chirp.stream_key_queue is not None
        assert chirp.token_queue is not None
        assert chirp.events_queue is not None

        # Check volume
        assert chirp.volume_adapter is not None
        assert chirp.volume_mount_path == "/volume"

        # Check secrets
        assert chirp.secrets_backend is not None

    def test_chirp_backend_queue_names(self):
        """Test Chirp backend uses correct queue names."""
        chirp = ChirpInferenceBackend("dev")

        assert chirp.chunk_queue_name == "chunk-queue-dev"
        assert chirp.webm_chunk_queue_name == "chunk-queue-webm-dev"
        assert chirp.stream_key_queue_name == "stream-key-queue-dev"
        assert chirp.token_queue_name == "token-queue-dev"

    def test_chirp_backend_get_volume_dict(self):
        """Test Chirp backend volume dict for Modal decorator."""
        chirp = ChirpInferenceBackend("dev")
        volume_dict = chirp.get_volume_dict()

        # Should return dict with mount path as key
        assert isinstance(volume_dict, dict)

    def test_chirp_backend_get_secrets_list(self):
        """Test Chirp backend secrets list for Modal decorator."""
        chirp = ChirpInferenceBackend("dev")
        secrets_list = chirp.get_secrets_list()

        # Should return list
        assert isinstance(secrets_list, list)


class TestProviderSwitching:
    """Test switching between providers."""

    def test_switch_provider_via_set_backend(self):
        """Test switching provider programmatically."""
        set_backend_provider(CloudProvider.MODAL)
        backend = get_backend()
        assert backend.provider == CloudProvider.MODAL

    @patch.dict(os.environ, {"CLOUD_PROVIDER": "modal"})
    def test_configure_from_env(self):
        """Test configuring provider from environment."""
        from suno_utils.cloud.backend import configure_backend_from_env

        configure_backend_from_env()
        backend = get_backend()
        assert backend.provider == CloudProvider.MODAL


class TestBackwardCompatibility:
    """Test backward compatibility with existing Modal code."""

    def test_queue_interface_matches_modal(self):
        """Test that queue interface matches Modal.Queue API."""
        backend = InferenceBackend(CloudProvider.MODAL)
        queue = backend.get_queue("test-queue")

        # Check all Modal Queue methods are available
        assert hasattr(queue, "put")
        assert hasattr(queue, "get")
        assert hasattr(queue, "iterate")

        # Check signature matches Modal
        import inspect

        put_sig = inspect.signature(queue.put)
        assert "partition" in put_sig.parameters
        assert "partition_ttl" in put_sig.parameters
        assert "block" in put_sig.parameters
        assert "timeout" in put_sig.parameters


class TestMocking:
    """Test that backends can be easily mocked."""

    def test_mock_queue_backend(self):
        """Test mocking queue backend for testing."""
        backend = InferenceBackend(CloudProvider.MODAL)

        # Create mock queue
        mock_queue = Mock()
        mock_queue.put.return_value = None
        mock_queue.get.return_value = "test_data"

        # Inject mock
        backend._queues["test-queue"] = mock_queue

        # Use it
        queue = backend.get_queue("test-queue")
        queue.put("data", partition="key")
        result = queue.get(partition="key")

        # Verify
        assert queue is mock_queue
        assert result == "test_data"
        mock_queue.put.assert_called_once()


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
