"""Step definitions for RemoteGraphManager scenarios in langgraph_platform_remote_graph.feature."""

from __future__ import annotations

from behave import given, then, when  # type: ignore[import-untyped]
from behave.runner import Context  # type: ignore[import-untyped]

from cleveragents.langgraph.remote_graph import (
    RemoteGraphConfig,
    RemoteGraphManager,
    RemoteGraphNotAvailableError,
)

# ---------------------------------------------------------------------------
# RemoteGraphManager — not configured
# ---------------------------------------------------------------------------


@given("a RemoteGraphManager with no platform URL")
def step_manager_no_platform_url(context: Context) -> None:
    context.manager = RemoteGraphManager()


@then("the manager should not be available")
def step_manager_not_available(context: Context) -> None:
    assert not context.manager.is_available, (
        "Expected manager.is_available=False but got True"
    )


@then("the manager platform_url should be None")
def step_manager_platform_url_none(context: Context) -> None:
    assert context.manager.platform_url is None, (
        f"Expected platform_url=None, got {context.manager.platform_url!r}"
    )


@when("I try to register a graph on the unconfigured manager")
def step_try_register_unconfigured(context: Context) -> None:
    try:
        config = RemoteGraphConfig(
            graph_id="test-actor",
            platform_url="https://langgraph.example.com",
        )
        context.manager.register_graph(config)
        context.manager_error = None
    except RemoteGraphNotAvailableError as exc:
        context.manager_error = exc


@when("I try to list graphs on the unconfigured manager")
def step_try_list_unconfigured(context: Context) -> None:
    try:
        context.manager.list_graphs()
        context.manager_error = None
    except RemoteGraphNotAvailableError as exc:
        context.manager_error = exc


@when("I try to invoke a graph on the unconfigured manager")
def step_try_invoke_unconfigured(context: Context) -> None:
    try:
        context.manager.invoke("test-actor", {})
        context.manager_error = None
    except RemoteGraphNotAvailableError as exc:
        context.manager_error = exc


@then("a RemoteGraphNotAvailableError should be raised")
def step_remote_graph_not_available_error(context: Context) -> None:
    assert isinstance(context.manager_error, RemoteGraphNotAvailableError), (
        f"Expected RemoteGraphNotAvailableError, got {type(context.manager_error)!r}"
    )


@when("I call health_check on the unconfigured manager")
def step_health_check_unconfigured(context: Context) -> None:
    context.health_check_result = context.manager.health_check()


@then("the health check result should be False")
def step_health_check_false(context: Context) -> None:
    assert context.health_check_result is False, (
        f"Expected health_check=False, got {context.health_check_result!r}"
    )


# ---------------------------------------------------------------------------
# RemoteGraphManager — configured
# ---------------------------------------------------------------------------


@given('a RemoteGraphManager with platform URL "{platform_url}"')
def step_manager_with_platform_url(context: Context, platform_url: str) -> None:
    context.manager = RemoteGraphManager(platform_url=platform_url)
    context.platform_url = platform_url


@then("the manager should be available")
def step_manager_available(context: Context) -> None:
    assert context.manager.is_available, (
        "Expected manager.is_available=True but got False"
    )


@then('the manager platform_url should be "{expected}"')
def step_manager_platform_url(context: Context, expected: str) -> None:
    assert context.manager.platform_url == expected, (
        f"Expected platform_url={expected!r}, got {context.manager.platform_url!r}"
    )


@when('I register a graph with id "{graph_id}"')
def step_register_graph(context: Context, graph_id: str) -> None:
    config = RemoteGraphConfig(
        graph_id=graph_id,
        platform_url=context.platform_url,
    )
    context.manager.register_graph(config)
    context.last_registered_graph_id = graph_id
    context.last_registered_config = config


@then('the graph "{graph_id}" should be registered')
def step_graph_registered(context: Context, graph_id: str) -> None:
    graphs = context.manager.list_graphs()
    assert graph_id in graphs, (
        f"Expected {graph_id!r} in registered graphs, got {graphs!r}"
    )


@when('I register graphs with ids "{graph_id_a}" and "{graph_id_b}"')
def step_register_two_graphs(
    context: Context, graph_id_a: str, graph_id_b: str
) -> None:
    for gid in (graph_id_a, graph_id_b):
        config = RemoteGraphConfig(
            graph_id=gid,
            platform_url=context.platform_url,
        )
        context.manager.register_graph(config)
    context.registered_graph_ids = [graph_id_a, graph_id_b]


@then('list_graphs should return "{graph_id_a}" and "{graph_id_b}" in sorted order')
def step_list_graphs_sorted(context: Context, graph_id_a: str, graph_id_b: str) -> None:
    graphs = context.manager.list_graphs()
    expected = sorted([graph_id_a, graph_id_b])
    assert graphs == expected, f"Expected {expected!r}, got {graphs!r}"


@then('get_graph_config for "{graph_id}" should return the config')
def step_get_graph_config(context: Context, graph_id: str) -> None:
    config = context.manager.get_graph_config(graph_id)
    assert config.graph_id == graph_id, (
        f"Expected config.graph_id={graph_id!r}, got {config.graph_id!r}"
    )


@when('I try to get config for unregistered graph "{graph_id}"')
def step_try_get_config_unregistered(context: Context, graph_id: str) -> None:
    try:
        context.manager.get_graph_config(graph_id)
        context.manager_error = None
    except KeyError as exc:
        context.manager_error = exc


@then("a KeyError should be raised for the unknown graph")
def step_key_error_unknown_graph(context: Context) -> None:
    assert isinstance(context.manager_error, KeyError), (
        f"Expected KeyError, got {type(context.manager_error)!r}"
    )


@when('I register then unregister graph "{graph_id}"')
def step_register_then_unregister(context: Context, graph_id: str) -> None:
    config = RemoteGraphConfig(
        graph_id=graph_id,
        platform_url=context.platform_url,
    )
    context.manager.register_graph(config)
    context.manager.unregister_graph(graph_id)


@then('the graph "{graph_id}" should not be registered')
def step_graph_not_registered(context: Context, graph_id: str) -> None:
    graphs = context.manager.list_graphs()
    assert graph_id not in graphs, (
        f"Expected {graph_id!r} NOT in registered graphs, but found it in {graphs!r}"
    )


@when('I try to unregister an unknown graph "{graph_id}"')
def step_try_unregister_unknown(context: Context, graph_id: str) -> None:
    try:
        context.manager.unregister_graph(graph_id)
        context.manager_error = None
    except KeyError as exc:
        context.manager_error = exc


@then("a KeyError should be raised for the unregistered graph")
def step_key_error_unregistered_graph(context: Context) -> None:
    assert isinstance(context.manager_error, KeyError), (
        f"Expected KeyError, got {type(context.manager_error)!r}"
    )


@when('I try to invoke the registered graph "{graph_id}"')
def step_try_invoke_registered(context: Context, graph_id: str) -> None:
    try:
        context.manager.invoke(graph_id, {"messages": []})
        context.manager_error = None
    except RemoteGraphNotAvailableError as exc:
        context.manager_error = exc


@then("a RemoteGraphNotAvailableError should be raised for the stub invocation")
def step_remote_graph_not_available_stub(context: Context) -> None:
    assert isinstance(context.manager_error, RemoteGraphNotAvailableError), (
        f"Expected RemoteGraphNotAvailableError, got {type(context.manager_error)!r}"
    )


@when('I try to invoke unregistered graph "{graph_id}"')
def step_try_invoke_unregistered(context: Context, graph_id: str) -> None:
    try:
        context.manager.invoke(graph_id, {})
        context.manager_error = None
    except KeyError as exc:
        context.manager_error = exc
    except RemoteGraphNotAvailableError as exc:
        context.manager_error = exc


@then("a KeyError should be raised for the missing graph invocation")
def step_key_error_missing_graph(context: Context) -> None:
    assert isinstance(context.manager_error, KeyError), (
        f"Expected KeyError, got {type(context.manager_error)!r}"
    )


@when("I call health_check on the configured manager")
def step_health_check_configured(context: Context) -> None:
    context.health_check_result = context.manager.health_check()
