using Predictalytics.Application.Services;
using Predictalytics.Domain.Entities;
using Xunit;

namespace Predictalytics.Application.Tests.Services;

public class EdgeFreshnessCalculatorTests
{
    private static TraderWindowMetrics Win(int closed, decimal avgReturn, decimal? pf = null)
        => new() { ClosedMarkets = closed, AvgReturnPct = avgReturn, ProfitFactor = pf };

    [Fact]
    public void TooFewMarkets_IsInsufficient()
    {
        var r = EdgeFreshnessCalculator.Compute(Win(3, 10m), Win(20, 8m));
        Assert.Equal("Insufficient", r.Verdict);
    }

    [Fact]
    public void HoldingEdge_IsFresh()
    {
        // Recent >= older and positive.
        var r = EdgeFreshnessCalculator.Compute(older: Win(30, 6m), recent: Win(25, 9m));
        Assert.Equal("Fresh", r.Verdict);
        Assert.True(r.Score > 50m);
    }

    [Fact]
    public void ReturnCollapse_IsFading()
    {
        // Return per market dropped well beyond the fade threshold.
        var r = EdgeFreshnessCalculator.Compute(older: Win(30, 12m), recent: Win(25, 2m));
        Assert.Equal("Fading", r.Verdict);
        Assert.True(r.Score < 50m);
    }

    [Fact]
    public void ProfitFactorCollapse_IsFading_EvenOnSmallReturnDrop()
    {
        // Return barely moves, but a once-strong profit factor fell below break-even.
        var r = EdgeFreshnessCalculator.Compute(
            older: Win(30, 5m, pf: 1.6m),
            recent: Win(25, 4m, pf: 0.8m));
        Assert.Equal("Fading", r.Verdict);
    }

    [Fact]
    public void MildDecline_IsStable()
    {
        // Small drop (< fade threshold), not an improvement -> Stable.
        var r = EdgeFreshnessCalculator.Compute(older: Win(30, 6m), recent: Win(25, 4m));
        Assert.Equal("Stable", r.Verdict);
    }
}
