using Xunit;
using KArtSell.Host.Features.ShadowRun;

namespace KArtSell.Integration.Tests;

/// <summary>
/// Tests for shadow run polling endpoint: in-progress, complete, failed scenarios.
/// </summary>
public sealed class GetShadowRunPollingTests
{
    [Fact]
    public void Query_InProgressStatus_ReturnsWithoutMetrics()
    {
        // Arrange
        var response = new GetShadowRunResponse(
            RunId: Guid.NewGuid(),
            ModelId: Guid.NewGuid(),
            Status: "DataBackfill",
            CreatedAt: DateTimeOffset.UtcNow.AddHours(-1),
            CompletedAt: null,
            Metrics: null,
            ValidationGates: null,
            ErrorMessage: null);

        // Assert
        Assert.Equal("DataBackfill", response.Status);
        Assert.Null(response.CompletedAt);
        Assert.Null(response.Metrics);
        Assert.Null(response.ValidationGates);
    }

    [Fact]
    public void Query_CompleteStatus_ReturnsWithMetrics()
    {
        // Arrange
        var runId = Guid.NewGuid();
        var modelId = Guid.NewGuid();
        var metrics = new ShadowRunMetricsDto(
            TotalReturn: 0.15m,
            SharpeRatio: 1.2m,
            CalmurRatio: 0.5m,
            MaximumDrawdown: 0.08m,
            WinRate: 0.55m,
            ProbOfBacktestOverfit: 0.15m,
            DailySharePercentile: 0.95m,
            TradingDays: 252);

        var gates = new ValidationGatesDto(
            PboUnder20: true,
            DsrAbove95: true,
            CostTwoXPositive: true,
            AllGatesPassed: true);

        var response = new GetShadowRunResponse(
            RunId: runId,
            ModelId: modelId,
            Status: "EvaluationComplete",
            CreatedAt: DateTimeOffset.UtcNow.AddHours(-2),
            CompletedAt: DateTimeOffset.UtcNow.AddHours(-1),
            Metrics: metrics,
            ValidationGates: gates,
            ErrorMessage: null);

        // Assert
        Assert.Equal("EvaluationComplete", response.Status);
        Assert.NotNull(response.CompletedAt);
        Assert.NotNull(response.Metrics);
        Assert.Equal(0.15m, response.Metrics!.ProbOfBacktestOverfit);
        Assert.NotNull(response.ValidationGates);
        Assert.True(response.ValidationGates!.AllGatesPassed);
    }

    [Fact]
    public void Query_FailedStatus_ReturnsWithErrorMessage()
    {
        // Arrange
        var response = new GetShadowRunResponse(
            RunId: Guid.NewGuid(),
            ModelId: Guid.NewGuid(),
            Status: "Failed",
            CreatedAt: DateTimeOffset.UtcNow.AddHours(-1),
            CompletedAt: DateTimeOffset.UtcNow.AddMinutes(-30),
            Metrics: null,
            ValidationGates: null,
            ErrorMessage: "OHLCV data fetch failed: HTTP 503 Service Unavailable");

        // Assert
        Assert.Equal("Failed", response.Status);
        Assert.NotNull(response.ErrorMessage);
        Assert.Contains("HTTP 503", response.ErrorMessage);
    }

    [Fact]
    public void Response_PartialGateFail_ReturnsWithGates()
    {
        // Arrange
        var gates = new ValidationGatesDto(
            PboUnder20: false,  // PBO > 20%
            DsrAbove95: true,
            CostTwoXPositive: true,
            AllGatesPassed: false);

        var response = new GetShadowRunResponse(
            RunId: Guid.NewGuid(),
            ModelId: Guid.NewGuid(),
            Status: "EvaluationComplete",
            CreatedAt: DateTimeOffset.UtcNow.AddHours(-2),
            CompletedAt: DateTimeOffset.UtcNow,
            Metrics: new ShadowRunMetricsDto(0.1m, 1.0m, 0.4m, 0.1m, 0.5m, 0.25m, 0.95m, 252),
            ValidationGates: gates,
            ErrorMessage: null);

        // Assert
        Assert.False(response.ValidationGates!.PboUnder20);
        Assert.False(response.ValidationGates.AllGatesPassed);
    }

    [Fact]
    public void Request_WithValidGuid_Deserializes()
    {
        // Arrange
        var runId = Guid.NewGuid();
        var request = new GetShadowRunPollingRequest(runId);

        // Assert
        Assert.Equal(runId, request.RunId);
    }

    [Fact]
    public void Metrics_AllFieldsPopulated_Deserializes()
    {
        // Arrange
        var metrics = new ShadowRunMetricsDto(
            TotalReturn: 0.25m,
            SharpeRatio: 1.5m,
            CalmurRatio: 0.75m,
            MaximumDrawdown: 0.12m,
            WinRate: 0.60m,
            ProbOfBacktestOverfit: 0.10m,
            DailySharePercentile: 0.98m,
            TradingDays: 252);

        // Assert
        Assert.Equal(0.25m, metrics.TotalReturn);
        Assert.Equal(0.10m, metrics.ProbOfBacktestOverfit);
        Assert.Equal(252, metrics.TradingDays);
    }
}
