using Moq;
using QuantEngine.Application.Services;
using QuantEngine.Core.Domain;
using QuantEngine.Core.Interfaces;

namespace QuantEngine.Core.Tests;

public class HistoryIngestionServiceTests
{
    [Fact]
    public async Task AppendDecisionAsync_NormalizesTypedPayload()
    {
        var store = new Mock<IPostgresqlHistoryStore>(MockBehavior.Strict);
        store.Setup(s => s.AppendAsync("decision_result_history", It.Is<IDictionary<string, object?>>(payload =>
            payload["instrument_id"] != null && payload["instrument_id"]!.ToString() == "005930" &&
            payload["action"] != null && payload["action"]!.ToString() == "BUY" &&
            payload["gate"] != null && payload["gate"]!.ToString() == "PASS" &&
            payload["source_version"] != null && payload["source_version"]!.ToString() == "v1"))).ReturnsAsync(1);

        var service = new HistoryIngestionService(store.Object);

        var result = await service.AppendDecisionAsync(
            new FinalDecisionResult
            {
                FinalAction = " BUY ",
                ActionPriority = 1,
                PriorityScore = 12.3,
                DecisionSource = " v1 "
            },
            new SellDecisionResult { Action = "SELL", Validation = " PASS " },
            null,
            " 005930 ",
            "  ",
            null);

        Assert.Equal(1, result);
        store.VerifyAll();
    }

    [Fact]
    public async Task AppendFactorOutputAsync_RejectsBlankCoreFields()
    {
        var service = new HistoryIngestionService(new Mock<IPostgresqlHistoryStore>().Object);

        await Assert.ThrowsAsync<ArgumentException>(() => service.AppendFactorOutputAsync(
            "  ",
            "1.0",
            1.0,
            "PASS"));
    }

    [Fact]
    public async Task AppendDecisionAsync_RejectsNullRawPayload()
    {
        var service = new HistoryIngestionService(new Mock<IPostgresqlHistoryStore>().Object);

        await Assert.ThrowsAsync<ArgumentNullException>(() => service.AppendDecisionAsync((IDictionary<string, object?>)null!));
    }
}
