using IntegrationKSSS.Models;
using Newtonsoft.Json;
using NLog;
using RnD.Common.Model.ActionBarButtons;
using RnD.Model;
using System;
using System.Collections.Generic;
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";
        #endregion

        #region Methods
        /// <summary>
        /// Export KSSS object to json
        /// </summary>
        /// <param name="specification"></param>
        /// <returns></returns>
        internal static ActionBarButtonResult ExportKsss(ISpecification specification)
        {
            var logger = LogManager.GetCurrentClassLogger();
            var infoCardKsss = specification.InfoCards.FirstOrDefault(c => c.ShortDescription.Contains(_ksssPrefix) &&
                                                                           c.ShortDescription != _ksssDataInfoCard);
            if (infoCardKsss == null)
            {
                logger.Error(MessageList.KsssInfoCardMissing.Eng);
                return new ActionBarButtonResult
                {
                    Message = MessageList.KsssInfoCardMissing.Rus,
                    MessageType = MessageList.KsssInfoCardMissing.Type
                };
            }

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

            bool isKsssServiceEmpty = string.IsNullOrEmpty(ksssServiceInfoField?.InfoFieldValue);
            bool ksssInsert = infoFieldKsssInsert?.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, ksssDictionary);
            }
            else
            {
                if (!ksssInsert)
                {
                    ksssDictionary.Add(ksssServiceInfoField.ShortDescription, ksssServiceInfoField.InfoFieldValue);
                }
                else
                {
                    FillKsss(infoCardKsss, ksssDictionary);
                }
            }


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

            logger.Info(MessageList.KsssSaved.Eng);
            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, Dictionary<string, string> ksssDictionary)
        {
            var exceptionInfoFields = new List<string> { "KSSS_Insert", "KSSS_Status" };

            infoCardKsss.InfoFields.Where(c => c.ShortDescription is string description &&
                                               description.Contains(_ksssPrefix) && !exceptionInfoFields.Contains(description))
                                   .ToList()
                                   .ForEach(infoField => ksssDictionary.Add(infoField.ShortDescription, infoField.InfoFieldValue));
        }
        /// <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);
        }
        #endregion
    }
}
