using IntegrationKSSS.Models;
using Newtonsoft.Json;
using NLog;
using RnD.Common.Model.ActionBarButtons;
using RnD.Model;
using RnD.Model.EF;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;

namespace IntegrationKSSS.Services
{
    /// <summary>
    /// Services for export KSSS
    /// </summary>
    public static class KsssService
    {
        #region Variables
        private const string _trueValue = "1";
        private const string _spKey = "SP";
        private const string _actionKey = "ACTION";
        private const string _guidKey = "Guid";
        private const string _ksssPrefix = "KSSS";
        private const string _ksssDataInfoCard = "KSSS_Data";
        private const string _ksssInsertInfoField = "KSSS_Insert";
        private const string _ksssServiceInfoField = "KSSS_KSSS";
        private const string _ksssStatusInfoField = "KSSS_Status";

        private static RnDConnection _dbConnection;
        #endregion

        #region Methods
        /// <summary>
        /// Export KSSS object to json
        /// </summary>
        /// <param name="specification"></param>
        /// <returns></returns>
        internal static ActionBarButtonResult ExportKsss(ISpecification specification, RnDConnection dbConnection)
        {
            _dbConnection = dbConnection;
            var logger = LogManager.GetCurrentClassLogger();
            var infoCardKsss = specification.InfoCards.FirstOrDefault(c => c.ShortDescription.Contains(_ksssPrefix) &&
                                                                           c.ShortDescription != _ksssDataInfoCard);
            var ksssStatusInfoField = infoCardKsss.InfoFields.FirstOrDefault(c => c.ShortDescription == _ksssStatusInfoField);

            if (infoCardKsss == null)
            {
                logger.Error(MessageList.KsssInfoCardMissing.Eng);
                ksssStatusInfoField.InfoFieldValue = "Failed";
                return new ActionBarButtonResult
                {
                    Message = MessageList.KsssInfoCardMissing.Rus,
                    MessageType = MessageList.KsssInfoCardMissing.Type
                };
            }

            var ksssInsertInfoField = infoCardKsss.InfoFields.FirstOrDefault(c => c.ShortDescription == _ksssInsertInfoField);
            var ksssServiceInfoField = infoCardKsss.InfoFields.FirstOrDefault(c => c.ShortDescription == _ksssServiceInfoField);

            bool isKsssServiceEmpty = string.IsNullOrEmpty(ksssServiceInfoField?.InfoFieldValue);
            bool ksssInsert = ksssInsertInfoField?.InfoFieldValue == _trueValue;
            var ksssActionValue = GetKsssActionValue(isKsssServiceEmpty, ksssInsert);

            var ksssDictionary = new Dictionary<string, string>();
            ksssDictionary.Add(_spKey, $"{specification.ID}");
            ksssDictionary.Add(_guidKey, $"{Guid.NewGuid()}");
            ksssDictionary.Add(_actionKey, ksssActionValue);

            if (isKsssServiceEmpty)
            {
                FillKsss(infoCardKsss, ref ksssDictionary);
            }
            else 
            {
                if (!ksssInsert)
                {
                    ksssDictionary.Add(ksssServiceInfoField.ShortDescription, ksssServiceInfoField.InfoFieldValue);
                }
                else
                {
                    FillKsss(infoCardKsss, ref ksssDictionary);
                }
            }


            var saveFilePath = GetSaveFilePath(specification.ID);
            var xmlFile = Serialization(ksssDictionary, saveFilePath);

            logger.Info(MessageList.KsssSaved.Eng);
            ksssStatusInfoField.InfoFieldValue = "Success";
            return new ActionBarButtonResult
            {
                Message = MessageList.KsssSaved.Rus,
                MessageType = MessageList.KsssSaved.Type
            };
        }
        /// <summary>
        /// Filling KSSS dictionary
        /// </summary>
        /// <param name="infoCardKsss"></param>
        /// <param name="ksssDictionary"></param>
        private static void FillKsss(IInfoCard infoCardKsss, ref Dictionary<string, string> ksssDictionary)
        {
            var exceptionInfoFields = new List<string> { "KSSS_Insert", "KSSS_Status", "KSSS_Density" };

            var infoFields = infoCardKsss.InfoFields.Where(c => c.ShortDescription is string description &&
                             description.Contains(_ksssPrefix) && !exceptionInfoFields.Contains(description));

            foreach (var infoField in infoFields)
            {
                var value = infoField.InfoFieldValue ?? string.Empty;
                var relationId = GetRelationId(infoField);
                if (relationId != null)
                {
                    ksssDictionary.Add(infoField.ShortDescription, $"{relationId}");
                }
                else
                {
                    ksssDictionary.Add(infoField.ShortDescription, value);
                }
            }
        }
        /// <summary>
        /// Choice action type
        /// </summary>
        /// <param name="isKsssServiceEmpty"></param>
        /// <param name="ksssInsert"></param>
        /// <returns></returns>
        private static string GetKsssActionValue(bool isKsssServiceEmpty, bool ksssInsert)
        {
            if (isKsssServiceEmpty)
            {
                return "CREATE";
            }
            else if (!isKsssServiceEmpty && ksssInsert)
            {
                return "CHANGE";
            }
            else if (!isKsssServiceEmpty && !ksssInsert)
            {
                return "UNLOAD";
            }
            else
            {
                return "UNDEFINED";
            }
        }
        /// <summary>
        /// Create save file path
        /// </summary>
        /// <param name="specificationId"></param>
        /// <returns></returns>
        private static string GetSaveFilePath(decimal? specificationId)
        {
            string saveFolderPath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}/JsonKSSSFiles";
            if (!Directory.Exists(saveFolderPath)) Directory.CreateDirectory(saveFolderPath);
            string saveFilePath = $@"{saveFolderPath}/KSSS_{specificationId}.json";
            return saveFilePath;
        }
        /// <summary>
        /// Serialization ksss dictionary to JSON file
        /// </summary>
        /// <param name="ksss"></param>
        /// <param name="saveFilePath"></param>
        /// <returns></returns>
        private static FileInfo Serialization(Dictionary<string, string> ksss, string saveFilePath)
        {
            JsonSerializer jsonSerializer = new JsonSerializer();
            jsonSerializer.NullValueHandling = NullValueHandling.Ignore;
            using (StreamWriter sw = new StreamWriter(saveFilePath))
            using (JsonWriter jw = new JsonTextWriter(sw) { Formatting = Formatting.Indented })
                jsonSerializer.Serialize(jw, ksss);
            return new FileInfo(saveFilePath);
        }

        private static int? GetRelationId(IInfoField infoField)
        {
            int? result = null;
            var rndvIpIeAu = _dbConnection.RndvIpIeAu.Where(c => c.IE == infoField.ID).OrderByDescending(c => c.VERSION).FirstOrDefault();
            var tableName = rndvIpIeAu?.VALUE;
            var tableValue = infoField.InfoFieldValue;
            if (!string.IsNullOrEmpty(tableName) && !string.IsNullOrEmpty(tableValue))
            {
                var sqlQuery = $"SELECT Id FROM [RndSuite].[{tableName}] WHERE [Name] = @Name";
                var sqlParam = new SqlParameter("@Name", tableValue);
                result = _dbConnection.Database.SqlQuery<int>(sqlQuery, sqlParam).FirstOrDefault();
            }

            return result;
        }
        #endregion
    }
}
