using ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts;

namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.Scripts;

/// <summary>
/// WP3.2 (site_events volume policy — docs/plans/2026-08-15-site-events-policy-design.md,
/// stage (b) test plan items 1–3): pure unit tests for
/// <see cref="ScriptRunEventPolicy.ShouldEmitPerRun"/>, isolated from any actor or DI
/// plumbing — the actor-level wiring (hot toggle, hosted-service registration) is covered by
/// <c>ScriptRunLauncherParityTests</c>.
/// </summary>
public class ScriptRunEventPolicyTests
{
    private static SiteRuntimeOptions Options(
        bool perRunScriptEvents = false, string[]? perRunScriptEventScripts = null)
        => new()
        {
            PerRunScriptEvents = perRunScriptEvents,
            PerRunScriptEventScripts = (perRunScriptEventScripts ?? []).ToList()
        };

    [Fact]
    public void DefaultOptions_EmitsNothing()
    {
        Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(Options(), "Inst1", "Runner"));
    }

    [Fact]
    public void GlobalSwitchOn_EmitsForEveryScript()
    {
        var options = Options(perRunScriptEvents: true);

        Assert.True(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst1", "Runner"));
        Assert.True(ScriptRunEventPolicy.ShouldEmitPerRun(options, "AnyOtherInstance", "AnyOtherScript"));
    }

    [Fact]
    public void ExactPerScriptMatch_Emits()
    {
        var options = Options(perRunScriptEventScripts: ["Inst1/Runner"]);

        Assert.True(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst1", "Runner"));
    }

    [Fact]
    public void ExactPerScriptMatch_DoesNotMatchADifferentScriptOnTheSameInstance()
    {
        var options = Options(perRunScriptEventScripts: ["Inst1/Runner"]);

        Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst1", "OtherScript"));
    }

    [Fact]
    public void ExactPerScriptMatch_DoesNotMatchTheSameScriptNameOnADifferentInstance()
    {
        var options = Options(perRunScriptEventScripts: ["Inst1/Runner"]);

        Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst2", "Runner"));
    }

    [Fact]
    public void InstanceWildcard_EmitsForEveryScriptOnThatInstanceOnly()
    {
        var options = Options(perRunScriptEventScripts: ["Inst1/*"]);

        Assert.True(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst1", "Runner"));
        Assert.True(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst1", "AnotherScript"));
        Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst2", "Runner"));
    }

    [Fact]
    public void NonMatchingScript_StaysSilent()
    {
        var options = Options(perRunScriptEventScripts: ["Inst1/Runner", "Inst2/*"]);

        Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst3", "Runner"));
    }

    [Fact]
    public void EmptyOptInList_StaysSilent()
    {
        Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(Options(), "Inst1", "Runner"));
    }
}
