from __future__ import annotations

import pytest

from src.domain.app_blocks.event_reactions import (
    EventReaction,
    ReactionAction,
    ReactionCondition,
    reaction_execution_context,
    reaction_matches,
)


def _reaction() -> EventReaction:
    return EventReaction(
        id="application-created-operations",
        event="application.created",
        conditions=(ReactionCondition(field="status", equals="submitted"),),
        actions=(
            ReactionAction(
                capability="workflow.assignment.create",
                input={"subject": "event.subject"},
                recipients=("resolver.default_staff",),
            ),
        ),
    )


def test_reaction_matches_authoritative_event_only():
    reaction = _reaction()
    assert reaction_matches(reaction, {"type": "application.created", "data": {"status": "submitted"}})
    assert not reaction_matches(reaction, {"type": "application.updated", "data": {"status": "submitted"}})
    assert not reaction_matches(reaction, {"type": "application.created", "data": {"status": "draft"}})


def test_reaction_context_is_retry_safe_and_carries_lineage():
    context = reaction_execution_context(_reaction(), source_event_id="evt_1", correlation_id="corr_1")
    assert context["causation_id"] == "evt_1"
    assert context["correlation_id"] == "corr_1"
    assert context["depth"] == 1
    assert context["idempotency_key"].startswith("reaction:application-created-operations:")


def test_reaction_depth_is_bounded():
    with pytest.raises(ValueError, match="reaction_depth_exceeded"):
        reaction_execution_context(_reaction(), source_event_id="evt_1", depth=8)


def test_reaction_rejects_unadmitted_capability():
    with pytest.raises(ValueError, match="reaction_capability_not_admitted"):
        EventReaction(
            id="unsafe",
            event="application.created",
            actions=(ReactionAction(capability="arbitrary.http"),),
        )
