using Shouldly;
using Xunit;

namespace ZB.MOM.WW.OtOpcUa.Driver.Calculation.Tests;

/// <summary>Parsing contract for <see cref="CalculationTagDefinition.TryFromTagConfig"/> — the calc tag's
/// <c>TagConfig</c> blob (<c>scriptId</c> + resolved <c>scriptSource</c> + trigger fields) → typed def with
/// its static dependency refs.</summary>
public sealed class CalculationTagDefinitionTests
{
    [Fact]
    public void Missing_scriptId_is_not_a_calc_tag()
    {
        CalculationTagDefinition.TryFromTagConfig("{\"changeTriggered\":true}", "calc/e/x", out _).ShouldBeFalse();
    }

    [Fact]
    public void Malformed_json_is_a_miss()
    {
        CalculationTagDefinition.TryFromTagConfig("not json", "calc/e/x", out _).ShouldBeFalse();
    }

    [Fact]
    public void Parses_scriptId_source_triggers_and_extracts_dependency_refs()
    {
        var json = "{\"scriptId\":\"s1\",\"changeTriggered\":true,\"timerIntervalMs\":5000," +
                   "\"scriptSource\":\"return (double)ctx.GetTag(\\\"src/a\\\").Value + (double)ctx.GetTag(\\\"src/b\\\").Value;\"}";
        CalculationTagDefinition.TryFromTagConfig(json, "calc/e/x", out var def).ShouldBeTrue();

        def.RawPath.ShouldBe("calc/e/x");
        def.ScriptId.ShouldBe("s1");
        def.ChangeTriggered.ShouldBeTrue();
        def.TimerInterval.ShouldBe(TimeSpan.FromMilliseconds(5000));
        def.DependencyRefs.ShouldBe(new[] { "src/a", "src/b" });
    }

    [Fact]
    public void ChangeTriggered_defaults_true_and_timer_is_optional()
    {
        CalculationTagDefinition.TryFromTagConfig(
            "{\"scriptId\":\"s1\",\"scriptSource\":\"return 1.0;\"}", "calc/e/x", out var def).ShouldBeTrue();
        def.ChangeTriggered.ShouldBeTrue();
        def.TimerInterval.ShouldBeNull();
        def.DependencyRefs.ShouldBeEmpty();
    }

    [Fact]
    public void Present_scriptId_with_empty_source_still_maps()
    {
        CalculationTagDefinition.TryFromTagConfig(
            "{\"scriptId\":\"s1\",\"changeTriggered\":false}", "calc/e/x", out var def).ShouldBeTrue();
        def.ScriptSource.ShouldBe("");
        def.ChangeTriggered.ShouldBeFalse();
    }
}
