using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces;
using PARR.EsppApi.Models;

namespace PARR.EsppOrderLoader.Services
{
    internal class OrderItemService : IOrderItemService
    {
        private readonly ILogger<OrderItemService> logger;
        private readonly IOrderService orderService;
        private readonly ITemplateService templateService;
        private readonly IOrderStatusService orderStatusService;

        public OrderItemService(
            ILogger<OrderItemService> logger,
            IOrderService orderService,
            ITemplateService templateService,
            IOrderStatusService orderStatusService
            )
        {
            this.orderService = orderService;
            this.templateService = templateService;
            this.orderStatusService = orderStatusService;
            this.logger = logger;
        }


        public async Task WriteOrderAsync(EsppOrder esppOrder)
        {
            var existOrder = await orderService.Get().FirstOrDefaultAsync(t => t.Number.ToLower() == esppOrder.Number.ToLower());
            if (existOrder != null)
            {
                logger.LogInformation($"Наряд {esppOrder.Number} уже есть в БД. Пропускаю.");
                return;
            }

            var template = await templateService.Get()
                                .Include(t => t.Job)
                                .FirstOrDefaultAsync(t => t.Name.ToLower() == esppOrder.TemplateName.ToLower());

            if (template == null)
                logger.LogWarning($"Не найден шаблон для наряда {esppOrder.Number}, краткое описание наряда: {esppOrder.ShortName}. {esppOrder.WorkGroup}");

            var newOrder = new Order
            {
                Id = Guid.NewGuid(),
                Number = esppOrder.Number,
                WorkGroup = esppOrder.WorkGroup,
                ShortName = esppOrder.ShortName,
                TemplateId = template?.Id,
                StatusCode = (int)orderStatusService.GetOrderStatusByName(esppOrder.Status),
                GenerateDate = template == null ?
                                                null
                                                //: CalcGenerationDate(template.ApplicationsInWork!.NextRun, template.ApplicationsInWork!.LastRun),
                                                : CalcGenerationDate(template.NextRun, template.LastRun),
                //CalcGenerationDate(esppOrder.ExpirationDateUTC, template.ApplicationsInWork!.TemplateDurationTimeSpan),
                ExpirationDate = esppOrder.ExpirationDateUTC
            };

            if (!await orderService.CreateAsync(newOrder) || !await orderService.CommitAsync())
                logger.LogError($"Ошибка при добавлении новой записи наряда в БД. {esppOrder.Number}, {esppOrder.WorkGroup}, {esppOrder.ShortName}");
            else
                logger.LogInformation($"Добавлен наряд в БД: {esppOrder.Number}, {esppOrder.ShortName}");
        }


        /// <summary>
        /// Рассчет GenerationDate относительно templateDuration
        /// </summary>
        /// <param name="expirationDateUTC"></param>
        /// <param name="templateDuration"></param>
        /// <returns></returns>
        private DateTimeOffset? CalcGenerationDate(DateTimeOffset expirationDateUTC, TimeSpan? templateDuration)
        {
            //TimeSpan duration;

            //try
            //{
            //    //ЕСПП кривоногие, они почему-то таймспан пишут так "7 00:00:00", а правильно так: "7:00:00:00"
            //    var durationWithTimeSpanFormat = templateDuration.Replace(" ", ":");
            //    duration = TimeSpan.Parse(durationWithTimeSpanFormat);
            //}
            //catch (Exception e)
            //{
            //    logger.LogError(e, $"Ошибка при конвертации templateDuration в TimeSpan, исходное значение: {templateDuration}");
            //    return null;
            //}

            if (templateDuration.HasValue)
                return expirationDateUTC.Add(-templateDuration.Value);
            else
            {
                logger.LogError($"templateDuration = null.");
                return null;
            }
        }


        /// <summary>
        /// Рассчет GenerationDate относительно текущей даты и nextRun из ApplicationInWorks
        /// </summary>
        /// <returns></returns>
        private DateTimeOffset? CalcGenerationDate(DateTimeOffset nextRun, DateTimeOffset? lastRun)
        {
            if (DateTimeOffset.UtcNow > nextRun)
                return nextRun;

            if (lastRun.HasValue)
                return lastRun.Value;

            return null;
        }

    }
}
