#nullable enable
using System;
using System.Runtime.Serialization;
using SVSim.BattleEngine.Ambient;

namespace SVSim.BattleEngine.Tests;

/// <summary>Per-test ambient scope. Each test that touches engine statics wraps its body
/// in `using var scope = new TestBattleScope();` (or with an explicit Mgr/ViewerId).
///
/// The constructor enters a fresh <see cref="BattleAmbientContext"/> (carrying a brand-new
/// <see cref="GameMgr"/> so per-test mgr/DataMgr writes never bleed across tests), then
/// runs the per-ambient seeders that <see cref="HeadlessEngineEnv.EnsureProcessGlobals"/>
/// no longer does (chara ids on DataMgr, NetworkUserInfoData). Process-globals
/// (card master, LoadDetail, Crossover, Certification.udid) come from
/// <see cref="HeadlessEngineEnv.EnsureProcessGlobals"/> which runs once per process.
///
/// Public surface (vs. internal) so SVSim.UnitTests can reuse it via the same project
/// reference in Task 7.</summary>
public sealed class TestBattleScope : IDisposable
{
    private readonly BattleAmbient.Scope _scope;
    public BattleAmbientContext Ctx { get; }

    public TestBattleScope(BattleManagerBase? mgr = null, int viewerId = 1001)
    {
        // Make sure process-globals are seeded before we enter; idempotent + cheap after first call.
        HeadlessEngineEnv.EnsureProcessGlobals();

        Ctx = new BattleAmbientContext
        {
            Mgr = mgr,
            GameMgr = new GameMgr(),
            ViewerId = viewerId,
            IsForecast = true,
            IsRandomDraw = true,
            RecoveryInfo = (Wizard.BattleRecoveryInfo)FormatterServices
                .GetUninitializedObject(typeof(Wizard.BattleRecoveryInfo)),
        };
        _scope = BattleAmbient.Enter(Ctx);

        // Per-ambient seeders MUST run AFTER scope entry so GameMgr.GetIns() resolves to this
        // scope's GameMgr (not a stray one). EnsureProcessGlobals used to do these writes against
        // the global GameMgr; now they're scoped.
        HeadlessEngineEnv.SeedCharaIdsOnCurrentAmbient();
        HeadlessEngineEnv.SeedNetUserOnCurrentAmbient();
    }

    public void Dispose() => _scope.Dispose();
}
