"""Step definitions for A2A module rename and symbol standardization.

Validates that all A2A symbols are properly exported from the ``cleveragents.a2a``
module following the JSON-RPC 2.0 specification naming convention, that no legacy
ACP references remain in the codebase, and that documentation is accurate.
"""

import inspect
import os
import re

from behave import when, then
import cleveragents.a2a as a2a_module
from cleveragents.a2a import (
    A2aError,
    A2aErrorDetail,
    A2aEvent,
    A2aEventQueue,
    A2aHttpTransport,
    A2aLocalFacade,
    A2aNotAvailableError,
    A2aOperationNotFoundError,
    A2aRequest,
    A2aResponse,
    A2aStdioTransport,
    A2aVersion,
    A2aVersionMismatchError,
    A2aVersionNegotiator,
    AuthClient,
    RemoteExecutionClient,
    ServerClient,
    ServerConnectionConfig,
    StubAuthClient,
    StubRemoteExecutionClient,
    StubServerClient,
    TransportSelector,
)


@when("I import from cleveragents.a2a")
def step_import_a2a(context):
    """Import from cleveragents.a2a."""
    context.a2a_symbols = {
        "A2aError": A2aError,
        "A2aErrorDetail": A2aErrorDetail,
        "A2aEvent": A2aEvent,
        "A2aEventQueue": A2aEventQueue,
        "A2aHttpTransport": A2aHttpTransport,
        "A2aLocalFacade": A2aLocalFacade,
        "A2aNotAvailableError": A2aNotAvailableError,
        "A2aOperationNotFoundError": A2aOperationNotFoundError,
        "A2aRequest": A2aRequest,
        "A2aResponse": A2aResponse,
        "A2aStdioTransport": A2aStdioTransport,
        "A2aVersion": A2aVersion,
        "A2aVersionMismatchError": A2aVersionMismatchError,
        "A2aVersionNegotiator": A2aVersionNegotiator,
        "AuthClient": AuthClient,
        "RemoteExecutionClient": RemoteExecutionClient,
        "ServerClient": ServerClient,
        "ServerConnectionConfig": ServerConnectionConfig,
        "StubAuthClient": StubAuthClient,
        "StubRemoteExecutionClient": StubRemoteExecutionClient,
        "StubServerClient": StubServerClient,
        "TransportSelector": TransportSelector,
    }


@then("I should have access to {symbol_name}")
def step_have_access_to_symbol(context, symbol_name):
    """Verify access to a specific symbol."""
    assert symbol_name in context.a2a_symbols
    assert context.a2a_symbols[symbol_name] is not None


@when("I check the A2A module for ACP references")
def step_check_acp_references(context):
    """Recursively scan all .py files in the A2A module for ACP references."""
    context.acp_references = {
        "imports": [],
        "class_names": [],
        "function_names": [],
    }

    # Recursively scan the entire a2a directory
    a2a_dir = os.path.dirname(inspect.getfile(a2a_module))
    for root, _dirs, files in os.walk(a2a_dir):
        for fname in files:
            if not fname.endswith(".py"):
                continue
            filepath = os.path.join(root, fname)
            with open(filepath, encoding="utf-8") as f:
                content = f.read()
            # Check imports
            acp_import = (
                "from cleveragents.acp" in content
                or "import cleveragents.acp" in content
            )
            if acp_import:
                context.acp_references["imports"].append(filepath)
            # Check class/function names for ACP prefix remnants
            acp_patterns = re.findall(r"\s+def\s+(_?[Aa][Cc][Pp]\w*)", content)
            acp_patterns += re.findall(r"\(\s*(_?[Aa][Cc][Pp]\w*)\)", content)
            for match in acp_patterns:
                context.acp_references["function_names"].append(match)

            acp_class_patterns = re.findall(r"class\s+(_?[Aa][Cc][Pp]\w*)", content)
            for match in acp_class_patterns:
                context.acp_references["class_names"].append(match)


@then("there should be no ACP imports")
def step_no_acp_imports(context):
    """Verify no ACP imports."""
    assert len(context.acp_references["imports"]) == 0


@then("there should be no ACP class names")
def step_no_acp_class_names(context):
    """Verify no ACP class names."""
    assert len(context.acp_references["class_names"]) == 0


@then("there should be no ACP function names")
def step_no_acp_function_names(context):
    """Verify no ACP function names."""
    assert len(context.acp_references["function_names"]) == 0


# Symbol definitions used by Step 3 to validate A2A documentation.
# Self-contained: does not depend on context set by other scenarios.
_A2A_DOCUMENTATION_SYMBOLS = {
    "A2aError": A2aError,
    "A2aErrorDetail": A2aErrorDetail,
    "A2aEvent": A2aEvent,
    "A2aEventQueue": A2aEventQueue,
    "A2aHttpTransport": A2aHttpTransport,
    "A2aLocalFacade": A2aLocalFacade,
    "A2aNotAvailableError": A2aNotAvailableError,
    "A2aOperationNotFoundError": A2aOperationNotFoundError,
    "A2aRequest": A2aRequest,
    "A2aResponse": A2aResponse,
    "A2aStdioTransport": A2aStdioTransport,
    "A2aVersion": A2aVersion,
    "A2aVersionMismatchError": A2aVersionMismatchError,
    "A2aVersionNegotiator": A2aVersionNegotiator,
    "AuthClient": AuthClient,
    "RemoteExecutionClient": RemoteExecutionClient,
    "ServerClient": ServerClient,
    "ServerConnectionConfig": ServerConnectionConfig,
    "StubAuthClient": StubAuthClient,
    "StubRemoteExecutionClient": StubRemoteExecutionClient,
    "StubServerClient": StubServerClient,
    "TransportSelector": TransportSelector,
}


@when("I check the A2A module documentation")
def step_check_a2a_documentation(context):
    """Check A2A module documentation."""
    context.module_doc = a2a_module.__doc__
    context.class_docs = {}
    for name, symbol in _A2A_DOCUMENTATION_SYMBOLS.items():
        if inspect.isclass(symbol):
            context.class_docs[name] = symbol.__doc__


@then("the module docstring should mention A2A")
def step_module_doc_mentions_a2a(context):
    """Verify module docstring mentions A2A."""
    assert context.module_doc is not None
    assert "A2A" in context.module_doc


@then("the module docstring should not mention ACP")
def step_module_doc_no_acp(context):
    """Verify module docstring doesn't mention ACP."""
    assert context.module_doc is not None
    assert "ACP" not in context.module_doc
