// AUTHORED SHIM (not copied). Per-battle ambient context that backs the
// AsyncLocal singleton seam for multi-instancing (see docs/superpowers/specs/
// 2026-06-07-engine-multi-instancing-design.md). The engine's per-battle
// statics (BattleManagerBase.main/IsForecast/IsRandomDraw, GameMgr.GetIns,
// Certification.viewer_id, ToolboxGame.RealTimeNetworkAgent,
// Data.BattleRecoveryInfo) resolve through Current when set; process-shared
// reference data (CardMaster.Default, Data.Master, etc.) stays static.
#nullable enable
using System;
using System.Threading;

namespace SVSim.BattleEngine.Ambient;

public sealed class BattleAmbientContext
{
    public BattleManagerBase? Mgr { get; set; }
    public GameMgr GameMgr { get; init; } = new();
    public RealTimeNetworkAgent? NetworkAgent { get; set; }
    public int ViewerId { get; init; } = 1001;
    public bool IsForecast { get; set; } = true;
    public bool IsRandomDraw { get; set; } = true;
    public Wizard.BattleRecoveryInfo? RecoveryInfo { get; set; }
}

public static class BattleAmbient
{
    internal static readonly AsyncLocal<BattleAmbientContext?> _current = new();

    public static BattleAmbientContext? Current => _current.Value;

    public static BattleAmbientContext Require() =>
        _current.Value ?? throw new InvalidOperationException(
            "No ambient battle context. Wrap engine entry points in BattleAmbient.Enter(ctx).");

    public static Scope Enter(BattleAmbientContext ctx)
    {
        var prior = _current.Value;
        _current.Value = ctx;
        return new Scope(prior);
    }

    public readonly struct Scope : IDisposable
    {
        private readonly BattleAmbientContext? _prior;
        internal Scope(BattleAmbientContext? prior) { _prior = prior; }
        public void Dispose() => _current.Value = _prior;
    }
}
