using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.BLL.Domain.Mq;
using PARR.BLL.Services.Interfaces;
using PARR.Common.Domain;
using PARR.Constants;
using PARR.DAL.Cache.Models;
using PARR.DAL.Contracts;
using PARR.DAL.DomainServices.Interfaces;
using PARR.DAL.DomainServices.Shortcodes;
using PARR.DAL.Models;
using PARR.DAL.Models.Job;
using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Unit;
using PARR.DAL.TransformServices;
using PARR.TemplateMatcher.Services.Interfaces;
using PARR.TemplateMatcher.Settings;
using System.Text.Json;

namespace PARR.TemplateMatcher.Services.Implementations;

internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
{
#if DEBUG
    private readonly Guid targetUnitId = Guid.Parse("358437ac-1eeb-4c00-840c-998326f657ac");
#endif

    private const bool DefaultUsedTemplateState = false;
    private const bool DefaultUsedScheduleState = false;

    // Маска для неиспользуемых шаблонов — хардкод, недоступна из GUI
    private const string UnusedTemplateNameMask = "%П-1%_НЕАКТУАЛЬНЫЕ_%ЭК%_%ТИКТАК%";

    private readonly ILogger<SimpleTemplateSynchronizer> logger;
    private readonly IUnitFilterService unitFilterService;
    private readonly MqSettings mqSettings;
    private readonly IMqService mqService;
    private readonly ITemplateService templateService;
    private readonly IJobService jobService;
    private readonly ITemplateReuser templateReuser;
    private readonly IEsppScheduleTransformService esppScheduleTransformService;
    private readonly ITemplateDeactivator templateDeactivator;
    private readonly ITemplateNameNormalizer templateNameNormalizer;
    private readonly ITemplateUpdaterMqSender templateUpdaterMqSender;
    private readonly IMatchingStatusService matchingStatusService;
    private readonly SettingsFromDb settingsFromDb;

    public SimpleTemplateSynchronizer(
        ILogger<SimpleTemplateSynchronizer> logger,
        IUnitFilterService unitFilterService,
        IUnitInUnitService unitInUnitService,
        IUnitInValueService unitInValueService,
        IUnitService unitService,
        MqSettings mqSettings,
        IMqService mqService,
        ITemplateService templateService,
        IJobService jobService,
        ITemplateReuser templateReuser,
        IShortcodesService shortcodesService,
        IEsppScheduleTransformService esppScheduleTransformService,
        IUnitRegionalEkPtkGroupService regionalEkPtkGroupService,
        IUnitFieldService unitFieldService,
        ITemplateDeactivator templateDeactivator,
        ITemplateNameNormalizer templateNameNormalizer,
        ITemplateUpdaterMqSender templateUpdaterMqSender,
        IMatchingStatusService matchingStatusService,
        SettingsFromDb settingsFromDb
        )
    {
        this.logger = logger;
        this.unitFilterService = unitFilterService;
        this.mqSettings = mqSettings;
        this.mqService = mqService;
        this.templateService = templateService;
        this.jobService = jobService;
        this.templateReuser = templateReuser;
        this.esppScheduleTransformService = esppScheduleTransformService;
        this.templateDeactivator = templateDeactivator;
        this.templateNameNormalizer = templateNameNormalizer;
        this.templateUpdaterMqSender = templateUpdaterMqSender;
        this.matchingStatusService = matchingStatusService;
        this.settingsFromDb = settingsFromDb;
    }

    public async Task SyncTemplatesForJobAsync(Guid jobId, HistoryInitiator initiator)
    {
        // === Специальная обработка для Job неиспользуемых шаблонов ===
        if (jobId == settingsFromDb.JobIdForUnusedTemplates)
        {
            logger.LogInformation("Обработка синхронизации для Job неиспользуемых шаблонов {JobId}", jobId);
            await SyncUnusedTemplatesAsync(jobId, initiator);
            return;
        }

        // === Обычная логика для всех остальных Job ===
        logger.LogDebug("Начало синхронизации шаблонов для Job {JobId}", jobId);

        // === Проверка: уже запущена? ===
        var existingStatus = await matchingStatusService.GetStatusAsync(jobId, SyncTaskEntityTypeEnum.Job);
        if (existingStatus.DetailsJobs?.Any() == true)
        {
            logger.LogWarning("Синхронизация для Job {JobId} уже запущена. Пропускаем.", jobId);
            return;
        }

        // === Устанавливаем статус "в процессе" ===
        var initialStatus = new MatchingStatusItemDto
        {
            DateStart = DateTimeOffset.UtcNow,
            Action = TemplateMatcherActionEnum.Sync,
            Comment = "Начало синхронизации"
        };
        await matchingStatusService.SetMatchingStatusAsync(
            jobId,
            SyncTaskEntityTypeEnum.Job,
            new MatchingStatusItem { Data = initialStatus, Timestamp = DateTimeOffset.UtcNow, Source = nameof(SimpleTemplateSynchronizer) },
            TimeSpan.FromMinutes(35)
        );

        try
        {
            var job = await jobService.Get()
                .AsNoTracking()
                .Include(j => j.AutoControl)
                .Include(j => j.Tnk)
                .Include(j => j.Group)
                    .ThenInclude(g => g!.GroupType)
                .Include(j => j.UnitFilters)
                    .ThenInclude(uf => uf.RelationshipFilters)
                .FirstOrDefaultAsync(j => j.Id == jobId);

            if (job == null)
            {
                logger.LogWarning("Job {JobId} не найден.", jobId);
                await UpdateMatchingStatusAsync(jobId, "Job не найден");
                return;
            }

            var unitIds = await unitFilterService.GetUnitsIdByJobFilterAsync(jobId);
            if (unitIds == null || !unitIds.Any())
            {
                logger.LogInformation("Для Job {JobId} фильтры не дали Unit'ов.", jobId);

                var existingTemplatesForDeactivation = await templateService.Get()
                    .AsNoTracking()
                    .Include(t => t.UnitsInTemplate)
                    .Where(t => t.JobId == jobId && t.StatusTypeId == TemplateStatusTypeEnum.Used)
                    .ToListAsync();

                await UpdateMatchingStatusAsync(jobId, $"Нет Unit'ов. Деактивация {existingTemplatesForDeactivation.Count} шаблонов...");

                foreach (var unusedTemplate in existingTemplatesForDeactivation)
                {
                    logger.LogInformation("Деактивация лишнего шаблона {TemplateId} (Job {JobId}, UnitId {UnitId}).", unusedTemplate.Id, jobId, unusedTemplate.UnitId);
                    await templateDeactivator.DeactivateTemplateAsync(unusedTemplate, initiator);
                }

                await UpdateMatchingStatusAsync(jobId, "Синхронизация завершена: нет Unit'ов");
                await matchingStatusService.DeleteMatchingStatusAsync(jobId, SyncTaskEntityTypeEnum.Job);
                logger.LogInformation("Синхронизация шаблонов завершена для Job {JobId}.", jobId);
                return;
            }

#if DEBUG
            // Отладка: проверить, есть ли юнит в unitIds
            if (unitIds.Contains(targetUnitId))
            {
                logger.LogDebug("Юнит {TargetUnitId} найден в unitIds.", targetUnitId);
            }
            else
            {
                logger.LogDebug("Юнит {TargetUnitId} НЕ найден в unitIds.", targetUnitId);
            }
#endif

            var existingTemplates = await templateService.Get()
                .Include(t => t.UnitsInTemplate)
                .Include(t => t.Job)
                    .ThenInclude(t => t!.Group)
                        .ThenInclude(t => t.GroupType)
                .Include(t => t.Job)
                    .ThenInclude(t => t!.Tnk)
                .Include(t => t.Unit)
                .Where(t => t.JobId == jobId)
                .ToListAsync();

            var existingUsedTemplates = existingTemplates
                .Where(t => t.StatusTypeId == TemplateStatusTypeEnum.Used)
                .ToList();

            var existingUnitIds = existingUsedTemplates
                .Select(t => t.UnitId)
                .ToHashSet();

            var newUnitIds = unitIds.Except(existingUnitIds).ToList();
            var unusedTemplates = existingUsedTemplates
                .Where(t => !unitIds.Contains(t.UnitId))
                .ToList();

            // === Подсчёт операций ===
            int toCreate = newUnitIds.Count;
            int toUpdate = 0;
            int toDeactivate = unusedTemplates.Count;

            // Подсчёт обновлений по имени
            foreach (var template in existingUsedTemplates)
            {
                if (unitIds.Contains(template.UnitId))
                {
                    var expectedName = await templateNameNormalizer.GetNormalizedTemplateNameAsync(template);
                    if (!string.Equals(template.Name, expectedName, StringComparison.OrdinalIgnoreCase))
                        toUpdate++;
                }
            }

            await UpdateMatchingStatusAsync(jobId, $"Осталось: создать={toCreate}, обновить={toUpdate}, деактивировать={toDeactivate}");

            // === Обработка новых юнитов ===
            int created = 0, updated = 0, deactivated = 0;
            foreach (var unitId in newUnitIds)
            {
                var reusableTemplate = await templateReuser.TryReuseOneUnusedTemplateAsync(jobId, unitId, initiator);
                if (reusableTemplate != null)
                {
                    logger.LogInformation("Переиспользован шаблон {TemplateId} для Job {JobId}, UnitId {UnitId}.", reusableTemplate.Id, jobId, unitId);

                    // === Создаём временный Template для нормализации имени ===
                    var tempTemplateForName = new Template
                    {
                        Id = reusableTemplate.Id,
                        Name = reusableTemplate.Name,
                        JobId = jobId,
                        UnitId = unitId,
                        Index = reusableTemplate.Index,
                        Job = job, // загруженный job
                        Unit = reusableTemplate.Unit, // может быть null — нормально
                        UnitsInTemplate = new List<UnitsInTemplate>() // для простого шаблона
                    };

                    var expectedName = await templateNameNormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
                    var nextRun = await GetNextRunAsync(job);

                    var updateRequest = new TemplateUpdaterMq
                    {
                        TemplateId = reusableTemplate.Id,
                        JobId = jobId,
                        UnitId = unitId,
                        Name = expectedName,
                        IsActiveTemplate = job.AutoControl?.InitUsedTemplateState ?? DefaultUsedTemplateState,
                        IsActiveSchedule = job.AutoControl?.InitUsedScheduleState ?? DefaultUsedScheduleState,
                        StatusTypeId = TemplateStatusTypeEnum.Used,
                        Initiator = initiator,
                        NextRun = nextRun,
                        UnitsInTemplate = new List<Guid>() // для простого шаблона
                    };

                    await templateUpdaterMqSender.SendTemplateUpdateMessageAsync(updateRequest);
                }
                else
                {
                    logger.LogDebug("Создание нового шаблона для Job {JobId}, UnitId {UnitId}.", jobId, unitId);
                    await CreateSimpleTemplateAsync(jobId, unitId, initiator);
                }
                created++;
                await UpdateMatchingStatusAsync(jobId, $"Прогресс: создано={created}, обновлено={updated}, деактивировано={deactivated}. Осталось: создать={toCreate - created}, обновить={toUpdate - updated}, деактивировать={toDeactivate - deactivated}");
            }

            // === Обработка существующих шаблонов (проверка имени) ===
            foreach (var template in existingUsedTemplates)
            {
                if (unitIds.Contains(template.UnitId))
                {
                    var expectedName = await templateNameNormalizer.GetNormalizedTemplateNameAsync(template);
                    if (!string.Equals(template.Name, expectedName, StringComparison.OrdinalIgnoreCase))
                    {
                        logger.LogDebug("Шаблон {TemplateId} требует обновления имени: старое = '{OldName}', новое = '{NewName}'", template.Id, template.Name, expectedName);

                        var nextRun = await GetNextRunAsync(job, template.NextRun);

                        var updateRequest = new TemplateUpdaterMq
                        {
                            TemplateId = template.Id,
                            JobId = jobId,
                            UnitId = template.UnitId,
                            Name = expectedName,
                            IsActiveTemplate = template.IsActiveTemplate,
                            IsActiveSchedule = template.IsActiveSchedule,
                            LastRun = template.LastRun,
                            NextRun = nextRun,
                            Index = template.Index,
                            StatusTypeId = TemplateStatusTypeEnum.Used,
                            Initiator = initiator,
                            UnitsInTemplate = new List<Guid>() // для простого шаблона
                        };

                        await templateUpdaterMqSender.SendTemplateUpdateMessageAsync(updateRequest);
                        updated++;
                        await UpdateMatchingStatusAsync(jobId, $"Прогресс: создано={created}, обновлено={updated}, деактивировано={deactivated}. Осталось: создать={toCreate - created}, обновить={toUpdate - updated}, деактивировать={toDeactivate - deactivated}");
                    }
                }
            }

            // === Деактивация лишних шаблонов ===
            foreach (var unusedTemplate in unusedTemplates)
            {
                logger.LogInformation("Деактивация лишнего шаблона {TemplateId} (Job {JobId}, UnitId {UnitId}).", unusedTemplate.Id, jobId, unusedTemplate.UnitId);
                await templateDeactivator.DeactivateTemplateAsync(unusedTemplate, initiator);
                deactivated++;
                await UpdateMatchingStatusAsync(jobId, $"Прогресс: создано={created}, обновлено={updated}, деактивировано={deactivated}. Осталось: создать={toCreate - created}, обновить={toUpdate - updated}, деактивировать={toDeactivate - deactivated}");
            }

            // === Успешное завершение ===
            await UpdateMatchingStatusAsync(jobId, "Синхронизация завершена успешно");
            await matchingStatusService.DeleteMatchingStatusAsync(jobId, SyncTaskEntityTypeEnum.Job);
            logger.LogInformation("Синхронизация шаблонов завершена для Job {JobId}.", jobId);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Ошибка при синхронизации Job {JobId}", jobId);
            await UpdateMatchingStatusAsync(jobId, $"Ошибка: {ex.Message}");
            throw;
        }
    }

    public async Task SyncTemplatesForJobGroupAsync(Guid jobGroupId, HistoryInitiator initiator)
    {
        logger.LogWarning("SimpleTemplateSynchronizer: SyncTemplatesForJobGroup вызван для JobGroup {JobGroupId}. Это не поддерживаемая операция.", jobGroupId);
    }

    public async Task UpdateTemplatesForJobAsync(Guid jobId, HistoryInitiator initiator)
    {
        logger.LogDebug("Обновление шаблонов для Job {JobId}", jobId);

        // === Проверка: уже запущена? ===
        var existingStatus = await matchingStatusService.GetStatusAsync(jobId, SyncTaskEntityTypeEnum.Job);
        if (existingStatus.DetailsJobs?.Any() == true)
        {
            logger.LogWarning("Обновление для Job {JobId} уже запущено. Пропускаем.", jobId);
            return;
        }

        var initialStatus = new MatchingStatusItemDto
        {
            DateStart = DateTimeOffset.UtcNow,
            Action = TemplateMatcherActionEnum.Update,
            Comment = "Начало обновления имён"
        };
        await matchingStatusService.SetMatchingStatusAsync(
            jobId,
            SyncTaskEntityTypeEnum.Job,
            new MatchingStatusItem { Data = initialStatus, Timestamp = DateTimeOffset.UtcNow, Source = nameof(SimpleTemplateSynchronizer) },
            TimeSpan.FromMinutes(30)
        );

        try
        {
            var job = await jobService.Get()
                .AsNoTracking()
                .Include(j => j.AutoControl)
                .Include(j => j.Tnk)
                .Include(j => j.Group)
                    .ThenInclude(g => g!.GroupType)
                .Include(j => j.UnitFilters)
                    .ThenInclude(uf => uf.RelationshipFilters)
                .FirstOrDefaultAsync(j => j.Id == jobId);

            if (job == null)
            {
                logger.LogWarning("Job {JobId} не найден.", jobId);
                await UpdateMatchingStatusAsync(jobId, "Job не найден");
                return;
            }

            var unitIds = await unitFilterService.GetUnitsIdByJobFilterAsync(jobId);
            if (unitIds == null || !unitIds.Any())
            {
                logger.LogInformation("Для Job {JobId} фильтры не дали Unit'ов.", jobId);
                await UpdateMatchingStatusAsync(jobId, "Нет Unit'ов — обновление не требуется");
                await matchingStatusService.DeleteMatchingStatusAsync(jobId, SyncTaskEntityTypeEnum.Job);
                return;
            }

#if DEBUG
            // Отладка: проверить, есть ли юнит в unitIds
            if (unitIds.Contains(targetUnitId))
            {
                logger.LogDebug("Юнит {TargetUnitId} найден в unitIds.", targetUnitId);
            }
            else
            {
                logger.LogDebug("Юнит {TargetUnitId} НЕ найден в unitIds.", targetUnitId);
            }
#endif

            var existingTemplates = await templateService.Get()
                .AsNoTracking()
                .Include(t => t.Unit)
                .Include(t => t.UnitsInTemplate)
                .Include(t => t.Job)
                    .ThenInclude(t => t!.Group)
                        .ThenInclude(t => t!.GroupType)
                .Include(t => t.Job)
                    .ThenInclude(t => t!.Tnk)
                .Where(t => t.JobId == jobId && t.StatusTypeId == TemplateStatusTypeEnum.Used)
                .ToListAsync();

            foreach (var template in existingTemplates)
            {
                if (unitIds.Contains(template.UnitId))
                {
                    var expectedName = await templateNameNormalizer.GetNormalizedTemplateNameAsync(template);
                    if (!string.Equals(template.Name, expectedName, StringComparison.OrdinalIgnoreCase))
                    {
                        logger.LogDebug("Шаблон {TemplateId} требует обновления имени: старое = '{OldName}', новое = '{NewName}'", template.Id, template.Name, expectedName);

                        var nextRun = await GetNextRunAsync(job, template.NextRun);

                        var updateRequest = new TemplateUpdaterMq
                        {
                            TemplateId = template.Id,
                            JobId = jobId,
                            UnitId = template.UnitId,
                            Name = expectedName,
                            IsActiveTemplate = template.IsActiveTemplate,
                            IsActiveSchedule = template.IsActiveSchedule,
                            LastRun = template.LastRun,
                            NextRun = nextRun,
                            Index = template.Index,
                            StatusTypeId = TemplateStatusTypeEnum.Used,
                            Initiator = initiator,
                            UnitsInTemplate = new List<Guid>() // для простого шаблона
                        };

                        await templateUpdaterMqSender.SendTemplateUpdateMessageAsync(updateRequest);
                    }
                }
            }

            await UpdateMatchingStatusAsync(jobId, "Обновление завершено");
            await matchingStatusService.DeleteMatchingStatusAsync(jobId, SyncTaskEntityTypeEnum.Job);
            logger.LogInformation("Обновление шаблонов завершено для Job {JobId}.", jobId);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Ошибка при обновлении Job {JobId}", jobId);
            await UpdateMatchingStatusAsync(jobId, $"Ошибка: {ex.Message}");
            throw;
        }
    }

    private async Task SyncUnusedTemplatesAsync(Guid unusedJobId, HistoryInitiator initiator)
    {
        // === Проверка: уже запущена? ===
        var existingStatus = await matchingStatusService.GetStatusAsync(unusedJobId, SyncTaskEntityTypeEnum.Job);
        if (existingStatus.DetailsJobs?.Any() == true)
        {
            logger.LogWarning("Синхронизация для Job неиспользуемых шаблонов {JobId} уже запущена. Пропускаем.", unusedJobId);
            return;
        }

        // === Устанавливаем статус "в процессе" ===
        var initialStatus = new MatchingStatusItemDto
        {
            DateStart = DateTimeOffset.UtcNow,
            Action = TemplateMatcherActionEnum.Sync,
            Comment = "Синхронизация неиспользуемых шаблонов"
        };
        await matchingStatusService.SetMatchingStatusAsync(
            unusedJobId,
            SyncTaskEntityTypeEnum.Job,
            new MatchingStatusItem { Data = initialStatus, Timestamp = DateTimeOffset.UtcNow, Source = nameof(SimpleTemplateSynchronizer) },
            TimeSpan.FromMinutes(30)
        );

        try
        {
            // Загружаем Job неиспользуемых шаблонов с Group
            var unusedJob = await jobService.Get()
                .AsNoTracking()
                .Include(j => j.Group)
                .FirstOrDefaultAsync(j => j.Id == unusedJobId);

            if (unusedJob == null)
            {
                logger.LogError("Job неиспользуемых шаблонов {JobId} не найден.", unusedJobId);
                await UpdateMatchingStatusAsync(unusedJobId, "Job не найден");
                return;
            }

            // Находим все шаблоны со статусом Unused
            var unusedTemplates = await templateService.Get()
                .Include(t => t.Unit)
                .Where(t => t.StatusTypeId == TemplateStatusTypeEnum.Unused)
                .ToListAsync();

            if (!unusedTemplates.Any())
            {
                logger.LogInformation("Не найдено шаблонов со статусом Unused.");
                await UpdateMatchingStatusAsync(unusedJobId, "Нет шаблонов для обработки");
                await matchingStatusService.DeleteMatchingStatusAsync(unusedJobId, SyncTaskEntityTypeEnum.Job);
                return;
            }

            await UpdateMatchingStatusAsync(unusedJobId, $"Найдено {unusedTemplates.Count} шаблонов для обработки");

            int processed = 0;
            foreach (var template in unusedTemplates)
            {
                // Генерируем ожидаемое имя один раз
                var expectedName = await GenerateUnusedTemplateNameAsync(template, unusedJob);

                // Проверяем, нужно ли обновление
                bool needsUpdate = template.JobId != unusedJobId ||
                                   !string.Equals(template.Name, expectedName, StringComparison.OrdinalIgnoreCase);

                if (!needsUpdate)
                {
                    logger.LogDebug("Шаблон {TemplateId} уже имеет актуальное имя и JobId. Пропускаем.", template.Id);
                    continue;
                }

                var nextRun = await GetNextRunAsync(unusedJob);

                var updateRequest = new TemplateUpdaterMq
                {
                    TemplateId = template.Id,
                    JobId = unusedJobId,
                    UnitId = template.UnitId,
                    Name = expectedName,
                    IsActiveTemplate = false,
                    IsActiveSchedule = false,
                    LastRun = template.LastRun,
                    NextRun = nextRun,
                    Index = null,
                    StatusTypeId = TemplateStatusTypeEnum.Unused,
                    Initiator = initiator,
                    UnitsInTemplate = new List<Guid>()
                };

                await templateUpdaterMqSender.SendTemplateUpdateMessageAsync(updateRequest);
                processed++;
                await UpdateMatchingStatusAsync(unusedJobId, $"Обработано: {processed}/{unusedTemplates.Count}");
            }

            await UpdateMatchingStatusAsync(unusedJobId, "Синхронизация неиспользуемых шаблонов завершена");
            await matchingStatusService.DeleteMatchingStatusAsync(unusedJobId, SyncTaskEntityTypeEnum.Job);
            logger.LogInformation("Синхронизация неиспользуемых шаблонов завершена. Обработано {Count} шаблонов.", unusedTemplates.Count);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Ошибка при синхронизации неиспользуемых шаблонов для Job {JobId}", unusedJobId);
            await UpdateMatchingStatusAsync(unusedJobId, $"Ошибка: {ex.Message}");
            throw;
        }
    }

    private async Task<string> GenerateUnusedTemplateNameAsync(Template template, Job unusedJob)
    {
        var tempJob = new Job
        {
            Id = unusedJob.Id,
            Name = unusedJob.Name,
            WorkName = unusedJob.WorkName,
            MinValueRelationships = unusedJob.MinValueRelationships,
            MaxValueRelationships = unusedJob.MaxValueRelationships,
            IsParentRelationships = unusedJob.IsParentRelationships,
            TemplateNameMask = UnusedTemplateNameMask,
            WorkGroupMask = unusedJob.WorkGroupMask,
            ResponseAreaMask = unusedJob.ResponseAreaMask,
            TnkId = unusedJob.TnkId,
            GroupId = unusedJob.GroupId,
            Group = unusedJob.Group,
            Tnk = unusedJob.Tnk,
            UnitFilters = unusedJob.UnitFilters,
            Templates = unusedJob.Templates,
            AutoControl = unusedJob.AutoControl
        };

        var tempTemplateForName = new Template
        {
            Id = template.Id,
            Name = template.Name,
            JobId = unusedJob.Id,
            UnitId = template.UnitId,
            Index = null,
            Job = tempJob,
            Unit = template.Unit,
            UnitsInTemplate = new List<UnitsInTemplate>()
        };

        return await templateNameNormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
    }

    private async Task CreateSimpleTemplateAsync(Guid jobId, Guid unitId, HistoryInitiator initiator)
    {
        logger.LogInformation("Создание нового простого шаблона для Job {JobId}, UnitId {UnitId}.", jobId, unitId);

        var mqRequest = new TemplateGeneratorMq
        {
            JobId = jobId,
            UnitId = unitId,
            UnitsInTemplate = new List<Guid>(), // для простого шаблона
            HistoryInitiator = initiator
        };

        var msg = JsonSerializer.Serialize(mqRequest);
        var result = await mqService.SendAsync(mqSettings.TemplateGenerator, new[] { msg });

        if (!result.IsSuccess)
            logger.LogError("Ошибка отправки команды создания простого шаблона для Job {JobId}, UnitId {UnitId}.", jobId, unitId);
    }

    private async Task<DateTimeOffset> GetNextRunAsync(Job job, DateTimeOffset? currentNextRun = null)
    {
        var referenceDate = job.Group?.ReferenceDate ?? DateTimeOffset.UtcNow;
        return await esppScheduleTransformService.GetNextDateAsync(job.GroupId, referenceDate);
    }

    private async Task UpdateMatchingStatusAsync(Guid jobId, string comment)
    {
        var status = new MatchingStatusItemDto
        {
            DateStart = DateTimeOffset.UtcNow,
            Action = TemplateMatcherActionEnum.Sync,
            Comment = comment
        };
        await matchingStatusService.SetMatchingStatusAsync(
            jobId,
            SyncTaskEntityTypeEnum.Job,
            new MatchingStatusItem { Data = status, Timestamp = DateTimeOffset.UtcNow, Source = nameof(SimpleTemplateSynchronizer) },
            TimeSpan.FromMinutes(30)
        );
    }
}