using Predictalytics.Domain.Entities;

namespace Predictalytics.Application.Services;

/// <summary>Result of comparing a trader's older out-of-sample window to the recent one (#5).</summary>
public sealed record EdgeFreshnessResult(
    string Verdict,               // "Fresh" | "Stable" | "Fading" | "Insufficient"
    decimal Score,                // 0..100; 50 = flat, higher = edge improving
    decimal RecentReturnPct,
    decimal OlderReturnPct,
    int RecentClosedMarkets,
    int OlderClosedMarkets,
    string Detail);

/// <summary>
/// Edge-freshness (#5): compares the recent out-of-sample window (A) against the older one (B) to
/// answer "is this trader's edge current or stale?". Pure — no DB access, fully unit-tested.
/// The two windows are produced by the analytics worker (recent = last 60d, older = day 60–180).
/// </summary>
public static class EdgeFreshnessCalculator
{
    /// <summary>Below this many closed markets in a window, we can't judge the edge.</summary>
    public const int MinClosedMarkets = 5;

    /// <summary>Return% per market dropping by at least this (recent vs older) counts as fading.</summary>
    public const decimal FadeReturnDropPct = 3m;

    public static EdgeFreshnessResult Compute(TraderWindowMetrics older, TraderWindowMetrics recent)
    {
        if (recent.ClosedMarkets < MinClosedMarkets || older.ClosedMarkets < MinClosedMarkets)
        {
            return new EdgeFreshnessResult("Insufficient", 0m,
                recent.AvgReturnPct, older.AvgReturnPct,
                recent.ClosedMarkets, older.ClosedMarkets,
                "Zu wenige abgeschlossene Märkte in einem Fenster für ein Urteil.");
        }

        var delta = recent.AvgReturnPct - older.AvgReturnPct;
        var score = Math.Clamp(50m + delta * 5m, 0m, 100m);

        // A once-profitable edge that collapsed below break-even is the clearest fade signal.
        var profitFactorCollapse = (older.ProfitFactor ?? 0m) >= 1.3m
                                   && recent.ProfitFactor.HasValue && recent.ProfitFactor.Value < 1.0m;

        string verdict;
        if (delta <= -FadeReturnDropPct || profitFactorCollapse)
            verdict = "Fading";
        else if (delta >= 0m && recent.AvgReturnPct > 0m)
            verdict = "Fresh";
        else
            verdict = "Stable";

        var detail = $"Rendite/Markt: {older.AvgReturnPct:F1}% (alt) → {recent.AvgReturnPct:F1}% (neu)";
        return new EdgeFreshnessResult(verdict, Math.Round(score, 1),
            recent.AvgReturnPct, older.AvgReturnPct,
            recent.ClosedMarkets, older.ClosedMarkets, detail);
    }
}
