"""Test CLI commands."""

import pytest
from click.testing import CliRunner
from unittest.mock import patch, MagicMock
from mcpbundles.cli import cli


@pytest.fixture
def runner():
    """Click CLI test runner."""
    return CliRunner()


def test_cli_version(runner):
    """Test version command."""
    result = runner.invoke(cli, ['--version'])
    assert result.exit_code == 0
    assert 'mcpbundles' in result.output
    assert 'version' in result.output


def test_cli_help(runner):
    """Test help command."""
    result = runner.invoke(cli, ['--help'])
    assert result.exit_code == 0
    assert 'MCPBundles CLI' in result.output
    assert 'login' in result.output
    assert 'tools' in result.output
    assert 'call' in result.output
    assert 'exec' in result.output
    assert 'shell' in result.output


def test_login_api_key(runner, tmp_path):
    """Test login with API key."""
    with patch('mcpbundles.commands.auth.save_token') as mock_save:
        result = runner.invoke(cli, ['login', '--api-key', 'mb_test_key'])
        assert result.exit_code == 0
        assert 'Authenticated' in result.output
        mock_save.assert_called_once_with({"access_token": "mb_test_key", "auth_type": "api_key"})


def test_login_oauth(runner):
    """Test login via OAuth flow."""
    with patch('mcpbundles.commands.auth.oauth_flow') as mock_oauth:
        mock_oauth.return_value = {"access_token": "test_token"}
        result = runner.invoke(cli, ['login'])
        assert result.exit_code == 0
        assert 'Authenticated' in result.output


def test_login_oauth_failure(runner):
    """Test OAuth login failure."""
    with patch('mcpbundles.commands.auth.oauth_flow') as mock_oauth:
        mock_oauth.side_effect = Exception("OAuth failed")
        result = runner.invoke(cli, ['login'])
        assert result.exit_code == 1
        assert 'Authentication failed' in result.output


def test_whoami_not_authenticated(runner):
    """Test whoami when not logged in."""
    with patch('mcpbundles.commands.auth.load_token', return_value=None):
        result = runner.invoke(cli, ['whoami'])
        assert result.exit_code == 1
        assert 'Not authenticated' in result.output


def test_whoami_authenticated(runner):
    """Test whoami when logged in."""
    with patch('mcpbundles.commands.auth.load_token', return_value={"access_token": "mb_test", "auth_type": "api_key"}):
        result = runner.invoke(cli, ['whoami'], catch_exceptions=False)
        assert result.exit_code == 0


def test_whoami_json(runner):
    """Test whoami JSON output."""
    with patch('mcpbundles.commands.auth.load_token', return_value={"access_token": "mb_test", "auth_type": "api_key"}):
        result = runner.invoke(cli, ['whoami', '--json'])
        assert result.exit_code == 0
        assert '"auth_type"' in result.output
        assert '"api_key"' in result.output


def test_logout(runner):
    """Test logout command."""
    with patch('mcpbundles.commands.auth.get_pid_file') as mock_pid:
        mock_pid.return_value = MagicMock(exists=MagicMock(return_value=False))
        with patch('mcpbundles.commands.auth.delete_token') as mock_delete:
            with patch('mcpbundles.connections.ConnectionManager.remove_all', return_value=0):
                result = runner.invoke(cli, ['logout'])
                assert result.exit_code == 0
                assert 'Logged out' in result.output
                mock_delete.assert_called_once()


def test_config_show(runner):
    """Test config show command."""
    with patch('mcpbundles.commands.config_cmd.config_with_defaults', return_value={"server": "https://mcp.mcpbundles.com", "output": "auto", "completion_ttl": 60}):
        result = runner.invoke(cli, ['config', 'show'], catch_exceptions=False)
        assert result.exit_code == 0


def test_config_get(runner):
    """Test config get command."""
    with patch('mcpbundles.commands.config_cmd.config_with_defaults', return_value={"server": "https://mcp.mcpbundles.com", "output": "auto"}):
        result = runner.invoke(cli, ['config', 'get', 'server'])
        assert result.exit_code == 0
        assert 'mcp.mcpbundles.com' in result.output


def test_config_set(runner):
    """Test config set command."""
    with patch('mcpbundles.commands.config_cmd.load_config', return_value={}):
        with patch('mcpbundles.commands.config_cmd.save_config') as mock_save:
            result = runner.invoke(cli, ['config', 'set', 'output', 'json'])
            assert result.exit_code == 0
            mock_save.assert_called_once_with({"output": "json"})


def test_tools_not_authenticated(runner):
    """Test tools command when not logged in and no connections exist."""
    with patch('mcpbundles.config.load_token', return_value=None), \
         patch('mcpbundles.connections.ConnectionManager.list_connections', return_value=[]), \
         patch('mcpbundles.connections.ConnectionManager.get_default', return_value=None):
        result = runner.invoke(cli, ['tools'])
        assert result.exit_code == 1
        assert 'credentials' in result.output or 'Not authenticated' in result.output


def test_connections_empty(runner):
    """Test connections list when empty."""
    with patch('mcpbundles.connections.ConnectionManager.list_connections', return_value=[]):
        result = runner.invoke(cli, ['connections'])
        assert result.exit_code == 0
        assert 'No connections' in result.output


def test_disconnect_not_found(runner):
    """Test disconnect nonexistent connection."""
    with patch('mcpbundles.connections.ConnectionManager.remove', return_value=False):
        result = runner.invoke(cli, ['disconnect', 'nope'])
        assert result.exit_code == 1
        assert 'not found' in result.output
