"""Behave steps exercising uncovered error-path branches in
``cleveragents.core.validation``.

Targets the defensive branches in the plan-tree, decision-dict, and
structured-output validators that ``structural_validation.feature`` does not
reach (non-dict nodes, duplicate decision_id, non-list children, invalid child
ULID, missing decision fields, wrong-typed confidence/parent/sequence,
malformed structured-output fields, unknown dispatcher target). These are pure
functions -- no database, CLI runner, or mocks required.

Step phrasing is deliberately distinct from ``structural_validation_steps.py``
to avoid step-definition collisions.
"""

from __future__ import annotations

import json

from behave import then, when
from behave.runner import Context

from cleveragents.core.validation import (
    ValidationError,
    validate_structured_component_output,
)


@when('I structurally validate "{target_type}" with the JSON payload')
def step_structural_validate_payload(context: Context, target_type: str) -> None:
    data = json.loads(context.text)
    context.cov_validation_error = None
    try:
        context.cov_validation_result = validate_structured_component_output(
            target_type, data
        )
    except ValidationError as exc:
        context.cov_validation_result = None
        context.cov_validation_error = exc


@when('I structurally validate the unknown target type "{target_type}"')
def step_structural_validate_unknown(context: Context, target_type: str) -> None:
    context.cov_validation_error = None
    try:
        context.cov_validation_result = validate_structured_component_output(
            target_type, []
        )
    except ValidationError as exc:
        context.cov_validation_result = None
        context.cov_validation_error = exc


@then("the structural validation fails")
def step_structural_validation_fails(context: Context) -> None:
    assert context.cov_validation_result is not None, "expected a result dict"
    assert context.cov_validation_result["valid"] is False, (
        f"expected invalid, got {context.cov_validation_result}"
    )


@then('the structural errors include "{substring}"')
def step_structural_errors_include(context: Context, substring: str) -> None:
    errors = context.cov_validation_result["errors"]
    assert any(substring in err for err in errors), (
        f"no error contained {substring!r}; errors={errors}"
    )


@then("a structural ValidationError is raised")
def step_structural_validation_error_raised(context: Context) -> None:
    assert isinstance(context.cov_validation_error, ValidationError), (
        f"expected ValidationError, got {context.cov_validation_error!r}"
    )
