using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BLL.APIService
{
    public class SyncUserInfoService
    {
        private const string GETTOKENAPI = "https://ppsintf.basf-ypc.net.cn/ppsinterface/token/getToken";
        private const string GETHRINfOAPI = "https://ppsintf.basf-ypc.net.cn/ppsinterface/interfaceInfo/getHrInfo";
        public static string GetUserToken()
        {
            string username = "itinforadm";
            string password = "B9$hxQ@?t<p*";
            string result = BLL.Common.HttpHelper.HttpPostRequest(GETTOKENAPI,$"username={username}&password={password}",string.Empty);
            var data = JsonHelper.DeserializeJsonToObject<ResultData>(result);
            if ("200"==data.code)
            {
                return data.token;
            }
            else
            {
                ErrLogInfo.WriteLog("请求失败:返回结果:" + result);
                return null;
            }
           
        }
        public static void GetSyncUserInfo()
        {
            // var token = GetUserToken(); //获取接口token
            var dic = GetDepartList();  //把本地数据库中的部门全部取出作为字典
            var dicUser = GetUserInfoByAccount();   //同上把所有用户取出来

            string result = BLL.Funs.DB.OriginDatas.Select(t => t.JsonData).FirstOrDefault();
            var data = JsonHelper.DeserializeJsonToObject<ResultData<List<UserInfo>>>(result);

            List<Model.SyncDataUserLogs> logList = new List<Model.SyncDataUserLogs>();
            if (data.code == "200")
            {
                //ErrLogInfo.WriteLog($"userinfo={data.data}");
                var userInfo = data.data;
                string batchNo= DateTime.Now.ToString("yyyyMMddHHmmss");
                DateTime syncTime = DateTime.Now;
                foreach (var item in userInfo)
                {
                 
                    var account = item.ppsHrOtherEmp.bgdid;// 当前json的账号
                    if (string.IsNullOrEmpty(account))
                    {
                        Model.SyncDataUserLogs log3 = new Model.SyncDataUserLogs();
                        log3.BatchNo = batchNo;
                        log3.CreatedTime = syncTime;
                        log3.DataType = 3;
                        log3.DepatId = string.Empty;
                        log3.UserId = string.Empty;
                        log3.IsSuccess = false;
                        log3.Remark = $"当前账号为空:{JsonHelper.SerializeObject(item)}";
                        logList.Add(log3);
                        continue;
                    }
                    var manager = item.ppsHrOtherEmp.manager;   //当前经理的员工号
                    account = account.ToLower();
                    var user = dicUser.ContainsKey(account);    //判断当前账号是否在我们数据库中
                    string userId = user ? dicUser[account] : null;   //存在那就是把用户id取出来,否则用户id就是null

                    #region 同步部门
                    //部门id
                    string departId = "";
                    Model.SyncDataUserLogs log = new Model.SyncDataUserLogs();
                    try
                    {
                        log.BatchNo = batchNo;
                        log.CreatedTime = syncTime;
                        //如果是经理,总经理,总监
                        if (item.position.Contains("Manager") || item.position.Contains("Director") || item.position.Contains("General Manager"))
                        {
                            //判断是否存在部门
                            if (IsExistsDepart(dic, item.section))
                            {
                                departId = dic[item.section];   //取出本地数据库部门ID
                                UpdateDepartInfo(userId, item.section); //更新部门表数据
                            }
                            else
                            {
                                departId = InsertDepartInfo(userId, item.section);  //插入本地数据库部门
                            }
                        }
                        else
                        {
                            //查找当前用户的上级经理是谁
                            var parentUser = userInfo.Where(t => t.ppsHrOtherEmp.bycstaffNo == manager).FirstOrDefault();
                            if (parentUser == null)
                            {
                                //找不到就是他自己
                                string itemDepartCode = item.section.ToUpper();
                                string itemUserId = userId;
                                //判断当前自身的部门是否存在
                                if (IsExistsDepart(dic, itemDepartCode))
                                {
                                    departId = dic[itemDepartCode]; //取出自身部门所在的部门ID
                                    UpdateDepartInfo(itemUserId, itemDepartCode);   //更新自身部门的部门数据。
                                }
                                else
                                {
                                    departId = InsertDepartInfo(itemUserId, itemDepartCode); //插入本地部门表数据
                                }
                            }
                            else
                            {
                                //找到了就是上级的用户部门+LeaderID;
                                string parentDepatCode = parentUser.section.ToUpper();    //上级部门编号
                                string parentAccount = parentUser.ppsHrOtherEmp.bgdid;  //上级用户的账号
                                if (!string.IsNullOrEmpty(parentAccount))
                                    parentAccount = parentAccount.ToLower();
                                else
                                    parentAccount = string.Empty;

                                var parentLocalUser = dicUser.ContainsKey(parentAccount);   //查找本地数据库的上级用户是否存在
                                string parentUserId = parentLocalUser ? dicUser[parentAccount] : null;
                                //上级用户所在的部门已经存在
                                if (IsExistsDepart(dic, parentDepatCode))
                                {
                                    departId = dic[parentDepatCode];                    //取出他上级用户所在的部门ID
                                    UpdateDepartInfo(parentUserId, parentDepatCode);    //更新部门信息
                                }
                                else
                                {
                                    departId = InsertDepartInfo(parentUserId, parentDepatCode);   //插入他上级用户所在的部门到部门表中去
                                }
                            }

                        }

                        log.DepatId = departId;
                        log.DataType = 0;
                        log.Remark = "同步成功";
                        log.IsSuccess = true;
                    }
                    catch (Exception ex)
                    {
                        log.DepatId = departId;
                        log.DataType = 0;
                        log.Remark = ex.Message;
                        log.IsSuccess = false;
                    }
                    //这里记录同步部门的日志
                    logList.Add(log);
                    #endregion

                    #region 同步用户
                    Model.SyncDataUserLogs log2 = new Model.SyncDataUserLogs();
                    string resultId = string.Empty;
                    try
                    {
                        log2.BatchNo = batchNo;
                        log2.CreatedTime = syncTime;
                        
                        //当前本地数据库用户表不存在此用户
                        if (!user)
                        {
                            //插入
                            resultId = InsertUserInfo(item, departId);
                            log.UserId = resultId;
                            log.DataType = 1;
                        }
                        else
                        {
                            resultId = UpdateUserInfo(item, departId);
                            log.UserId = resultId;
                            log.DataType = 1;
                        }
                        log2.Remark = "同步成功";
                        log2.IsSuccess = true;
                    }
                    catch (Exception ex)
                    {
                        log.UserId = resultId;
                        log.DataType = 1;
                        log2.Remark =$"同步失败:{ex.Message}";
                        log2.IsSuccess = false;
                    }
                    //这里记录同步用户的日志
                    logList.Add(log2);
                    #endregion
                }

                AddSyncLogs(logList);
            }
            else
            {
                ErrLogInfo.WriteLog("请求失败:返回结果:" + result);
            }
        }

        #region 私有方法
        /// <summary>
        /// 获取所有的BU
        /// </summary>
        /// <returns></returns>
        private static Dictionary<string,string> GetDepartList()
        {
            return BLL.Funs.DB.Base_Depart.ToList()
                .ToDictionary(t => t.DepartCode.ToUpper(), t => t.DepartId);
            
        }
        /// <summary>
        /// 获取所有的User
        /// </summary>
        /// <returns></returns>
        private static Dictionary<string,string> GetUserInfoByAccount()
        {
            return BLL.Funs.DB.Sys_User.Select(t => new { t.UserId, t.Account }).ToList()
               .ToDictionary(t => t.Account.ToLower(), t => t.UserId);

        }
        /// <summary>
        /// 更新BU
        /// </summary>
        /// <param name="leaderId"></param>
        /// <param name="depatCode"></param>
        private static void UpdateDepartInfo(string leaderId,string depatCode)
        {
            //更新leader字段
            if (!string.IsNullOrEmpty(leaderId))
            {
                string sql = string.Format("update Base_Depart set DepartLeader='{0}' where DepartCode='{1}'", leaderId, depatCode);
                Funs.DB.ExecuteCommand(sql);
            }
        }
        /// <summary>
        /// 新增BU
        /// </summary>
        /// <returns></returns>
        private static string InsertDepartInfo(string leaderId, string depatCode)
        {
            //插入部门信息,并且把leader字段写入
            var depatModel = new Model.Base_Depart();
            depatModel.DepartId = SQLHelper.GetNewID(typeof(Model.Base_Depart));
            depatModel.DepartCode = depatCode;
            depatModel.DepartName = depatCode;
            depatModel.DepartLeader = leaderId;
            BLL.DepartService.AddDepart(depatModel);
            return depatModel.DepartId;
        }
        /// <summary>
        /// 判断是否存在BU
        /// </summary>
        /// <returns></returns>
        private static bool IsExistsDepart(Dictionary<string,string> depatDbData, string departCode)
        {
            return depatDbData.ContainsKey(departCode.ToUpper());
        }

        /// <summary>
        /// 插入用户信息
        /// </summary>
        private static string InsertUserInfo(UserInfo user,string departId)
        {
            var userModel = new Model.Sys_User();
            userModel.UserId = SQLHelper.GetNewID(typeof(Model.Sys_User));
            userModel.Account = user.ppsHrOtherEmp.bgdid;
            userModel.UserName = user.name;
            userModel.ChineseName = user.nameCN;
            userModel.Email = user.emailAddress;
            userModel.DepartId = departId;
            userModel.Password = Sys_UserService.GetEncryptionPassword(userModel.Account);
            if (user.ppsHrOtherEmp.leftEffectiveDate.HasValue)
            {
                userModel.IsPost = user.ppsHrOtherEmp.leftEffectiveDate.HasValue ? false : true;
            }

            Funs.DB.Sys_User.InsertOnSubmit(userModel);
            Funs.DB.SubmitChanges();
            return userModel.UserId;
        }

        /// <summary>
        ///  更新用户信息
        /// </summary>
        private static string UpdateUserInfo(UserInfo user, string departId)
        {
            //更新6个字段
            var updateUser = Funs.DB.Sys_User.FirstOrDefault(e => e.Account == user.ppsHrOtherEmp.bgdid);
            updateUser.UserName = user.name;
            updateUser.ChineseName = user.nameCN;
            updateUser.Email = user.emailAddress;
            updateUser.DepartId = departId;
            if (user.ppsHrOtherEmp.leftEffectiveDate.HasValue)
            {
                updateUser.IsPost = user.ppsHrOtherEmp.leftEffectiveDate.HasValue ? false : true;
            }
            Funs.DB.SubmitChanges();
            return updateUser.UserId;
        }
        /// <summary>
        /// 记录logos日志
        /// </summary>
        private static void AddSyncLogs(List<Model.SyncDataUserLogs> logs)
        {
            Funs.DB.SyncDataUserLogs.InsertAllOnSubmit(logs);
            Funs.DB.SubmitChanges();
        }
        #endregion


    }
    #region 内部类
    [Serializable]
    internal class UserInfo
    {
        public long id { get; set; }

        public string name { get; set; }

        public string nameCN { get; set; }

        public string div { get; set; }

        public string dept { get; set; }

        public string section { get; set; }

        public string shift { get; set; }

        public string employeeType { get; set; }

        public string joinDate { get; set; }
        public string gender { get; set; }

        public string age { get; set; }
        public string emailAddress { get; set; }

        public string position { get; set; }

        public string positionCN { get; set; }

        public string officePhone { get; set; }
        public string faxNumber { get; set; }
        public string mobilePhone { get; set; }

        public string bycstaffNo { get; set; }
        public ppsHrOtherEmp ppsHrOtherEmp { get; set; }

        public List<ppsHrCertificateList> ppsHrCertificateList { get; set; }

        public List<ppsHrTrainingList> ppsHrTrainingList { get; set; }


    }
    [Serializable]
    internal class ppsHrOtherEmp
    {
        public long id { get; set; }
        public string costCenter { get; set; }
        public string reportTo { get; set; }
        public string manager { get; set; }
        public string director { get; set; }
        public string generalManager { get; set; }
        public DateTime? joinBYCDate { get; set; }
        public DateTime? leftEffectiveDate { get; set; }
        public string employeeType { get; set; }
        public string eMailAddress { get; set; }
        public string bycstaffNo { get; set; }

        public string ppsmac { get; set; }
        public string bgdid { get; set; }

        public string sappersonnelNumber { get; set; }
    }
    
    internal class ppsHrCertificateList
    {
        public long id { get; set; }

        public string certificateName { get; set; }

        public string certificateType { get; set; }
        public DateTime? getDate { get; set; }
        public DateTime? expirationDate { get; set; }
        public DateTime? certificateValidDate { get; set; }
        public string certificateNo { get; set; }

        public string mechanism { get; set; }
        public string remarks { get; set; }

        public ppsHrOtherEmp ppsHrOtherEmp { get; set; }

        public string bycstaffNo { get; set; }
    }
    internal class ppsHrTrainingList {

        public long id { get; set; }
        public string courseName { get; set; }
        public DateTime? tringDate { get; set; }

        public string bycstaffNo { get; set; }
    }

    [Serializable]
    internal class ResultData<T>:ResultData
    {
        public new T data { get; set; }

        public ResultData<T> SetResult(string code,T resultData,string message=null)
        {
            this.code = code;
            this.data = resultData;
            return this;
        }
    }
    [Serializable]
    internal class ResultData
    {
        public ResultData SetResult(string code,object data,string msg = null)
        {
            this.code = code;
            this.msg = msg;
            this.data = data;
            return this;
        }
        public string code { get; set; }

        public string msg { get; set; }

        public string token { get; set; }

        public object data { get; set; }
    }

    #endregion
}