"""
Tests for the configuration modal TUI component.

This module contains unit tests for the ConfigModal class,
validating modal behavior and configuration interaction.
"""

from unittest.mock import Mock

from textual.widgets import Button

from hosts.core.config import Config
from hosts.tui.config_modal import ConfigModal


class TestConfigModal:
    """Test cases for the ConfigModal class."""

    def test_modal_initialization(self):
        """Test modal initialization with config."""
        mock_config = Mock(spec=Config)
        mock_config.should_show_default_entries.return_value = False

        modal = ConfigModal(mock_config)
        assert modal.config == mock_config

    def test_modal_compose_method_exists(self):
        """Test that modal has compose method."""
        mock_config = Mock(spec=Config)
        mock_config.should_show_default_entries.return_value = True

        modal = ConfigModal(mock_config)

        # Test that compose method exists and is callable
        assert hasattr(modal, "compose")
        assert callable(modal.compose)

    def test_action_save_updates_config(self):
        """Test that save action updates configuration."""
        mock_config = Mock(spec=Config)
        mock_config.should_show_default_entries.return_value = False

        modal = ConfigModal(mock_config)
        modal.dismiss = Mock()

        # Mock the checkbox query
        mock_checkbox = Mock()
        mock_checkbox.value = True
        modal.query_one = Mock(return_value=mock_checkbox)

        # Trigger save action
        modal.action_save()

        # Verify config was updated
        mock_config.set.assert_called_once_with("show_default_entries", True)
        mock_config.save.assert_called_once()
        modal.dismiss.assert_called_once_with(True)

    def test_action_save_preserves_false_state(self):
        """Test that save action preserves False checkbox state."""
        mock_config = Mock(spec=Config)
        mock_config.should_show_default_entries.return_value = True

        modal = ConfigModal(mock_config)
        modal.dismiss = Mock()

        # Mock the checkbox query with False value
        mock_checkbox = Mock()
        mock_checkbox.value = False
        modal.query_one = Mock(return_value=mock_checkbox)

        # Trigger save action
        modal.action_save()

        # Verify the False value was saved
        mock_config.set.assert_called_once_with("show_default_entries", False)
        mock_config.save.assert_called_once()
        modal.dismiss.assert_called_once_with(True)

    def test_action_cancel_no_config_changes(self):
        """Test that cancel action doesn't modify configuration."""
        mock_config = Mock(spec=Config)
        mock_config.should_show_default_entries.return_value = False

        modal = ConfigModal(mock_config)
        modal.dismiss = Mock()

        # Trigger cancel action
        modal.action_cancel()

        # Verify config was NOT updated
        mock_config.set.assert_not_called()
        mock_config.save.assert_not_called()
        modal.dismiss.assert_called_once_with(False)

    def test_save_button_pressed_event(self):
        """Test save button pressed event handling."""
        mock_config = Mock(spec=Config)
        mock_config.should_show_default_entries.return_value = False

        modal = ConfigModal(mock_config)
        modal.action_save = Mock()

        # Create mock save button
        save_button = Mock()
        save_button.id = "save-button"
        event = Button.Pressed(save_button)

        modal.on_button_pressed(event)

        modal.action_save.assert_called_once()

    def test_cancel_button_pressed_event(self):
        """Test cancel button pressed event handling."""
        mock_config = Mock(spec=Config)
        mock_config.should_show_default_entries.return_value = False

        modal = ConfigModal(mock_config)
        modal.action_cancel = Mock()

        # Create mock cancel button
        cancel_button = Mock()
        cancel_button.id = "cancel-button"
        event = Button.Pressed(cancel_button)

        modal.on_button_pressed(event)

        modal.action_cancel.assert_called_once()

    def test_unknown_button_pressed_ignored(self):
        """Test that unknown button presses are ignored."""
        mock_config = Mock(spec=Config)
        mock_config.should_show_default_entries.return_value = False

        modal = ConfigModal(mock_config)
        modal.action_save = Mock()
        modal.action_cancel = Mock()

        # Create a mock button with unknown ID
        unknown_button = Mock()
        unknown_button.id = "unknown-button"
        event = Button.Pressed(unknown_button)

        # Should not raise exception
        modal.on_button_pressed(event)

        # Should not trigger any actions
        modal.action_save.assert_not_called()
        modal.action_cancel.assert_not_called()

    def test_modal_bindings_defined(self):
        """Test that modal has expected key bindings."""
        mock_config = Mock(spec=Config)
        modal = ConfigModal(mock_config)

        # Check that bindings are defined
        assert len(modal.BINDINGS) == 2

        # Check specific bindings
        binding_keys = [binding.key for binding in modal.BINDINGS]
        assert "escape" in binding_keys
        assert "enter" in binding_keys

        binding_actions = [binding.action for binding in modal.BINDINGS]
        assert "cancel" in binding_actions
        assert "save" in binding_actions

    def test_modal_css_defined(self):
        """Test that modal has CSS styling defined."""
        mock_config = Mock(spec=Config)
        modal = ConfigModal(mock_config)

        # Check that CSS is defined
        assert hasattr(modal, "CSS")
        assert isinstance(modal.CSS, str)
        assert len(modal.CSS) > 0

        # Check for key CSS classes
        assert "config-container" in modal.CSS
        assert "config-title" in modal.CSS
        assert "button-row" in modal.CSS

    def test_config_method_called_during_initialization(self):
        """Test that config method is called during modal setup."""
        mock_config = Mock(spec=Config)

        # Test with True
        mock_config.should_show_default_entries.return_value = True
        modal = ConfigModal(mock_config)

        # Verify the config object is stored
        assert modal.config == mock_config

        # Test with False
        mock_config.should_show_default_entries.return_value = False
        modal = ConfigModal(mock_config)

        # Verify the config object is stored
        assert modal.config == mock_config

    def test_compose_method_signature(self):
        """Test that compose method has the expected signature."""
        mock_config = Mock(spec=Config)
        mock_config.should_show_default_entries.return_value = False

        modal = ConfigModal(mock_config)

        # Test that compose method exists and has correct signature
        import inspect

        sig = inspect.signature(modal.compose)
        assert len(sig.parameters) == 0  # No parameters except self

        # Test return type annotation if present
        if sig.return_annotation != inspect.Signature.empty:
            from textual.app import ComposeResult

            assert sig.return_annotation == ComposeResult

    def test_modal_inheritance(self):
        """Test that ConfigModal properly inherits from ModalScreen."""
        mock_config = Mock(spec=Config)
        modal = ConfigModal(mock_config)

        from textual.screen import ModalScreen

        assert isinstance(modal, ModalScreen)

        # Should have the config attribute
        assert hasattr(modal, "config")
        assert modal.config == mock_config
