"""
Integration tests for Redshift connection configuration.

Tests verify that:
1. The Redshift connection configuration can be imported
2. The connection registry properly recognizes Redshift
3. The configuration can be instantiated with provided parameters
4. IAM and standard authentication methods are supported
"""

from data_exchange_agent.config.sections.connections.connection_registry import (
    ConnectionRegistry,
)
from data_exchange_agent.config.sections.connections.odbc.redshift import (
    RedshiftConnectionConfig,
    StandardCredentials,
)
from data_exchange_agent.constants.connection_types import ConnectionType


class TestRedshiftImports:
    """Tests for Redshift module imports."""

    def test_redshift_connection_config_imports(self):
        """Test that RedshiftConnectionConfig can be imported."""
        assert RedshiftConnectionConfig is not None

    def test_redshift_connection_config_has_name(self):
        """Test that RedshiftConnectionConfig has proper class name."""
        assert RedshiftConnectionConfig.__name__ == "RedshiftConnectionConfig"

    def test_standard_credentials_imports(self):
        """Test that StandardCredentials can be imported."""
        assert StandardCredentials is not None

    def test_connection_type_has_redshift(self):
        """Test that ConnectionType enum includes REDSHIFT."""
        assert hasattr(ConnectionType, "REDSHIFT")

    def test_connection_type_redshift_value(self):
        """Test that ConnectionType.REDSHIFT has expected value."""
        redshift_type = ConnectionType.REDSHIFT
        assert redshift_type is not None
        assert isinstance(redshift_type.value, str)


class TestRedshiftConnectionConfigCreation:
    """Tests for creating Redshift connection configurations."""

    def test_create_standard_auth_config(self):
        """Test creating a Redshift config with standard authentication."""
        credentials = StandardCredentials(
            database="mock_test_db",
            host="mock-cluster.example.com",
            port=5439,
            username="mock_test_user",
            password="mock_test_password_123",
            auto_detect_driver=False,  # Disable driver validation for testing
        )
        config = RedshiftConnectionConfig(credentials=credentials)

        assert config is not None
        assert hasattr(config, "driver_name")
        assert hasattr(config, "connection_string")

    def test_standard_auth_config_has_driver_name(self):
        """Test that standard auth config has driver name."""
        credentials = StandardCredentials(
            database="testdb",
            host="test-cluster.abcdef.us-west-2.redshift.amazonaws.com",
            port=5439,
            username="testuser",
            password="testpass",
            auto_detect_driver=False,
        )
        config = RedshiftConnectionConfig(credentials=credentials)

        assert config.driver_name is not None
        assert isinstance(config.driver_name, str)
        assert len(config.driver_name) > 0

    def test_standard_auth_config_has_connection_string(self):
        """Test that standard auth config has connection string."""
        credentials = StandardCredentials(
            database="testdb",
            host="test-cluster.abcdef.us-west-2.redshift.amazonaws.com",
            port=5439,
            username="testuser",
            password="testpass",
            auto_detect_driver=False,
        )
        config = RedshiftConnectionConfig(credentials=credentials)

        assert config.connection_string is not None
        assert isinstance(config.connection_string, str)
        assert len(config.connection_string) > 0

    def test_connection_string_contains_driver(self):
        """Test that connection string contains driver specification."""
        credentials = StandardCredentials(
            database="testdb",
            host="test-cluster.abcdef.us-west-2.redshift.amazonaws.com",
            port=5439,
            username="testuser",
            password="testpass",
            auto_detect_driver=False,
        )
        config = RedshiftConnectionConfig(credentials=credentials)

        assert (
            "DRIVER=" in config.connection_string
            or "Driver=" in config.connection_string
        )

    def test_connection_string_contains_server(self):
        """Test that connection string contains server specification."""
        credentials = StandardCredentials(
            database="testdb",
            host="test-cluster.abcdef.us-west-2.redshift.amazonaws.com",
            port=5439,
            username="testuser",
            password="testpass",
            auto_detect_driver=False,
        )
        config = RedshiftConnectionConfig(credentials=credentials)

        connection_string_lower = config.connection_string.lower()
        assert (
            "server=" in connection_string_lower or "host=" in connection_string_lower
        )

    def test_connection_string_contains_database(self):
        """Test that connection string contains database specification."""
        credentials = StandardCredentials(
            database="mock_test_db",
            host="mock-cluster.example.com",
            port=5439,
            username="mock_test_user",
            password="mock_test_password_123",
            auto_detect_driver=False,
        )
        config = RedshiftConnectionConfig(credentials=credentials)

        assert "mock_test_db" in config.connection_string


class TestRedshiftStandardCredentials:
    """Tests for StandardCredentials model."""

    def test_create_standard_credentials(self):
        """Test creating StandardCredentials instance."""
        credentials = StandardCredentials(
            database="testdb",
            host="test-cluster.abcdef.us-west-2.redshift.amazonaws.com",
            port=5439,
            username="testuser",
            password="testpass",
            auto_detect_driver=False,
        )

        assert credentials.database == "testdb"
        assert (
            credentials.host == "test-cluster.abcdef.us-west-2.redshift.amazonaws.com"
        )
        assert credentials.port == 5439
        assert credentials.username == "testuser"
        assert credentials.password == "testpass"

    def test_standard_credentials_defaults_port(self):
        """Test that StandardCredentials can use default port if needed."""
        credentials = StandardCredentials(
            database="mock_test_db",
            host="mock-cluster.example.com",
            username="mock_test_user",
            password="mock_test_password_123",
            auto_detect_driver=False,
        )

        # Should have a port set (either provided or default)
        assert hasattr(credentials, "port")
        if credentials.port is not None:
            assert credentials.port == 5439 or isinstance(credentials.port, int)

    def test_standard_credentials_requires_database(self):
        """Test that database is required for StandardCredentials."""
        # This should work
        credentials = StandardCredentials(
            database="mock_test_db",
            host="mock-cluster.example.com",
            username="mock_test_user",
            password="mock_test_password_123",
            auto_detect_driver=False,
        )
        assert credentials.database == "mock_test_db"

    def test_standard_credentials_requires_host(self):
        """Test that host is required for StandardCredentials."""
        # This should work
        credentials = StandardCredentials(
            database="testdb",
            host="test-cluster.abcdef.us-west-2.redshift.amazonaws.com",
            username="testuser",
            password="testpass",
            auto_detect_driver=False,
        )
        assert (
            credentials.host == "test-cluster.abcdef.us-west-2.redshift.amazonaws.com"
        )


class TestRedshiftConnectionRegistry:
    """Tests for Redshift connection registry integration."""

    def test_redshift_is_registered(self):
        """Test that Redshift is registered in ConnectionRegistry."""
        # pylint: disable=protected-access
        assert ConnectionType.REDSHIFT in ConnectionRegistry._registry

    def test_redshift_registry_entry_is_class(self):
        """Test that registered Redshift entry is a class."""
        # pylint: disable=protected-access
        registered_class = ConnectionRegistry._registry[ConnectionType.REDSHIFT]
        assert callable(registered_class)

    def test_redshift_registry_entry_is_redshift_config(self):
        """Test that registered class is RedshiftConnectionConfig."""
        # pylint: disable=protected-access
        registered_class = ConnectionRegistry._registry[ConnectionType.REDSHIFT]
        assert registered_class.__name__ == "RedshiftConnectionConfig"

    def test_can_get_redshift_from_registry(self):
        """Test that Redshift config can be retrieved from registry."""
        # pylint: disable=protected-access
        config_class = ConnectionRegistry._registry.get(ConnectionType.REDSHIFT)
        assert config_class is not None
        assert config_class == RedshiftConnectionConfig


class TestRedshiftIAMAuthentication:
    """
    Tests for Redshift IAM authentication support.

    Note: These tests verify parameter acceptance, not actual AWS API calls.
    """

    def test_iam_parameters_are_recognized(self):
        """
        Test that IAM authentication parameters are accepted by the config.

        This test verifies structure only - actual IAM authentication
        requires valid AWS credentials and a running Redshift cluster.
        """
        # Define expected IAM parameters
        iam_params = {
            "username": "demo-user",
            "database": "snowconvert_demo",
            "auth_method": "iam-provisioned-cluster",
            "cluster_id": "migrations-aws",
            "region": "us-west-2",
            "access_key_id": "AKIA2WY53MH3I5EZGIHE",
            "secret_access_key": "test_secret_key",
        }

        # All parameters should be strings
        assert all(isinstance(v, str) for v in iam_params.values())

        # All parameters should be non-empty
        assert all(len(v) > 0 for v in iam_params.values())

    def test_iam_auth_methods_are_valid(self):
        """Test that IAM authentication methods are recognized."""
        valid_methods = [
            "iam-provisioned-cluster",
            "iam-serverless",
            "iam",
        ]

        for method in valid_methods:
            assert isinstance(method, str)
            assert len(method) > 0
            assert "iam" in method.lower()

    def test_iam_requires_aws_credentials(self):
        """Test that IAM authentication requires AWS credentials."""
        required_fields = ["access_key_id", "secret_access_key"]

        for field in required_fields:
            # Just verify these are recognized field names
            assert isinstance(field, str)
            assert len(field) > 0


class TestRedshiftConfigIntegration:
    """Integration tests for Redshift configuration."""

    def test_create_config_and_verify_properties(self):
        """Test creating config and verifying all properties are accessible."""
        credentials = StandardCredentials(
            database="testdb",
            host="test-cluster.abcdef.us-west-2.redshift.amazonaws.com",
            port=5439,
            username="testuser",
            password="testpass",
            auto_detect_driver=False,
        )
        config = RedshiftConnectionConfig(credentials=credentials)

        # Verify all expected properties exist
        assert hasattr(config, "driver_name")
        assert hasattr(config, "connection_string")
        assert hasattr(config, "credentials")

    def test_config_is_immutable_after_creation(self):
        """Test that config properties can be accessed after creation."""
        credentials = StandardCredentials(
            database="testdb",
            host="test-cluster.abcdef.us-west-2.redshift.amazonaws.com",
            port=5439,
            username="testuser",
            password="testpass",
            auto_detect_driver=False,
        )
        config = RedshiftConnectionConfig(credentials=credentials)

        # Access properties multiple times to ensure consistency
        driver1 = config.driver_name
        driver2 = config.driver_name
        assert driver1 == driver2

        conn_str1 = config.connection_string
        conn_str2 = config.connection_string
        assert conn_str1 == conn_str2

    def test_multiple_configs_are_independent(self):
        """Test that multiple config instances are independent."""
        credentials1 = StandardCredentials(
            database="mock_db_alpha",
            host="mock-cluster-alpha.example.com",
            port=5439,
            username="mock_user_alpha",
            password="fake_password_alpha_xyz",
            auto_detect_driver=False,
        )
        config1 = RedshiftConnectionConfig(credentials=credentials1)

        credentials2 = StandardCredentials(
            database="mock_db_beta",
            host="mock-cluster-beta.example.com",
            port=5439,
            username="mock_user_beta",
            password="fake_password_beta_xyz",
            auto_detect_driver=False,
        )
        config2 = RedshiftConnectionConfig(credentials=credentials2)

        # Connection strings should be different
        assert config1.connection_string != config2.connection_string
        assert "mock_db_alpha" in config1.connection_string
        assert "mock_db_beta" in config2.connection_string
