using DeviceRepair.Models;
using DeviceRepair.Models.History;
using DeviceRepair.Utils.Security;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;

namespace DeviceRepair.DataAccess
{
    public class UserAccess : DbContext<UserInfoModel>
    {
        private static UserAccess manager;
        public static UserAccess Instance
        {
            get
            {
                if (manager == null)
                    manager = new UserAccess();
                return manager;
            }
        }

        /// <summary>
        /// 获取所有用户
        /// </summary>
        /// <returns></returns>
        public APIResponseData GetAllUsers()
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "没有查询到数据！" };
            try
            {
                db.ChangeDatabase("main");

                var Datas = base.GetList();

                foreach (var item in Datas)
                {
                    item.PassWord = string.Empty;
                }

                apiResponseData.Code = 1;
                apiResponseData.Data = Datas;
                apiResponseData.Message = "";
            }
            catch (SqlSugarException ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 获取用户名称及用户编号映射
        /// </summary>
        /// <returns></returns>
        public APIResponseData GetUserMapping()
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "没有查询到数据！" };
            try
            {
                db.ChangeDatabase("main");

                Dictionary<int, string> Datas = base.GetList().ToDictionary(x => x.AutoID, x => x.RealName);

                apiResponseData.Code = 1;
                apiResponseData.Data = Datas;
                apiResponseData.Message = "";
            }
            catch (SqlSugarException ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 查询最后修改密码时间
        /// </summary>
        /// <param name="loginCode"></param>
        /// <returns></returns>
        public APIResponseData CheckChangePwdDate(string loginCode)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "查询出错！" };
            if (string.IsNullOrWhiteSpace(loginCode))
                return new APIResponseData { Code = -1, Message = "参数【用户编号】不能为空！" };

            try
            {
                DateTime CurrentTime = DateTime.Now;
                DateTime LastChangeDate = DateTime.Now;

                base.db.ChangeDatabase("log");
                DateTime l = db.Queryable<UserPassChangeLogInfo>().Where(x => x.LoginCode == loginCode).Max(x => x.OperationDate);

                // 没有修改密码的记录，第一次登录要求修改密码
                if (l == DateTime.MinValue)
                {
                    apiResponseData.Code = 1;
                    apiResponseData.Data = true;
                }
                else
                {
                    apiResponseData.Code = 1;
                    apiResponseData.Data = (l.AddMonths(3).Date <= DateTime.Today);
                }
            }
            catch (SqlSugarException e)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = e.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 判断用户名是否存在
        /// </summary>
        /// <param name="loginCode"></param>
        /// <returns></returns>
        public APIResponseData ExistLoginCode(string loginCode)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "未能获取到数据！" };
            if (string.IsNullOrWhiteSpace(loginCode))
                return new APIResponseData { Code = -1, Message = "参数【用户编号】不能为空！" };
            try
            {
                db.ChangeDatabase("main");
                bool ExistData = base.CurrentDb.AsQueryable().Any(x => x.LoginCode == loginCode);

                apiResponseData.Code = 1;
                apiResponseData.Data = ExistData;
            }
            catch (SqlSugarException e)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = e.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 根据账户密码验证获取实体
        /// </summary>
        /// <param name="loginCode"></param>
        /// <param name="passWord"></param>
        /// <returns></returns>
        public APIResponseData GetLoginEntity(string loginCode, string passWord, HeaderModel OperationInfo)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "账户或密码错误！" };

            if (string.IsNullOrWhiteSpace(loginCode))
                return new APIResponseData { Code = -1, Message = "参数【用户编号】不能为空！" };

            if (string.IsNullOrWhiteSpace(passWord))
                return new APIResponseData { Code = -1, Message = "参数【用户密码】不能为空！" };

            try
            {
                DateTime CurrentTime = DateTime.Now;

                // 获取用户对象
                base.db.ChangeDatabase("main");
                UserInfoModel entity = base.CurrentDb.AsQueryable().First(x => x.LoginCode == loginCode && x.PassWord == passWord);
                if (entity == null)
                {
                    // 登录失败，账户密码错误
                    db.ChangeDatabase("log");

                    UserPwdErrorLogInfo fLog = null;

                    if (db.Queryable<UserLogin>().Any(s => s.LoginCode == loginCode && s.OperationType == "登录"))
                    {
                        fLog = db.Queryable<UserPwdErrorLogInfo>()
                        .OrderBy(x => x.OperationDate, OrderByType.Desc).First(x => x.LoginCode == loginCode
                           && SqlFunc.Subqueryable<UserLogin>().Where(s => s.LoginCode == loginCode && s.OperationType == "登录")
                           .Max(s => s.OperationDate) < x.OperationDate);
                    }
                    else
                    {
                        fLog = db.Queryable<UserPwdErrorLogInfo>().Take(1).OrderBy(x => x.OperationDate, OrderByType.Desc).First(x => x.LoginCode == loginCode);
                    }

                    if (fLog != null)
                    {
                        // 找出最后一次登录成功之后的登录失败记录
                        int Count = 0;
                        if (int.TryParse(fLog.TryCount, out Count))
                        {
                            Count++;
                            fLog.TryCount = Count.ToString();
                            fLog.OperationDate = CurrentTime;
                        }
                        db.Updateable(fLog).ExecuteCommand();

                        if (Count > 3 && loginCode != "admin")
                        {
                            base.db.ChangeDatabase("main");

                            entity = base.CurrentDb.AsQueryable().First(x => x.LoginCode == loginCode);

                            if (entity != null)
                            {
                                entity.ModifyBy = 1;
                                entity.ModifyDate = CurrentTime;
                                entity.Status = false;
                                entity.Description = "登录失败3次，自动锁定！";

                                if (db.Updateable(entity).UpdateColumns(it => new { it.ModifyDate, it.ModifyBy, it.Status, it.Description })
                                    .Where(it => it.LoginCode == entity.LoginCode).ExecuteCommand() > 0)
                                {
                                    db.ChangeDatabase("log");
                                    UserLockLogInfo log2 = new UserLockLogInfo
                                    {
                                        UserAutoID = entity.AutoID,
                                        LockType = "锁定",
                                        LoginCode = entity.LoginCode,
                                        Description = entity.Description,
                                        OperationComputer = OperationInfo.ClientName,
                                        OperationUserName = entity.RealName,
                                        OperationDate = CurrentTime,
                                        OperationIP = OperationInfo.IPAddress,
                                        OperationType = "修改",
                                        OperationUser = entity.AutoID
                                    };

                                    db.Insertable(log2).ExecuteCommand();

                                    throw new Exception("登录失败3次，自动锁定！");
                                }
                            }
                        }
                    }
                    else
                    {
                        db.Insertable(new UserPwdErrorLogInfo
                        {
                            LoginCode = loginCode,
                            OperationComputer = OperationInfo.ClientName,
                            OperationDate = CurrentTime,
                            OperationIP = OperationInfo.IPAddress,
                            OperationUser = 0,
                            OperationUserName = "",
                            TryCount = "1"
                        }).ExecuteCommand();
                    }

                    return apiResponseData;
                }
                // 更新最后登录时间
                base.CurrentDb.AsUpdateable(entity).UpdateColumns("LastLoginTime").ReSetValue(x => x.LastLoginTime == SqlFunc.GetDate()).ExecuteCommand();

                entity.AuthItems = db.Queryable<RoleAuthModel, AuthModel>((t1, t2) => new object[] {
                      JoinType.Left,t1.AuthID == t2.AutoID
                }).Where((t1, t2) => t1.RoleID == entity.RoleGroup).Select((t1, t2) => t2).ToList();

                UserLogin log = new UserLogin
                {
                    LoginCode = entity.LoginCode,
                    OperationType = "登录",
                    OperationIP = OperationInfo.IPAddress,
                    OperationComputer = OperationInfo.ClientName
                };

                // 写入登录日志
                base.db.ChangeDatabase("log");
                base.db.Insertable(log).IgnoreColumns("OperationDate").ExecuteCommand();

                apiResponseData.Code = 1;
                apiResponseData.Data = entity;
            }
            catch (SqlSugarException e)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = e.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 用户登出，插入日志
        /// </summary>
        /// <param name="OperationInfo"></param>
        public void LogOut(HeaderModel OperationInfo)
        {
            try
            {
                base.db.ChangeDatabase("log");
                db.Insertable(new UserLogin
                {
                    LoginCode = OperationInfo.OperatorCode,
                    OperationType = "登出",
                    OperationIP = OperationInfo.IPAddress,
                    OperationComputer = OperationInfo.ClientName
                }).IgnoreColumns("OperationDate").ExecuteCommand();
            }
            catch
            {
            }
        }

        /// <summary>
        /// 验证账户及密码
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public APIResponseData ValidePassWord(string LoginCode, string PassWord)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "原密码输入不正确！" };
            try
            {
                if (string.IsNullOrWhiteSpace(LoginCode))
                    throw new Exception("用户名不能为空");

                if (string.IsNullOrWhiteSpace(PassWord))
                    throw new Exception("密码不能为空");

                base.db.ChangeDatabase("main");
                UserInfoModel um = db.Queryable<UserInfoModel>().Single(x => x.LoginCode == LoginCode
               && x.PassWord == PassWord);
                if (um != null)
                    apiResponseData.Code = 1;
            }
            catch (SqlSugarException e)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = e.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="LoginCode"></param>
        /// <param name="PassWord"></param>
        /// <returns></returns>
        public APIResponseData UpdateUserPassword(string LoginCode, string PassWord, HeaderModel Operation)
        {
            APIResponseData result = new APIResponseData { Code = -1, Message = "操作失败！" };
            try
            {
                base.db.ChangeDatabase("main");
                DateTime CurrentDate = DateTime.Now;

                UserInfoModel m = db.Queryable<UserInfoModel>().Single(x => x.LoginCode == LoginCode);
                if (m == null)
                    return new APIResponseData { Code = -1, Message = "账户不存在！" };

                if (m.PassWord.Equals(PassWord, StringComparison.CurrentCultureIgnoreCase))
                    return new APIResponseData { Code = -1, Message = "新密码不允许与旧密码相同！" };

                if (Operation.OperatorCode == LoginCode && PassWord.Equals(EncryptionHelper.EncryptByMD5("Kanghui1"), StringComparison.CurrentCultureIgnoreCase))
                    return new APIResponseData { Code = -1, Message = "新密码不允许为默认密码！" };

                base.db.ChangeDatabase("log");
                List<UserPassChangeLogInfo> logs = db.Queryable<UserPassChangeLogInfo>().Where(x => x.LoginCode == LoginCode).OrderBy(x => x.OperationDate, OrderByType.Desc).Take(2).ToList();
                if (logs.Any(x => x.PwdNew.Equals(PassWord, StringComparison.CurrentCultureIgnoreCase)))
                    return new APIResponseData { Code = -1, Message = "新密码不允许与最近3次的密码相同！" };

                base.db.ChangeDatabase("main");

                if (db.Updateable(m).UpdateColumns(it => new { it.PassWord, it.ModifyDate, it.ModifyBy })
                    .ReSetValue(it => it.PassWord == PassWord)
                    .ReSetValue(it => it.ModifyBy == Operation.Operator)
                    .ReSetValue(it => it.ModifyDate == CurrentDate).ExecuteCommand() > 0)
                {
                    base.db.ChangeDatabase("log");
                    UserPassChangeLogInfo log = new UserPassChangeLogInfo
                    {
                        LoginCode = m.LoginCode,
                        OperationComputer = Operation.ClientName,
                        OperationDate = CurrentDate,
                        OperationIP = Operation.IPAddress,
                        OperationType = "修改密码",
                        OperationUser = Operation.Operator,
                        OperationUserName = Operation.OperatorName,
                        PwdNew = PassWord,
                        PwdOld = m.PassWord,
                        UserAutoID = m.AutoID
                    };
                    db.Insertable(log).ExecuteCommand();

                    return new APIResponseData { Code = 1, Message = "操作成功！" };
                }
                return result;
            }
            catch (Exception e)
            {
                return new APIResponseData { Code = -1, Message = e.Message };
            }
        }


        /// <summary>
        /// 用户修改
        /// </summary>
        /// <param name="item"></param>
        /// <param name="Operation"></param>
        /// <returns></returns>
        public APIResponseData Update(UserInfoModel item, HeaderModel Operation)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = "没有查询到数据！" };
            try
            {
                db.ChangeDatabase("main");

                UserInfoModel Datas = db.Queryable<UserInfoModel>().First(x => x.AutoID == item.AutoID);
                if (Datas == null)
                {
                    throw new Exception($"找不到ID为{item.AutoID}的用户！");
                }

                DateTime CurrentDate = DateTime.Now;
                string OperationType = Datas.Status != item.Status ? (item.Status ? "解锁" : "锁定") : "修改";

                if (OperationType != "修改")
                {
                    Datas.Status = item.Status;
                }
                else
                {
                    Datas.ModifyBy = Operation.Operator;
                    Datas.ModifyDate = CurrentDate;
                    Datas.RoleGroup = item.RoleGroup;
                    Datas.Email = item.Email;
                    Datas.RealName = item.RealName;
                    Datas.Phone = item.Phone;
                    Datas.Description = item.Description;
                }


                if (db.Updateable(Datas).ExecuteCommand() > 0)
                {
                    apiResponseData.Code = 1;
                    apiResponseData.Data = Datas;
                    apiResponseData.Message = "";

                    db.ChangeDatabase("log");

                    if (OperationType != "修改")
                    {
                        UserLockLogInfo log2 = new UserLockLogInfo
                        {
                            UserAutoID = Datas.AutoID,
                            LockType = OperationType,
                            LoginCode = Datas.LoginCode,
                            Description = item.Description,
                            OperationComputer = Operation.ClientName,
                            OperationUserName = Datas.RealName,
                            OperationDate = CurrentDate,
                            OperationIP = Operation.IPAddress,
                            OperationType = "修改",
                            OperationUser = Operation.Operator
                        };

                        db.Insertable(log2).ExecuteCommand();
                    }
                    else
                    {
                        db.Insertable(new UserInfoChangeLogInfo
                        {
                            UserAutoID = Datas.AutoID,
                            LoginCode = Datas.LoginCode,
                            RealName = Datas.RealName,
                            Phone = Datas.Phone,
                            Email = Datas.Email,
                            Status = Datas.Status,
                            OperationContent = OperationType,
                            OperationType = OperationType,
                            Description = Datas.Description,
                            OperationComputer = Operation.ClientName,
                            OperationDate = CurrentDate,
                            OperationIP = Operation.IPAddress,
                            OperationUser = Operation.Operator,
                            OperationUserName = Operation.OperatorName
                        }).ExecuteCommand();
                    }
                }
            }
            catch (SqlSugarException ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }


        /// <summary>
        /// 根据主键编号是插入/更新
        /// </summary>
        /// <param name="Item"></param>
        /// <returns></returns>
        public APIResponseData InsertOrEdit(UserInfoModel Item, HeaderModel Operation)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1 };
            try
            {
                DateTime CurrentDate = DateTime.Now;
                UserInfoModel model = null;
                if (Item.AutoID == 0)
                {
                    if (db.Queryable<UserInfoModel>().Any(x => x.LoginCode == Item.LoginCode))
                    {
                        throw new Exception("用户账户已存在!");
                    }

                    Item.CreateDate = CurrentDate;
                    model = db.Saveable(Item).ExecuteReturnEntity();

                }
                else
                {
                    UserInfoModel ufm = db.Queryable<UserInfoModel>().Single(x => x.AutoID == Item.AutoID);

                    // 日志
                    UserInfoChangeLogInfo log = new UserInfoChangeLogInfo
                    {
                        Description = ufm.Description,
                        Email = ufm.Email,
                        LoginCode = ufm.LoginCode,
                        OperationComputer = Operation.ClientName,
                        OperationContent = "修改",
                        OperationDate = CurrentDate,
                        OperationIP = Operation.IPAddress,
                        OperationType = "修改",
                        OperationUser = Operation.Operator,
                        OperationUserName = Operation.OperatorName,
                        Phone = ufm.Phone,
                        RealName = ufm.RealName,
                        Status = ufm.Status,
                        UserAutoID = ufm.AutoID
                    };

                    UserRoleLogInfo log2 = null;
                    if (ufm.RoleGroup != Item.RoleGroup)
                    {
                        RoleModel r = db.Queryable<RoleModel>().First(x => x.AutoID == Item.RoleGroup);
                        if (r != null)
                            log2 = new UserRoleLogInfo
                            {
                                UserAutoID = ufm.AutoID,
                                RoleAutoID = ufm.RoleGroup,
                                RoleCode = r.RoleCode,
                                RoleName = r.RoleName,
                                UserCode = ufm.LoginCode,
                                UserName = ufm.RealName,
                                Description = ufm.Description,
                                OperationContent = "权限修改",
                                OperationUser = Operation.Operator,
                                OperationUserName = Operation.OperatorName,
                                OperationComputer = Operation.ClientName,
                                OperationIP = Operation.IPAddress,
                                OperationType = "权限修改",
                            };
                    }

                    ufm.RoleGroup = Item.RoleGroup;
                    ufm.RealName = Item.RealName;
                    ufm.Email = Item.Email;
                    ufm.Phone = Item.Phone;
                    ufm.Description = Item.Description;
                    ufm.ModifyBy = Item.ModifyBy;
                    ufm.ModifyDate = CurrentDate;
                    model = db.Saveable(ufm).ExecuteReturnEntity();

                    db.ChangeDatabase("log");
                    db.Insertable(log).ExecuteCommand();

                    if (log2 != null)
                        db.Insertable(log2).ExecuteCommand();
                }

                if (model != null)
                {
                    apiResponseData.Code = 1;
                    apiResponseData.Message = "操作成功！";
                }
            }
            catch (SqlSugarException ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            catch (Exception ex)
            {
                apiResponseData.Code = -1;
                apiResponseData.Message = ex.Message;
            }
            return apiResponseData;
        }
    }
}
