using Xunit;
using KArtSell.BuildingBlocks.Time;
using KArtSell.Modules.ModelOperations.ShadowRun;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace KArtSell.Integration.Tests;

public sealed class SignalGenerationTests
{
    private readonly ILogger<ReplayEngine> _logger = new NoOpLogger<ReplayEngine>();

    [Fact]
    public async Task GenerateSignals_EMA_ProducesTradeSignals()
    {
        // Arrange
        var replay = new ReplayEngine(_logger);
        
        // Create OHLCV bars with clear trend
        var bars = new List<DataBackfiller.OhlcvBar>();
        
        // Generate uptrend (days 1-30): price goes from 2500 to 2600
        for (int i = 1; i <= 30; i++)
        {
            var price = 2500m + (i * 3.33m);  // Linear uptrend
            bars.Add(new DataBackfiller.OhlcvBar(
                new DateOnly(2026, 1, i),
                "KOSPI",
                price - 10,      // open
                price + 10,      // high
                price - 15,      // low
                price,           // close
                1_000_000L));
        }

        // Downtrend (days 31-45): price goes from 2600 down to 2500
        for (int i = 31; i <= 45; i++)
        {
            var price = 2600m - ((i - 30) * 6.67m);  // Linear downtrend
            bars.Add(new DataBackfiller.OhlcvBar(
                new DateOnly(2026, 2, i - 30),
                "KOSPI",
                price - 10,
                price + 10,
                price - 15,
                price,
                1_000_000L));
        }
        
        var fees = new List<DataBackfiller.FeeScheduleEntry>
        {
            new(new DateOnly(2026, 1, 1), 0.001m, 0.0005m),
        };
        
        var sessions = bars.Select(b => b.Date).Distinct().OrderBy(d => d).ToList();
        
        // Act
        var result = await replay.ReplayAsync(
            Guid.NewGuid(), bars, fees, 10_000_000m, sessions, CancellationToken.None);
        
        // Assert
        Assert.NotNull(result);
        Assert.NotEmpty(result.Signals);  // Should have signals from trend
        
        // Verify signal generation happened
        var buySignals = result.Signals.Where(s => s.Action == ReplayEngine.SignalAction.Buy).ToList();
        var sellSignals = result.Signals.Where(s => s.Action == ReplayEngine.SignalAction.Sell).ToList();
        
        Assert.NotEmpty(buySignals);  // Should have BUY signals during uptrend
        Assert.NotEmpty(sellSignals);  // Should have SELL signals during downtrend
    }
    
    private sealed class NoOpLogger<T> : ILogger<T>
    {
        public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;
        public bool IsEnabled(LogLevel logLevel) => false;
        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception,
            Func<TState, Exception?, string> formatter) { }
    }
}
