"""Test suite for SSH functionality."""

import subprocess
import sys
import pytest
from unittest.mock import Mock, patch, call

from mithril.ssh import ssh_to_instance
from mithril.errors import SSHError


class TestSSHToInstance:
    """Test SSH connectivity functionality."""
    
    def test_ssh_success(self):
        """Test successful SSH connection."""
        with patch('subprocess.run') as mock_run:
            ssh_to_instance("1.2.3.4")
            
            expected_args = [
                "ssh",
                "-o", "StrictHostKeyChecking=no",
                "-o", "UserKnownHostsFile=/dev/null",
                "-o", "ConnectTimeout=10",
                "ubuntu@1.2.3.4"
            ]
            
            mock_run.assert_called_once_with(expected_args, check=False)
            
    def test_ssh_with_custom_user(self):
        """Test SSH with custom username."""
        with patch('subprocess.run') as mock_run:
            ssh_to_instance("1.2.3.4", user="admin")
            
            args = mock_run.call_args[0][0]
            assert "admin@1.2.3.4" in args
            
    def test_ssh_with_key_file(self):
        """Test SSH with specific key file."""
        with patch('subprocess.run') as mock_run:
            ssh_to_instance("1.2.3.4", ssh_key="/path/to/key")
            
            args = mock_run.call_args[0][0]
            assert "-i" in args
            assert "/path/to/key" in args
            
    def test_ssh_no_ip_address(self):
        """Test SSH with missing IP address."""
        with pytest.raises(SSHError, match="No IP address available"):
            ssh_to_instance("")
            
        with pytest.raises(SSHError, match="No IP address available"):
            ssh_to_instance(None)
            
    def test_ssh_keyboard_interrupt(self):
        """Test clean exit on Ctrl+C."""
        with patch('subprocess.run', side_effect=KeyboardInterrupt):
            with pytest.raises(SystemExit) as exc_info:
                ssh_to_instance("1.2.3.4")
            assert exc_info.value.code == 0
            
    def test_ssh_general_exception(self):
        """Test SSH connection failure."""
        with patch('subprocess.run', side_effect=Exception("Connection failed")):
            with pytest.raises(SSHError, match="SSH connection failed: Connection failed"):
                ssh_to_instance("1.2.3.4")
                
    def test_ssh_args_construction(self):
        """Test proper SSH argument construction."""
        with patch('subprocess.run') as mock_run:
            ssh_to_instance(
                ip="1.2.3.4",
                user="myuser",
                ssh_key="/home/user/.ssh/custom_key"
            )
            
            expected_args = [
                "ssh",
                "-i", "/home/user/.ssh/custom_key",
                "-o", "StrictHostKeyChecking=no",
                "-o", "UserKnownHostsFile=/dev/null",
                "-o", "ConnectTimeout=10",
                "myuser@1.2.3.4"
            ]
            
            mock_run.assert_called_once_with(expected_args, check=False)