using Newtonsoft.Json.Linq;
using PTMedicalInsurance.Forms;
using PTMedicalInsurance.Helper;
using PTMedicalInsurance.Variables;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PTMedicalInsurance.Common
{
    public class Utils
    {
        #region 工具

        /// <summary>
        /// 返回当前日期
        /// </summary>
        /// <returns></returns>
        public static string GetDateTimeNow()
        {
            return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }

        public static string GetDateNow()
        {
            return DateTime.Now.ToString("yyyy-MM-dd");
        }

        /// <summary>
        /// 获取交易号
        /// </summary>
        /// <returns></returns>
        public static string GetTradeNo()
        { 
            return Global.inf.hospitalNO + DateTime.Now.ToString("yyyyMMddHHmmssffff"); 
        }
        /// <summary>
        /// 日期转换为时间戳Timestamp
        /// </summary>
        /// <param name="dateTime">要转换的日期</param>
        /// <returns></returns>
        public static long GetTimeStamp(DateTime dateTime)
        {
            DateTime _dtStart = new DateTime(1970, 1, 1, 8, 0, 0);
            //10位的时间戳
            long timeStamp = Convert.ToInt32(dateTime.Subtract(_dtStart).TotalSeconds);
            //13位的时间戳
            //long timeStamp = Convert.ToInt64(dateTime.Subtract(_dtStart).TotalMilliseconds);
            return timeStamp;
        }

        /// <summary>
        /// UTC时间戳Timestamp转换为北京时间
        /// </summary>
        /// <param name="timestamp">要转换的时间戳</param>
        /// <returns></returns>
        public static DateTime GetDateTime(long timestamp)
        {
            //DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); 
            //使用上面的方式会显示TimeZone已过时
            DateTime dtStart = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Local);
            DateTime targetDt = dtStart.AddMilliseconds(timestamp).AddHours(8);
            return targetDt;
        }

        /// <summary>
        /// 将JObject对象中的timestamp数据转为yyyy-MM-dd格式
        /// </summary>
        /// <param name="joObject"></param>
        /// <param name="key"></param>
        public static void convertTimestamp(JObject joObject,string key)
        {
            if (joObject.ContainsKey(key))
            {
                Global.writeLog(string.Format("当前对象[{0}]的类型为:{1}", key, joObject.GetValue(key).Type.GetType()));
            }
            
            if (joObject.ContainsKey(key) && joObject.GetValue(key).Type.GetType() != typeof(string))
            {
                long timestamp = long.Parse(joObject.GetValue(key).ToString());
                string datetime = Utils.GetDateTime(timestamp).ToString("yyyy-MM-dd");
                joObject[key] = datetime;
                Global.writeLog(string.Format("转换后的日期为:{0}",datetime));
            }

        }

        public static string ConvertLongToDate(string strValue)
        {
            DateTime dateTime = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(strValue)).DateTime;
            return dateTime.ToString("yyyy-MM-dd");
        }
        public static string ConvertShortDate(string strValue)
        {
            if (!strValue.Contains("-") && strValue.Length >= 8)
            {
                return strValue.Substring(0, 4) + "-" + strValue.Substring(4, 2) + "-" + strValue.Substring(6, 2);
            }
            return strValue.Length > 10 ? strValue.Substring(0, 10) : strValue;
        }


        public static string ConvertNoSplitDate(string strValue)
        {
            strValue = strValue.Replace("-", "");
            if(strValue.Length>8)
            {
                strValue = strValue.Substring(0, 8);
            }
            return strValue;
        }

        #endregion

        #region BeanUtils
        /// <summary>
        /// 用反射对实体进行属性值合并,返回合并后的属性并集
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity">合并对象1</param>
        /// <param name="addtional">合并对象2</param>
        /// <param name="forceCover">是否强制覆盖</param>
        /// <returns></returns>
        public static T merge<T>(T entity, T addtional,bool forceCover)
        {
            if (entity == null) return addtional;
            if (addtional == null) return entity;
            // 进行合并
            Type mType = typeof(T);
            object result = Activator.CreateInstance(mType);
            PropertyInfo[] pi = mType.GetProperties();
            pi.ToList().ForEach((p) =>
            {
                object v1 = p.GetValue(entity);
                object v2 = p.GetValue(addtional);
                if (forceCover)
                {
                    v1 = v2;
                }
                else {
                    v1 = (v1 == null ? v2 : v1);
                }
                p.SetValue(result, v1);
            });
            return (T)result;
        }
        /// <summary>
        /// 对2个对象进行合并,以第一个对象为重点
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <param name="addtional"></param>
        /// <returns></returns>
        public static T merge<T>(T entity, T addtional)
        {
            return merge(entity, addtional, false);
        }

        private static JObject merge(JObject to, JObject from)
        {
            to.Merge(from);
            return to;
        }
        /// <summary>
        /// 采用Json的方式进行属性合并(默认会覆盖)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="to"></param>
        /// <param name="from"></param>
        /// <returns></returns>
        public static T mergeObject<T>(T to, T from)
        {
            JObject toObj = JObject.FromObject(to);
            JObject fromObj = JObject.FromObject(from);
            JObject result = merge(toObj, fromObj);
            return result.ToObject<T>();
        }

        #endregion


        #region 业务个性化

        /// <summary>
        /// 在JObject对象基础上进行包装
        /// </summary>
        /// <param name="jsonInParam"></param>
        /// <returns></returns>
        public static JObject Wrapper(JObject jsonInParam)
        {
            //dynamic request = new JObject();
            //request.arg0 = jsonInParam;
            //return request;
            return jsonInParam;
        }
        /// <summary>
        /// 删除JObject上的进行包装
        /// </summary>
        /// <param name="jsonInParam"></param>
        /// <returns></returns>
        public static JObject removeWrapper(JObject jsonInParam)
        {
            //if (jsonInParam.ContainsKey("arg0"))
            //{
            //    return (JObject)jsonInParam.GetValue("arg0");
            //}
            return jsonInParam;
        }

        /// <summary>
        /// 获取参保地编码
        /// </summary>
        /// <returns></returns>
        public static string GetInsuCode()
        {
            //if (string.IsNullOrEmpty(Global.pat.insuplc_admdvs))
            //{
            //    Global.pat.insuplc_admdvs = Global.inf.areaCode;
            //}
            //Global.writeLog("参保地判断:"+ Global.pat.insuplc_admdvs);

            //if (!string.IsNullOrEmpty(Global.pat.insuplc_admdvs))
            //{
            //    if (Global.inf.fixedPointType == "1") //省本级
            //    {
            //        //适用于南昌
            //        if (Global.pat.insuplc_admdvs.Substring(0, 4) != Global.inf.areaCode.Substring(0, 4))
            //        {
            //            Global.inf.areaCode = "369900";
            //        }
            //    }
            //    else
            //    {
            //        //适用于红谷滩
            //        if (Global.pat.insuplc_admdvs.Substring(0, 4) == "3699") //有且只有在患者为省直的情况下传369900
            //        {
            //            Global.inf.areaCode = "369900";
            //        }
            //    }
            //}

            return Global.pat.insuplc_admdvs;
        }

        /// <summary>
        /// 获取医院编码(社保)
        /// </summary>
        /// <returns></returns>
        public static string GetInsuOrgCode()
        {
            return Global.inf.hospitalNO;
        }

        /// <summary>
        /// 跨省异地
        /// </summary>
        /// <returns></returns>
        public static bool isOtherProvice(string areaCode)
        {
            if (!string.IsNullOrEmpty(areaCode) && areaCode.Length>2 && areaCode.Substring(0, 2) != "36")
            {
                return true;
            }
            return false;
        }

        public static bool isOtherProvice()
        {
            return isOtherProvice(getAreaCode());
        }

        private static string getAreaCode()
        {
            string areaCode = Global.pat.insuplc_admdvs ?? Global.inf.areaCode;
            if (Global.pat.OtherProv == 1)
            {
                areaCode = Global.pat.card.SearchAdmCode;
            }
            return areaCode;
        }
        public static bool isOtherCity()
        {
            return isOtherCity(getAreaCode());
        }
        /// <summary>
        /// 省内异地
        /// </summary>
        /// <returns></returns>
        public static bool isOtherCity(string areaCode)
        {
            if (!string.IsNullOrEmpty(areaCode) && areaCode.Length > 4 && areaCode.Substring(0, 4) != "3601")
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 将入参进行标准化转换
        /// </summary>
        /// <returns></returns>
        public static JObject ConvertRequest<T>(TradeEnum trade,JObject request)
        {
            JObject joOutput = request;
            JsonMapper mapper = new JsonMapper(trade.GetCode());
            // 非基线版需要转换
            if (!Global.curEvt.ext.BaseLineMode)
            {
                // 调试模式,可手动配置转换规则
                if (Global.curEvt.showJson)
                {
                    JsonMappingForm form = new JsonMappingForm(request.ToString(),mapper.GetInputJson(),trade.GetCode());
                    form.ShowDialog();
                    mapper.reload();  //修改后重新加载
                }
                joOutput = mapper.MapRequest<JObject, T>(request);
            }
            // 日志
            //Global.writeLog("ConvertRequest", request.ToString(),joOutput.ToString());
            return joOutput;
        }

        public static JObject ConvertResponse<T>(TradeEnum trade, JObject response)
        {
            return ConvertResponse<T>(trade, response, false);
        }

        /// <summary>
        /// 将交易输出进行标准化转换
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="trade"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        public static JObject ConvertResponse<T>(TradeEnum trade, JObject response,bool forceConvertFlag)
        {
            JsonMapper mapper = new JsonMapper(trade.GetCode());
            JObject joOutput = response;
            // 非基线版或要求转换
            if (!Global.curEvt.ext.BaseLineMode || forceConvertFlag)
            {
                //如果没有配置转换规则,调试模式,可手动配置
                if (Global.curEvt.showJson)
                {
                    JsonMappingForm form = new JsonMappingForm(response.ToString(), mapper.GetOutputJson(), trade.GetCode(),false);
                    form.ShowDialog();
                    mapper.reload();  //修改后重新加载
                }

                joOutput = mapper.MapResponse<JObject, T>(response);
            }
            // 日志
            //Global.writeLog("ConvertResponse", "", joOutput.ToString());
            return joOutput;
        }
        /// <summary>
        /// 部分业务需要使用特殊的就诊凭证号
        /// </summary>
        /// <returns></returns>
        public static string ConvertMdtrtcertNo(bool flag = true)
        {
            if ("03".Equals(Global.pat.mdtrtcertType) && !string.IsNullOrEmpty(Global.pat.card.NO))
            {
                return Global.pat.card.NO;
            }
            return Global.pat.mdtrtcertNO;
        }

        /// <summary>
        /// 保存信息到pat.Expand字段
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void ExpandData(string key,object value)
        {
            string expand = Global.pat.ExpContent;
            JObject obj = new JObject();
            if (!string.IsNullOrEmpty(expand))
            {
                obj = JObject.Parse(expand);
            }
            if (!obj.ContainsKey(key))
            {
                obj.Add(key, value?.ToString());
            }
            else
            {
                obj[key] = value?.ToString();
            }
            Global.pat.ExpContent = obj.ToString();
        }

        public static string convertAdmDr(string admNo)
        {
            // 重庆异地(每次唯一)
            //if (isOtherCity())
            //{
            //    // 住院号15位,控制总长度不超过20
            //    string ret = admNo + "-" + DateTime.Now.ToString("HHmm");
            //    // 保存到扩展信息字段中
            //    ExpandData("admDr", ret);

            //    return ret;
            //}

            return admNo;
        }

        public static bool Confirm(string title)
        {
            if (MessageBox.Show(title, "警告", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
            {
                return false;
            }

            return true;
        }

        public static void WriteMockData(bool requestFlag, string tradeNo,string content)
        {
            string dataFile = Global.curEvt.path + "/config/mock/" + (requestFlag ? "request" : "response") + "/" + tradeNo + ".json";
            File.WriteAllText(dataFile, content);
        }

        public static string MockData(bool requestFlag,string tradeNo)
        {
            string dataFile = Global.curEvt.path +"/config/mock/" + (requestFlag ? "request" : "response") + "/" + tradeNo + ".json";
            // 加载字段映射配置
            if (File.Exists(dataFile))
            {
                return File.ReadAllText(dataFile);
            }
            else
            {
                Global.writeLog("配置文件不存在:"+dataFile);
            }
            return "";
        }
        #endregion

        #region 加解密

        ///// <summary>
        ///// API密钥
        ///// </summary>
        //private static void LoadAPIKey(string prefix)
        //{
        //    //获取AK,SK(可配置)
        //    IniFile urlIni = new IniFile(Global.curEvt.path + @"\EncrypInfo.ini");
        //    string ak = urlIni.ReadValue(prefix, "AK");
        //    string sk = urlIni.ReadValue(prefix, "SK");
        //    if (!string.IsNullOrEmpty(ak) && !string.IsNullOrEmpty(sk))
        //    {
        //        Global.inf.AK = ak;
        //        Global.inf.SK = sk;
        //    }
        //}

        /// <summary>
        /// 接口加密标志
        /// </summary>
        /// <param name="funNo"></param>
        /// <returns></returns>
        public static bool LoadEncyptFlag(string funNo)
        {
            IniFile urlIni = new IniFile(Global.curEvt.path + @"\EncrypInfo.ini");
            string flag = urlIni.ReadValue(Global.inf.interfaceID+"_FUNNO", funNo);
            return "1".Equals(flag);
        }

        ///// <summary>
        ///// 核心接口密钥
        ///// </summary>
        //public static void LoadCoreAPIKey()
        //{
        //    LoadAPIKey("KEY");
        //}
        ///// <summary>
        ///// 移动支付密钥
        ///// </summary>
        //public static void LoadMobileAPIKey()
        //{
        //    LoadAPIKey("MOBILE");
        //}

        #endregion


    }
}