using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;

namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared;

/// <summary>
/// Round-trip coverage for the WhileTrue/OnTrue <c>mode</c> field on the
/// Conditional and Expression script triggers.
/// </summary>
public class ScriptTriggerConfigCodecTests
{
    // ── Parse: mode field ──────────────────────────────────────────────────

    [Fact]
    public void Parse_Conditional_WithoutMode_DefaultsToOnTrue()
    {
        const string json = @"{""attributeName"":""Temp"",""operator"":"">"",""threshold"":80}";

        var model = ScriptTriggerConfigCodec.Parse(json, ScriptTriggerKind.Conditional);

        Assert.Equal(ScriptTriggerMode.OnTrue, model.Mode);
    }

    [Fact]
    public void Parse_Conditional_WhileTrue_IsRead()
    {
        const string json =
            @"{""attributeName"":""Temp"",""operator"":"">"",""threshold"":80,""mode"":""WhileTrue""}";

        var model = ScriptTriggerConfigCodec.Parse(json, ScriptTriggerKind.Conditional);

        Assert.Equal(ScriptTriggerMode.WhileTrue, model.Mode);
    }

    [Fact]
    public void Parse_Expression_WithoutMode_DefaultsToOnTrue()
    {
        const string json = @"{""expression"":""Attributes[\""T\""] > 1""}";

        var model = ScriptTriggerConfigCodec.Parse(json, ScriptTriggerKind.Expression);

        Assert.Equal(ScriptTriggerMode.OnTrue, model.Mode);
    }

    [Fact]
    public void Parse_Expression_WhileTrue_IsRead()
    {
        const string json =
            @"{""expression"":""Attributes[\""T\""] > 1"",""mode"":""WhileTrue""}";

        var model = ScriptTriggerConfigCodec.Parse(json, ScriptTriggerKind.Expression);

        Assert.Equal(ScriptTriggerMode.WhileTrue, model.Mode);
    }

    [Fact]
    public void Parse_UnrecognizedMode_DefaultsToOnTrue()
    {
        const string json =
            @"{""attributeName"":""Temp"",""operator"":"">"",""threshold"":80,""mode"":""Sometimes""}";

        var model = ScriptTriggerConfigCodec.Parse(json, ScriptTriggerKind.Conditional);

        Assert.Equal(ScriptTriggerMode.OnTrue, model.Mode);
    }

    // ── Serialize: mode field ──────────────────────────────────────────────

    [Fact]
    public void Serialize_Conditional_WhileTrue_WritesMode()
    {
        var model = new ScriptTriggerModel
        {
            AttributeName = "Temp",
            Operator = ">",
            Threshold = 80,
            Mode = ScriptTriggerMode.WhileTrue
        };

        var json = ScriptTriggerConfigCodec.Serialize(model, ScriptTriggerKind.Conditional);

        Assert.Contains("\"mode\":\"WhileTrue\"", json);
    }

    [Fact]
    public void Serialize_Expression_WhileTrue_WritesMode()
    {
        var model = new ScriptTriggerModel
        {
            Expression = "Attributes[\"T\"] > 1",
            Mode = ScriptTriggerMode.WhileTrue
        };

        var json = ScriptTriggerConfigCodec.Serialize(model, ScriptTriggerKind.Expression);

        Assert.Contains("\"mode\":\"WhileTrue\"", json);
    }

    // ── Round-trip ─────────────────────────────────────────────────────────

    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public void RoundTrip_Conditional_PreservesMode(bool whileTrue)
    {
        var mode = whileTrue ? ScriptTriggerMode.WhileTrue : ScriptTriggerMode.OnTrue;
        var original = new ScriptTriggerModel
        {
            AttributeName = "Temp",
            Operator = ">=",
            Threshold = 12.5,
            Mode = mode
        };

        var json = ScriptTriggerConfigCodec.Serialize(original, ScriptTriggerKind.Conditional);
        var reparsed = ScriptTriggerConfigCodec.Parse(json, ScriptTriggerKind.Conditional);

        Assert.Equal(mode, reparsed.Mode);
    }

    // ── SupportsMinTimeBetweenRuns ─────────────────────────────────────────

    [Theory]
    [InlineData("ValueChange")]
    [InlineData("Conditional")]
    [InlineData("Expression")]
    public void SupportsMinTimeBetweenRuns_TrueForAutoTriggersThatThrottle(string triggerType)
    {
        Assert.True(ScriptTriggerConfigCodec.SupportsMinTimeBetweenRuns(triggerType));
    }

    [Theory]
    [InlineData("Interval")]   // has its own period control
    [InlineData("Call")]       // invoked explicitly — no throttle applies
    [InlineData(null)]         // None — never runs automatically
    [InlineData("Bogus")]      // Unknown trigger type
    public void SupportsMinTimeBetweenRuns_FalseForIntervalCallNoneAndUnknown(string? triggerType)
    {
        Assert.False(ScriptTriggerConfigCodec.SupportsMinTimeBetweenRuns(triggerType));
    }

    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public void RoundTrip_Expression_PreservesMode(bool whileTrue)
    {
        var mode = whileTrue ? ScriptTriggerMode.WhileTrue : ScriptTriggerMode.OnTrue;
        var original = new ScriptTriggerModel
        {
            Expression = "Attributes[\"T\"] > 1",
            Mode = mode
        };

        var json = ScriptTriggerConfigCodec.Serialize(original, ScriptTriggerKind.Expression);
        var reparsed = ScriptTriggerConfigCodec.Parse(json, ScriptTriggerKind.Expression);

        Assert.Equal(mode, reparsed.Mode);
    }
}
