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

namespace FasdDesktopUi.Basics.Services.ProtocollService
{
    internal class QuickActionProtocollEntry : IProtocollEntry
    {
        private readonly cFasdQuickAction _quickActionDefinition;
        private readonly cQuickActionCopyData _quickActionCopyData;

        const string AsciiSeperator = "\n\n";

        public QuickActionProtocollEntry(cFasdQuickAction quickActionDefinition, cQuickActionCopyData quickActionCopyData)
        {
            _quickActionDefinition = quickActionDefinition;
            _quickActionCopyData = quickActionCopyData;
        }

        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;

                if (dataProvider.HealthCardDataHelper.HeadingData.TryGetValue(enumFasdInformationClass.Computer, out var computerHeadingData))
                    quickActionCopyData.AffectedDeviceName = computerHeadingData.HeadingText;

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

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

            return quickActionCopyData;
        }

        internal cQuickActionResult GetResult()
        {
            return new cQuickActionResult()
            {
                QuickActionId = _quickActionDefinition.Id,
                QuickActionName = _quickActionDefinition.Name,
                QuickActionExecutionType = (int)_quickActionDefinition.ExecutionType,
                wasRunningOnAffectedDevice = _quickActionCopyData.WasRunningOnAffectedDevice,
                AffectedDeviceName = _quickActionCopyData.AffectedDeviceName,
                ExecutionTime = DateTime.UtcNow,
                ResultCode = (int?)(_quickActionCopyData.QuickActionOutput?.ResultCode),
                ErrorMessage = _quickActionCopyData.QuickActionOutput?.ErrorDescription,
                Output = GetQuickActionHtmlOutput(_quickActionCopyData.QuickActionOutput),
                MeasureValues = GetQuickActionHtmlValueComparison(_quickActionCopyData.MeasureValues)
            };
        }

        public string GetAscii() => GetQuickActionAscii(_quickActionCopyData);

        public string GetHtml() => GetQuickActionHtml(_quickActionCopyData);

        private bool ShouldHideQuickActionOutput(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 string GetQuickActionAscii(cQuickActionCopyData copyData)
        {
            string ascii = string.Empty;

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

            return ascii;
        }

        private string GetQuickActionAsciiDescription(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");
                asciiDescription = string.Format(rawDescription, quickActionName, deviceName, executionTime.ToString("g", new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage)), quickActionStatusString);
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return asciiDescription;
        }

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

            return errorMessage;
        }

        private string GetQuickActionAsciiOutput(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(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(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(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 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));

                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 string GetQuickActionHtml(cQuickActionCopyData copyData)
        {
            string output = string.Empty;

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

            return output;
        }

        private string GetQuickActionHtmlDescription(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");
                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 string GetQuickActionHtmlOutput(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(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(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(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 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));

                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
    }
}
