using AutoMapper;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Performance.Services
{
    public class UserService : IAutoInjection
    {
        private Application application;
        private PerforUserRepository _userRepository;
        private PerforSmsRepository _smsRepository;
        private PerforHospitalRepository _hospitalRepository;
        private PerforUserhospitalRepository _userhospitalRepository;
        private PerforRoleRepository _roleRepository;
        private PerforUserroleRepository _userroleRepository;
        private PerforImemployeeRepository _employeeRepository;
        private PerforPerallotRepository _perforPerallotRepository;
        private PerforImaccountbasicRepository _perforImaccountbasicRepository;
        public UserService(IOptions<Application> application,
            PerforSmsRepository smsRepository,
            PerforUserRepository userRepository,
            PerforHospitalRepository hospitalRepository,
            PerforUserhospitalRepository userhospitalRepository,
            PerforRoleRepository roleRepository,
            PerforUserroleRepository userroleRepository,
            PerforImemployeeRepository employeeRepository,
            PerforPerallotRepository perforPerallotRepository,
            PerforImaccountbasicRepository perforImaccountbasicRepository)
        {
            this.application = application.Value;
            this._userRepository = userRepository;
            this._smsRepository = smsRepository;
            this._hospitalRepository = hospitalRepository;
            this._userhospitalRepository = userhospitalRepository;
            this._roleRepository = roleRepository;
            this._userroleRepository = userroleRepository;
            this._employeeRepository = employeeRepository;
            this._perforPerallotRepository = perforPerallotRepository;
            this._perforImaccountbasicRepository = perforImaccountbasicRepository;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public UserIdentity Login(LoginRequest request)
        {
            //手机号登录
            if (request.LoginType == 1)
            {
                var sms = _smsRepository.GetEntity(t => t.Mobile == request.Account.Trim() && t.SmsCode == request.Password.Trim());
                if (sms == null)
                    throw new PerformanceException("验证码验证失败");
                var user = _userRepository.GetEntity(t => t.Mobile == request.Account && t.IsDelete == 1);
                if (user == null)
                    throw new PerformanceException("用户信息查询失败");

                var data = Mapper.Map<UserIdentity>(user);
                data.Token = Guid.NewGuid().ToString("N");
                return data;
            }
            //账号密码登录
            else if (request.LoginType == 2)
            {
                var user = _userRepository.GetEntity(t => t.Login == request.Account && t.IsDelete == 1);
                if (user == null)
                    throw new PerformanceException($"用户不存在 UserId:{request.Account}");
                if (!user.Password.Equals(request.Password, StringComparison.OrdinalIgnoreCase))
                    throw new PerformanceException($"密码错误");

                var data = Mapper.Map<UserIdentity>(user);
                data.Token = Guid.NewGuid().ToString("N");
                return data;
            }
            throw new PerformanceException($"登录类型LoginType：{request.LoginType}暂不支持");
        }

        public UserIdentity GetUser(int userId)
        {
            var user = _userRepository.GetEntity(t => t.ID == userId);
            if (user == null)
                throw new PerformanceException("用户信息查询失败");

            return Mapper.Map<UserIdentity>(user);
        }

        /// <summary>
        /// 查询用户列表
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        public List<UserResponse> GetUserList(int userID)
        {
            var userlist = _userRepository.GetEntities(t => t.CreateUser == userID && t.IsDelete == 1);
            var result = Mapper.Map<List<UserResponse>>(userlist);
            if (result != null && result.Count > 0)
            {
                foreach (var item in result)
                {
                    var hoslist = _userhospitalRepository.GetEntities(p => p.UserID == item.UserID);
                    if (hoslist != null && hoslist.Count() > 0)
                    {
                        item.Hospital = string.Join(",", hoslist.Select(p => p.HospitalID.Value));
                    }
                    var userRole = _userroleRepository.GetEntity(t => t.UserID == item.UserID);
                    if (userRole != null)
                        item.Role = userRole.RoleID;
                }
            }
            return result;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="iD"></param>
        /// <returns></returns>
        public ApiResponse Delete(int iD)
        {
            var user = _userRepository.GetEntity(t => t.ID == iD && t.IsDelete == 1);
            if (null == user)
                throw new PerformanceException($"用户不存在 UserId：{iD}");
            user.IsDelete = 2;
            var result = _userRepository.Remove(user);
            return result ? new ApiResponse(ResponseType.OK) : new ApiResponse(ResponseType.Fail);
        }

        /// <summary>
        /// 新增用户
        /// </summary>
        /// <param name="request"></param>
        public UserResponse Insert(UserRequest request, int userid)
        {
            var isAgainAdmin = new int[] { application.DirectorRole, application.NurseRole }.Contains(request.Role);
            if (null != _userRepository.GetEntity(t => t.Login == request.Login && t.IsDelete == 1))
                throw new PerformanceException("登录名重复");
            if (null != _userRepository.GetEntity(t => t.Mobile == request.Mobile && t.IsDelete == 1))
                throw new PerformanceException("手机号重复");
            if (request.Role == 3 && string.IsNullOrEmpty(request.Department))
                throw new PerformanceException("请选择科室");
            if (isAgainAdmin && request.HosIDArray.Length > 1)
                throw new PerformanceException("二次绩效管理员只支持单家医院");
            if (isAgainAdmin && string.IsNullOrEmpty(request.Department))
                throw new PerformanceException("二次绩效管理员科室不能为空");

            var user = Mapper.Map<sys_user>(request);
            user.CreateDate = DateTime.Now;
            user.CreateUser = userid;
            user.States = (int)States.Enabled;
            user.Department = request.Department;
            user.IsDelete = 1;

            if (!_userRepository.Add(user))
                throw new PerformanceException("保存失败");
            //添加用户角色关联关系
            _userroleRepository.Add(new sys_user_role { UserID = user.ID, RoleID = request.Role });
            //添加用户医院
            SetHospital(user.ID, request.HosIDArray);

            return Mapper.Map<UserResponse>(user);
        }

        /// <summary>
        /// 设置用户医院
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public bool SetHospital(int userId, int[] hosIDArray)
        {
            var user = _userRepository.GetEntity(t => t.ID == userId && t.IsDelete == 1);
            if (null == user)
                throw new PerformanceException($"用户不存在 UserId：{userId}");
            var userHospital = _userhospitalRepository.GetUserHospital(userId);

            bool rmResult = true, addResult = true;
            //获取需要删除的医院
            var rmHospital = userHospital.Where(t => !hosIDArray.Contains(t.HospitalID.Value));
            if (rmHospital != null && rmHospital.Count() > 0)
                rmResult = _userhospitalRepository.RemoveRange(rmHospital.ToArray());

            //获取需要新增的医院
            var addHospital = hosIDArray.Where(t => !userHospital.Select(u => u.HospitalID).Contains(t));
            if (addHospital != null && addHospital.Count() > 0)
            {
                var allHospital = _hospitalRepository.GetEntities();
                //获取有效医院ID
                var array = addHospital.Where(t => allHospital.Select(h => h.ID).Contains(t))
                    .Select(t => new sys_user_hospital { UserID = userId, HospitalID = t }).ToArray();
                addResult = _userhospitalRepository.AddRange(array);
            }

            return rmResult && addResult;
        }

        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public UserResponse Update(UserRequest request, bool isAgainAdmin)
        {
            var user = _userRepository.GetEntity(t => t.ID == request.ID && t.IsDelete == 1);
            if (null == user)
                throw new PerformanceException($"用户不存在 UserId：{request.ID}");

            var vlist = _userRepository.GetEntities(t => t.ID != user.ID && t.Login == request.Login && t.IsDelete == 1);
            if (null != vlist && vlist.Count() > 0)
                throw new PerformanceException("登录名重复");

            vlist = _userRepository.GetEntities(t => t.ID != user.ID && t.Mobile == request.Mobile && t.IsDelete == 1);
            if (null != vlist && vlist.Count() > 0)
                throw new PerformanceException("手机号重复");

            if (isAgainAdmin && string.IsNullOrEmpty(request.Department))
                throw new PerformanceException("二次绩效管理员科室不能为空");

            if (isAgainAdmin && request.HosIDArray.Length > 1)
                throw new PerformanceException("二次绩效管理员只支持单家医院");

            user.Login = request.Login;
            user.Mobile = request.Mobile;
            user.RealName = request.RealName;
            user.Mail = request.Mail;
            user.States = request.States;
            user.Password = string.IsNullOrEmpty(request.Password) ? user.Password : request.Password;
            user.Department = request.Department;

            if (!_userRepository.Update(user))
                throw new PerformanceException("保存失败");

            //删除用户角色关联关系
            var userRole = _userroleRepository.GetEntity(t => t.UserID == request.ID);
            if (null != userRole)
                _userroleRepository.Remove(userRole);
            //添加用户角色关联关系
            _userroleRepository.Add(new sys_user_role { UserID = request.ID, RoleID = request.Role });
            //添加用户医院
            SetHospital(user.ID, request.HosIDArray);

            return Mapper.Map<UserResponse>(user);
        }


        /// <summary>
        /// 修改个人信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public UserResponse UpdateSelf(UserRequest request)
        {
            var user = _userRepository.GetEntity(t => t.ID == request.ID && t.IsDelete == 1);
            if (null == user)
                throw new PerformanceException($"用户不存在 UserId：{request.ID}");

            var vlist = _userRepository.GetEntities(t => t.ID != user.ID && t.Login == request.Login && t.IsDelete == 1);
            if (null != vlist && vlist.Count() > 0)
                throw new PerformanceException("登录名重复");

            vlist = _userRepository.GetEntities(t => t.ID != user.ID && t.Mobile == request.Mobile && t.IsDelete == 1);
            if (null != vlist && vlist.Count() > 0)
                throw new PerformanceException("手机号重复");

            user.Mobile = string.IsNullOrEmpty(request.RealName) ? user.Mobile : request.Mobile;
            user.RealName = string.IsNullOrEmpty(request.RealName) ? user.RealName : request.RealName;
            user.Mail = string.IsNullOrEmpty(request.Mail) ? user.Mail : request.Mail;
            user.Password = string.IsNullOrEmpty(request.Password) ? user.Password : request.Password;

            if (!_userRepository.Update(user))
                throw new PerformanceException("保存失败");
            return Mapper.Map<UserResponse>(user);
        }

        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <param name="request"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public UserResponse UpdatePwd(PasswordRequest request, int userId)
        {
            var user = _userRepository.GetEntity(t => t.ID == userId && t.IsDelete == 1);
            if (null == user)
                throw new PerformanceException($"用户不存在 UserId：{userId}");

            if (request.OldPwd != user.Password)
                throw new PerformanceException("原密码错误");

            user.Password = string.IsNullOrEmpty(request.NewPwd) ? user.Password : request.NewPwd;

            if (!_userRepository.Update(user))
                throw new PerformanceException("保存失败");
            return Mapper.Map<UserResponse>(user);
        }

        /// <summary>
        /// 角色列表
        /// </summary>
        /// <returns></returns>
        public List<sys_role> RoleList(int userId)
        {
            var user = _userroleRepository.GetEntity(t => t.UserID == userId);
            if (user == null)
                throw new PerformanceException("登录用户不存在！");

            var roles = _roleRepository.GetEntities(t => t.States == 1);
            var role = roles.FirstOrDefault(s => s.ID == user.RoleID);
            if (user == null)
                throw new PerformanceException("当前用户角色无效！");
            List<sys_role> result = new List<sys_role>() { role };
            GetChildrenRole(roles, role.ID, result);

            return result?.Distinct().ToList();
        }

        /// <summary>
        /// 科室列表
        /// </summary>
        /// <returns></returns>
        public List<TitleValue> Department(int hospitalID)
        {
            var allotList = _perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalID);
            var result = new List<string>();
            if (allotList != null)
            {
                var idList = allotList.Select(s => s.ID).ToList();
                //var department = _employeeRepository.GetEntities(t => t.Department != "" && idList.Contains(t.AllotID.Value)).Select(t => t.Department);
                //if (department != null && department.Count() > 0)
                //    result.AddRange(department);

                var department = _perforImaccountbasicRepository.GetEntities(t => !string.IsNullOrEmpty(t.DoctorAccountingUnit) && idList.Contains(t.AllotID.Value)).Select(t => t.DoctorAccountingUnit);
                if (department != null && department.Count() > 0)
                    result.AddRange(department);
                if (result != null && result.Any())
                {
                    result = result.Distinct().OrderBy(t => t).ToList();
                }
            }
            return result?.Select(t => new TitleValue { Title = t, Value = t }).ToList();
        }



        /// <summary>
        /// 递归获取所有下属角色
        /// </summary>
        /// <param name="roles"></param>
        /// <param name="roleId"></param>
        /// <param name="result"></param>
        private void GetChildrenRole(List<sys_role> roles, int roleId, List<sys_role> result)
        {
            foreach (var role in roles.Where(s => !string.IsNullOrEmpty(s.ParentRoles)))
            {
                if (role.ParentRoles.SplitRemoveEmpty(",").Contains(roleId.ToString()))
                {
                    result.Add(role);
                    GetChildrenRole(roles, role.ID, result);
                }
            }
        }
    }
}
