using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace AsbCloudInfrastructure.Background;

/// <summary>
/// Сервис для фонового выполнения работы
/// </summary>
public class BackgroundWorker : BackgroundService
{
    private static readonly TimeSpan executePeriod = TimeSpan.FromSeconds(10);
    private static readonly TimeSpan minDelay = TimeSpan.FromSeconds(2);
    private readonly IServiceProvider serviceProvider;

    public WorkStore WorkStore { get; } = new WorkStore();
    public Work? CurrentWork;

    public string MainLoopLastException { get; private set; } = string.Empty;

    public BackgroundWorker(IServiceProvider serviceProvider)
    {
        this.serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            try
            {
                var work = WorkStore.GetNext();
                if (work is null)
                {
                    await Task.Delay(executePeriod, token);
                    continue;
                }

                CurrentWork = work;
                using var scope = serviceProvider.CreateScope();

                var result = await work.Start(scope.ServiceProvider, token);

                if (!result)
                    WorkStore.Felled.Add(work);
                else
                    WorkStore.Done.Add(work);

                CurrentWork = null;
                await Task.Delay(minDelay, token);
            }
            catch (Exception ex)
            {
                MainLoopLastException = $"BackgroundWorker " +
                    $"MainLoopLastException: \r\n" +
                    $"date: {DateTime.Now:O}\r\n" +
                    $"message: {ex.Message}\r\n" +
                    $"inner: {ex.InnerException?.Message}\r\n" +
                    $"stackTrace: {ex.StackTrace}";
                Trace.TraceError(MainLoopLastException);
            }
        }
    }
}