from click.testing import CliRunner

from gsearch_mcp_cli.cli.main import cli


def test_config_show():
    runner = CliRunner()
    result = runner.invoke(cli, ["config", "show"])
    assert result.exit_code == 0
    assert "browser" in result.output


def test_config_set_help():
    runner = CliRunner()
    result = runner.invoke(cli, ["config", "set", "--help"])
    assert result.exit_code == 0


def test_doctor_help():
    runner = CliRunner()
    result = runner.invoke(cli, ["doctor", "--help"])
    assert result.exit_code == 0


def test_setup_help():
    runner = CliRunner()
    result = runner.invoke(cli, ["setup", "--help"])
    assert result.exit_code == 0
    assert "--reset" in result.output
    assert "--check" in result.output


def test_skill_list():
    runner = CliRunner()
    result = runner.invoke(cli, ["skill", "list"])
    assert result.exit_code == 0
    assert "claude-code" in result.output
    assert "cursor" in result.output
    assert "cc-claw" in result.output
    assert "openclaw" in result.output
    assert "opencode" in result.output
    assert "antigravity" in result.output
    assert "cline" in result.output
    assert "agents" in result.output


def test_skill_install_help():
    runner = CliRunner()
    result = runner.invoke(cli, ["skill", "install", "--help"])
    assert result.exit_code == 0


def test_skill_install_creates_files(tmp_path):
    from gsearch_mcp_cli.cli.skill_cmd import _install_to
    target = tmp_path / "test-skill"
    _install_to(target)
    assert (target / "SKILL.md").is_file()
    assert (target / "references").is_dir()


def test_skill_install_all(tmp_path, monkeypatch):
    """gsearch skill install all should install to all tool user paths."""
    import gsearch_mcp_cli.cli.skill_cmd as mod

    # Monkeypatch TOOL_CONFIGS to use temp dirs
    test_configs = {
        "tool-a": {"user": tmp_path / "a-skills", "description": "Test A"},
        "tool-b": {"user": tmp_path / "b-skills", "description": "Test B"},
    }
    monkeypatch.setattr(mod, "TOOL_CONFIGS", test_configs)

    runner = CliRunner()
    result = runner.invoke(cli, ["skill", "install", "all"])
    assert result.exit_code == 0
    assert (tmp_path / "a-skills" / "SKILL.md").is_file()
    assert (tmp_path / "b-skills" / "SKILL.md").is_file()
    assert "Summary" in result.output


def test_skill_install_comma_separated(tmp_path, monkeypatch):
    """gsearch skill install tool-a,tool-b should install to both."""
    import gsearch_mcp_cli.cli.skill_cmd as mod

    test_configs = {
        "tool-a": {"user": tmp_path / "a-skills", "description": "Test A"},
        "tool-b": {"user": tmp_path / "b-skills", "description": "Test B"},
        "other": {"project": tmp_path / "other", "description": "Other"},
    }
    monkeypatch.setattr(mod, "TOOL_CONFIGS", test_configs)

    runner = CliRunner()
    result = runner.invoke(cli, ["skill", "install", "tool-a,tool-b"])
    assert result.exit_code == 0
    assert (tmp_path / "a-skills" / "SKILL.md").is_file()
    assert (tmp_path / "b-skills" / "SKILL.md").is_file()


def test_skill_install_invalid_target():
    """Invalid target should fail with a clear error."""
    runner = CliRunner()
    result = runner.invoke(cli, ["skill", "install", "nonexistent"])
    assert result.exit_code != 0
    assert "Unknown target" in result.output


def test_skill_update_shows_version(tmp_path, monkeypatch):
    """gsearch skill update should show version transition."""
    import gsearch_mcp_cli.cli.skill_cmd as mod

    # Pre-install an older version
    skill_dir = tmp_path / "skills"
    skill_dir.mkdir()
    (skill_dir / "SKILL.md").write_text('---\nversion: "0.0.1"\n---\n# Test\n')

    test_configs = {
        "tool-a": {"user": skill_dir, "description": "Test A"},
    }
    monkeypatch.setattr(mod, "TOOL_CONFIGS", test_configs)

    runner = CliRunner()
    result = runner.invoke(cli, ["skill", "update"])
    assert result.exit_code == 0
    assert "Updating" in result.output
    assert "tool-a" in result.output


def test_extract_version():
    """_extract_version should parse SKILL.md frontmatter."""
    import tempfile
    from pathlib import Path

    from gsearch_mcp_cli.cli.skill_cmd import _extract_version

    with tempfile.NamedTemporaryFile(mode="w", suffix=".md", delete=False) as f:
        f.write('---\nname: test\nversion: "1.2.3"\n---\n# Hello\n')
        f.flush()
        assert _extract_version(Path(f.name)) == "1.2.3"


# -- Setup MCP tests --

def test_setup_add_list():
    runner = CliRunner()
    result = runner.invoke(cli, ["setup", "list"])
    assert result.exit_code == 0
    assert "claude-code" in result.output
    assert "cursor" in result.output
    assert "gemini-cli" in result.output
    assert "windsurf" in result.output
    assert "cline" in result.output
    assert "antigravity" in result.output
    assert "codex" in result.output
    assert "opencode" in result.output


def test_setup_add_json():
    runner = CliRunner()
    result = runner.invoke(cli, ["setup", "add", "json"])
    assert result.exit_code == 0
    assert "gsearch-mcp" in result.output
    assert "mcpServers" in result.output
    assert "uvx" in result.output


def test_setup_add_help():
    runner = CliRunner()
    result = runner.invoke(cli, ["setup", "add", "--help"])
    assert result.exit_code == 0


def test_setup_add_invalid_tool():
    """Invalid tool should fail with a clear error."""
    runner = CliRunner()
    result = runner.invoke(cli, ["setup", "add", "nonexistent"])
    assert result.exit_code != 0
    assert "Unknown tool" in result.output


def test_setup_add_json_config(tmp_path, monkeypatch):
    """gsearch setup add should create a JSON config for json-method tools."""
    import gsearch_mcp_cli.cli.setup_cmd as mod

    config_file = tmp_path / "settings.json"
    test_registry = {
        "test-tool": {
            "name": "Test Tool",
            "description": "A test",
            "method": "json",
            "config_path_fn": lambda: config_file,
        },
    }
    monkeypatch.setattr(mod, "CLIENT_REGISTRY", test_registry)

    runner = CliRunner()
    result = runner.invoke(cli, ["setup", "add", "test-tool"])
    assert result.exit_code == 0
    assert "Added" in result.output
    assert config_file.exists()

    # Second run should say "Updated"
    result2 = runner.invoke(cli, ["setup", "add", "test-tool"])
    assert result2.exit_code == 0
    assert "Updated" in result2.output


def test_setup_add_comma_separated(tmp_path, monkeypatch):
    """gsearch setup add tool-a,tool-b should configure both."""
    import gsearch_mcp_cli.cli.setup_cmd as mod

    config_a = tmp_path / "a.json"
    config_b = tmp_path / "b.json"
    test_registry = {
        "tool-a": {
            "name": "Tool A",
            "description": "A",
            "method": "json",
            "config_path_fn": lambda: config_a,
        },
        "tool-b": {
            "name": "Tool B",
            "description": "B",
            "method": "json",
            "config_path_fn": lambda: config_b,
        },
    }
    monkeypatch.setattr(mod, "CLIENT_REGISTRY", test_registry)

    runner = CliRunner()
    result = runner.invoke(cli, ["setup", "add", "tool-a,tool-b"])
    assert result.exit_code == 0
    assert config_a.exists()
    assert config_b.exists()


def test_setup_remove_help():
    runner = CliRunner()
    result = runner.invoke(cli, ["setup", "remove", "--help"])
    assert result.exit_code == 0
