"""
Tests for cert_trust.cli module
"""
import sys
from io import StringIO
from unittest.mock import patch, MagicMock

import pytest
from cert_trust import cli, core


class TestCLIMain:
    """Test CLI main function."""
    
    def test_main_no_args_shows_help(self, capsys):
        """Running without args should show help."""
        with patch.object(sys, 'argv', ['cert-trust']):
            result = cli.main()
            assert result == 1
    
    def test_main_version(self, capsys):
        """--version should print version and exit."""
        with patch.object(sys, 'argv', ['cert-trust', '--version']):
            with pytest.raises(SystemExit) as exc:
                cli.main()
            assert exc.value.code == 0


class TestEnableCommand:
    """Test enable command."""
    
    def test_enable_success(self):
        """Enable command should call core.enable()."""
        with patch.object(sys, 'argv', ['cert-trust', 'enable']):
            with patch.object(core, 'enable') as mock_enable:
                mock_enable.return_value = {"success": True, "already_enabled": False}
                result = cli.main()
                assert result == 0
                mock_enable.assert_called_once()
    
    def test_enable_already_enabled(self):
        """Enable when already enabled should succeed."""
        with patch.object(sys, 'argv', ['cert-trust', 'enable']):
            with patch.object(core, 'enable') as mock_enable:
                mock_enable.return_value = {"success": True, "already_enabled": True}
                result = cli.main()
                assert result == 0


class TestDisableCommand:
    """Test disable command."""
    
    def test_disable_success(self):
        """Disable command should call core.disable()."""
        with patch.object(sys, 'argv', ['cert-trust', 'disable']):
            with patch.object(core, 'disable') as mock_disable:
                mock_disable.return_value = {"success": True, "was_enabled": True, "removed": []}
                result = cli.main()
                assert result == 0
                mock_disable.assert_called_once()


class TestStatusCommand:
    """Test status command."""
    
    def test_status_normal_output(self):
        """Status should display formatted output."""
        with patch.object(sys, 'argv', ['cert-trust', 'status']):
            with patch.object(core, 'status') as mock_status:
                mock_status.return_value = {
                    "python": {
                        "enabled": True,
                        "env_disabled": False,
                        "effective": True,
                        "pth_files": [],
                        "has_truststore": False,
                    },
                    "curl": {
                        "available": True,
                        "ca_bundle": None,
                        "uses_windows_store": True,
                    },
                    "platform": "Windows",
                    "python_version": "3.12.0",
                }
                result = cli.main()
                assert result == 0
    
    def test_status_json_output(self, capsys):
        """Status --json should output JSON."""
        with patch.object(sys, 'argv', ['cert-trust', 'status', '--json']):
            with patch.object(core, 'status') as mock_status:
                mock_status.return_value = {
                    "python": {"enabled": True},
                    "curl": {"available": True},
                    "platform": "Windows",
                    "python_version": "3.12.0",
                }
                result = cli.main()
                assert result == 0
                captured = capsys.readouterr()
                assert '"python"' in captured.out
                assert '"curl"' in captured.out
    
    def test_status_verbose(self):
        """Status -v should show verbose output."""
        with patch.object(sys, 'argv', ['cert-trust', 'status', '-v']):
            with patch.object(core, 'status') as mock_status:
                mock_status.return_value = {
                    "python": {
                        "enabled": True,
                        "env_disabled": False,
                        "effective": True,
                        "pth_files": ["/path/to/pth"],
                        "has_truststore": True,
                    },
                    "curl": {"available": True},
                    "platform": "Linux",
                    "python_version": "3.12.0",
                }
                result = cli.main()
                assert result == 0


class TestAddCommand:
    """Test add command."""
    
    def test_add_file_not_found(self):
        """Add with nonexistent file should fail."""
        with patch.object(sys, 'argv', ['cert-trust', 'add', '/nonexistent.crt']):
            result = cli.main()
            assert result == 1
    
    def test_add_success(self, tmp_path):
        """Add with valid file should succeed."""
        # Create a temp cert file
        cert_file = tmp_path / "test.crt"
        cert_file.write_text("-----BEGIN CERTIFICATE-----\nfake\n-----END CERTIFICATE-----\n")
        
        with patch.object(sys, 'argv', ['cert-trust', 'add', str(cert_file)]):
            with patch.object(core, 'add_cert') as mock_add:
                mock_add.return_value = {
                    "success": True,
                    "results": {
                        "python_pth": {"success": True},
                        "curl_system": {"success": True},
                    }
                }
                result = cli.main()
                assert result == 0
                mock_add.assert_called_once_with(str(cert_file))
    
    def test_add_json_output(self, tmp_path, capsys):
        """Add --json should output JSON."""
        cert_file = tmp_path / "test.crt"
        cert_file.write_text("-----BEGIN CERTIFICATE-----\nfake\n-----END CERTIFICATE-----\n")
        
        with patch.object(sys, 'argv', ['cert-trust', 'add', str(cert_file), '--json']):
            with patch.object(core, 'add_cert') as mock_add:
                mock_add.return_value = {"success": True, "results": {}}
                result = cli.main()
                assert result == 0
                captured = capsys.readouterr()
                assert '"success"' in captured.out


class TestVerifyCommand:
    """Test verify command."""
    
    def test_verify_success(self):
        """Verify with valid URL should succeed."""
        with patch.object(sys, 'argv', ['cert-trust', 'verify', 'https://example.com']):
            with patch.object(core, 'verify') as mock_verify:
                mock_verify.return_value = {
                    "url": "https://example.com",
                    "curl": {"success": True, "http_code": "200"},
                    "python": {"success": True, "http_code": 200},
                }
                result = cli.main()
                assert result == 0
                mock_verify.assert_called_once_with('https://example.com')
    
    def test_verify_failure(self):
        """Verify with failed connection should return error code."""
        with patch.object(sys, 'argv', ['cert-trust', 'verify', 'https://invalid.test']):
            with patch.object(core, 'verify') as mock_verify:
                mock_verify.return_value = {
                    "url": "https://invalid.test",
                    "curl": {"success": False, "error": "Failed"},
                    "python": {"success": False, "error": "Failed"},
                }
                result = cli.main()
                assert result == 1
    
    def test_verify_json_output(self, capsys):
        """Verify --json should output JSON."""
        with patch.object(sys, 'argv', ['cert-trust', 'verify', 'https://example.com', '--json']):
            with patch.object(core, 'verify') as mock_verify:
                mock_verify.return_value = {
                    "url": "https://example.com",
                    "curl": {"success": True},
                    "python": {"success": True},
                }
                result = cli.main()
                assert result == 0
                captured = capsys.readouterr()
                assert '"url"' in captured.out
                assert 'example.com' in captured.out


class TestPrintHelpers:
    """Test CLI print helper functions."""
    
    def test_print_result_success(self):
        """print_result should return 0 on success."""
        result = cli.print_result({"success": True}, success_msg="Test OK")
        assert result == 0
    
    def test_print_result_failure(self):
        """print_result should return 1 on failure."""
        result = cli.print_result(
            {"success": False, "message": "Error occurred"},
            error_msg="Test failed"
        )
        assert result == 1
    
    def test_print_status_no_rich(self):
        """print_status should work without rich module."""
        status_data = {
            "python": {
                "enabled": True,
                "env_disabled": False,
                "effective": True,
                "pth_files": [],
                "has_truststore": False,
            },
            "curl": {"available": True, "ca_bundle": None, "uses_windows_store": False},
            "platform": "Linux",
            "python_version": "3.12.0",
        }
        
        # Should not raise
        with patch('sys.modules', {'rich': None, 'rich.console': None}):
            cli.print_status(status_data)


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