using Xunit;
using KArtSell.Modules.ModelOperations.ShadowRun.Events;

namespace KArtSell.Integration.Tests;

/// <summary>
/// E2E async pipeline: Shadow Run → Outbox → Inbox → Consumer
/// Tests event structure, routing, and idempotency contracts.
/// Note: Database integration tests deferred (requires PostgreSQL fixture).
/// </summary>
public sealed class ShadowRunAsyncPipelineTests
{
    [Fact]
    public void Event_CreatedWithAllGatesPassed_IsRouteableToConsumers()
    {
        // Arrange: Create event matching async pipeline contract
        var runId = Guid.NewGuid();
        var modelId = Guid.NewGuid();
        var correlationId = Guid.NewGuid();

        var @event = new ShadowRunCompletedEvent(
            RunId: runId,
            ModelId: modelId,
            CorrelationId: correlationId,
            WindowStartDate: new DateOnly(2024, 1, 1),
            WindowEndDate: new DateOnly(2024, 8, 31),
            AllGatesPassed: true,
            TotalReturn: 0.15m,
            SharpeRatio: 1.8m,
            ProbOfBacktestOverfit: 0.12m,
            DailySharePercentile: 0.96m,
            ErrorMessage: null,
            CompletedAt: DateTime.UtcNow);

        // Assert: Event has all required fields for downstream routing
        Assert.Equal(runId, @event.RunId);
        Assert.Equal(modelId, @event.ModelId);
        Assert.Equal(correlationId, @event.CorrelationId);
        Assert.True(@event.AllGatesPassed);
        Assert.NotEqual(default(DateTime), @event.CompletedAt);
    }

    [Fact]
    public void Event_IdempotencyKey_EnsuresDuplicateDetection()
    {
        // Arrange: Same event, two instances
        var runId = Guid.NewGuid();
        var event1 = new ShadowRunCompletedEvent(
            RunId: runId,
            ModelId: Guid.NewGuid(),
            CorrelationId: Guid.NewGuid(),
            WindowStartDate: new DateOnly(2024, 1, 1),
            WindowEndDate: new DateOnly(2024, 8, 31),
            AllGatesPassed: true,
            TotalReturn: 0.15m,
            SharpeRatio: 1.8m,
            ProbOfBacktestOverfit: 0.12m,
            DailySharePercentile: 0.96m,
            ErrorMessage: null,
            CompletedAt: DateTime.UtcNow);

        var event2 = new ShadowRunCompletedEvent(
            RunId: runId,
            ModelId: event1.ModelId,
            CorrelationId: event1.CorrelationId,
            WindowStartDate: event1.WindowStartDate,
            WindowEndDate: event1.WindowEndDate,
            AllGatesPassed: event1.AllGatesPassed,
            TotalReturn: event1.TotalReturn,
            SharpeRatio: event1.SharpeRatio,
            ProbOfBacktestOverfit: event1.ProbOfBacktestOverfit,
            DailySharePercentile: event1.DailySharePercentile,
            ErrorMessage: event1.ErrorMessage,
            CompletedAt: event1.CompletedAt);

        // Assert: Idempotency keys match (same event = duplicate detected)
        Assert.Equal(event1.IdempotencyKey, event2.IdempotencyKey);
        Assert.Equal($"{runId}#1", event1.IdempotencyKey);
    }

    [Fact]
    public void Pipeline_ApprovalQueueRoute_OnlyProcessesPassedGates()
    {
        // Arrange: Event with AllGatesPassed=false
        var @event = new ShadowRunCompletedEvent(
            RunId: Guid.NewGuid(),
            ModelId: Guid.NewGuid(),
            CorrelationId: Guid.NewGuid(),
            WindowStartDate: new DateOnly(2024, 1, 1),
            WindowEndDate: new DateOnly(2024, 8, 31),
            AllGatesPassed: false,  // ← Failed validation
            TotalReturn: 0.05m,
            SharpeRatio: 0.8m,      // < 1.0 target
            ProbOfBacktestOverfit: 0.35m,  // > 20% limit
            DailySharePercentile: 0.90m,   // < 95% target
            ErrorMessage: "PBO exceeded",
            CompletedAt: DateTime.UtcNow);

        // Assert: ApprovalQueueConsumer logic (should skip)
        // "Only create approval queue if all gates passed"
        Assert.False(@event.AllGatesPassed);
        // In production: ApprovalQueueConsumer.HandleAsync returns early
    }
}
