from fxhnt.application.backtest_refs import registry_backtest_kind
from fxhnt.application.forward_ingest import CockpitBacktestRefProvider
from fxhnt.registry import STRATEGY_REGISTRY


def _is_reconciliation_gated(entry) -> bool:
    return entry.get("gate_spec", {}).get("gate_type") == "reconciliation"


def test_every_reconciliation_gated_strategy_has_a_backtest_provider():
    """THE invariant: a reconciliation-gated strategy without a non-`none` backtest kind can never gate-PASS
    (its gate WAITs forever on a missing ref). Making that a CI failure is what turns a silent live gap into
    a caught error. If you add a reconciliation-gated strategy, declare its `definition.backtest.kind`."""
    offenders = [sid for sid, entry in STRATEGY_REGISTRY.items()
                 if _is_reconciliation_gated(entry) and registry_backtest_kind(sid) == "none"]
    assert not offenders, f"reconciliation-gated strategies with no backtest ref provider: {offenders}"


def test_every_reconciliation_gated_model_ref_twin_has_a_resolving_alias():
    """A `model-ref` twin declares kind != none (so the test above passes) but gets its reconciliation ref
    SOLELY from CockpitBacktestRefProvider._REF_ALIAS. Without an alias entry whose target resolves to a
    real (non-none) provider, its gate silently WAITs forever — the vrp_exec bug. Make it structural."""
    alias = CockpitBacktestRefProvider._REF_ALIAS
    offenders = []
    for sid, entry in STRATEGY_REGISTRY.items():
        if _is_reconciliation_gated(entry) and registry_backtest_kind(sid) == "model-ref":
            target = alias.get(sid)
            if target is None:
                offenders.append(f"{sid}: model-ref with no _REF_ALIAS entry")
            elif registry_backtest_kind(target) == "none":
                offenders.append(f"{sid}: alias target {target!r} has a 'none' provider")
    assert not offenders, f"model-ref twins whose reconciliation ref never resolves: {offenders}"
