using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces;
using ZB.MOM.WW.ScadaBridge.Commons.Types;
using ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts;

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

/// <summary>
/// Audit Log #23 (M3 Bundle A — Task A3) — script-side API tests for
/// <c>Tracking.Status(TrackedOperationId)</c>. The helper reads the site-local
/// <see cref="IOperationTrackingStore"/> directly (no central round-trip) and
/// returns the latest <see cref="TrackingStatusSnapshot"/>, or <c>null</c> when
/// the id is unknown.
/// </summary>
public class TrackingApiTests
{
    private static ScriptRuntimeContext.TrackingHelper CreateHelper(
        IOperationTrackingStore? store)
    {
        return new ScriptRuntimeContext.TrackingHelper(store, NullLogger.Instance);
    }

    [Fact]
    public async Task Status_UnknownId_ReturnsNull()
    {
        var store = new Mock<IOperationTrackingStore>();
        store
            .Setup(s => s.GetStatusAsync(It.IsAny<TrackedOperationId>(), It.IsAny<CancellationToken>()))
            .ReturnsAsync((TrackingStatusSnapshot?)null);

        var helper = CreateHelper(store.Object);
        var result = await helper.Status(TrackedOperationId.New());

        Assert.Null(result);
    }

    [Fact]
    public async Task Status_KnownId_ReturnsLatestSnapshot()
    {
        var id = TrackedOperationId.New();
        var expected = new TrackingStatusSnapshot(
            Id: id,
            Kind: "ApiCallCached",
            TargetSummary: "ERP.GetOrder",
            Status: "Delivered",
            RetryCount: 2,
            LastError: null,
            HttpStatus: 200,
            CreatedAtUtc: new DateTime(2026, 5, 20, 10, 0, 0, DateTimeKind.Utc),
            UpdatedAtUtc: new DateTime(2026, 5, 20, 10, 2, 30, DateTimeKind.Utc),
            TerminalAtUtc: new DateTime(2026, 5, 20, 10, 2, 30, DateTimeKind.Utc),
            SourceInstanceId: "Plant.Pump42",
            SourceScript: "ScriptActor:OnTick",
            SourceNode: null);

        var store = new Mock<IOperationTrackingStore>();
        store
            .Setup(s => s.GetStatusAsync(id, It.IsAny<CancellationToken>()))
            .ReturnsAsync(expected);

        var helper = CreateHelper(store.Object);
        var result = await helper.Status(id);

        Assert.NotNull(result);
        Assert.Equal(expected, result);
    }

    [Fact]
    public async Task Status_NoStoreWired_Throws()
    {
        var helper = CreateHelper(store: null);
        await Assert.ThrowsAsync<InvalidOperationException>(
            () => helper.Status(TrackedOperationId.New()));
    }

}
