using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.Constants;
using PARR.DAL.Context;
using PARR.DAL.Contracts;
using PARR.DAL.Models;
using PARR.DAL.Services.Abstracts;
using PARR.DAL.Services.Interfaces;

namespace PARR.DAL.Services.Implementations
{
    internal class RobotConfigurationService : BaseService<RobotConfiguration>, IRobotConfigurationService
    {
        private readonly DataContext dataContext;
        private readonly ILogger<RobotConfigurationService> logger;

        public RobotConfigurationService(DataContext dataContext, ILogger<RobotConfigurationService> logger) : base(logger)
        {
            this.dataContext = dataContext;
            this.logger = logger;
        }

        protected override DbSet<RobotConfiguration> EntitySet => dataContext.RobotConfigurations;

        protected override DataContext EntitiContext => dataContext;


        public void ChangeTaskStatus(TaskStatusEnum taskStatus, RobotConfiguration configuration)
        {
            configuration.TaskStatusCode = (int)taskStatus;

            switch (taskStatus)
            {
                case TaskStatusEnum.Creating:
                    ChangeRobotStatus(RobotStatusEnum.Wait, configuration);
                    break;
                case TaskStatusEnum.Updating:
                    ChangeRobotStatus(RobotStatusEnum.Wait, configuration);
                    break;
                case TaskStatusEnum.Ok:
                    ChangeRobotStatus(RobotStatusEnum.Complete, configuration);
                    break;
                default:
                    break;
            }

        }

        public void ChangeRobotStatus(RobotStatusEnum robotStatus, RobotConfiguration configuration)
        {
            configuration.RobotStatusCode = (int)robotStatus;

            switch (robotStatus)
            {
                case RobotStatusEnum.InProgress:
                    configuration.AttemptsNumber++;
                    configuration.LastRobotStatusUpdated = DateTimeOffset.UtcNow;
                    break;
                //case RobotStatusEnum.Error:
                //    break;
                case RobotStatusEnum.Complete:
                    configuration.LastRobotStatusUpdated = DateTimeOffset.UtcNow;
                    break;
                case RobotStatusEnum.Wait:
                    configuration.LastRobotStatusUpdated = null;
                    configuration.AttemptsNumber = 0;
                    break;
                default:
                    break;
            }
        }

        public RobotConfiguration GetFromTemplateByRobotCode(RobotsEnum robotsEnum, Template template)
        {
            var config = template.RobotConfigurations.FirstOrDefault(t => t.RobotCode == (int)robotsEnum);

            if (config == null)
            {
                logger.LogError($"У шаблона нет конфигурации роботов. TemplateId: {template.Id}");
                throw new Exception($"У шаблона нет конфигурации роботов. TemplateId: {template.Id}");
            }

            return config;
        }


        // Поиск невыполненных заданий и установка им статуса ошибки робота
        public async Task FindUnfulfilledTaskAndSetRobotErrorStatusAsync(int robotAttemptsNumber, TimeSpan robotWaitTime)
        {
            //Ищем `RobotStatusCode` = 22 и `LastStatusUpdated` истекло и `AttemptsNumber` >= допустимого значения из настроек,
            //ставим всем этим записям `RobotStatusCode`= 33

            var endDate = DateTimeOffset.UtcNow.Add(-robotWaitTime);

            var configObjs = await EntitySet.Where(t =>
                                            t.RobotStatusCode == (int)RobotStatusEnum.InProgress
                                            && t.AttemptsNumber >= robotAttemptsNumber
                                            && t.LastRobotStatusUpdated <= endDate
                                        ).ToListAsync();

            if (!configObjs.Any())
                return;

            configObjs.ForEach(item =>
            {
                ChangeRobotStatus(RobotStatusEnum.Error, item);
                logger.LogInformation($"Устанавливаю RobotStatus: {RobotStatusEnum.Error} для RobotConfigurationId {item.Id}");
            });

            var result = await CommitAsync();

            if (!result)
                logger.LogError($"Ошибка при сохранении изменений RobotStatus для RobotConfigurationId: item.Id, RobotStatus: {RobotStatusEnum.Error}");

        }


    }
}
