"""Behave step definitions for domain repository protocol compliance tests.

Verifies that:
1. Protocol interfaces are defined in the domain layer (not infrastructure)
2. Infrastructure repositories satisfy the domain protocols
3. All protocols are runtime-checkable
"""

from __future__ import annotations

from typing import Any

from behave import given, then, when

# ---------------------------------------------------------------------------
# Background
# ---------------------------------------------------------------------------


@given("the domain repository protocols are importable")
def step_protocols_importable(context: Any) -> None:
    """Verify all domain repository protocols can be imported."""
    from cleveragents.domain.repositories import (
        ActionRepositoryProtocol,
        DecisionRepositoryProtocol,
        LifecyclePlanRepositoryProtocol,
        ProjectRepositoryProtocol,
    )

    context.protocols = {
        "LifecyclePlanRepositoryProtocol": LifecyclePlanRepositoryProtocol,
        "ActionRepositoryProtocol": ActionRepositoryProtocol,
        "DecisionRepositoryProtocol": DecisionRepositoryProtocol,
        "ProjectRepositoryProtocol": ProjectRepositoryProtocol,
    }
    context.current_protocol = None


# ---------------------------------------------------------------------------
# When — inspect protocol
# ---------------------------------------------------------------------------


@when("I inspect the LifecyclePlanRepositoryProtocol")
def step_inspect_plan_protocol(context: Any) -> None:
    context.current_protocol = context.protocols["LifecyclePlanRepositoryProtocol"]


@when("I inspect the ActionRepositoryProtocol")
def step_inspect_action_protocol(context: Any) -> None:
    context.current_protocol = context.protocols["ActionRepositoryProtocol"]


@when("I inspect the DecisionRepositoryProtocol")
def step_inspect_decision_protocol(context: Any) -> None:
    context.current_protocol = context.protocols["DecisionRepositoryProtocol"]


@when("I inspect the ProjectRepositoryProtocol")
def step_inspect_project_protocol(context: Any) -> None:
    context.current_protocol = context.protocols["ProjectRepositoryProtocol"]


# ---------------------------------------------------------------------------
# Then — protocol assertions
# ---------------------------------------------------------------------------


@then("it should be a runtime-checkable Protocol")
def step_is_runtime_checkable(context: Any) -> None:
    """Verify the protocol is decorated with @runtime_checkable."""
    proto = context.current_protocol
    assert hasattr(proto, "__protocol_attrs__") or hasattr(proto, "_is_protocol"), (
        f"{proto} is not a Protocol"
    )
    is_runtime = getattr(proto, "_is_runtime_protocol", False)
    assert is_runtime, f"{proto.__name__} is not @runtime_checkable"


@then('it should define a "{method_name}" method')
def step_defines_method(context: Any, method_name: str) -> None:
    """Verify the protocol defines the named method."""
    proto = context.current_protocol
    assert hasattr(proto, method_name), (
        f"{proto.__name__} does not define method '{method_name}'"
    )
    assert callable(getattr(proto, method_name)), (
        f"{proto.__name__}.{method_name} is not callable"
    )


# ---------------------------------------------------------------------------
# Given — infrastructure classes
# ---------------------------------------------------------------------------


@given("the infrastructure LifecyclePlanRepository class")
def step_given_plan_repo(context: Any) -> None:
    from cleveragents.infrastructure.database.repositories import (
        LifecyclePlanRepository,
    )

    context.infra_class = LifecyclePlanRepository
    context.check_protocol = context.protocols["LifecyclePlanRepositoryProtocol"]


@given("the infrastructure ActionRepository class")
def step_given_action_repo(context: Any) -> None:
    from cleveragents.infrastructure.database.repositories import ActionRepository

    context.infra_class = ActionRepository
    context.check_protocol = context.protocols["ActionRepositoryProtocol"]


@given("the infrastructure DecisionRepository class")
def step_given_decision_repo(context: Any) -> None:
    from cleveragents.infrastructure.database.repositories import DecisionRepository

    context.infra_class = DecisionRepository
    context.check_protocol = context.protocols["DecisionRepositoryProtocol"]


@given("the infrastructure NamespacedProjectRepository class")
def step_given_project_repo(context: Any) -> None:
    from cleveragents.infrastructure.database.repositories import (
        NamespacedProjectRepository,
    )

    context.infra_class = NamespacedProjectRepository
    context.check_protocol = context.protocols["ProjectRepositoryProtocol"]


# ---------------------------------------------------------------------------
# When — check protocol satisfaction
# ---------------------------------------------------------------------------


@when("I check if it satisfies LifecyclePlanRepositoryProtocol")
def step_check_plan_protocol(context: Any) -> None:
    context.protocol_check_result = issubclass(
        context.infra_class, context.check_protocol
    )


@when("I check if it satisfies ActionRepositoryProtocol")
def step_check_action_protocol(context: Any) -> None:
    context.protocol_check_result = issubclass(
        context.infra_class, context.check_protocol
    )


@when("I check if it satisfies DecisionRepositoryProtocol")
def step_check_decision_protocol(context: Any) -> None:
    context.protocol_check_result = issubclass(
        context.infra_class, context.check_protocol
    )


@when("I check if it satisfies ProjectRepositoryProtocol")
def step_check_project_protocol(context: Any) -> None:
    context.protocol_check_result = issubclass(
        context.infra_class, context.check_protocol
    )


@then("the isinstance check should pass")
def step_isinstance_passes(context: Any) -> None:
    assert context.protocol_check_result, (
        f"{context.infra_class.__name__} does not satisfy "
        f"{context.check_protocol.__name__}"
    )


# ---------------------------------------------------------------------------
# When/Then — package exports
# ---------------------------------------------------------------------------


@when("I import from cleveragents.domain.repositories")
def step_import_domain_repositories(context: Any) -> None:
    import cleveragents.domain.repositories as repo_pkg

    context.repo_pkg = repo_pkg


@then("LifecyclePlanRepositoryProtocol should be available")
def step_plan_protocol_available(context: Any) -> None:
    assert hasattr(context.repo_pkg, "LifecyclePlanRepositoryProtocol"), (
        "LifecyclePlanRepositoryProtocol not exported from domain.repositories"
    )


@then("ActionRepositoryProtocol should be available")
def step_action_protocol_available(context: Any) -> None:
    assert hasattr(context.repo_pkg, "ActionRepositoryProtocol"), (
        "ActionRepositoryProtocol not exported from domain.repositories"
    )


@then("DecisionRepositoryProtocol should be available")
def step_decision_protocol_available(context: Any) -> None:
    assert hasattr(context.repo_pkg, "DecisionRepositoryProtocol"), (
        "DecisionRepositoryProtocol not exported from domain.repositories"
    )


@then("ProjectRepositoryProtocol should be available")
def step_project_protocol_available(context: Any) -> None:
    assert hasattr(context.repo_pkg, "ProjectRepositoryProtocol"), (
        "ProjectRepositoryProtocol not exported from domain.repositories"
    )


# ---------------------------------------------------------------------------
# When/Then — module path checks
# ---------------------------------------------------------------------------


@when("I check the module path of LifecyclePlanRepositoryProtocol")
def step_check_plan_module(context: Any) -> None:
    from cleveragents.domain.repositories import LifecyclePlanRepositoryProtocol

    context.current_module = LifecyclePlanRepositoryProtocol.__module__


@when("I check the module path of ActionRepositoryProtocol")
def step_check_action_module(context: Any) -> None:
    from cleveragents.domain.repositories import ActionRepositoryProtocol

    context.current_module = ActionRepositoryProtocol.__module__


@when("I check the module path of DecisionRepositoryProtocol")
def step_check_decision_module(context: Any) -> None:
    from cleveragents.domain.repositories import DecisionRepositoryProtocol

    context.current_module = DecisionRepositoryProtocol.__module__


@when("I check the module path of ProjectRepositoryProtocol")
def step_check_project_module(context: Any) -> None:
    from cleveragents.domain.repositories import ProjectRepositoryProtocol

    context.current_module = ProjectRepositoryProtocol.__module__


@then('the module should be under "cleveragents.domain"')
def step_module_under_domain(context: Any) -> None:
    assert context.current_module.startswith("cleveragents.domain"), (
        f"Protocol module '{context.current_module}' is not under 'cleveragents.domain'"
    )
