"""Behave steps for UKO Layer 2 vocabulary registry tests.

All step definitions use the ``for uko_l2`` suffix to avoid
AmbiguousStep collisions with other feature files.
"""

from __future__ import annotations

from _uko_l2_test_helpers import capture_error
from behave import given, then, when
from behave.runner import Context

from cleveragents.acms.uko.vocabularies import (
    get_func_vocabulary,
    get_oo_vocabulary,
    get_proc_vocabulary,
)
from cleveragents.acms.uko.vocabulary_registry import VocabularyRegistry

# ---------------------------------------------------------------------------
# VocabularyRegistry -- construction and lookup
# ---------------------------------------------------------------------------


@given("a vocabulary registry with all paradigm vocabularies for uko_l2")
def step_create_registry(ctx: Context) -> None:
    ctx.registry = VocabularyRegistry(
        vocabularies=(
            get_oo_vocabulary(),
            get_func_vocabulary(),
            get_proc_vocabulary(),
        )
    )


@then("the registry should have {count:d} vocabularies for uko_l2")
def step_check_registry_count(ctx: Context, count: int) -> None:
    assert len(ctx.registry) == count


@then('the registry should contain prefix "{prefix}" for uko_l2')
def step_check_registry_prefix(ctx: Context, prefix: str) -> None:
    assert ctx.registry.get_by_prefix(prefix) is not None


@when('I look up vocabulary by prefix "{prefix}" for uko_l2')
def step_lookup_vocab_prefix(ctx: Context, prefix: str) -> None:
    ctx.looked_up_vocab = ctx.registry.get_by_prefix(prefix)


@when('I look up vocabulary by IRI "{iri}" for uko_l2')
def step_lookup_vocab_iri(ctx: Context, iri: str) -> None:
    ctx.looked_up_vocab = ctx.registry.get_by_iri(iri)


@then("the looked up vocabulary should not be None for uko_l2")
def step_vocab_not_none(ctx: Context) -> None:
    assert ctx.looked_up_vocab is not None


@then("the looked up vocabulary should be None for uko_l2")
def step_vocab_is_none(ctx: Context) -> None:
    assert ctx.looked_up_vocab is None


@then('the looked up vocabulary prefix should be "{expected}" for uko_l2')
def step_check_looked_up_vocab_prefix(ctx: Context, expected: str) -> None:
    assert ctx.looked_up_vocab is not None
    assert ctx.looked_up_vocab.prefix == expected


# ---------------------------------------------------------------------------
# Registration / deregistration
# ---------------------------------------------------------------------------


@when("I try to register a duplicate vocabulary for uko_l2")
def step_register_duplicate(ctx: Context) -> None:
    with capture_error(ctx, ValueError):
        ctx.registry.register(get_oo_vocabulary())


@then("a duplicate registration error should be raised for uko_l2")
def step_check_duplicate_error(ctx: Context) -> None:
    assert ctx.error is not None
    assert isinstance(ctx.error, ValueError)
    assert "already registered" in str(ctx.error)


@when('I unregister prefix "{prefix}" from the registry for uko_l2')
def step_unregister_prefix(ctx: Context, prefix: str) -> None:
    ctx.unregister_result = ctx.registry.unregister(prefix)


@then("the unregister result should be False for uko_l2")
def step_check_unregister_false(ctx: Context) -> None:
    assert ctx.unregister_result is False


# ---------------------------------------------------------------------------
# Enumeration and contains
# ---------------------------------------------------------------------------


@then('list_prefixes should return "{expected}" for uko_l2')
def step_check_list_prefixes(ctx: Context, expected: str) -> None:
    prefixes = ctx.registry.list_prefixes()
    assert ",".join(prefixes) == expected


@then("list_all should return {count:d} vocabularies for uko_l2")
def step_check_list_all(ctx: Context, count: int) -> None:
    assert len(ctx.registry.list_all()) == count


@then('"{prefix}" should be in the registry for uko_l2')
def step_check_contains(ctx: Context, prefix: str) -> None:
    assert prefix in ctx.registry


@then('"{prefix}" should not be in the registry for uko_l2')
def step_check_not_contains(ctx: Context, prefix: str) -> None:
    assert prefix not in ctx.registry
