"""
Test Standalone integration for CyborgDB Service.
"""

import os
import tempfile
import pytest
from pydantic import ValidationError


ENV_VARS = [
    "CYBORGDB_CONNECTION_STRING",
    "CYBORGDB_DB_TYPE",
    "INDEX_LOCATION",
    "CONFIG_LOCATION",
    "ITEMS_LOCATION",
    "INDEX_CONNECTION_STRING",
    "CONFIG_CONNECTION_STRING",
    "ITEMS_CONNECTION_STRING",
]


class TestStandaloneIntegration:
    """Test Standalone fallback functionality"""

    @pytest.fixture(autouse=True)
    def clean_env(self):
        saved = {key: os.environ.get(key) for key in ENV_VARS}
        for key in ENV_VARS:
            os.environ.pop(key, None)
        yield
        for key, value in saved.items():
            if value is not None:
                os.environ[key] = value
            else:
                os.environ.pop(key, None)

    def test_config_uses_standalone_when_no_db_type(self):
        """Test that config automatically uses Standalone when no db type is provided"""
        import importlib
        from cyborgdb_service.core import config

        importlib.reload(config)
        settings = config.settings

        # Verify that locations were set to standalone
        assert settings.INDEX_LOCATION == "rocksdb"
        assert settings.CONFIG_LOCATION == "rocksdb"
        assert settings.ITEMS_LOCATION == "rocksdb"

        # Connection strings should be None (C++ layer handles the default)
        assert settings.INDEX_CONNECTION_STRING is None
        assert settings.CONFIG_CONNECTION_STRING is None
        assert settings.ITEMS_CONNECTION_STRING is None

    def test_config_with_explicit_standalone_type(self):
        """Test that config works with explicit standalone db type and custom path"""
        with tempfile.TemporaryDirectory() as tmpdir:
            os.environ["CYBORGDB_DB_TYPE"] = "standalone"
            os.environ["CYBORGDB_CONNECTION_STRING"] = tmpdir

            import importlib
            from cyborgdb_service.core import config

            importlib.reload(config)
            settings = config.settings

            # Should pass through the custom path as-is (C++ layer handles it)
            assert settings.INDEX_LOCATION == "rocksdb"
            assert settings.INDEX_CONNECTION_STRING == tmpdir

    def test_config_with_explicit_standalone_no_connection_string(self):
        """Test that config works with explicit standalone type but no connection string"""
        os.environ["CYBORGDB_DB_TYPE"] = "standalone"

        import importlib
        from cyborgdb_service.core import config

        importlib.reload(config)
        settings = config.settings

        # Should use standalone with None connection string (C++ layer defaults)
        assert settings.INDEX_LOCATION == "rocksdb"
        assert settings.INDEX_CONNECTION_STRING is None
        assert settings.CONFIG_CONNECTION_STRING is None
        assert settings.ITEMS_CONNECTION_STRING is None

    def test_config_error_with_redis_but_no_connection_string(self):
        """Test that config raises error when redis is specified without connection string"""
        os.environ["CYBORGDB_DB_TYPE"] = "redis"

        from cyborgdb_service.core.config import Settings

        with pytest.raises(ValidationError) as exc_info:
            Settings(_env_file=None)

        assert "but no connection string is provided" in str(exc_info.value)

    def test_config_error_with_postgres_but_no_connection_string(self):
        """Test that config raises error when postgres is specified without connection string"""
        os.environ["CYBORGDB_DB_TYPE"] = "postgres"

        from cyborgdb_service.core.config import Settings

        with pytest.raises(ValidationError) as exc_info:
            Settings(_env_file=None)

        assert "but no connection string is provided" in str(exc_info.value)

    def test_config_memory_location(self):
        """Test that memory location works correctly"""
        os.environ["CYBORGDB_DB_TYPE"] = "memory"

        import importlib
        from cyborgdb_service.core import config

        importlib.reload(config)
        settings = config.settings

        # Memory should be converted to threadsafememory
        assert settings.INDEX_LOCATION == "threadsafememory"
        assert settings.CONFIG_LOCATION == "threadsafememory"
        assert settings.ITEMS_LOCATION == "threadsafememory"

    def test_config_invalid_location(self):
        """Test that invalid location raises error"""
        os.environ["CYBORGDB_DB_TYPE"] = "mysql"

        import importlib
        from cyborgdb_service.core import config

        with pytest.raises(ValueError) as exc_info:
            importlib.reload(config)

        assert "Invalid" in str(exc_info.value)
        assert "mysql" in str(exc_info.value)
