from __future__ import annotations

from pathlib import Path

from sync_state_machine.engine import StateMachineConfig, StateMachineRuntime


CFG_PATH = Path(__file__).resolve().parents[2] / "sync_state_machine" / "config" / "node_state_machine.yaml"


def test_all_event_outcomes_are_dispatchable() -> None:
    cfg = StateMachineConfig.load(CFG_PATH)
    runtime = StateMachineRuntime(cfg)

    covered_events: set[str] = set()

    for event_id, transition in cfg.transitions.items():
        if not transition.outcomes:
            continue

        for idx, outcome in enumerate(transition.outcomes):
            if outcome.to is None:
                continue

            src = next((s for s in transition.from_states if s != "*"), "*")
            decision = runtime.dispatch(current_state=src, event_id=event_id, context=dict(outcome.when))
            assert decision is not None, f"{event_id}[{idx}] did not dispatch"
            assert decision.to_state == outcome.to, f"{event_id}[{idx}] target mismatch"
            assert decision.outcome_index == idx, f"{event_id}[{idx}] wrong branch matched"
            covered_events.add(event_id)

    assert covered_events == set(cfg.transitions.keys())
