"""Step definitions for a2a_cli_facade_integration.feature.

Tests the integration between CLI commands and the A2A local facade,
verifying that the facade bootstrap, dispatch helpers, and
notification wrappers work correctly.
"""

from __future__ import annotations

from typing import Any
from unittest.mock import MagicMock, patch

from behave import given, then, when

try:
    from cleveragents.a2a.cli_bootstrap import get_facade, reset_facade
    from cleveragents.a2a.facade import A2aLocalFacade
    from cleveragents.a2a.models import A2aRequest
except ImportError:
    pass  # a2a module not available

# ---------------------------------------------------------------------------
# Given
# ---------------------------------------------------------------------------


@given("a facade created via the CLI bootstrap")
def step_create_bootstrap_facade(context: Any) -> None:
    reset_facade()
    context.facade = get_facade()


@given("a facade with a mock session service")
def step_facade_with_mock_session(context: Any) -> None:
    mock_session_svc = MagicMock()
    mock_session_svc.create.return_value = MagicMock(
        session_id="test-session-001",
        actor_name="stub",
    )
    context.facade = A2aLocalFacade(services={"session_service": mock_session_svc})


@given("a facade with a mock plan lifecycle service")
def step_facade_with_mock_plan(context: Any) -> None:
    mock_plan_svc = MagicMock()
    mock_plan_svc.get_plan.return_value = MagicMock(
        identity=MagicMock(plan_id="test-plan-001"),
        phase=MagicMock(value="execute"),
        state=MagicMock(value="complete"),
    )
    context.facade = A2aLocalFacade(services={"plan_lifecycle_service": mock_plan_svc})


@given("a facade that raises an error on dispatch")
def step_facade_raises_error(context: Any) -> None:
    context.error_facade = MagicMock(spec=A2aLocalFacade)
    context.error_facade.dispatch.side_effect = RuntimeError("test error")


# ---------------------------------------------------------------------------
# When
# ---------------------------------------------------------------------------


@when("I dispatch a session.create operation via the CLI facade helper")
def step_dispatch_session_create(context: Any) -> None:
    request = A2aRequest(method="session.create", params={"actor": "stub"})
    context.response = context.facade.dispatch(request)


@when("I dispatch a plan.create operation via the CLI facade helper")
def step_dispatch_plan_create(context: Any) -> None:
    request = A2aRequest(method="plan.create", params={"action_name": "test"})
    context.response = context.facade.dispatch(request)


@when("I dispatch a plan.execute operation via the CLI facade helper")
def step_dispatch_plan_execute(context: Any) -> None:
    request = A2aRequest(method="plan.execute", params={"plan_id": "test-plan-001"})
    context.response = context.facade.dispatch(request)


@when("I dispatch a plan.apply operation via the CLI facade helper")
def step_dispatch_plan_apply(context: Any) -> None:
    request = A2aRequest(method="plan.apply", params={"plan_id": "test-plan-001"})
    context.response = context.facade.dispatch(request)


@when("I dispatch a plan.status operation via the CLI facade helper")
def step_dispatch_plan_status(context: Any) -> None:
    request = A2aRequest(method="plan.status", params={"plan_id": "test-plan-001"})
    context.response = context.facade.dispatch(request)


@when("I dispatch a plan.diff operation via the CLI facade helper")
def step_dispatch_plan_diff(context: Any) -> None:
    request = A2aRequest(method="plan.diff", params={"plan_id": "test-plan-001"})
    context.response = context.facade.dispatch(request)


@when('I call the plan notify_facade helper with operation "{operation}"')
def step_call_notify_facade(context: Any, operation: str) -> None:
    # Patch the bootstrap module so _notify_facade gets the error facade
    with patch(
        "cleveragents.a2a.cli_bootstrap.get_facade",
        return_value=context.error_facade,
    ):
        from cleveragents.a2a.cli_bootstrap import reset_facade

        reset_facade()
        from cleveragents.cli.commands.plan import _notify_facade

        # This should not raise even though the facade errors
        context.notify_exception = None
        try:
            _notify_facade(operation, {"plan_id": "test"})
        except Exception as e:
            context.notify_exception = e
    reset_facade()


# ---------------------------------------------------------------------------
# Then
# ---------------------------------------------------------------------------


@then("the facade should support all 42 operations")
def step_check_42_operations(context: Any) -> None:
    ops = context.facade.list_operations()
    assert len(ops) == 42, f"Expected 42 operations, got {len(ops)}: {ops}"


@then("the facade should be cached on subsequent calls")
def step_check_facade_cached(context: Any) -> None:
    facade2 = get_facade()
    assert facade2 is context.facade, "Facade should be the same cached instance"
    reset_facade()


@then("the facade should return an ok response")
def step_check_ok_response(context: Any) -> None:
    assert context.response.error is None, (
        f"Expected no error, got error: {context.response.error}"
    )


@then("no exception should propagate to the caller")
def step_check_no_exception(context: Any) -> None:
    assert context.notify_exception is None, (
        f"Expected no exception, got: {context.notify_exception}"
    )
