using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PARR.BLL.Helpers;
using PARR.Core.Common.Interfaces.RabbitServices;
using PARR.Core.Repositories.Interfaces;
using PARR.Core.Repositories.Interfaces.Schedule;
using PARR.Core.Services.NextRunServices;
using PARR.Domain.Entities;
using PARR.Domain.Entities.Base.History;
using PARR.Domain.Enums;
using PARR.Domain.Settings;
using PARR.EsppScheduleSync.Domain;
using PARR.EsppScheduleSync.Settings;
using PARR.EsppSync;
using PARR.EsppSync.Helpers;

namespace PARR.EsppScheduleSync
{
    internal class ScheduleSyncher : IScheduleSyncher
    {
        private readonly ILogger<ScheduleSyncher> logger;
        private readonly GlobalSettings globalSettings;
        private readonly IRabbitService mqService;
        private readonly ISyncService<EsppObjectSchedule> syncService;
        private readonly SettingsFromDb settingsFromDb;
        private readonly IServiceProvider serviceProvider;
        private string noneExcludeCalendarEsppValue;


        public ScheduleSyncher(
            ILogger<ScheduleSyncher> logger,
            GlobalSettings globalSettings,
            IRabbitService mqService,
            ISyncService<EsppObjectSchedule> syncService,
            SettingsFromDb settingsFromDb,
            IServiceProvider serviceProvider
            )
        {
            this.logger = logger;
            this.globalSettings = globalSettings;
            this.mqService = mqService;
            this.syncService = syncService;
            this.settingsFromDb = settingsFromDb;
            this.serviceProvider = serviceProvider;
            this.noneExcludeCalendarEsppValue = string.Empty;

            if (globalSettings.MqSettings == null)
            {
                logger.LogError("Нет секции настроек хранилища. MqSettings, EsppTemplates");
                throw new Exception("Нет секции настроек хранилища. MqSettings, EsppTemplates");
            }

            if (string.IsNullOrEmpty(globalSettings.ParsingSeparator))
                throw new ArgumentException("ParsingSeparator не задан в GlobalSettings.");
        }


        public async Task StartAsync()
        {

            if (string.IsNullOrEmpty(noneExcludeCalendarEsppValue))
                await GetNoneExcludeCalendarEsppValueAsync();



            var isConnected = await mqService.InitConsumerAsync(globalSettings!.MqSettings!, SyncScheduleAsync);

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

            logger.LogInformation("Запущена проверка очереди {QueueName}.", globalSettings.MqSettings!.QueueName);
        }


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

            logger.LogInformation("=== === === Соединение с очередью {QueueName} закрыто === === ===", globalSettings.MqSettings!.QueueName);
        }


        /// <summary>
        /// Получение типа исключения
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        private async Task GetNoneExcludeCalendarEsppValueAsync()
        {
            using var scope = serviceProvider.CreateScope();
            var service = scope.ServiceProvider.GetRequiredService<IScheduleExcludeTypeRepository>();

            var noneExcludeType = await service.Get().AsNoTracking().FirstOrDefaultAsync(t => t.Code == nameof(ScheduleExcludeTypeEnum.None));

            if (noneExcludeType == null)
                throw new InvalidOperationException($"Не найден тип исключения с кодом '{nameof(ScheduleExcludeTypeEnum.None)}'");

            noneExcludeCalendarEsppValue = noneExcludeType.EsppValue;
        }


        /// <summary>
        /// Старт синхронизации, получили сообщение
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private async Task SyncScheduleAsync(string str)
        {
            await syncService.SyncEsppObjectAsync(str, ParseStrToEsppObject, ConvertDbObjToEsppObj, CustomComparisionCheckAsyncHandler, AfterParseStringToEsppObjectAsyncHandler);
        }

        /// <summary>
        /// Выполняется после парсинга строки в объект ЕСПП.
        /// Проверка, есть ли у расписания шаблон. Если имена шаблона и расписания не совпадают, установить шаблону статус обновления.
        /// </summary>
        /// <param name="esppObject"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private async Task AfterParseStringToEsppObjectAsyncHandler(EsppObjectSchedule esppObject)
        {
            var esppScheduleId = esppObject.Code;
            var esppTemplateName = esppObject.TemplateName;

            using var scope = serviceProvider.CreateScope();
            var templateService = scope.ServiceProvider.GetRequiredService<ITemplateRepository>();

            // это не очень, так как esppScheduleId может быть null или empty, а в БД таких значений может быть много
            //var candidates = await templateService.Get()
            //                               .Include(t => t.RobotConfigurations)
            //                               .Where(t => t.Name == esppTemplateName || t.ScheduleEsppId == esppScheduleId)
            //                               .ToListAsync();

            IQueryable<Template> query = templateService.Get().Include(t => t.RobotConfigurations);
            if (string.IsNullOrEmpty(esppScheduleId))
            {
                query = query.Where(t => t.Name == esppTemplateName);
            }
            else
            {
                //ScheduleEsppId не нулл и не пустой, поищем по нему тоже
                query = query.Where(t => t.Name == esppTemplateName || t.ScheduleEsppId == esppScheduleId);
            }

            var candidates = await query.ToListAsync();

            var templateByName = candidates.FirstOrDefault(t => t.Name == esppTemplateName);
            var templateByScheduleId = candidates.FirstOrDefault(t => t.ScheduleEsppId == esppScheduleId);

            if (templateByName == null && templateByScheduleId == null)
            {
                // Нет ни по имени, ни по ID
                logger.LogWarning("Расписание из ЕСПП не привязано ни к одному шаблону: TemplateName='{TemplateName}', ScheduleEsppId='{EsppId}'", esppTemplateName, esppScheduleId);
            }
            else if (templateByName == null && templateByScheduleId != null)
            {
                // Есть только по ID → имя не совпадает
                logger.LogWarning("Расхождение привязки: расписание из ЕСПП с ScheduleEsppId='{EsppId}' и TemplateName='{TemplateName}' соответствует шаблону в БД с именем '{DbTemplateName}', Id='{TemplateId}'.",
                    esppScheduleId, esppTemplateName, templateByScheduleId.Name, templateByScheduleId.Id);

                // Принудительно выставляем статус обновления шаблона, так как имя в ЕСПП изменилось
                var robotConfigurationService = scope.ServiceProvider.GetRequiredService<IRobotConfigurationRepository>();
                var config = robotConfigurationService.GetFromTemplateByRobotCode(RobotsEnum.TemplateOrder, templateByScheduleId);

                logger.LogDebug("Текущий статус задания {taskStatusCode} шаблона {templateId}", config.TaskStatusCode, templateByScheduleId.Id);
                //robotConfigurationService.ChangeTaskStatus(TaskStatusEnum.Updating, config);
                robotConfigurationService.SetUpdateTaskStatusIfAllow(config);

                // Сохраняем изменения в базу данных
                if (!await templateService.CommitAsync(new HistoryInitiator { InitiatorParrComponentId = ParrComponentsEnum.EsppScheduleSync, InitiatorComment = "Расхождение привязки, расписание из ЕСПП не соответствует имени шаблона в БД" }))
                {
                    logger.LogError("Не удалось сохранить изменения статуса задачи для шаблона Id='{TemplateId}'", templateByScheduleId.Id);
                }
                else
                {
                    logger.LogDebug("Для шаблона {templateId} установлен статус задания {taskStatus} при обнаружении расхождения имени с ЕСПП",
                               templateByScheduleId.Id, TaskStatusEnum.Updating.ToString());
                }
            }
            else if (templateByName != null)
            {
                var dbScheduleId = templateByName.ScheduleEsppId ?? string.Empty;

                if (string.IsNullOrEmpty(dbScheduleId))
                {
                    // Утерян ID в БД
                    logger.LogWarning("У шаблона '{TemplateName}' (Id='{TemplateId}') отсутствует ScheduleEsppId в БД, но в ЕСПП он равен '{EsppId}'", esppTemplateName, templateByName.Id, esppScheduleId);
                }
                else if (dbScheduleId != esppScheduleId)
                {
                    // ID не совпадают — проверяем, не занят ли esppScheduleId другим шаблоном
                    var conflictingTemplate = candidates.FirstOrDefault(t => t.Id != templateByName.Id && t.ScheduleEsppId == esppScheduleId);

                    if (conflictingTemplate != null)
                    {
                        logger.LogWarning("Конфликт ScheduleEsppId: расписание '{EsppId}' из ЕСПП с именем '{TemplateName}' уже привязано к другому шаблону '{OtherTemplateName}' (Id='{OtherTemplateId}') в БД.",
                            esppScheduleId, esppTemplateName, conflictingTemplate.Name, conflictingTemplate.Id);
                    }
                    else
                    {
                        logger.LogWarning("Несовпадение ScheduleEsppId для шаблона '{TemplateName}' (Id='{TemplateId}'): в БД='{DbId}', в ЕСПП='{EsppId}'",
                            esppTemplateName, templateByName.Id, dbScheduleId, esppScheduleId);
                    }
                }
            }

        }

        /// <summary>
        /// Преобразование модели БД в модель для сравнения
        /// </summary>
        /// <param name="template"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private EsppObjectSchedule ConvertDbObjToEsppObj(Template template)
        {
            //дефолтное значение, nextRun в часовом поясе робота ЕСПП
            var nextRunWithEsppTz = DateTimeOffset.MinValue;
            //// дефолтное значение, изменится в ApplyShortcodesAsync
            //var responseArea = "%ЗО_РГ%";

            using (var scope = serviceProvider.CreateScope())
            {
                //var nextRunModifierService = scope.ServiceProvider.GetService<INextRunModifierService>();
                //if (nextRunModifierService == null)
                //    throw new Exception($"Не найден сервис: {nameof(INextRunModifierService)}");

                //nextRunWithTimeZone = nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun);

                var nextRunService = scope.ServiceProvider.GetRequiredService<INextRunService>();
                //var shortcodeService = scope.ServiceProvider.GetRequiredService<IShortcodesService>();

                //responseArea = shortcodeService.ApplyShortcodesAsync(template.Job!.ResponseAreaMask, template).GetAwaiter().GetResult();
                nextRunWithEsppTz = template.NextRun.Add(nextRunService.GetEsppAccountOffset());
            }

            var esppObjectFromDb = new EsppObjectSchedule
            {
                TemplateName = template.Name.ToUpper(),
                Code = template.ScheduleEsppId ?? "",
                ScheduleName = template.Name,
                IsActive = template.IsActiveSchedule,
                //ResponseArea = template.Host!.ResponseArea!.Name,//TODO Migration to job
                //WorkGroup = template.Host!.WorkGroup!,//TODO Migration to job
                //WorkGroup = template.Host!.WorkGroup!.Name,//TODO Migration to job
                //Мы решили, что для всех расписаний "Нет исключений", если что-то поменяется, тут нужно переделать
                //TypeV60calendar = settingsFromDb.ScheduleExcludeType == "Нет исключений" ? "NONE" : "",
                TypeV60calendar = GetTypeV60calendar(template),
                V60calendar = GetV60calendar(template),
                //Scheduled = EsppScheduleHelpers.GetNextRun(template.NextRun),
                //Scheduled = EsppScheduleHelpers.GetNextRun(nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun)),
                //BasisTime = EsppScheduleHelpers.GetGenerationTime(nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun)),
                Scheduled = EsppScheduleHelpers.GetNextRun(nextRunWithEsppTz),
                BasisTime = EsppScheduleHelpers.GetGenerationTime(nextRunWithEsppTz),
                Timezone = GetTimezone(/*template, responseArea*/),
                //Мы решили, что для всех расписаний "Отсутствует дата завершения", если что-то поменяется, тут нужно переделать
                TerminationType = settingsFromDb.ScheduleRepeatRange == "Отсутствует дата завершения" ? "forever" : "",
                CompleteAfter = ""
            };

            FillScheduleFromDb(template, ref esppObjectFromDb);
            return ClearOptionalFields(esppObjectFromDb);
        }


        /// <summary>
        /// Кастомная дополнительная проверка полей
        /// </summary>
        /// <param name="esppObject"></param>
        /// <param name="dbObject"></param>
        /// <param name="templateId"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private async Task<bool> CustomComparisionCheckAsyncHandler(EsppObjectSchedule esppObject, EsppObjectSchedule dbObject, Guid templateId)
        {
            // рассчитать nextRun, и сравнить все три nextRun, БД - ЕСПП - Расчитанное

            // в часовой зоне робота
            var calculatedNextRun = await CalcNextRunWithRobotTzAsync(templateId);
            if (calculatedNextRun == null)
            {
                return false;
            }

            var scheduledCalculated = EsppScheduleHelpers.GetNextRun(calculatedNextRun.Value);
            var basisTimeCalculated = EsppScheduleHelpers.GetGenerationTime(calculatedNextRun.Value);

            logger.LogDebug("Рассчитанные значения для шаблона '{templateName}', {templateId}, следующее срабатывание {scheduledCalculated}, время создания наряда: {basisTimeCalculated}",
                                                               dbObject.TemplateName, templateId, scheduledCalculated, basisTimeCalculated);

            var dbScheduledNormalized = EsppSyncHelpers.Normalize(dbObject.Scheduled);
            var esppScheduledNormalized = EsppSyncHelpers.Normalize(esppObject.Scheduled);
            var scheduleCalculatedNormalized = EsppSyncHelpers.Normalize(scheduledCalculated);

            //if (EsppSyncHelpers.Normalize(dbObject.Scheduled) != EsppSyncHelpers.Normalize(esppObject.Scheduled) || EsppSyncHelpers.Normalize(dbObject.Scheduled) != scheduledCalculated || EsppSyncHelpers.Normalize(esppObject.Scheduled) != scheduledCalculated)
            if (dbScheduledNormalized != esppScheduledNormalized || dbScheduledNormalized != scheduleCalculatedNormalized || esppScheduledNormalized != scheduleCalculatedNormalized)
            {
                logger.LogInformation("Не совпадают поля ({PropertyName}), dbValueStr: {dbValueStr}, esppValueStr: {esppValueStr}, scheduledCalculated: {scheduledCalculated}. Имя шаблона: {templateName}",
                                                nameof(dbObject.Scheduled), dbObject.Scheduled, esppObject.Scheduled, scheduledCalculated, dbObject.TemplateName);
                return false;
            }

            var dbBasisTimeNormalized = EsppSyncHelpers.Normalize(dbObject.BasisTime);
            var esppBasisTimeNormalized = EsppSyncHelpers.Normalize(esppObject.BasisTime);
            var calculatedBasisTimeNormalized = EsppSyncHelpers.Normalize(basisTimeCalculated);

            //if (EsppSyncHelpers.Normalize(dbObject.BasisTime) != EsppSyncHelpers.Normalize(esppObject.BasisTime) || EsppSyncHelpers.Normalize(dbObject.BasisTime) != basisTimeCalculated || EsppSyncHelpers.Normalize(esppObject.BasisTime) != basisTimeCalculated)
            if (dbBasisTimeNormalized != esppBasisTimeNormalized || dbBasisTimeNormalized != calculatedBasisTimeNormalized || esppBasisTimeNormalized != calculatedBasisTimeNormalized)
            {
                logger.LogInformation("Не совпадают поля ({PropertyName}), dbValueStr: {dbValueStr}, esppValueStr: {esppValueStr}, basisTimeCalculated: {basisTimeCalculated}. Имя шаблона: {templateName}",
                                               nameof(dbObject.BasisTime), dbObject.BasisTime, esppObject.BasisTime, basisTimeCalculated, dbObject.TemplateName);
                return false;
            }

            logger.LogDebug("Значения nextRun в БД, ЕСПП, расчитанное, все совпадают. Scheduled: {scheduled}, basisTime: {basisTime}", scheduledCalculated, basisTimeCalculated);

            return true;



        }

        /// <summary>
        /// Рассчитать nextRun в часовом поясе УЗ робота
        /// </summary>
        /// <param name="templateId"></param>
        /// <returns></returns>
        private async Task<DateTimeOffset?> CalcNextRunWithRobotTzAsync(Guid templateId)
        {
            using var scope = serviceProvider.CreateScope();
            var nextRunService = scope.ServiceProvider.GetRequiredService<INextRunService>();

            var nextRun = await nextRunService.GetNextRunForTemplateAsync(templateId, isNew: false);

            if (nextRun.HasValue)
            {
                var nextRunWithEsppAccountTz = nextRun.Value.Add(nextRunService.GetEsppAccountOffset());
                logger.LogDebug("Расчитанный nextRun для шаблона {templateId}, UTC: {nextRun}, EsppAccountTz: {nextRunWithEsppAccountTz}", templateId, nextRun, nextRunWithEsppAccountTz);

                return nextRunWithEsppAccountTz;
            }
            else
            {
                logger.LogError("При расчете nextRun для templateId: {templateId} верунлся null", templateId);
                return null;
            }
        }


        /// <summary>
        /// Получить "В каком часовом поясе"
        /// </summary>
        /// <returns></returns>
        private string GetTimezone(/*Template template, string responseArea*/)
        {
            // договорились, что у роботоа ТЗ МСК
            return settingsFromDb.EsppScheduleTimezone;

            #region old
            ////if (template.Job?.Group?.IsWorkGroupTimezone != true)
            ////    return settingsFromDb.ScheduleTimezone;

            //if (template.Job?.Group?.IsResponseAreaTimezone != true)
            //    return scheduleResponseAreaTimeOffsetService.GetDefault.EsppValue;

            ////var responseArea = template.Unit?.BaseFields?.ResponseArea;

            ////if (string.IsNullOrEmpty(responseArea))
            ////{
            ////    throw new InvalidOperationException(
            ////        $"У шаблона Id={template.Id}, Name='{template.Name}' не задана ResponseArea в Unit.BaseFields, " +
            ////        "но включена настройка 'использовать часовой пояс рабочей группы'.");
            ////}

            ////if (!responseAreaTimeOffsetDict.TryGetValue(responseArea, out var offset))
            ////{
            ////    throw new InvalidOperationException(
            ////        $"Не найдено временное смещение для ResponseArea '{responseArea}' у шаблона Id={template.Id}, Name='{template.Name}'. " +
            ////        "Проверьте наличие записи в таблице ScheduleResponseAreaTimeOffset.");
            ////}

            ////return offset;

            //return scheduleResponseAreaTimeOffsetService.GetByResponseAreaOrDefault(responseArea).EsppValue;
            #endregion
        }


        /// <summary>
        /// Получить исключение - Календарь
        /// </summary>
        /// <param name="template"></param>
        /// <returns></returns>
        private string GetV60calendar(Template template)
        {
            // мы знаем, что у нас точно в шаблоне есть инклуды до ScheduleExcludeType и ScheduleExcludeTypeCalendar
            if (template.Job?.Group?.ScheduleExcludeTypeCalendar == null)
            {
                logger.LogDebug("Для шаблона шаблона {TemplateName}, {TemplateId} нет исключений календаря", template.Name, template.Id);

                //TODO:!!!!!!!!!!! Вот тут null или string.Empty??? Спросить у Андрея что он нам вернет!

                return string.Empty;
            }

            logger.LogDebug("Для шаблона шаблона {TemplateName}, {TemplateId} установлено исключений календаря \"{Name}\", EsppValue: {EsppValue}", template.Name, template.Id, template.Job.Group.ScheduleExcludeTypeCalendar.Title, template.Job.Group.ScheduleExcludeTypeCalendar.EsppValue);

            return template.Job.Group.ScheduleExcludeTypeCalendar.EsppValue;
        }


        /// <summary>
        /// Получить тип календаря
        /// </summary>
        /// <returns></returns>
        private string GetTypeV60calendar(Template template)
        {
            // мы знаем, что у нас точно в шаблоне есть инклуды до ScheduleExcludeType и ScheduleExcludeTypeCalendar

            // на всякий конечно же проверим
            if (template.Job?.Group?.ScheduleExcludeType == null)
            {
                logger.LogError("Для шаблона {TemplateName}, {TemplateId} не смог получить тип исключения, установил значение по умолчанию \"Без исключения\"", template.Name, template.Id);
                return "NONE";
            }

            logger.LogDebug("Для шаблона шаблона {TemplateName}, {TemplateId} тип исключения \"{Name}\", EsppValue: {EsppValue}", template.Name, template.Id, template.Job.Group.ScheduleExcludeType.Title, template.Job.Group.ScheduleExcludeType.EsppValue);

            return template.Job.Group.ScheduleExcludeType.EsppValue;
        }


        /// <summary>
        /// Заполнить расписание из БД
        /// </summary>
        /// <returns></returns>
        private void FillScheduleFromDb(Template template, ref EsppObjectSchedule esppObject)
        {
            using (var scope = serviceProvider.CreateScope())
            {
                var esppSchTypeConfigService = scope.ServiceProvider.GetService<IEsppSchTypeConfigRepository>();
                if (esppSchTypeConfigService == null)
                    throw new Exception($"Не найден сервис: {nameof(IEsppSchTypeConfigRepository)}");

                var esppSchedule = esppSchTypeConfigService.GetEsppScheduleDto(template.Job!.GroupId);
                if (esppSchedule == null)
                {
                    logger.LogError("Не смог получить расписание из БД для шаблона templateId: {TemplateId}, {TemplateName}", template.Id, template.Name);
                    return;
                }

                var typeSchedule = GetTypeScheduleByString(esppSchedule.TypeSchedule.Name);
                if (!typeSchedule.HasValue)
                    return;

                //тип повторения
                esppObject.TypeSchedule = typeSchedule.Value;

                //в зависимости от типа, присваиваем значения
                switch (esppObject.TypeSchedule)
                {
                    case EsppSchTypeScheduleEnum.Regularly:
                        esppObject.Interval = esppSchedule.Values.First(t => t.Order == 0).Value.EsppExportValue;
                        break;
                    case EsppSchTypeScheduleEnum.Weekly:
                        esppObject.Dayofweek = esppSchedule.Values.First(t => t.Order == 0).Value.EsppExportValue;
                        break;
                    case EsppSchTypeScheduleEnum.Monthly:
                        esppObject.Dayofmonth = esppSchedule.Values.First(t => t.Order == 0).Value.EsppExportValue;
                        break;
                    case EsppSchTypeScheduleEnum.Monthly2:
                        esppObject.Md1 = esppSchedule.Values.First(t => t.Order == 0).Value.EsppExportValue;
                        esppObject.Md2 = esppSchedule.Values.First(t => t.Order == 1).Value.EsppExportValue;
                        break;
                    case EsppSchTypeScheduleEnum.Annually:
                        esppObject.Annualm = esppSchedule.Values.First(t => t.Order == 0).Value.EsppExportValue;
                        esppObject.Annualday = esppSchedule.Values.First(t => t.Order == 1).Value.EsppExportValue;
                        break;
                    case EsppSchTypeScheduleEnum.Annually2:
                        esppObject.An1 = esppSchedule.Values.First(t => t.Order == 0).Value.EsppExportValue;
                        esppObject.An2 = esppSchedule.Values.First(t => t.Order == 1).Value.EsppExportValue;
                        esppObject.An3 = esppSchedule.Values.First(t => t.Order == 2).Value.EsppExportValue;
                        break;
                }
            }
        }


        /// <summary>
        /// Парсинг из строки в модель для сравнения
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private EsppObjectSchedule? ParseStrToEsppObject(string str)
        {
            var splittedContent = str.Split(globalSettings.ParsingSeparator);
            if (splittedContent.Length != 24)
            {
                logger.LogError("Входная строка после сплита не содержит 24 объекта (факт: {Length}).", splittedContent.Length);
                return null;
            }

            var templateName = splittedContent[6].ToUpper();
            var scheduleName = splittedContent[2];

            if (!IsValidName(templateName) || !IsValidName(scheduleName))
                return null;

            bool.TryParse(splittedContent[1].Trim(), out var isActive);

            var typeSchedule = GetTypeScheduleByString(splittedContent[7]);
            if (!typeSchedule.HasValue)
                return null;

            var esppObject = new EsppObjectSchedule
            {
                TemplateName = templateName,
                Code = splittedContent[0],
                ScheduleName = scheduleName,
                IsActive = isActive,
                ResponseArea = splittedContent[5],
                WorkGroup = splittedContent[3],
                TypeSchedule = typeSchedule.Value,
                Interval = splittedContent[8],
                Dayofweek = splittedContent[15],
                Dayofmonth = splittedContent[14],
                Md1 = splittedContent[16],
                Md2 = splittedContent[17],
                Annualm = splittedContent[13],
                Annualday = splittedContent[12],
                An1 = splittedContent[9],
                An2 = splittedContent[10],
                An3 = splittedContent[11],
                TypeV60calendar = splittedContent[21],
                Scheduled = splittedContent[4],
                Timezone = splittedContent[18],
                TerminationType = splittedContent[19],
                CompleteAfter = splittedContent[20],
                V60calendar = splittedContent[22],
                BasisTime = splittedContent[23]
            };

            return ClearOptionalFields(esppObject);
        }


        /// <summary>
        /// Преобразовать из строки в Тип Повторения
        /// </summary>
        /// <param name="typeSchedule"></param>
        /// <returns></returns>
        private EsppSchTypeScheduleEnum? GetTypeScheduleByString(string typeSchedule)
        {
            typeSchedule = typeSchedule.ToLower();

            //Regularly, Регулярно (значение в ЕСПП и в БД не совпадают, в бд Regularly, в ЕСПП simple)
            if (typeSchedule == "simple" || typeSchedule == EsppSchTypeScheduleEnum.Regularly.ToString().ToLower())
                return EsppSchTypeScheduleEnum.Regularly;

            if (typeSchedule == EsppSchTypeScheduleEnum.Weekly.ToString().ToLower())
                return EsppSchTypeScheduleEnum.Weekly;

            if (typeSchedule == EsppSchTypeScheduleEnum.Monthly.ToString().ToLower())
                return EsppSchTypeScheduleEnum.Monthly;

            if (typeSchedule == EsppSchTypeScheduleEnum.Monthly2.ToString().ToLower())
                return EsppSchTypeScheduleEnum.Monthly2;

            if (typeSchedule == EsppSchTypeScheduleEnum.Annually.ToString().ToLower())
                return EsppSchTypeScheduleEnum.Annually;

            if (typeSchedule == EsppSchTypeScheduleEnum.Annually2.ToString().ToLower())
                return EsppSchTypeScheduleEnum.Annually2;

            logger.LogError("Не смог преобразовать Тип повторения из ЕСПП в EsppSchTypeScheduleEnum. Получено значение {TypeSchedule}", typeSchedule);

            return null;
        }


        /// <summary>
        /// Проверка имени шаблона и расписание на соответствие префиксу из настроек
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private bool IsValidName(string name)
        {
            var currentCulture = Thread.CurrentThread.CurrentCulture;

            //if (!string.IsNullOrEmpty(settingsFromDb.TemplatePrefixName) && name.StartsWith(settingsFromDb.TemplatePrefixName, true, currentCulture))
            //    return true;

            if (!string.IsNullOrEmpty(settingsFromDb.TemplatePrefixWithoutVariable) && name.Contains(settingsFromDb.TemplatePrefixWithoutVariable)) // , StringComparison.CurrentCultureIgnoreCase
                return true;

            logger.LogWarning("Имя шаблона или расписания не соответствует обязательному префиксу({Prefix}). {Name} игнорирован", settingsFromDb.TemplatePrefixWithoutVariable, name);

            return false;
        }


        /// <summary>
        /// Очистка полей которые не нуждаются в синхронизации
        /// </summary>
        /// <param name="esppObject"></param>
        /// <returns></returns>
        private EsppObjectSchedule ClearOptionalFields(EsppObjectSchedule esppObject)
        {
            #region Отключение синхронизации не нужных полей настраивается через атрибут SkipComparison в моделе
            // Обнуляем ЕСПП ИД, потому что У НАС РЕАЛЬНЫЙ ЕСПП ИД И ЕСПП ИД В БД МОГУ РАСХОДИТЬСЯ!!! УЖАССС!!!
            //esppObject.Code = string.Empty;
            //esppObject.ScheduleName = string.Empty;
            //esppObject.ResponseArea = string.Empty;
            //esppObject.WorkGroup = string.Empty;
            //esppObject.CompleteAfter = string.Empty;
            #endregion

            if (esppObject.TypeV60calendar == noneExcludeCalendarEsppValue)
                esppObject.V60calendar = string.Empty;

            // В ЕСПП, при изменении "Повторять задачу", остаются предыдущие значения, их не нужно синхронизировать (касается только данных полученных из ЕСПП, в БД все ок)
            // т.е. если стояло Ежедненвно:понедельник, а изменили например на Еженедельно..., то в ежедневно значения останутся, но будут отрабатывать значения из Еженедельно.
            // Т е значения из Ежедненвно проверять не нужно, вот их и будем очищать 

            switch (esppObject.TypeSchedule)
            {
                case EsppSchTypeScheduleEnum.Regularly:
                    //esppObject.Interval = string.Empty;
                    esppObject.Dayofweek = string.Empty;
                    esppObject.Dayofmonth = string.Empty;
                    esppObject.Md1 = string.Empty;
                    esppObject.Md2 = string.Empty;
                    esppObject.Annualm = string.Empty;
                    esppObject.Annualday = string.Empty;
                    esppObject.An1 = string.Empty;
                    esppObject.An2 = string.Empty;
                    esppObject.An3 = string.Empty;
                    break;
                case EsppSchTypeScheduleEnum.Weekly:
                    esppObject.Interval = string.Empty;
                    //esppObject.Dayofweek = string.Empty;
                    esppObject.Dayofmonth = string.Empty;
                    esppObject.Md1 = string.Empty;
                    esppObject.Md2 = string.Empty;
                    esppObject.Annualm = string.Empty;
                    esppObject.Annualday = string.Empty;
                    esppObject.An1 = string.Empty;
                    esppObject.An2 = string.Empty;
                    esppObject.An3 = string.Empty;
                    break;
                case EsppSchTypeScheduleEnum.Monthly:
                    esppObject.Interval = string.Empty;
                    esppObject.Dayofweek = string.Empty;
                    //esppObject.Dayofmonth = string.Empty;
                    esppObject.Md1 = string.Empty;
                    esppObject.Md2 = string.Empty;
                    esppObject.Annualm = string.Empty;
                    esppObject.Annualday = string.Empty;
                    esppObject.An1 = string.Empty;
                    esppObject.An2 = string.Empty;
                    esppObject.An3 = string.Empty;
                    break;
                case EsppSchTypeScheduleEnum.Monthly2:
                    esppObject.Interval = string.Empty;
                    esppObject.Dayofweek = string.Empty;
                    esppObject.Dayofmonth = string.Empty;
                    //esppObject.Md1 = string.Empty;
                    //esppObject.Md2 = string.Empty;
                    esppObject.Annualm = string.Empty;
                    esppObject.Annualday = string.Empty;
                    esppObject.An1 = string.Empty;
                    esppObject.An2 = string.Empty;
                    esppObject.An3 = string.Empty;
                    break;
                case EsppSchTypeScheduleEnum.Annually:
                    esppObject.Interval = string.Empty;
                    esppObject.Dayofweek = string.Empty;
                    esppObject.Dayofmonth = string.Empty;
                    esppObject.Md1 = string.Empty;
                    esppObject.Md2 = string.Empty;
                    //esppObject.Annualm = string.Empty;
                    //esppObject.Annualday = string.Empty;
                    esppObject.An1 = string.Empty;
                    esppObject.An2 = string.Empty;
                    esppObject.An3 = string.Empty;
                    break;
                case EsppSchTypeScheduleEnum.Annually2:
                    esppObject.Interval = string.Empty;
                    esppObject.Dayofweek = string.Empty;
                    esppObject.Dayofmonth = string.Empty;
                    esppObject.Md1 = string.Empty;
                    esppObject.Md2 = string.Empty;
                    esppObject.Annualm = string.Empty;
                    esppObject.Annualday = string.Empty;
                    //esppObject.An1 = string.Empty;
                    //esppObject.An2 = string.Empty;
                    //esppObject.An3 = string.Empty;
                    break;
            }

            return esppObject;
        }

    }
}