using SVSim.BattleNode.Bridge;
namespace SVSim.EmulatedEntrypoint.Matching;
///
/// Single source of truth for how a /do_matching request is resolved into a wire
/// matching_state + battle_id + node_server_url across every battle family.
///
/// Lives here (and not on each controller) because the resolution rules are the same
/// regardless of which URL family carried the request:
///
///
/// - Honor the dev-affordance scripted opt-in (route flag and/or
/// ) — bypass pair-up,
/// register a Scripted match, return immediately.
/// - Otherwise consult and translate the
/// resulting into a wire matching_state per the
/// 3002 / 3004 / 3007 / 3011 vocabulary.
///
///
/// Family-specific details (DTO shapes, family-specific request fields like
/// card_master_id, error-mapping like rank-battle's 3001 on a missing deck) stay
/// on the controllers. The resolver only owns the cross-cutting "did the flag win, did
/// pair-up resolve, what's the state code" decision.
///
///
public interface IMatchingResolver
{
///
/// The matching-mode key the resolver passes through to
/// — one of the
/// registry's mode names (e.g. "arena_two_pick_battle",
/// "rotation_rank_battle", "unlimited_rank_battle").
///
/// Caller's (viewer-id + built MatchContext).
///
/// Per-request opt-in from a controller-specific signal (e.g. TK2's ?scripted=1
/// query param). OR'd with ;
/// either being true short-circuits to a Scripted match.
///
Task ResolveAsync(
string mode,
BattlePlayer player,
bool scriptedOptIn,
CancellationToken ct);
}
///
/// Wire-level outcome of a /do_matching resolution. Always carries a non-null
/// — empty string while parked (3002), real URL on resolution —
/// because the client's DoMatchingBase.SettingDoMatchingData() calls
/// .ToString() on the wire field without a Keys.Contains guard.
///
public sealed record MatchingResolution(int MatchingState, string? BattleId, string NodeServerUrl);