using Managing.Application.Abstractions.Services;
using Managing.Core;
using Managing.Domain.Backtests;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using static Managing.Common.Enums;

namespace Managing.Application.Workers;

/// <summary>
/// Worker that processes genetic algorithm requests
/// </summary>
public class GeneticAlgorithmWorker : BaseWorker<GeneticAlgorithmWorker>
{
    private readonly IServiceScopeFactory _scopeFactory;

    public GeneticAlgorithmWorker(
        ILogger<GeneticAlgorithmWorker> logger,
        IServiceProvider serviceProvider,
        IServiceScopeFactory scopeFactory)
        : base(WorkerType.GeneticAlgorithm, logger, TimeSpan.FromMinutes(5), serviceProvider)
    {
        _scopeFactory = scopeFactory;
    }

    protected override async Task Run(CancellationToken cancellationToken)
    {
        try
        {
            _logger.LogInformation("[GeneticAlgorithm] Starting genetic algorithm processing");

            // TODO: Implement method to get pending genetic requests
            // For now, we'll create a placeholder for the genetic algorithm logic
            await ProcessPendingGeneticRequests(cancellationToken);

            _logger.LogInformation("[GeneticAlgorithm] Completed genetic algorithm processing");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[GeneticAlgorithm] Error during genetic algorithm processing");
            throw;
        }
    }

    private async Task ProcessPendingGeneticRequests(CancellationToken cancellationToken)
    {
        try
        {
            // Get pending genetic requests from the repository using scoped service
            var pendingRequests = await ServiceScopeHelpers.WithScopedService<IGeneticService, IEnumerable<GeneticRequest>>(_scopeFactory, 
                async geneticService => await geneticService.GetGeneticRequestsAsync(GeneticRequestStatus.Pending));
            
            if (!pendingRequests.Any())
            {
                _logger.LogInformation("[GeneticAlgorithm] No pending genetic requests found");
                return;
            }

            _logger.LogInformation("[GeneticAlgorithm] Found {Count} pending genetic requests", pendingRequests.Count());
            
            foreach (var request in pendingRequests)
            {
                try
                {
                    _logger.LogInformation("[GeneticAlgorithm] Processing request {RequestId}", request.RequestId);
                    
                    // Update status to Running using scoped service
                    request.Status = GeneticRequestStatus.Running;
                    await ServiceScopeHelpers.WithScopedService<IGeneticService>(_scopeFactory, 
                        async geneticService => await geneticService.UpdateGeneticRequestAsync(request));

                    // Run genetic algorithm using the service
                    var results = await ServiceScopeHelpers.WithScopedServices<IGeneticService, IBacktester, GeneticAlgorithmResult>(_scopeFactory,
                        async (geneticService, backtester) => await geneticService.RunGeneticAlgorithm(request, cancellationToken));

                    // Update request with results using scoped service
                    request.Status = GeneticRequestStatus.Completed;
                    request.CompletedAt = DateTime.UtcNow;
                    request.BestFitness = results.BestFitness;
                    request.BestIndividual = results.BestIndividual;
                    request.ProgressInfo = results.ProgressInfo;

                    await ServiceScopeHelpers.WithScopedService<IGeneticService>(_scopeFactory, 
                        async geneticService => await geneticService.UpdateGeneticRequestAsync(request));
                    
                    _logger.LogInformation("[GeneticAlgorithm] Successfully completed request {RequestId}", request.RequestId);
                }
                catch (Exception ex)
                {
                    request.Status = GeneticRequestStatus.Failed;
                    request.ErrorMessage = ex.Message;
                    request.CompletedAt = DateTime.UtcNow;
                    await ServiceScopeHelpers.WithScopedService<IGeneticService>(_scopeFactory, 
                        async geneticService => await geneticService.UpdateGeneticRequestAsync(request));
                    
                    _logger.LogError(ex, "[GeneticAlgorithm] Error processing request {RequestId}", request.RequestId);
                }
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[GeneticAlgorithm] Error retrieving pending genetic requests");
            throw;
        }
    }
} 