using C4IT.F4SD.SupportCaseProtocoll.Models;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using C4IT.F4SD.DisplayFormatting;
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UserControls;
using static C4IT.Logging.cLogManager;
using static FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitor;

namespace FasdDesktopUi.Basics.Services.ProtocollService
{
    internal static class QuickActionProtocollEntryOutput
    {
        const string AsciiSeperator = "\n\n";

        public static QuickActionProtocollEntry GetQuickActionProtocollEntry(cFasdQuickAction quickActionDefinition, cQuickActionCopyData quickActionCopyData)
        {
            string ascii = GetAscii(quickActionDefinition, quickActionCopyData);
            string html = GetHtml(quickActionDefinition, quickActionCopyData);

            return new QuickActionProtocollEntry(ascii, html)
            {
                Id = quickActionDefinition.Id,
                Name = quickActionDefinition.Name,
                ExecutionTypeId = (int)quickActionDefinition.ExecutionType,
                WasRunningOnAffectedDevice = quickActionCopyData.WasRunningOnAffectedDevice,
                AffectedDeviceName = quickActionCopyData.AffectedDeviceName,
                ResultCode = (int?)quickActionCopyData.QuickActionOutput?.ResultCode,
                ErrorMessage = quickActionCopyData.QuickActionOutput?.ErrorDescription,
                MeasureValues = GetQuickActionHtmlValueComparison(quickActionCopyData.MeasureValues)
            };
        }

        internal static cQuickActionCopyData GetCopyData(cFasdQuickAction quickActionDefinition, cSupportCaseDataProvider dataProvider, bool wasRunningOnAffectedDevice, cQuickActionOutput quickActionOutput, List<cQuickActionMeasureValue> measureValues)
        {
            cQuickActionCopyData quickActionCopyData = new cQuickActionCopyData();
            try
            {
                string currentLanguage = cMultiLanguageSupport.CurrentLanguage;
                cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage ?? currentLanguage;

                quickActionCopyData.Name = quickActionDefinition.Names.GetValue();
                quickActionCopyData.ExecutionTime = DateTime.UtcNow;
                var infoClass = dataProvider.HealthCardDataHelper.SelectedHealthCard.InformationClasses.FirstOrDefault();
                quickActionCopyData.AffectedDeviceName = dataProvider.HealthCardDataHelper.GetInformationObjectHeadingName(infoClass);

                quickActionCopyData.WasRunningOnAffectedDevice = wasRunningOnAffectedDevice;
                quickActionCopyData.QuickActionOutput = quickActionOutput;
                quickActionCopyData.MeasureValues = measureValues;

                cMultiLanguageSupport.CurrentLanguage = currentLanguage;
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return quickActionCopyData;
        }

        private static string GetAscii(cFasdQuickAction quickActionDefinition, cQuickActionCopyData quickActionCopyData) => GetQuickActionAscii(quickActionDefinition, quickActionCopyData);

        private static string GetHtml(cFasdQuickAction quickActionDefinition, cQuickActionCopyData quickActionCopyData) => GetQuickActionHtml(quickActionDefinition, quickActionCopyData);

        private static bool ShouldHideQuickActionOutput(cFasdQuickAction quickActionDefinition, string outputValueKey)
        {
            try
            {
                if (quickActionDefinition.ColumnOutputFormattings is null)
                    return false;

                if (!quickActionDefinition.ShowAllOutputContent && !quickActionDefinition.ColumnOutputFormattings.ContainsKey(outputValueKey))
                    return true;

                if (quickActionDefinition.ColumnOutputFormattings.TryGetValue(outputValueKey, out var columnFormatting))
                    return columnFormatting.Hidden;
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return false;
        }

        #region Ascii

        private static string GetQuickActionAscii(cFasdQuickAction quickActionDefinition, cQuickActionCopyData copyData)
        {
            string ascii = string.Empty;

            ascii += GetQuickActionAsciiDescription(quickActionDefinition,copyData.Name, copyData.AffectedDeviceName, copyData.WasRunningOnAffectedDevice, copyData.ExecutionTime, copyData.QuickActionOutput?.ResultCode);
            ascii += GetQuickActionAsciiError(copyData.QuickActionOutput?.ErrorDescription);
            ascii += GetQuickActionAsciiOutput(quickActionDefinition, copyData.QuickActionOutput);
            ascii += GetQuickActionAsciiValueComparisonString(copyData.MeasureValues);

            return ascii;
        }

        private static string GetQuickActionAsciiDescription(cFasdQuickAction quickActionDefinition,string quickActionName, string deviceName, bool wasRunningOnAffectedDevice, DateTime executionTime, enumQuickActionSuccess? quickActionStatus)
        {
            string asciiDescription = string.Empty;
            try
            {
                var quickActionStatusString = string.Empty;

                switch (quickActionStatus)
                {
                    case null:
                    case enumQuickActionSuccess.successfull:
                        quickActionStatusString = cMultiLanguageSupport.GetItem("QuickAction.Copy.RevisionStatus.Successfull");
                        break;
                    case enumQuickActionSuccess.error:
                        quickActionStatusString = cMultiLanguageSupport.GetItem("QuickAction.Copy.RevisionStatus.Error");
                        break;
                }

                var rawDescription = wasRunningOnAffectedDevice ? cMultiLanguageSupport.GetItem("QuickAction.Remote.Copy.Description") : cMultiLanguageSupport.GetItem("QuickAction.Local.Copy.Description");
                if (quickActionDefinition.Section == enumDataHistoryOrigin.Citrix.ToString())
                {
                    rawDescription = cMultiLanguageSupport.GetItem("QuickAction.RemoteSession.Copy.Description");

                }
                                
                asciiDescription = string.Format(rawDescription, quickActionName, deviceName, executionTime.ToString("g", new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage)), quickActionStatusString);
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return asciiDescription;
        }

        private static string GetQuickActionAsciiError(string errorMessage)
        {
            if (!string.IsNullOrEmpty(errorMessage))
                errorMessage.Insert(0, AsciiSeperator);

            return errorMessage;
        }

        private static string GetQuickActionAsciiOutput(cFasdQuickAction quickActionDefinition, QuickActionStatusMonitor.cQuickActionOutput quickActionOutput)
        {
            string output = string.Empty;

            try
            {
                if (!string.IsNullOrWhiteSpace(quickActionOutput?.ErrorDescription))
                    return output;

                switch (quickActionOutput)
                {
                    case QuickActionStatusMonitor.cQuickActionOutputSingle singleOutput:
                        {
                            if (singleOutput.Value is null)
                                return output;

                            output += AsciiSeperator;
                            output += cMultiLanguageSupport.GetItem("QuickAction.Copy.Output") + " ";
                            output += singleOutput.GetDisplayValue(quickActionDefinition.ColumnOutputFormattings);

                            break;
                        }
                    case QuickActionStatusMonitor.cQuickActionOutputList listOutput:
                        {
                            output += AsciiSeperator;
                            output += cMultiLanguageSupport.GetItem("QuickAction.Copy.Output") + "\n";


                            foreach (var value in listOutput.Values[0])
                            {
                                if (ShouldHideQuickActionOutput(quickActionDefinition, value.Key))
                                    continue;

                                if (quickActionDefinition.ColumnOutputFormattings?.TryGetValue(value.Key, out var outputFormatting) ?? false)
                                    output += outputFormatting.Names.GetValue();
                                else
                                    output += value.Key;

                                output += " | ";
                            }

                            for (int i = 0; i < listOutput.Values.Count; i++)
                            {
                                output += "\n";

                                for (int j = 0; j < listOutput.Values[i].Count; j++)
                                {
                                    string valueKey = listOutput.Values[0][j].Key;

                                    if (ShouldHideQuickActionOutput(quickActionDefinition, valueKey))
                                        continue;

                                    string displayValue = listOutput.GetDisplayValue(i, j, quickActionDefinition.ColumnOutputFormattings);

                                    if (string.IsNullOrWhiteSpace(displayValue))
                                        continue;

                                    output += displayValue;
                                    output += " | ";
                                }
                            }

                            break;
                        }
                    case QuickActionStatusMonitor.cQuickActionOutputObject objectOutput:
                        {
                            output += AsciiSeperator;
                            output += cMultiLanguageSupport.GetItem("QuickAction.Copy.Output") + "\n";

                            for (int i = 0; i < objectOutput.Values.Count; i++)
                            {
                                var value = objectOutput.Values[i];

                                if (ShouldHideQuickActionOutput(quickActionDefinition, value.Key))
                                    continue;

                                string columnTitle = string.Empty;

                                if (quickActionDefinition.ColumnOutputFormattings?.TryGetValue(value.Key, out var outputFormatting) ?? false)
                                    columnTitle = outputFormatting.Names.GetValue();
                                else
                                    columnTitle = value.Key;

                                if (!string.IsNullOrEmpty(columnTitle))
                                    output += $"{columnTitle}: ";

                                string displayValue = objectOutput.GetDisplayValue(i, quickActionDefinition.ColumnOutputFormattings);
                                output += !string.IsNullOrWhiteSpace(displayValue) ? displayValue : null;

                                output += "\n";
                            }

                            break;
                        }
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        private static string GetQuickActionAsciiValueComparisonString(List<QuickActionStatusMonitor.cQuickActionMeasureValue> measureValues)
        {
            string output = string.Empty;

            try
            {
                if (measureValues is null || measureValues.Count <= 0)
                    return output;

                output += AsciiSeperator + cMultiLanguageSupport.GetItem("QuickAction.Copy.Measure");

                cUtility.RawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
                cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);

                foreach (var measureValue in measureValues)
                {
                    try
                    {
                        string value = cUtility.RawValueFormatter.GetDisplayValue(measureValue.Value, measureValue.Display);
                        string postValue = cUtility.RawValueFormatter.GetDisplayValue(measureValue.PostValue, measureValue.Display);
                        string difference = string.Empty;

                        if (measureValue.Difference != null)
                            difference = $" (∆ {cUtility.RawValueFormatter.GetDisplayValue(measureValue.Difference, measureValue.Display)})";

                        output += "\n" + measureValue.Names.GetValue(cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage) + ": " + value + " ➜ " + postValue + difference;
                    }
                    catch (Exception E)
                    {
                        LogException(E);
                    }
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        #endregion

        #region Html

        private static string GetQuickActionHtml(cFasdQuickAction quickActionDefinition, cQuickActionCopyData copyData)
        {
            string output = string.Empty;

            try
            {
                output += GetQuickActionHtmlDescription(quickActionDefinition,copyData.Name, copyData.AffectedDeviceName, copyData.WasRunningOnAffectedDevice, copyData.ExecutionTime, copyData.QuickActionOutput?.ResultCode);
                output += GetQuickActionHtmlError(copyData.QuickActionOutput?.ErrorDescription);
                output += GetQuickActionHtmlOutput(quickActionDefinition, copyData.QuickActionOutput);
                output += GetQuickActionHtmlValueComparison(copyData.MeasureValues);
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        private static string GetQuickActionHtmlDescription(cFasdQuickAction quickActionDefinition, string quickActionName, string deviceName, bool wasRunningOnAffectedDevice, DateTime executionTime, enumQuickActionSuccess? quickActionStatus)
        {
            string output = string.Empty;
            try
            {
                var quickActionStatusString = string.Empty;

                switch (quickActionStatus)
                {
                    case null:
                    case enumQuickActionSuccess.successfull:
                        quickActionStatusString = cMultiLanguageSupport.GetItem("QuickAction.Copy.RevisionStatus.Successfull");
                        break;
                    case enumQuickActionSuccess.error:
                        quickActionStatusString = cMultiLanguageSupport.GetItem("QuickAction.Copy.RevisionStatus.Error");
                        break;
                }

                var rawDescription = wasRunningOnAffectedDevice ? cMultiLanguageSupport.GetItem("QuickAction.Remote.Copy.Description.Html") : cMultiLanguageSupport.GetItem("QuickAction.Local.Copy.Description.Html");
                if(quickActionDefinition.Section == enumDataHistoryOrigin.Citrix.ToString())
                {
                    rawDescription = cMultiLanguageSupport.GetItem("QuickAction.RemoteSession.Copy.Description.Html");

                }
                output = string.Format(rawDescription, quickActionName, deviceName, executionTime.ToString("g", new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage)), quickActionStatusString);
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        private static string GetQuickActionHtmlError(string errorMessage)
        {
            if (!string.IsNullOrEmpty(errorMessage))
                errorMessage = $"<br/><p style=\"color:red\">{errorMessage}</p>";

            return errorMessage;
        }

        private static string GetQuickActionHtmlOutput(cFasdQuickAction quickActionDefinition, QuickActionStatusMonitor.cQuickActionOutput quickActionOutput)
        {
            string output = string.Empty;

            try
            {
                if (!string.IsNullOrWhiteSpace(quickActionOutput?.ErrorDescription))
                    return output;

                output += "<br/>";

                switch (quickActionOutput)
                {
                    case QuickActionStatusMonitor.cQuickActionOutputSingle singleOutput:
                        {
                            if (singleOutput.Value is null)
                                return output;

                            var displayValue = singleOutput.GetDisplayValue(quickActionDefinition?.ColumnOutputFormattings);
                            output += "<p>" + cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Html") + " " + displayValue + "</p>";
                            break;
                        }
                    case QuickActionStatusMonitor.cQuickActionOutputList listOutput:
                        {
                            output += "<p>" + cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Html") + "</p>";

                            output += "<table border=\"1\">";
                            output += "<tr>";

                            foreach (var value in listOutput.Values[0])
                            {
                                if (ShouldHideQuickActionOutput(quickActionDefinition, value.Key))
                                    continue;

                                string headingValue = value.Key;
                                if (quickActionDefinition.ColumnOutputFormattings?.TryGetValue(value.Key, out var outputFormatting) ?? false)
                                    headingValue = outputFormatting.Names.GetValue();

                                output += "<th align=\"left\">";
                                output += headingValue;
                                output += "</th>";
                            }

                            output += "</tr>";

                            for (int i = 0; i < listOutput.Values.Count; i++)
                            {
                                output += "<tr>";

                                for (int j = 0; j < listOutput.Values[i].Count; j++)
                                {
                                    string valueKey = listOutput.Values[0][j].Key;
                                    if (ShouldHideQuickActionOutput(quickActionDefinition, valueKey))
                                        continue;

                                    string displayValue = listOutput.GetDisplayValue(i, j, quickActionDefinition.ColumnOutputFormattings);

                                    if (string.IsNullOrWhiteSpace(displayValue))
                                        continue;

                                    output += "<td>";
                                    output += displayValue;
                                    output += "</td>";
                                }

                                output += "</tr>";
                            }

                            output += "</table>";
                            break;
                        }
                    case QuickActionStatusMonitor.cQuickActionOutputObject objectOutput:
                        {
                            output += "<p>" + cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Html") + "</p>";

                            output += "<table border=\"1\">";

                            for (int i = 0; i < objectOutput.Values.Count; i++)
                            {
                                var value = objectOutput.Values[i];

                                if (ShouldHideQuickActionOutput(quickActionDefinition, value.Key))
                                    continue;

                                string headingValue = value.Key;
                                if (quickActionDefinition.ColumnOutputFormattings?.TryGetValue(value.Key, out var outputFormatting) ?? false)
                                    headingValue = outputFormatting.Names.GetValue();

                                output += "<tr>";
                                output += "<td>";
                                output += headingValue;
                                output += "</td>";

                                output += "<td>";
                                string displayValue = objectOutput.GetDisplayValue(i, quickActionDefinition.ColumnOutputFormattings);
                                output += !string.IsNullOrWhiteSpace(displayValue) ? displayValue : null;
                                output += "</td>";

                                output += "</tr>";
                            }

                            output += "</table>";
                            break;
                        }
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        private static string GetQuickActionHtmlValueComparison(List<QuickActionStatusMonitor.cQuickActionMeasureValue> measureValues)
        {
            string output = string.Empty;

            try
            {
                if (measureValues is null || measureValues.Count <= 0)
                    return output;

                output += "<p>" + cMultiLanguageSupport.GetItem("QuickAction.Copy.Measure.Html") + "</p>";

                cUtility.RawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
                cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);

                foreach (var measureValue in measureValues)
                {
                    try
                    {
                        string value = cUtility.RawValueFormatter.GetDisplayValue(measureValue.Value, measureValue.Display);
                        string postValue = cUtility.RawValueFormatter.GetDisplayValue(measureValue.PostValue, measureValue.Display);
                        string difference = string.Empty;

                        if (measureValue.Difference != null)
                            difference = $" (∆ {cUtility.RawValueFormatter.GetDisplayValue(measureValue.Difference, measureValue.Display)})";

                        output += "<p>";
                        output += "<b>" + measureValue.Names.GetValue(cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage) + ": </b>" + value + " ➜ " + postValue + difference;
                        output += "</p>";
                    }
                    catch (Exception E)
                    {
                        LogException(E);
                    }
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        #endregion
    }
}
