#!/usr/bin/env python
"""
Unit tests for CascadeCorrelationConfig and exceptions.

P2-NEW-001: Coverage improvement.
"""

import pytest
import torch
from helpers.utilities import set_deterministic_behavior


class TestCascadeCorrelationConfig:
    """Tests for CascadeCorrelationConfig class."""

    @pytest.mark.unit
    def test_config_default_values(self):
        """Test config has default values."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig()

        assert config.input_size is not None
        assert config.output_size is not None

    @pytest.mark.unit
    def test_config_custom_input_size(self):
        """Test config with custom input size."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(input_size=10)

        assert config.input_size == 10

    @pytest.mark.unit
    def test_config_custom_output_size(self):
        """Test config with custom output size."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(output_size=5)

        assert config.output_size == 5

    @pytest.mark.unit
    def test_config_learning_rate(self):
        """Test config learning rate."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(learning_rate=0.05)

        assert config.learning_rate == 0.05

    @pytest.mark.unit
    def test_config_max_hidden_units(self):
        """Test config max hidden units."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(max_hidden_units=100)

        assert config.max_hidden_units == 100

    @pytest.mark.unit
    def test_config_candidate_pool_size(self):
        """Test config candidate pool size."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(candidate_pool_size=16)

        assert config.candidate_pool_size == 16

    @pytest.mark.unit
    def test_config_candidate_epochs(self):
        """Test config candidate epochs."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(candidate_epochs=200)

        assert config.candidate_epochs == 200

    @pytest.mark.unit
    def test_config_output_epochs(self):
        """Test config output epochs."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(output_epochs=100)

        assert config.output_epochs == 100

    @pytest.mark.unit
    def test_config_correlation_threshold(self):
        """Test config correlation threshold."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(correlation_threshold=0.01)

        assert config.correlation_threshold == 0.01

    @pytest.mark.unit
    def test_config_patience(self):
        """Test config patience."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(patience=10)

        assert config.patience == 10

    @pytest.mark.unit
    def test_config_random_seed(self):
        """Test config random seed."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(random_seed=42)

        assert config.random_seed == 42

    @pytest.mark.unit
    def test_config_activation_function_name(self):
        """Test config activation function name."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(activation_function_name="tanh")

        assert config.activation_function_name == "tanh"

    @pytest.mark.unit
    def test_config_to_dict(self):
        """Test config to_dict method if it exists."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(input_size=4, output_size=2)

        if hasattr(config, "to_dict"):
            config_dict = config.to_dict()
            assert isinstance(config_dict, dict)


class TestCascadeCorrelationExceptions:
    """Tests for custom exceptions."""

    @pytest.mark.unit
    def test_configuration_error(self):
        """Test ConfigurationError can be raised."""
        from cascade_correlation.cascade_correlation_exceptions.cascade_correlation_exceptions import ConfigurationError

        with pytest.raises(ConfigurationError):
            raise ConfigurationError("Test configuration error")

    @pytest.mark.unit
    def test_training_error(self):
        """Test TrainingError can be raised."""
        from cascade_correlation.cascade_correlation_exceptions.cascade_correlation_exceptions import TrainingError

        with pytest.raises(TrainingError):
            raise TrainingError("Test training error")

    @pytest.mark.unit
    def test_validation_error(self):
        """Test ValidationError can be raised."""
        from cascade_correlation.cascade_correlation_exceptions.cascade_correlation_exceptions import ValidationError

        with pytest.raises(ValidationError):
            raise ValidationError("Test validation error")

    @pytest.mark.unit
    def test_exception_messages(self):
        """Test exception messages are preserved."""
        from cascade_correlation.cascade_correlation_exceptions.cascade_correlation_exceptions import ConfigurationError

        msg = "Custom error message"
        try:
            raise ConfigurationError(msg)
        except ConfigurationError as e:
            assert msg in str(e)


class TestConfigValidation:
    """Tests for config validation."""

    @pytest.mark.unit
    def test_config_with_zero_input_size(self):
        """Test config handles edge case of zero input size."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        try:
            config = CascadeCorrelationConfig(input_size=0)
            assert config.input_size == 0
        except (ValueError, AssertionError):
            pass

    @pytest.mark.unit
    def test_config_with_negative_learning_rate(self):
        """Test config handles negative learning rate."""
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        try:
            config = CascadeCorrelationConfig(learning_rate=-0.01)
            assert config.learning_rate == -0.01 or True
        except (ValueError, AssertionError):
            pass


class TestNetworkWithConfig:
    """Tests for network creation with various configs."""

    @pytest.mark.unit
    def test_network_from_config(self):
        """Test network creation from config."""
        from cascade_correlation.cascade_correlation import CascadeCorrelationNetwork
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(
            input_size=4,
            output_size=2,
            learning_rate=0.01,
        )
        network = CascadeCorrelationNetwork(config=config)

        assert network.input_size == 4
        assert network.output_size == 2

    @pytest.mark.unit
    def test_network_with_all_config_options(self):
        """Test network with all config options."""
        from cascade_correlation.cascade_correlation import CascadeCorrelationNetwork
        from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig

        config = CascadeCorrelationConfig(
            input_size=2,
            output_size=2,
            learning_rate=0.01,
            max_hidden_units=50,
            candidate_pool_size=8,
            candidate_epochs=50,
            output_epochs=50,
            correlation_threshold=0.01,
            patience=5,
            random_seed=42,
        )
        network = CascadeCorrelationNetwork(config=config)

        assert network is not None
