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

namespace PARR.TemplateMatcher
{
    internal class MqTemplateMatcher : IMqTemplateMatcher
    {
        private readonly ILogger<MqTemplateMatcher> logger;
        private readonly MqSettings mqSettings;
        private readonly IMqService mqService;
        private readonly ITransformService transformService;
        private readonly IServiceProvider serviceProvider;

        public MqTemplateMatcher(
            ILogger<MqTemplateMatcher> 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.TemplateMatcher, HandleMessageAsync);

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


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

            var query = transformService.GetModelFromJson<TemplateMatcherMq>(msg);
            if (query == null)
            {
                logger.LogWarning("Не удалось десериализовать сообщение в TemplateMatcherMq: {Message}", msg);
                return;
            }

            await using (var scope = serviceProvider.CreateAsyncScope())
            {
                var templateMatcherService = GetServiceInScope<ITemplateMatcher>(scope);

                switch (query.EntityType)
                {
                    case SyncTaskEntityTypeEnum.Job:
                        var jobValidatorService = GetServiceInScope<IJobValidatorService>(scope);
                        if (!await jobValidatorService.IsValidJobAsync(query.Id))
                        {
                            logger.LogWarning("Сущность {EntityType} с Id {Id} не прошла валидацию", query.EntityType, query.Id);
                            return;
                        }

                        switch (query.Action)
                        {
                            case TemplateMatcherActionEnum.Sync:
                                // Создать недостающие шаблоны, привязать к нужному Job, включить/выключить по фильтрам
                                await templateMatcherService.SyncTemplatesForJob(query.Id, query.Initiator);
                                break;
                            case TemplateMatcherActionEnum.Update:
                                // Обновить существующие шаблоны: имя, привязка к Job, вкл/выкл по фильтрам
                                await templateMatcherService.UpdateTemplatesForJob(query.Id, query.Initiator);
                                break;
                            default:
                                logger.LogWarning("Неизвестное действие для {EntityType}: {Action}", query.EntityType, query.Action);
                                break;
                        }
                        break;

                    case SyncTaskEntityTypeEnum.JobGroup:
                        var jobGroupValidatorService = GetServiceInScope<IJobGroupValidatorService>(scope);
                        if (!await jobGroupValidatorService.IsValidJobGroupAsync(query.Id))
                        {
                            logger.LogWarning("Сущность {EntityType} с Id {Id} не прошла валидацию", query.EntityType, query.Id);
                            return;
                        }

                        switch (query.Action)
                        {
                            case TemplateMatcherActionEnum.Sync:
                                await templateMatcherService.SyncTemplatesForJobGroup(query.Id, query.Initiator);
                                break;

                            case TemplateMatcherActionEnum.Update:
                                //await templateMatcherService.UpdateTemplatesForJob(query.Id, query.Initiator);
                                await templateMatcherService.UpdateTemplatesForJobGroup(query.Id, query.Initiator);
                                break;

                            default:
                                logger.LogWarning("Неизвестное действие для {EntityType}: {Action}", query.EntityType, query.Action);
                                break;
                        }
                        break;
                    case SyncTaskEntityTypeEnum.Template:
                        logger.LogWarning("Обработка EntityType Template не реализована. Id: {Id}, Action: {Action}", query.Id, query.Action);
                        break;

                    default:
                        logger.LogWarning("Неизвестный тип сущности: {EntityType}", query.EntityType);
                        break;
                }
            }
        }


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


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

            return service;
        }
    }
}
