using Siger.Middlelayer.Common.Extensions;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Siger.Middlelayer.Common.Helpers
{
    public class LicenseHelper
    {
        private const string EncryptKey = "Sg#li018";
        private static readonly byte[] Keys = { 0x12, 0x78, 0x56, 0x31, 0x6F, 0x6A, 0x25, 0x7A };

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string Decrypt(string value)
        {
            if (string.IsNullOrEmpty(value)) return string.Empty;
            try
            {
                byte[] rgbKey = Encoding.UTF8.GetBytes(EncryptKey);
                byte[] rgbIv = Keys;
                byte[] inputByteArray = Convert.FromBase64String(value);
                var dcsp = new DESCryptoServiceProvider();
                using (var stream = new MemoryStream())
                {
                    using (var cStream = new CryptoStream(stream, dcsp.CreateDecryptor(rgbKey, rgbIv), CryptoStreamMode.Write))
                    {
                        cStream.Write(inputByteArray, 0, inputByteArray.Length);
                        cStream.FlushFinalBlock();
                        return Encoding.UTF8.GetString(stream.ToArray());
                    }
                }
            }
            catch
            {
                return value;
            }
        }

        public static LicenseInformation GetLicenseStatus(string license)
        {
            var information = new LicenseInformation();
            try
            {
                var lic = Decrypt(license);
                if (lic == license)
                {
                    information.Status = LicenseStatus.Invalid;
                }
                var lics = lic.Split(new string[] { "#" }, StringSplitOptions.RemoveEmptyEntries);
                if(lics.Length == 7)
                {
                    var startTimeStr = lics[5].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                    if (startTimeStr.Length != 2)
                    {
                        information.Status = LicenseStatus.Invalid;
                    }

                    var endTimeStr = lics[6].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                    if (endTimeStr.Length != 2)
                    {
                        information.Status = LicenseStatus.Invalid;
                    }

                    var machineCountStr = lics[2].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                    if (machineCountStr.Length != 2)
                    {
                        information.Status = LicenseStatus.Invalid;
                    }

                    var userCountStr = lics[3].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                    if (userCountStr.Length != 2)
                    {
                        information.Status = LicenseStatus.Invalid;
                    }

                    if (endTimeStr[1].ToDateTime() < DateTime.Now || startTimeStr[1].ToDateTime() > DateTime.Now)
                    {
                        information.Status = LicenseStatus.HasExpity;
                    }
                    information.MaxMachineCount = machineCountStr[1].ToInt();
                    information.MaxUserCount = userCountStr[1].ToInt();
                    information.Status = LicenseStatus.Valid;
                    return information;
                }
                else
                {
                    var expityTime = lics[0].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                    if (expityTime.Length != 2)
                    {
                        information.Status = LicenseStatus.Invalid;
                    }

                    var createTimeStr = lics[5].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                    if (createTimeStr.Length != 2)
                    {
                        information.Status = LicenseStatus.Invalid;
                    }

                    if (!DateTime.TryParse(createTimeStr[1], out DateTime createTime))
                    {
                        information.Status = LicenseStatus.Invalid;
                    }

                    var machineCountStr = lics[3].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                    if (machineCountStr.Length != 2)
                    {
                        information.Status = LicenseStatus.Invalid;
                    }

                    var userCountStr = lics[4].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                    if (userCountStr.Length != 2)
                    {
                        information.Status = LicenseStatus.Invalid;
                    }

                    var time = GetTime(expityTime[1], createTime);
                    if (time < DateTime.Now)
                    {
                        information.Status = LicenseStatus.HasExpity;
                    }
                    information.MaxMachineCount = machineCountStr[1].ToInt();
                    information.MaxUserCount = userCountStr[1].ToInt();
                    information.Status = LicenseStatus.Valid;
                    return information;
                }
            }
            catch
            {
                return information;
            }
        }

        public static DateTime GetTime(string id, DateTime createTime)
        {
            switch (id)
            {
                case "3947367637C448A39AFB5B8AAE91E498":
                    return createTime.AddMonths(1);
                case "E1A547F7F6CD42429388D17DCD882CB3":
                    return createTime.AddMonths(3);
                case "6429C5A2190446758A6C0615FD576ECC":
                    return createTime.AddMonths(6);
                case "5B499D85EE8B4A89A90B3BF3C37344EC":
                    return createTime.AddYears(1);
                case "5154D6D90F774ECFB464A4BA3F8C6F7A":
                    return createTime.AddYears(2);
                case "CEE6431D18804AF089CC88C8EDA3E737":
                    return createTime.AddYears(3);
                case "D7504260E3E64D8D8FA2678BB2785249":
                    return createTime.AddYears(5);
                case "B5C4CBFF7BB54CBBBBC1D1638D7D3FBD":
                    return createTime.AddYears(1000);
                default:
                    throw new ArgumentException();
            }
        }
    }

    public enum LicenseStatus
    {
        NotFound,
        Invalid,
        HasExpity,
        Valid
    }

    public class LicenseInformation
    {
        public LicenseStatus Status { get; set; }

        public int MaxUserCount { get; set; } = 0;

        public int MaxMachineCount { get; set; } = 0;

        public LicenseInformation()
        {
            Status = LicenseStatus.Invalid;
        }
    }

    public class ModuleStatus
    {
        public string ModuleName { get; set; }

        public bool IsValid { get; set; } = false;

        public ModuleStatus(string name, string expireTime, DateTime createTime)
        {
            ModuleName = name;
            var date = LicenseHelper.GetTime(expireTime, createTime);
            if (date > DateTime.Now)
            {
                IsValid = true;
            }
        }
    }
}
