"""Helper script for Robot Framework LSP registry smoke tests.

Usage:
    python helper_lsp_registry.py <command>

Commands:
    register-and-get     Register an LSP server and retrieve it
    list-filter          Register servers and list with namespace filter
    remove-server        Register and remove an LSP server
    runtime-stub         Verify runtime stub raises in local mode
    tool-adapter         Verify tool adapter generates specs
"""

from __future__ import annotations

import sys
from pathlib import Path

# Ensure src is on the path
src_dir = str(Path(__file__).resolve().parents[1] / "src")
if src_dir not in sys.path:
    sys.path.insert(0, src_dir)

from cleveragents.lsp.errors import (  # noqa: E402
    LspError,
    LspNotAvailableError,
    LspServerNotFoundError,
)
from cleveragents.lsp.models import (  # noqa: E402
    LspCapability,
    LspServerConfig,
)
from cleveragents.lsp.registry import LspRegistry  # noqa: E402
from cleveragents.lsp.runtime import LspRuntime  # noqa: E402
from cleveragents.lsp.tool_adapter import LspToolAdapter  # noqa: E402


def _make_config(
    name: str,
    command: str = "stub-cmd",
    languages: list[str] | None = None,
    capabilities: list[LspCapability] | None = None,
) -> LspServerConfig:
    return LspServerConfig(
        name=name,
        command=command,
        languages=languages or [],
        capabilities=capabilities or [],
    )


def cmd_register_and_get() -> None:
    registry = LspRegistry()
    config = _make_config("local/pyright", "pyright-langserver", ["python"])
    registry.register(config)

    result = registry.get("local/pyright")
    assert result is not None, "LSP server not found"
    assert result.name == "local/pyright"
    assert "python" in result.languages
    print("lsp-registry-ok")


def cmd_list_filter() -> None:
    registry = LspRegistry()
    registry.register(_make_config("local/pyright", languages=["python"]))
    registry.register(_make_config("local/tsserver", languages=["typescript"]))
    registry.register(_make_config("devops/clangd", languages=["c"]))

    all_servers = registry.list_servers()
    assert len(all_servers) == 3

    local_servers = registry.list_servers(namespace="local")
    assert len(local_servers) == 2

    python_servers = registry.list_servers(language="python")
    assert len(python_servers) == 1

    print("lsp-list-ok")


def cmd_remove_server() -> None:
    registry = LspRegistry()
    registry.register(_make_config("local/pyright", languages=["python"]))

    assert registry.remove("local/pyright") is True
    assert registry.get("local/pyright") is None
    assert registry.remove("local/pyright") is False
    print("lsp-remove-ok")


def cmd_runtime_stub() -> None:
    runtime = LspRuntime()

    # The functional runtime raises LspServerNotFoundError for
    # unregistered servers (not LspNotAvailableError like the old stub).
    for fn_name, args in [
        ("start_server", ("local/pyright", "/tmp")),
        ("stop_server", ("local/pyright",)),
        ("get_diagnostics", ("local/pyright", "/tmp/test.py")),
        ("get_completions", ("local/pyright", "/tmp/test.py", 1, 1)),
    ]:
        try:
            getattr(runtime, fn_name)(*args)
            print(f"FAIL: {fn_name} should have raised an error")
            sys.exit(1)
        except (LspNotAvailableError, LspServerNotFoundError, LspError):
            pass

    print("lsp-runtime-stub-ok")


def cmd_tool_adapter() -> None:
    config = _make_config(
        "local/pyright",
        languages=["python"],
        capabilities=[LspCapability.DIAGNOSTICS, LspCapability.COMPLETIONS],
    )
    adapter = LspToolAdapter()
    specs = adapter.generate_tool_specs(config)

    assert len(specs) == 2, f"Expected 2 specs, got {len(specs)}"
    names = {s["name"] for s in specs}
    assert "local/pyright/diagnostics" in names
    assert "local/pyright/completions" in names

    # Verify handler raises in local mode
    try:
        specs[0]["handler"]()
        print("FAIL: handler should have raised LspNotAvailableError")
        sys.exit(1)
    except LspNotAvailableError:
        pass

    print("lsp-tool-adapter-ok")


COMMANDS = {
    "register-and-get": cmd_register_and_get,
    "list-filter": cmd_list_filter,
    "remove-server": cmd_remove_server,
    "runtime-stub": cmd_runtime_stub,
    "tool-adapter": cmd_tool_adapter,
}


if __name__ == "__main__":
    if len(sys.argv) < 2 or sys.argv[1] not in COMMANDS:
        print(f"Usage: {sys.argv[0]} <{'|'.join(COMMANDS)}>", file=sys.stderr)
        sys.exit(1)
    COMMANDS[sys.argv[1]]()
