using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using static C4IT.Logging.cLogManager;

namespace C4IT.FASD.Base
{
    public enum enumFasdInformationClass
    {
        Unknown = -1,
        Main = 0,
        Computer = 1,
        User = 2,
        Ticket = 3
    }

    public enum enumF4sdSearchResultClass
    {
        Unknown = -1,
        Computer = 0,
        User = 1,
        Phone = 2,
        Ticket = 3
    }

    public enum enumF4sdSearchResultStatus
    {
        Unknown = -1,
        Inactive = 0,
        Active = 1
    }

    public enum enumFasdValueType
    {
        Unknown = 0,
        STRING = 1,
        GUID = 2,
        INT = 3,
        BIGINT = 4,
        FLOAT = 5,
        DATETIME = 6,
        VERSION = 7,
        MD5 = 8,
        SID = 9,
        IPV4 = 10,
        IPV6 = 11,
        TEXT = 12,
        BOOLEAN = 13,
        AUTOID = 255
    };

    public enum enumFasdCharCaseType { none = 0, lower = 1, upper = 2 };

    public enum enumFasdConfigurationType
    {
        unknown = 0,
        commonIcons,
        menuSections,
        quickActions,
        copyTemplates,
        healthCard
    }

    public class cFasdApiConnectionInfo
    {
        public string ServerVersion { get; set; }
        public string MinCockpitVersion { get; set; }
        public UInt64 ConfigRevision { get; set; } = 0;
    }

    public class cAgentApiConfiguration
    {
        public string LogonUrl { get; set; }
        public string ApiUrl { get; set; }
        public string ClientId { get; set; }
        public string ClientSecret { get; set; }
        public int? OrganizationCode { get; set; }

        [JsonIgnore]
        public static cAgentApiConfiguration Instance { get; set; }
    }

    public class cFasdApiSearchResultDefault
    {
        public enumF4sdSearchResultClass Type { get; set; }
        public string Name { get; set; }
        public Guid id { get; set; }
        public enumF4sdSearchResultStatus Status { get; set; } = enumF4sdSearchResultStatus.Unknown;
        public Dictionary<string, string> Infos { get; set; } = null;

        static public enumF4sdSearchResultClass getSearchClass(enumFasdInformationClass infoClass)
        {
            switch (infoClass)
            {
                case enumFasdInformationClass.User:
                    return enumF4sdSearchResultClass.User;
                case enumFasdInformationClass.Computer:
                    return enumF4sdSearchResultClass.Computer;
                default:
                    return enumF4sdSearchResultClass.Unknown;
            }

        }
    }

    public class cF4sdIdentityEntry
    {
        public enumFasdInformationClass Class { get; set; }
        public Guid Id { get; set; }

        public static enumFasdInformationClass GetFromSearchResult(enumF4sdSearchResultClass searchResult)
        {
            var infoClass = enumFasdInformationClass.Unknown;
            switch (searchResult)
            {
                case enumF4sdSearchResultClass.Computer:
                    infoClass = enumFasdInformationClass.Computer;
                    break;
                case enumF4sdSearchResultClass.User:
                case enumF4sdSearchResultClass.Phone:
                    infoClass = enumFasdInformationClass.User;
                    break;
            }

            return infoClass;
        }
    }

    public class cF4sdApiSearchResultRelation : cFasdApiSearchResultDefault
    {
        public DateTime LastUsed { get; set; }
        public double UsingLevel { get; set; }
        public List<cF4sdIdentityEntry> Identities { get; set; } = null;
    }

    public class cF4sdHealthCardRawDataRequest
    {
        public List<string> Tables { get; set; }
        public List<cF4sdIdentityEntry> Identities { get; set; }

        public int MaxAge { get; set; } = 14;

        public DateTime RefTime { get; set; } = DateTime.Now.Date.ToUniversalTime();
    }

    public class cF4SDHealthCardRawData
    {
        public class cHealthCardTableColumn
        {
            public string ColumnName { get; set; }
            public List<object> Values { get; set; } = new List<object>();
            public bool IsIncomplete { get; set; } = false;
        }

        public class cHealthCardTable
        {
            public string Name { get; set; }
            public int StartingIndex { get; set; } = 0;
            public bool IsIncomplete { get; set; } = false;
            public bool IsStatic { get; set; }
            public DateTime[,] TimeFrames { get; set; }
            public Dictionary<string, cHealthCardTableColumn> Columns { get; set; } = new Dictionary<string, cHealthCardTableColumn>();
        }

        public class cHealthCardDetailsTable
        {
            public string Name { get; set; }
            public List<string> Columns { get; set; }
            public Dictionary<int, List<object[]>> Values { get; set; }
        }

        public Guid Id { get; set; }

        public Dictionary<string, cHealthCardTable> Tables { get; set; } = new Dictionary<string, cHealthCardTable>();

        #region GetObjects

        #region GetInteger

        public static int? GetInteger(object Value, int? Default = null)
        {
            int? output = Default;

            if (Value == null)
                return output;

            try
            {
                var valuetype = Value.GetType();

                if (Value is int @int)
                    output = @int;
                if (Value is Int64 @int64)
                    output = Convert.ToInt32(@int64);
                else if (Value is double @double)
                    output = Convert.ToInt32(@double);
                else if (Value is string @string)
                {
                    if (int.TryParse(@string, out int parsedInt))
                        output = parsedInt;
                    else
                        output = Default;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        public int? GetIntegerByAddressInfo(string TableName, string TableColumn, int index = 0, int? Default = null)
        {
            int? output = Default;

            try
            {
                if (Tables.TryGetValue(TableName, out var selectedTable))
                    if (selectedTable.Columns.TryGetValue(TableColumn, out var selectedColumn))
                        output = GetInteger(selectedColumn.Values[index], Default);
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        #endregion

        #region GetString

        public static string GetString(object Value, string Default = null)
        {
            string output = Default;
            try
            {
                if (Value is int @int)
                    output = Convert.ToString(@int);
                else if (Value is double @double)
                    output = Convert.ToString(@double);
                else if (Value is string @string)
                    output = @string;
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output?.ToString();
        }

        public string GetStringByAddressInfo(string TableName, string TableColumn, int index = 0, string Default = null)
        {
            string output = Default;

            try
            {
                if (Tables.TryGetValue(TableName, out var selectedTable))
                    if (selectedTable.Columns.TryGetValue(TableColumn, out var selectedColumn))
                        output = GetString(selectedColumn.Values[index], Default);
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        #endregion

        #region GetVersion

        public static Version GetVersion(object Value, Version Default = null)
        {
            Version output = Default;

            if (Value == null)
                return output;

            try
            {
                if (Value is string @string)
                {
                    if (Version.TryParse(@string, out var tempVersionFromString))
                        output = tempVersionFromString;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        public Version GetVersionByAddressInfo(string TableName, string TableColumn, int index = 0, Version Default = null)
        {
            Version output = Default;

            try
            {
                if (Tables.TryGetValue(TableName, out var selectedTable))
                    if (selectedTable.Columns.TryGetValue(TableColumn, out var selectedColumn))
                        output = GetVersion(selectedColumn.Values[index], Default);
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        #endregion

        #region GetDateTime

        public static DateTime? GetDateTime(object Value, DateTime? Default = null)
        {
            DateTime? output = Default;

            if (Value == null)
                return output;

            try
            {
                if (Value is DateTime time)
                    output = time;
                else if (Value is string @string)
                {
                    var tempOutput = Convert.ToDateTime(@string);
                    DateTime.SpecifyKind(tempOutput, DateTimeKind.Utc);
                    if (tempOutput != null)
                        output = tempOutput;
                    else
                        output = Default;

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

            return output;
        }

        public DateTime? GetDateTimeByAddressInfo(string TableName, string TableColumn, int index = 0, DateTime? Default = null)
        {
            DateTime? output = Default;

            try
            {
                if (Tables.TryGetValue(TableName, out var selectedTable))
                    if (selectedTable.Columns.TryGetValue(TableColumn, out var selectedColumn))
                        output = GetDateTime(selectedColumn.Values[index], Default);
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        #endregion

        #region GetDouble

        public static double? GetDouble(object Value, double? Default = null)
        {
            double? output = Default;

            try
            {
                if (Value is int @int)
                    output = Convert.ToDouble(@int);
                else if (Value is Int64 @int64)
                    output = Convert.ToDouble(@int64);
                else if (Value is double @double)
                    output = @double;
                else if (Value is string @string)
                {
                    if (double.TryParse(@string, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.GetCultureInfo("en-US").NumberFormat, out double tempOutput))
                        output = tempOutput;
                    else
                        output = Default;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        public double? GetDoubleByAddressInfo(string TableName, string TableColumn, int index = 0, double? Default = null)
        {
            double? output = Default;

            try
            {
                if (Tables.TryGetValue(TableName, out var selectedTable))
                    if (selectedTable.Columns.TryGetValue(TableColumn, out var selectedColumn))
                        output = GetDouble(selectedColumn.Values[index], Default);
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        #endregion

        #endregion
    }
    public class cApiM42TicketQueueInfo
    {
        public string QueueName { get; set; }
        public Guid QueueID { get; set; }
    }

    public class cF4SDTicketSummary
    {
        public Guid TicketObjectId { get; set; }
        public string Name { get; set; }
        public string ActivityType { get; set; }
        public string Summary { get; set; }
        public string Sid { get; set; }
        public string Status { get; set; }
        public int StatusId { get; set; }
        public string Urgency { get; set; }
        public int UrgencyId { get; set; }
        public string Impact { get; set; }
        public int ImpactId { get; set; }
        public string AssetCIName { get; set; }
        public string AssetName { get; set; }
        public string ServiceName { get; set; }
        public Guid ServiceId { get; set; }
        public bool IsPrimaryAccount { get; set; }
    }

    public class cF4SDTicket : cF4SDTicketSummary
    {
        public enum enumTicketCreationSource
        {
            Unknown = 0,
            Mail = 1,
            Phone = 2,
            F4SD = 3
        }

        public class cTicketJournalItem
        {
            public DateTime CreationDate { get; set; }
            public string Header { get; set; }
            public string CreatedBy { get; set; }
            public string DescriptionHtml { get; set; }
            public string Description { get; set; }
            public bool IsVisibleForUser { get; set; }
            public Guid ActivityObjectId { get; set; }
            public Guid JournalId { get; set; }
        }

        public Guid AffectedUserId { get; set; }
        public Guid AssetId { get; set; }
        public DateTime CreationDate { get; set; }
        public DateTime? ClosingDate { get; set; }
        public int CreationSourceId { get; set; }
        public string CreationSource { get; set; }

        public string Description { get; set; }
        public string DescriptionHtml { get; set; }
        public int PriorityId { get; set; }
        public string Priority { get; set; }
        public Guid CategoryId { get; set; }
        public string Category { get; set; }
        public string CategoryHierarchical { get; set; }
        public string CIName { get; set; }
        public string DirectLinkEdit { get; set; }
        public Guid AssetCIId { get; set; }
        public int AssetSKUAssetGroupId { get; set; }
        public string AssetSKUAssetGroup { get; set; }
        public int AssetSKUTypeId { get; set; }
        public string AssetSKUType { get; set; }
        public string DirectLinkPreview { get; set; }
        public string DirectLinkClose { get; set; }
        public string AffectedUser { get; set; }
        public string SolutionHtml { get; set; }
        public string Solution { get; set; }
        public string AssetDomain { get; set; }
    }
}