"""Helper for LSP resource type Robot integration tests.

Issue: #832
"""

from __future__ import annotations

import sys
from typing import Any


def _import_lsp_types() -> None:
    """Verify LSP_RESOURCE_TYPES can be imported."""
    from cleveragents.application.services._resource_registry_lsp import (
        LSP_RESOURCE_TYPES,
    )

    assert len(LSP_RESOURCE_TYPES) == 4, f"Expected 4, got {len(LSP_RESOURCE_TYPES)}"
    names = [t["name"] for t in LSP_RESOURCE_TYPES]
    for expected in ("executable", "lsp-server", "lsp-workspace", "lsp-document"):
        assert expected in names, f"{expected} not in LSP_RESOURCE_TYPES: {names}"

    print("import-lsp-types-ok")


def _check_builtin_names() -> None:
    """Verify all 4 LSP types are in BUILTIN_NAMES."""
    from cleveragents.domain.models.core.resource_type import ResourceTypeSpec

    for name in ("executable", "lsp-server", "lsp-workspace", "lsp-document"):
        assert name in ResourceTypeSpec.BUILTIN_NAMES, f"{name} not in BUILTIN_NAMES"

    print("check-builtin-names-ok")


def _db_roundtrip() -> None:
    """Bootstrap in-memory DB and verify all 4 LSP types are retrievable."""
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker

    from cleveragents.application.services.resource_registry_service import (
        ResourceRegistryService,
    )
    from cleveragents.infrastructure.database.models import Base

    engine = create_engine("sqlite:///:memory:", echo=False)
    Base.metadata.create_all(engine)
    factory = sessionmaker(bind=engine, expire_on_commit=False)
    svc = ResourceRegistryService(session_factory=factory)

    for name in ("executable", "lsp-server", "lsp-workspace", "lsp-document"):
        spec = svc.show_type(name)
        assert spec is not None, f"{name} not found after bootstrap"
        assert str(spec.resource_kind) == "physical", (
            f"{name} kind: {spec.resource_kind}"
        )
        assert str(spec.sandbox_strategy) == "none", (
            f"{name} strategy: {spec.sandbox_strategy}"
        )

    print("db-roundtrip-ok")


def _check_hierarchy() -> None:
    """Verify parent/child relationships: server->workspace->document."""
    from cleveragents.application.services._resource_registry_lsp import (
        LSP_RESOURCE_TYPES,
    )

    types = {t["name"]: t for t in LSP_RESOURCE_TYPES}

    # lsp-server has lsp-workspace as child
    assert "lsp-workspace" in types["lsp-server"]["child_types"], (
        "lsp-server missing lsp-workspace child"
    )
    # lsp-workspace has lsp-server as parent
    assert "lsp-server" in types["lsp-workspace"]["parent_types"], (
        "lsp-workspace missing lsp-server parent"
    )
    # lsp-workspace has lsp-document as child
    assert "lsp-document" in types["lsp-workspace"]["child_types"], (
        "lsp-workspace missing lsp-document child"
    )
    # lsp-document has lsp-workspace as parent
    assert "lsp-workspace" in types["lsp-document"]["parent_types"], (
        "lsp-document missing lsp-workspace parent"
    )
    # executable has no children
    assert types["executable"]["child_types"] == [], (
        "executable should have no children"
    )

    print("check-hierarchy-ok")


def _check_auto_discovery() -> None:
    """Verify executable has auto_discovery with trigger_types."""
    from cleveragents.application.services._resource_registry_lsp import (
        LSP_RESOURCE_TYPES,
    )

    types = {t["name"]: t for t in LSP_RESOURCE_TYPES}

    # executable has auto_discovery
    ad = types["executable"].get("auto_discovery")
    assert ad is not None, "executable missing auto_discovery"
    assert "container-exec-env" in ad.get("trigger_types", []), (
        "executable missing container-exec-env trigger"
    )
    assert ad.get("lazy") is True, "executable auto_discovery should be lazy"

    # lsp-workspace has auto_discovery from lsp-server
    ad_ws = types["lsp-workspace"].get("auto_discovery")
    assert ad_ws is not None, "lsp-workspace missing auto_discovery"
    assert "lsp-server" in ad_ws.get("trigger_types", []), (
        "lsp-workspace missing lsp-server trigger"
    )

    print("check-auto-discovery-ok")


def _check_user_addable_guard() -> None:
    """Verify lsp-workspace and lsp-document reject manual registration."""
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker

    from cleveragents.application.services.resource_registry_service import (
        ResourceRegistryService,
    )
    from cleveragents.infrastructure.database.models import Base

    engine = create_engine("sqlite:///:memory:", echo=False)
    Base.metadata.create_all(engine)
    factory = sessionmaker(bind=engine, expire_on_commit=False)
    svc = ResourceRegistryService(session_factory=factory)

    for non_addable in ("lsp-workspace", "lsp-document"):
        try:
            svc.register_resource(type_name=non_addable, name=f"test-{non_addable}")
            print(f"FAIL: {non_addable} registration should have been rejected")
            sys.exit(1)
        except Exception as exc:
            assert "not user-addable" in str(exc), (
                f"{non_addable}: expected 'not user-addable' in error, got: {exc}"
            )

    print("check-user-addable-guard-ok")


_COMMANDS: dict[str, Any] = {
    "import-lsp-types": _import_lsp_types,
    "check-builtin-names": _check_builtin_names,
    "db-roundtrip": _db_roundtrip,
    "check-hierarchy": _check_hierarchy,
    "check-auto-discovery": _check_auto_discovery,
    "check-user-addable-guard": _check_user_addable_guard,
}

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <command>")
        print(f"Commands: {', '.join(sorted(_COMMANDS))}")
        sys.exit(1)

    cmd = sys.argv[1]
    fn = _COMMANDS.get(cmd)
    if fn is None:
        print(f"Unknown command: {cmd}")
        sys.exit(1)

    try:
        fn()
    except Exception as exc:
        print(f"FAIL [{cmd}]: {type(exc).__name__}: {exc}")
        import traceback

        traceback.print_exc()
        sys.exit(1)
