using Microsoft.EntityFrameworkCore;
using PARR.BLL.Domain.Mq;
using PARR.BLL.Services.Interfaces;
using PARR.Common.Domain;
using PARR.Constants;
using PARR.DAL.DomainServices.Shortcodes;
using PARR.DAL.DomainServices.Shortcodes.Models;
using PARR.DAL.Models;
using PARR.DAL.Models.Job;
using PARR.DAL.Models.Unit;
using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.TransformServices;
using PARR.TemplateGeneratorWorker.Services;

namespace PARR.TemplateGeneratorWorker
{
    internal class TemplateGenerator : ITemplateGenerator
    {
        private readonly ILogger<TemplateGenerator> logger;
        private readonly ITransformService transformService;
        private readonly IValidatorService validatorService;
        private readonly IJobService jobService;
        private readonly IShortcodesService shortcodesService;
        private readonly ITemplateService templateService;
        private readonly IEsppScheduleTransformService esppScheduleTransformService;

        public TemplateGenerator(
            ILogger<TemplateGenerator> logger,
            ITransformService transformService,
            IValidatorService validatorService,
            IJobService jobService,
            IShortcodesService shortcodesService,
            ITemplateService templateService,
            IEsppScheduleTransformService esppScheduleTransformService
            )
        {
            this.logger = logger;
            this.transformService = transformService;
            this.validatorService = validatorService;
            this.jobService = jobService;
            this.shortcodesService = shortcodesService;
            this.templateService = templateService;
            this.esppScheduleTransformService = esppScheduleTransformService;
        }

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

            var query = transformService.GetModelFromJson<TemplateGeneratorMq>(msg);

            if (query == null)
            {
                logger.LogError("Не удалось десериализовать запрос: {Message}", msg);
                return;
            }

            // Проверяем всё 
            if (!await validatorService.IsValidAsync(query.JobId, query.UnitId, query.Index, query.UnitsInTemplate))
            {
                logger.LogError($"Параметры запроса не прошли валидацию: JobId={query.JobId}, UnitId={query.UnitId}, Index={query.Index}, UnitsInTemplateCount={query.UnitsInTemplate?.Count ?? 0}");
                return;
            }

            var job = await jobService
                            .Get().AsNoTracking()
                            .Include(t => t.Group)
                            .ThenInclude(g => g!.GroupType)
                            .Include(t => t.Tnk)
                            .FirstOrDefaultAsync(t => t.Id == query.JobId);

            if (job == null)
            {
                logger.LogError("Job не найден: {JobId}", query.JobId);
                return;
            }

            if (job.Group == null)
            {
                logger.LogError("Job {JobId} не привязан к JobGroup", query.JobId);
                return;
            }

            // === Создаём временный Template для подстановки шорткодов ===
            var tempTemplateForShortcodes = new Template
            {
                Id = Guid.Empty, // ещё не создан
                Name = "", // не используется
                JobId = query.JobId,
                UnitId = query.UnitId,
                Index = query.Index,
                Job = job,
                Unit = null, // ShortcodesService сам догрузит при необходимости
                UnitsInTemplate = query.UnitsInTemplate?.Select(unitId => new UnitsInTemplate { UnitId = unitId }).ToList() ?? new List<UnitsInTemplate>()
            };

            var templateName = await shortcodesService.ApplyShortcodesAsync(job.TemplateNameMask!, tempTemplateForShortcodes);

            var nextRun = await esppScheduleTransformService.GetNextDateAsync(job.GroupId, job.Group!.ReferenceDate);

            var template = new Template
            {
                Id = Guid.NewGuid(),
                Name = templateName.ToUpper(),
                UnitId = query.UnitId,
                JobId = query.JobId,
                IsActiveTemplate = query.IsActiveTemplate ?? false,
                IsActiveSchedule = query.IsActiveSchedule ?? false,
                NextRun = nextRun,
                StatusTypeId = TemplateStatusTypeEnum.Used,
                InitiatorComment = query.HistoryInitiator?.InitiatorComment,
                InitiatorParrComponentId = query.HistoryInitiator?.InitiatorParrComponentId,
                Index = query.Index,
                UnitsInTemplate = query.UnitsInTemplate?.Select(unitId => new UnitsInTemplate { UnitId = unitId }).ToList() ?? new List<UnitsInTemplate>()
            };

            if (await templateService.CreateAsync(template) && await templateService.CommitAsync(new HistoryInitiator { InitiatorComment = "Запрос на генерацию с тестового шаблона", InitiatorParrComponentId = ParrComponentsEnum.TemplateTaskGenerator }))
            {
                logger.LogInformation("Создан шаблон: Id={TemplateId}, Name={Name}, Job={JobId}, Unit={UnitId}, Index={Index}, UnitsInTemplateCount={UnitsCount}",
                    template.Id, template.Name, query.JobId, query.UnitId, query.Index, template.UnitsInTemplate.Count);
            }
            else
            {
                logger.LogError("Ошибка создания шаблона: Name={Name}, JobId={JobId}, UnitId={UnitId}, Index={Index}", templateName, query.JobId, query.UnitId, query.Index);
            }
        }
    }
}