using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PARR.BLL.Domain.Mq;
using PARR.BLL.Services.Interfaces;
using PARR.TemplateTaskGenerator.Services;
using PARR.TemplateTaskGenerator.Settings;

namespace PARR.TemplateTaskGenerator
{
    internal class MqTemplateTaskGenerator : IMqTemplateTaskGenerator
    {
        private readonly ILogger<MqTemplateTaskGenerator> logger;
        private readonly MqSettings mqSettings;
        private readonly IMqService mqService;
        private readonly ITransformService transformService;
        private readonly IServiceProvider serviceProvider;

        public MqTemplateTaskGenerator(
            ILogger<MqTemplateTaskGenerator> logger,
            MqSettings mqSettings,
            IMqService mqService,
            ITransformService transformService,
            IServiceProvider serviceProvider
            )
        {
            this.logger = logger;
            this.mqSettings = mqSettings;
            this.mqService = mqService;
            this.transformService = transformService;
            this.serviceProvider = serviceProvider;
        }


        public async Task StartAsync()
        {
            var isConnected = await mqService.InitConsumerAsync(mqSettings.TemplateTaskGenerator, GenerateTemplateTaskAsync);

            if (!isConnected)
                throw new Exception("Ошибка при подключении к RabbitMq");
        }


        public async Task StopAsync()
        {
            await mqService.DisposeAsync();
        }


        private async Task GenerateTemplateTaskAsync(string msg)
        {
            logger.LogInformation($"Получили запрос: {msg}");

            var query = transformService.GetModelFromJson<TemplateTaskGeneratorMq>(msg);
            if (query == null)
                return;

            await using (var scope = serviceProvider.CreateAsyncScope())
            {
                var validatorService = GetServiceInScope<IValidatorService>(scope);
                if (!await validatorService.IsValidAsync(query.JobId))
                    return;

                var templateTaskGenerator = GetServiceInScope<ITemplateTaskGenerator>(scope);
                await templateTaskGenerator.GenerateTemplateTaskAsync(query.JobId);

            }
        }


        private Service GetServiceInScope<Service>(IServiceScope scope)
        {
            var service = scope.ServiceProvider.GetService<Service>();
            if (service == null)
                throw new Exception($"Не найден сервис: {nameof(Service)}");

            return service;
        }
    }
}
