"""
Tests for the save confirmation modal.

This module tests the save confirmation functionality when exiting edit entry mode.
"""

import pytest
from unittest.mock import Mock, patch
from textual.widgets import Button

from hosts.tui.app import HostsManagerApp
from hosts.tui.save_confirmation_modal import SaveConfirmationModal


class TestSaveConfirmationModal:
    """Test cases for the SaveConfirmationModal class."""

    def test_modal_creation(self):
        """Test that the modal can be created."""
        modal = SaveConfirmationModal()
        assert modal is not None

    def test_modal_compose(self):
        """Test that the modal composes correctly."""
        # Note: Cannot test compose() directly without app context
        # This is a basic existence check for the modal
        modal = SaveConfirmationModal()
        assert hasattr(modal, "compose")
        assert callable(modal.compose)

    def test_action_save(self):
        """Test save action dismisses with 'save'."""
        modal = SaveConfirmationModal()
        modal.dismiss = Mock()

        modal.action_save()

        modal.dismiss.assert_called_once_with("save")

    def test_action_discard(self):
        """Test discard action dismisses with 'discard'."""
        modal = SaveConfirmationModal()
        modal.dismiss = Mock()

        modal.action_discard()

        modal.dismiss.assert_called_once_with("discard")

    def test_action_cancel(self):
        """Test cancel action dismisses with 'cancel'."""
        modal = SaveConfirmationModal()
        modal.dismiss = Mock()

        modal.action_cancel()

        modal.dismiss.assert_called_once_with("cancel")

    @patch.object(SaveConfirmationModal, "query_one")
    def test_on_mount_sets_focus(self, mock_query_one):
        """Test that on_mount sets focus to the save button."""
        modal = SaveConfirmationModal()
        mock_save_button = Mock()
        mock_query_one.return_value = mock_save_button

        modal.on_mount()

        mock_query_one.assert_called_once_with("#save-button", Button)
        mock_save_button.focus.assert_called_once()


class TestSaveConfirmationIntegration:
    """Test cases for save confirmation integration with the main app."""

    @pytest.fixture
    def app(self):
        """Create a test app instance."""
        return HostsManagerApp()

    def test_has_entry_changes_no_original_values(self, app):
        """Test has_entry_changes returns False when no original values stored."""
        app.original_entry_values = None
        app.entry_edit_mode = True

        assert not app.has_entry_changes()

    def test_has_entry_changes_not_in_edit_mode(self, app):
        """Test has_entry_changes returns False when not in edit mode."""
        app.original_entry_values = {
            "ip_address": "127.0.0.1",
            "hostnames": ["localhost"],
            "comment": None,
            "is_active": True,
        }
        app.entry_edit_mode = False

        assert not app.has_entry_changes()

    @patch.object(HostsManagerApp, "query_one")
    def test_has_entry_changes_no_changes(self, mock_query_one, app):
        """Test has_entry_changes returns False when no changes made."""
        # Setup original values
        app.original_entry_values = {
            "ip_address": "127.0.0.1",
            "hostnames": ["localhost"],
            "comment": None,
            "is_active": True,
        }
        app.entry_edit_mode = True

        # Mock form fields with original values
        mock_ip_input = Mock()
        mock_ip_input.value = "127.0.0.1"
        mock_hostname_input = Mock()
        mock_hostname_input.value = "localhost"
        mock_comment_input = Mock()
        mock_comment_input.value = ""
        mock_checkbox = Mock()
        mock_checkbox.value = True

        def mock_query_side_effect(selector, widget_type=None):
            if selector == "#ip-input":
                return mock_ip_input
            elif selector == "#hostname-input":
                return mock_hostname_input
            elif selector == "#comment-input":
                return mock_comment_input
            elif selector == "#active-checkbox":
                return mock_checkbox

        mock_query_one.side_effect = mock_query_side_effect

        assert not app.has_entry_changes()

    @patch.object(HostsManagerApp, "query_one")
    def test_has_entry_changes_ip_changed(self, mock_query_one, app):
        """Test has_entry_changes returns True when IP address changed."""
        # Setup original values
        app.original_entry_values = {
            "ip_address": "127.0.0.1",
            "hostnames": ["localhost"],
            "comment": None,
            "is_active": True,
        }
        app.entry_edit_mode = True

        # Mock form fields with changed IP
        mock_ip_input = Mock()
        mock_ip_input.value = "192.168.1.1"  # Changed IP
        mock_hostname_input = Mock()
        mock_hostname_input.value = "localhost"
        mock_comment_input = Mock()
        mock_comment_input.value = ""
        mock_checkbox = Mock()
        mock_checkbox.value = True

        def mock_query_side_effect(selector, widget_type=None):
            if selector == "#ip-input":
                return mock_ip_input
            elif selector == "#hostname-input":
                return mock_hostname_input
            elif selector == "#comment-input":
                return mock_comment_input
            elif selector == "#active-checkbox":
                return mock_checkbox

        mock_query_one.side_effect = mock_query_side_effect

        assert app.has_entry_changes()

    @patch.object(HostsManagerApp, "query_one")
    def test_has_entry_changes_hostname_changed(self, mock_query_one, app):
        """Test has_entry_changes returns True when hostname changed."""
        # Setup original values
        app.original_entry_values = {
            "ip_address": "127.0.0.1",
            "hostnames": ["localhost"],
            "comment": None,
            "is_active": True,
        }
        app.entry_edit_mode = True

        # Mock form fields with changed hostname
        mock_ip_input = Mock()
        mock_ip_input.value = "127.0.0.1"
        mock_hostname_input = Mock()
        mock_hostname_input.value = "localhost, test.local"  # Added hostname
        mock_comment_input = Mock()
        mock_comment_input.value = ""
        mock_checkbox = Mock()
        mock_checkbox.value = True

        def mock_query_side_effect(selector, widget_type=None):
            if selector == "#ip-input":
                return mock_ip_input
            elif selector == "#hostname-input":
                return mock_hostname_input
            elif selector == "#comment-input":
                return mock_comment_input
            elif selector == "#active-checkbox":
                return mock_checkbox

        mock_query_one.side_effect = mock_query_side_effect

        assert app.has_entry_changes()

    @patch.object(HostsManagerApp, "query_one")
    def test_has_entry_changes_comment_added(self, mock_query_one, app):
        """Test has_entry_changes returns True when comment added."""
        # Setup original values
        app.original_entry_values = {
            "ip_address": "127.0.0.1",
            "hostnames": ["localhost"],
            "comment": None,
            "is_active": True,
        }
        app.entry_edit_mode = True

        # Mock form fields with added comment
        mock_ip_input = Mock()
        mock_ip_input.value = "127.0.0.1"
        mock_hostname_input = Mock()
        mock_hostname_input.value = "localhost"
        mock_comment_input = Mock()
        mock_comment_input.value = "Test comment"  # Added comment
        mock_checkbox = Mock()
        mock_checkbox.value = True

        def mock_query_side_effect(selector, widget_type=None):
            if selector == "#ip-input":
                return mock_ip_input
            elif selector == "#hostname-input":
                return mock_hostname_input
            elif selector == "#comment-input":
                return mock_comment_input
            elif selector == "#active-checkbox":
                return mock_checkbox

        mock_query_one.side_effect = mock_query_side_effect

        assert app.has_entry_changes()

    @patch.object(HostsManagerApp, "query_one")
    def test_has_entry_changes_active_state_changed(self, mock_query_one, app):
        """Test has_entry_changes returns True when active state changed."""
        # Setup original values
        app.original_entry_values = {
            "ip_address": "127.0.0.1",
            "hostnames": ["localhost"],
            "comment": None,
            "is_active": True,
        }
        app.entry_edit_mode = True

        # Mock form fields with changed active state
        mock_ip_input = Mock()
        mock_ip_input.value = "127.0.0.1"
        mock_hostname_input = Mock()
        mock_hostname_input.value = "localhost"
        mock_comment_input = Mock()
        mock_comment_input.value = ""
        mock_checkbox = Mock()
        mock_checkbox.value = False  # Changed active state

        def mock_query_side_effect(selector, widget_type=None):
            if selector == "#ip-input":
                return mock_ip_input
            elif selector == "#hostname-input":
                return mock_hostname_input
            elif selector == "#comment-input":
                return mock_comment_input
            elif selector == "#active-checkbox":
                return mock_checkbox

        mock_query_one.side_effect = mock_query_side_effect

        assert app.has_entry_changes()

    def test_exit_edit_entry_mode(self, app):
        """Test exit_edit_entry_mode cleans up properly."""
        app.entry_edit_mode = True
        app.original_entry_values = {"test": "data"}

        # Mock the details_handler and query_one methods
        app.details_handler.update_entry_details = Mock()
        app.query_one = Mock()
        app.update_status = Mock()

        mock_table = Mock()
        app.query_one.return_value = mock_table

        app.exit_edit_entry_mode()

        assert not app.entry_edit_mode
        assert app.original_entry_values is None
        app.details_handler.update_entry_details.assert_called_once()
        mock_table.focus.assert_called_once()
        app.update_status.assert_called_once_with("Exited entry edit mode")
