using Predictalytics.Domain.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace Predictalytics.Worker.Services;

public class TraderCleanupWorker : BackgroundService
{
    private readonly IServiceProvider _services;
    private readonly ILogger<TraderCleanupWorker> _logger;
    private readonly TimeSpan _checkInterval = TimeSpan.FromHours(12);

    public TraderCleanupWorker(IServiceProvider services, ILogger<TraderCleanupWorker> logger)
    {
        _services = services;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                await DoCleanupWorkAsync(stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error occurred executing TraderCleanupWorker.");
            }

            await Task.Delay(_checkInterval, stoppingToken);
        }
    }

    private async Task DoCleanupWorkAsync(CancellationToken ct)
    {
        using var scope = _services.CreateScope();
        var traderRepo = scope.ServiceProvider.GetRequiredService<ITraderRepository>();
        var platformProviders = scope.ServiceProvider.GetRequiredService<IEnumerable<IPlatformProvider>>();

        // Inactive since 1 year ago, or API error since 48 hours ago
        var inactiveSince = DateTime.UtcNow.AddYears(-1);
        var errorSince = DateTime.UtcNow.AddHours(-48);

        var tradersToCleanup = await traderRepo.GetTradersForCleanupAsync(inactiveSince, errorSince, 50, ct);
        
        if (tradersToCleanup.Count == 0) return;

        _logger.LogInformation("Found {Count} traders for cleanup verification", tradersToCleanup.Count);

        foreach (var trader in tradersToCleanup)
        {
            var provider = platformProviders.FirstOrDefault(p => p.Platform == trader.Platform);
            if (provider == null || !provider.IsImplemented) continue;

            _logger.LogInformation("Verifying trader {PlatformUserId} for cleanup...", trader.PlatformUserId);

            try
            {
                var recentTrades = await provider.GetTraderTradesAsync(trader.PlatformUserId, 1, ct);
                
                if (recentTrades.Count > 0)
                {
                    // Trader is still active and API is working
                    trader.LastApiErrorAt = null;
                    trader.LastPolledAt = DateTime.UtcNow;
                    await traderRepo.UpdateAsync(trader, ct);
                    _logger.LogInformation("Trader {PlatformUserId} is still active. Resetting error state.", trader.PlatformUserId);
                }
                else
                {
                    // Check if positions API also returns nothing/error
                    var positions = await provider.GetTraderPositionsAsync(trader.PlatformUserId, ct);
                    if (positions.Count > 0)
                    {
                         trader.LastApiErrorAt = null;
                         trader.LastPolledAt = DateTime.UtcNow;
                         await traderRepo.UpdateAsync(trader, ct);
                         _logger.LogInformation("Trader {PlatformUserId} has open positions. Resetting error state.", trader.PlatformUserId);
                    }
                    else
                    {
                         // Truly inactive or deleted
                         _logger.LogWarning("Trader {PlatformUserId} verified as inactive/deleted. Deleting from database.", trader.PlatformUserId);
                         await traderRepo.DeleteAsync(trader.Id, ct);
                    }
                }
            }
            catch (Exception ex)
            {
                // If API throws an exception again, it might be a confirmed 404
                // We assume persistent error means deleted account
                _logger.LogWarning(ex, "API error fetching {PlatformUserId} during cleanup. Deleting trader.", trader.PlatformUserId);
                await traderRepo.DeleteAsync(trader.Id, ct);
            }

            // Small delay to prevent API spam
            await Task.Delay(1000, ct);
        }
    }
}
