using PolyTrader.Core.Trading;
using Xunit;
using static PolyTrader.Core.Trading.FeeModel;

namespace PolyTrader.Tests
{
    /// <summary>
    /// Sicherheitsnetz für die Fee-Logik (Phase 0.2): Kategorie-Fallback + Fee-Berechnung.
    /// </summary>
    public class FeeModelTests
    {
        [Theory]
        [InlineData("Sports", 75)]
        [InlineData("SPORTS", 75)]        // case-insensitive
        [InlineData("Crypto", 180)]
        [InlineData("Geopolitics", 0)]
        [InlineData("Politics", 100)]
        [InlineData("Finance", 100)]
        [InlineData("Economics", 100)]
        [InlineData("Weird-Unknown", 100)] // konservativer Default
        [InlineData("", 100)]
        [InlineData(null, 100)]
        public void FallbackBps_maps_category(string? category, int expected)
        {
            Assert.Equal(expected, FallbackBps(category));
        }

        [Fact]
        public void FeeUsd_is_notional_times_bps()
        {
            Assert.Equal(1.0m, FeeUsd(100m, 100));   // 1,0 % von 100
            Assert.Equal(0.9m, FeeUsd(50m, 180));     // 1,8 % von 50
        }

        [Theory]
        [InlineData(100, 0)]     // kein Satz
        [InlineData(0, 100)]     // kein Notional
        [InlineData(-5, 100)]    // negatives Notional
        public void FeeUsd_zero_cases(double notional, int bps)
        {
            Assert.Equal(0m, FeeUsd((decimal)notional, bps));
        }

        // ----- ResolveBps (M6) -----

        [Theory]
        [InlineData(120, "Sports", 120)]   // realer Satz gewinnt
        [InlineData(0, "Sports", 75)]      // kein realer Satz -> Kategorie-Fallback
        [InlineData(0, "Crypto", 180)]
        [InlineData(0, null, 100)]         // unbekannt -> Default
        public void ResolveBps_prefers_actual_then_fallback(int takerFeeBps, string? category, int expected)
        {
            Assert.Equal(expected, ResolveBps(takerFeeBps, category));
        }
    }
}
