using IWS5.Importer.Abstractions.Interfaces;
using Serilog.Context;
using Serilog;
using IWS5.Importer.Worker.Extensions;

namespace IWS5.Importer.Worker.Workers;

/// <summary>
/// Background service responsible for periodically importing files.
/// </summary>
public class FileImportWorker : BackgroundService
{
    private readonly IServiceScopeFactory _serviceScopeFactory;
    private readonly Serilog.ILogger _logService;
    private readonly IGeneralImportSettingsProvider _settingsProvider;

    public FileImportWorker(
        IGeneralImportSettingsProvider settingsProvider,
        IServiceScopeFactory serviceScopeFactory,
        Serilog.ILogger logService)
    {
        _settingsProvider = settingsProvider;
        _serviceScopeFactory = serviceScopeFactory;
        _logService = logService;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using (LogContext.PushProperty("LogContext", nameof(ExecuteAsync)))
        {
            _logService.Information("FileImportWorker started.");

            while (!stoppingToken.IsCancellationRequested)
            {
                await RunImportCycleAsync(stoppingToken);
                _logService.Information("Import Cycle in progress. Next run in {PauseTimeMinutes} minutes.", _settingsProvider.Settings.PauseTimeMinutes);

                await Task.Delay(TimeSpan.FromMinutes(_settingsProvider.Settings.PauseTimeMinutes), stoppingToken);
            }

            _logService.Information("FileImportWorker stopped.");
        }
    }

    private async Task RunImportCycleAsync(CancellationToken stoppingToken)
    {
        try
        {
            CorrelationIdEnricher.SetCorrelationId(Guid.NewGuid().ToString());
            using var scope = _serviceScopeFactory.CreateScope();
            var fileImportProcessor = scope.ServiceProvider.GetRequiredService<IFileImportProcessor>();

            using (LogContext.PushProperty("LogContext", nameof(RunImportCycleAsync)))
                _logService.Information("Starting import cycle.");

            await fileImportProcessor.ProcessImportDirectory(stoppingToken);
        }
        catch (OperationCanceledException)
        {
            using (LogContext.PushProperty("LogContext", nameof(RunImportCycleAsync)))
                _logService.Warning("Import operation was canceled.");
        }
        catch (Exception ex)
        {
            using (LogContext.PushProperty("LogContext", nameof(RunImportCycleAsync)))
                _logService.Error(ex, "Unexpected error occurred during import cycle.");
        }
    }
}
