"""Additional tests for SSH Copy ID GUI connection testing functionality."""

from __future__ import annotations

import subprocess
import sys
from unittest.mock import MagicMock, patch

import pytest
from PySide2.QtWidgets import QApplication

# Import GUI components
try:
    from ..gui import SSHCopyIDGUI

    GUI_AVAILABLE = True
except ImportError as e:
    GUI_AVAILABLE = False
    print(f"GUI import failed: {e}")


@pytest.fixture(scope="module")
def app():
    """Create QApplication fixture."""
    if not GUI_AVAILABLE:
        pytest.skip("GUI components not available")

    app_instance = QApplication.instance()
    if app_instance is None:
        app_instance = QApplication(sys.argv)
    return app_instance


@pytest.fixture
def gui_window(app):
    """Create GUI window fixture."""
    if not GUI_AVAILABLE:
        pytest.skip("GUI components not available")

    window = SSHCopyIDGUI()
    yield window
    window.close()


class TestSSHCopyIDGUIConnection:
    """Tests for SSH Copy ID GUI connection testing functionality."""

    @pytest.mark.skipif(not GUI_AVAILABLE, reason="GUI not available")
    def test_hostname_input_enables_test_button(self, gui_window):
        """Test that entering all required fields enables the test button."""
        # Initially button should be disabled
        assert not gui_window.test_connection_button.isEnabled()
        assert gui_window.connection_status_label.text() == ""

        # Enter hostname only - should still be disabled
        gui_window.hostname_input.setText("192.168.1.1")
        assert not gui_window.test_connection_button.isEnabled()

        # Enter username - should still be disabled
        gui_window.username_input.setText("testuser")
        assert not gui_window.test_connection_button.isEnabled()

        # Enter password - should now be enabled
        gui_window.password_input.setText("testpass")
        assert gui_window.test_connection_button.isEnabled()

        # Clear password - should be disabled again
        gui_window.password_input.clear()
        assert not gui_window.test_connection_button.isEnabled()
        assert gui_window.connection_status_label.text() == ""

    @pytest.mark.skipif(not GUI_AVAILABLE, reason="GUI not available")
    def test_connection_status_display(self, gui_window):
        """Test connection status display updates correctly."""
        # Test successful connection display
        gui_window.update_connection_status(True, "Connected successfully")
        assert gui_window.connection_status_label.text() == "✓"
        assert "green" in gui_window.connection_status_label.styleSheet()

        # Test failed connection display
        gui_window.update_connection_status(False, "Connection failed")
        assert gui_window.connection_status_label.text() == "✗"
        assert "red" in gui_window.connection_status_label.styleSheet()

        # Test testing state display
        gui_window.connection_status_label.setText("⏳")
        gui_window.connection_status_label.setStyleSheet("color: orange; font-size: 16px; font-weight: bold;")
        assert gui_window.connection_status_label.text() == "⏳"
        assert "orange" in gui_window.connection_status_label.styleSheet()

    @pytest.mark.skipif(not GUI_AVAILABLE, reason="GUI not available")
    def test_clear_form_resets_connection_status(self, gui_window):
        """Test that clearing form resets connection status."""
        # Fill all required fields and set connection status
        gui_window.hostname_input.setText("192.168.1.1")
        gui_window.username_input.setText("testuser")
        gui_window.password_input.setText("testpass")
        gui_window.update_connection_status(True, "Connected")
        assert gui_window.connection_status_label.text() == "✓"

        # Clear form
        gui_window.clear_form()

        # Connection status should be reset
        assert gui_window.connection_status_label.text() == ""
        assert gui_window.hostname_input.text() == ""

    @pytest.mark.skipif(not GUI_AVAILABLE, reason="GUI not available")
    @patch("subprocess.run")
    def test_perform_connection_test_success(self, mock_run, gui_window):
        """Test successful connection test."""
        # Mock successful SSH connection
        mock_process = MagicMock()
        mock_process.returncode = 0
        mock_process.stdout = "connection_test\n"
        mock_process.stderr = ""
        mock_run.return_value = mock_process

        # Test the connection test method
        gui_window._perform_connection_test("localhost", 22, "testuser")

        # Verify subprocess was called with correct arguments
        mock_run.assert_called_once()
        call_args = mock_run.call_args[0][0]
        assert "ssh" in call_args
        assert "-p" in call_args
        assert "22" in call_args
        assert "testuser@localhost" in call_args

    @pytest.mark.skipif(not GUI_AVAILABLE, reason="GUI not available")
    @patch("subprocess.run")
    def test_perform_connection_test_permission_denied(self, mock_run, gui_window):
        """Test connection test with permission denied (still successful connection)."""
        # Mock permission denied error (connection established but auth failed)
        mock_process = MagicMock()
        mock_process.returncode = 255
        mock_process.stdout = ""
        mock_process.stderr = "Permission denied (publickey,password)."
        mock_run.return_value = mock_process

        # Test the connection test method
        gui_window._perform_connection_test("localhost", 22, "testuser")

        # Should still report success since connection was established
        mock_run.assert_called_once()

    @pytest.mark.skipif(not GUI_AVAILABLE, reason="GUI not available")
    @patch("subprocess.run")
    def test_perform_connection_test_connection_refused(self, mock_run, gui_window):
        """Test connection test with connection refused."""
        # Mock connection refused error
        mock_process = MagicMock()
        mock_process.returncode = 255
        mock_process.stdout = ""
        mock_process.stderr = "ssh: connect to host localhost port 22: Connection refused"
        mock_run.return_value = mock_process

        # Test the connection test method
        gui_window._perform_connection_test("localhost", 22, "testuser")

        # Should report failure
        mock_run.assert_called_once()

    @pytest.mark.skipif(not GUI_AVAILABLE, reason="GUI not available")
    @patch("subprocess.run")
    def test_perform_connection_test_timeout(self, mock_run, gui_window):
        """Test connection test timeout handling."""
        # Mock timeout exception
        mock_run.side_effect = subprocess.TimeoutExpired("ssh command", 10)

        # Test the connection test method
        gui_window._perform_connection_test("slow-host", 22, "testuser")

        # Should report timeout failure
        mock_run.assert_called_once()


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
