using NLog;
using NLog.Config;
using ProfitGroup.Rdnl.Extensions;
using ProfitGroup.SampleService.Models;
using RnD.API;
using RnD.BusinessLayer.EF.Interfaces;
using RnD.BusinessLayer.Interfaces.ExtensionMethods;
using RnD.BusinessLayer.Interfaces.Model;
using RnD.Model.EF;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProfitGroup.SampleService.Core.Services
{
    public class SampleService : ISampleService
    {
        private RnDConnection _databaseContext;
        private readonly RDnLManager _manager;
        private readonly API _api;
        private readonly SampleConfirmationService _sampleConfirmationService;

        private ILogger Logger
        {
            get
            {
                var loggerConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "nlog.config");
                LogManager.Setup().LoadConfigurationFromFile(loggerConfig);
                LogManager.Configuration = new XmlLoggingConfiguration(loggerConfig);

                return LogManager.GetCurrentClassLogger();
            }
        }

        public SampleService(RDnLManager manager, API api, SampleConfirmationService sampleConfirmationService)
        {
            _manager = manager;
            _api = api;
            _sampleConfirmationService = sampleConfirmationService;
            _databaseContext = ((ISession<RnDConnection>)manager.EventAwareObjectFactory.FactorySession).Context;
        }


        public IEnumerable<TaskFilterDTO> GetTaskKeys(string plantName, string operationControlName,
            string packageOrStage)
        {
            
            var task = _api.BusinessObjectFactory.TaskTypes.GetAllTaskTypes()
                .FirstOrDefault(c => c.Description == "Sample Creation");
            
            var tasks = _databaseContext.RndvTk.Join(_databaseContext.RndvTkDetails,
                    g => g.TK,
                    taskDetail => taskDetail.TK,
                    (taskEntity, taskDetail) => new { Task = taskEntity, TaskDetail = taskDetail })
                .Where(c => c.Task.TK_TP == task.TaskType
                            && c.Task.ACTIVE_STR == "1"
                            && c.Task.VERSION == c.TaskDetail.VERSION)
                .Select(c => c.TaskDetail)
                .ToList()
                .GroupBy(c => c.TK);

            var creationTasks = tasks.Where(c =>
                c.FirstOrDefault(taskEntity => taskEntity.DEF_VAL == plantName) != null
                && c.FirstOrDefault(taskEntity => taskEntity.DEF_VAL == operationControlName) != null);

            if (creationTasks.Count() > 1)
            {
                if (string.IsNullOrEmpty(packageOrStage))
                {
                    creationTasks = creationTasks.Where(c => c.FirstOrDefault(attribute => attribute.COL_ID == "38") == null); // Ищем тот таск, у которого отсутствует стадия
                }else
                {
                    creationTasks = creationTasks.Where(c => c.FirstOrDefault(attribute => attribute.COL_ID == "38") != null); // Ищем тот таск, у которого имеется стадия
                }
            }

            if (creationTasks.Count() > 1)
            {
                if (!string.IsNullOrEmpty(packageOrStage))
                {
                    creationTasks = creationTasks.Where(c =>
                        c.FirstOrDefault(attribute => attribute.DEF_VAL == packageOrStage) != null);
                }
            }

            var creationTask = creationTasks.SingleOrDefault();

            if (creationTask == null)
            {
                return Enumerable.Empty<TaskFilterDTO>();
            }

            var taskObject =
                _api.BusinessObjectFactory.TaskDefinition.GetActiveVersion(task.TaskType, creationTask.Key);

            // var taskKeys = _api.BusinessObjectFactory.TaskKeys.GetAll(task.TaskType, (decimal)taskObject.ID,
            //     (decimal)taskObject.Version);

            var taskKeys = _databaseContext.RndvTkDetails.Where(c =>
                c.TK == (decimal)taskObject.ID
                && c.VERSION == (decimal)taskObject.Version
            ).ToList();


            return taskKeys.Select(c => new TaskFilterDTO
            {
                Field = $"{c.COL_ID}@{c.COL_TP}",
                Operator = c.OPERAT,
                Value = c.DEF_VAL,
                Sequence = c.SEQ
            });


            //var task = _api.BusinessObjectFactory.TaskTypes.GetAllTaskTypes()
            //    .FirstOrDefault(c => c.Description == "Sample Creation");


            //var tasks = _databaseContext.RndvTk.Join(_databaseContext.RndvTkDetails,
            //        task => task.TK,
            //        taskDetail => taskDetail.TK,
            //        (task, taskDetail) => new { Task = task, TaskDetail = taskDetail })
            //    .Where(c => c.Task.TK_TP == task.TaskType
            //                && c.Task.ACTIVE_STR == "1"
            //                && c.Task.VERSION == c.TaskDetail.VERSION
            //                && c.TaskDetail.DEF_VAL_MAIN == plantName
            //                && c.Task.DESCRIPTION_MAIN.Contains(operationControlName))
            //    .ToList();

            //var creationTask = tasks.SingleOrDefault();

            //if (creationTask == null)
            //{
            //    return Enumerable.Empty<TaskFilterDTO>();
            //}

            //var taskObject =
            //    _api.BusinessObjectFactory.TaskDefinition.GetActiveVersion(task.TaskType, creationTask.Task.TK);

            //var taskKeys = _api.BusinessObjectFactory.TaskKeys.GetAll(task.TaskType, (decimal)taskObject.ID,
            //    (decimal)taskObject.Version);

            //return taskKeys.Select(c => new TaskFilterDTO
            //{
            //    Field = $"{c.ColumnID}@{c.ColumnType}",
            //    Operator = c.Operator,
            //    Value = c.DefaultValue,
            //    Sequence = c.Sequence
            //});
        }

        public void FillSampleInfoCards(decimal sampleId, List<InfoCardSetting> infoFieldInfoElements)
        {
            var sample = _api.Sample.GetSample(sampleId);

            foreach (var infoFieldInfo in infoFieldInfoElements)
            {
                var infoFields = sample.InfoCards
                    .SelectMany(c => c.InfoFields)
                    .Where(c => c.ShortDescription == infoFieldInfo.InfoField);

                foreach (var infoField in infoFields)
                    infoField.InfoFieldValue = infoFieldInfo.Value;
            }


            //foreach (var infoCard in infoCards)
            //{
            //    var searchedCard = sample.InfoCards.FirstOrDefault(c => c.ShortDescription == infoCard.InfoCard);

            //    if (searchedCard == null)
            //    {
            //        Logger.Error(
            //            $@"Проба {sample.ShortDescription}:{sample.ID}. Инфокарта shortDesc: ""{infoCard.InfoCard}"" не найдена. Запись данных на инфополе отменено!");
            //        continue;
            //    }

            //    var infoField =
            //        searchedCard.InfoFields.FirstOrDefault(c => c.ShortDescription == infoCard.InfoField);

            //    if (infoField == null)
            //    {
            //        Logger.Error(
            //            $@"Проба {sample.ShortDescription}:{sample.ID}. Инфокарта shortDesc: ""{infoCard.InfoCard}"". Инфополе ""{infoCard.InfoField}"" не найдено. Запись данных на данное инфополе отменено!");
            //        continue;
            //    }

            //    infoField.InfoFieldValue = infoCard.Value;
            //}

            _api.BusinessObjectFactory.SaveChanges();
        }

        public async Task<bool> ValidateSample(string shortDescription)
        {
            var sample = await _databaseContext.RndvSc.FirstOrDefaultAsync(c => c.SC_VALUE == shortDescription);

            return sample.SS == 8; // Создан
        }

        public async Task SendConfirmation(MT_InspLot request, SampleFullDTO sampleFullDto)
        {
            var sampleIsCreated = await ValidateSample(sampleFullDto.ShortDescription);

            var sampleIsConfirmed = false;

            try
            {
                sampleIsConfirmed = await _sampleConfirmationService
                    .SendConfirmationToSap(request, sampleFullDto, sampleIsCreated);
            }
            catch (Exception ex)
            {
                Logger.Log(LogLevel.Error, string.Concat(ex.Message, "\n", ex.StackTrace));
            }

            var requestMessageBuilder = new StringBuilder();

            requestMessageBuilder.Append(sampleIsCreated
                ? $@"Проба ""{sampleFullDto.ShortDescription}"" успешно сформирована. "
                : $@"Проба не сформирована. ");

            requestMessageBuilder.Append(sampleIsConfirmed
                ? "Был отправлен Confirmation в SAP/S4. Получен успешный HttpStatus"
                : "Был отправлен Confirmation в SAP/S4. Получен ошибочный HttpStatus");

            Logger.Log(LogLevel.Info, requestMessageBuilder.ToString());
        }
    }
}