using LifePayment.Application.Contracts;
using LifePayment.Domain;
using LifePayment.Domain.Models;
using LifePayment.Domain.Shared;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using Z.EntityFramework.Plus;
using ZeroD.Util;
using static LifePayment.Domain.Shared.LifePaymentConstant;

namespace HumanResourcesServices.Application
{
    public class UserRoleService : ApplicationService, IUserRoleService
    {
        private readonly IRepository<User, Guid> _userRepository;
        private readonly IRepository<Role, Guid> _roleRepository;
        private readonly IRepository<LifePayChannles, Guid> _channleRepository;
        private readonly IRepository<UserRole, Guid> _userRoleRep;
        private readonly IRepository<UserChannle, Guid> _userChannleRep;
        private readonly IIdentityUserAppService _identityUserService;

        public UserRoleService(
               IRepository<User, Guid> userRepository,
               IRepository<Role, Guid> roleRepository,
               IRepository<LifePayChannles, Guid> channleRepository,
               IRepository<UserRole, Guid> userRoleRep,
               IRepository<UserChannle, Guid> userChannleRep,
               IIdentityUserAppService identityUserService)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _channleRepository = channleRepository;
            _userRoleRep = userRoleRep;
            _userChannleRep = userChannleRep;
            _identityUserService = identityUserService;
        }

        public async Task<PageOutput<UserDto>> GetBackClientUsers(GetBackClientUsersInput input)
        {
            var query = _userRepository.Where(s => s.ClientId == Constant.ClientType.Back).Include(i => i.UserRoles).Include(i => i.UserChannle).Select(u => new UserDto
            {
                Id = u.Id,
                UserName = u.UserName,
                Name = u.Name,
                PhoneNumber = u.PhoneNumber,
                IsLocked = u.IsLocked ?? default,
                Roles = from ur in u.UserRoles
                        from r in _roleRepository.Where(s => s.Id == ur.RoleId)
                        select new RoleDto
                        {
                            Id = r.Id,
                            Name = r.Name,
                        },
                Channles = from uc in u.UserChannle
                           from c in _channleRepository.Where(s => s.ChannlesNum == uc.ChannleId)
                        select new UserChannleDto
                        {
                            Id = c.Id,
                            ChannlesNum = c.ChannlesNum,
                            Name = c.ChannlesName,
                        },
                Remark = u.Remark,
                CompanyOrgId = u.CompanyOrgId,
                DepartmentOrgId = u.DepartmentOrgId
            });
            if (input.IsLocked.HasValue)
            {
                query = query.Where(s => s.IsLocked == input.IsLocked);
            }

            if (!input.QueryCondition.IsNullOrEmpty())
            {
                query = query.Where(s => s.UserName.Contains(input.QueryCondition) ||
                                         s.Name.Contains(input.QueryCondition));
            }

            var result = await query.GetPageResult(input.PageModel);
            return result;
        }

        public async Task<int> UpdateBackClientUser(UpdateBackClientUserInput input)
        {
            var entity = await _userRepository.FirstOrDefaultAsync(s => s.Id == input.Id && s.ClientId == Constant.ClientType.Back);
            if (entity == null)
            {
                throw new UserFriendlyException("未找到对应用户");
            }

            entity.Name = input.Name;
            entity.PhoneNumber = input.PhoneNumber;
            entity.UserName = input.UserName;
            entity.Remark = input.Remark;
            entity.DepartmentOrgId = input.DepartmentOrgId;
            entity.CompanyOrgId = input.CompanyOrgId;

            var userchannle = await _userChannleRep.Where(s => s.UserId == input.Id).DeleteAsync();
            List<UserChannle> userChannles = new List<UserChannle>();
            foreach (var item in input.ChannlesId)
            {
                var channleNum = item;
                if (IsGuid(channleNum))
                {
                    channleNum = await _channleRepository.Where(x => x.Id == Guid.Parse(item)).Select(s => s.ChannlesNum).FirstOrDefaultAsync();
                }

                userChannles.Add(new UserChannle()
                {
                    Id = Guid.NewGuid(),
                    ChannleId = channleNum,
                    UserId = entity.Id
                });
            }

            await _userChannleRep.InsertManyAsync(userChannles);

            return Constant.SUCCESS;
        }

        /// <summary>
        /// 重置密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task ResetPassword(ResetPasswordBaseInput input)
        {
            var user = await _userRepository.FirstOrDefaultAsync(x => x.Id == input.UserId);
            CheckExtensions.IfTrueThrowUserFriendlyException(user == null, CustomeErrorMessage.IsNoExistUser);
            CheckExtensions.IfTrueThrowUserFriendlyException(string.IsNullOrEmpty(input.Password), "请输入密码");
            var identiResetInput = new ResetPassWordInput
            {
                UserId = input.UserId,
                Name = user.Name,
                UserName = user.UserName,
                Password = input.Password,
                PhoneNumber = user.PhoneNumber
            };
            var result = await _identityUserService.ResetPassword(identiResetInput);
            CheckExtensions.IfTrueThrowUserFriendlyException(result != Constant.SUCCESS,
                                                             CustomeErrorMessage.ResetPasswordFail);
        }
        public async Task<int> DeleteBackClientUser(Guid id)
        {
            var entity = await _userRepository.FirstOrDefaultAsync(s => s.Id == id && s.ClientId == Constant.ClientType.Back);
            if (entity == null)
            {
                throw new UserFriendlyException("未找到对应用户");
            }

            entity.IsDeleted = true;
            return Constant.SUCCESS;
        }

        public async Task<Guid> CreateRole(CreateOrUpdateRoleInput input)
        {
            var entity = ObjectMapper.Map<CreateOrUpdateRoleInput, Role>(input);
            return await _roleRepository.InsertAndGetIdAsync(entity);
        }

        public async Task<PageOutput<RoleInfo>> GetRoles(GetRolesInput input)
        {
            var query = _roleRepository.Select(r => new RoleInfo
            {
                Id = r.Id,
                Name = r.Name,
                Sequence = r.Sequence,
                IsEnable = r.IsEnable,
                DepartmentId = r.DepartmentId,
                DataRange = r.DataRange,
                Remark = r.Remark,
            });
            if (!input.QueryCondition.IsNullOrEmpty())
            {
                query = query.Where(s => s.Name.Contains(input.QueryCondition));
            }

            var result = await query.GetPageResult(input.PageModel);
            var listrols = new List<UserRole>();
            if (result.Data.Any())
            {
                listrols = await (from ur in _userRoleRep.Where(r => result.Data.Select(d => d.Id).Contains(r.RoleId))
                                  join u in _userRepository.Where(r => !r.IsDeleted) on ur.UserId equals u.Id
                                  select ur).ToListAsync();
            }
            foreach (var item in result.Data)
            {
                item.UserCount = listrols.Where(r => r.RoleId == item.Id).Count();
            }
            return result;
        }

        public async Task<int> UpdateRole(CreateOrUpdateRoleInput input)
        {
            var entity = await _roleRepository.FirstOrDefaultAsync(s => s.Id == input.Id);
            if (entity == null)
            {
                throw new UserFriendlyException("未找到对应角色");
            }

            entity.Name = input.Name;
            entity.Sequence = input.Sequence;
            entity.DepartmentId = input.DepartmentId;
            entity.DataRange = input.DataRange;
            entity.Remark = input.Remark;
            return Constant.SUCCESS;
        }

        public async Task<int> RoleEnableOrForbid(Guid id, bool isEnable)
        {
            var entity = await _roleRepository.FirstOrDefaultAsync(s => s.Id == id);
            if (entity == null)
            {
                throw new UserFriendlyException("未找到对应角色");
            }

            entity.IsEnable = isEnable;
            return Constant.SUCCESS;
        }

        public async Task<int> DeleteRole(Guid id)
        {
            await _roleRepository.DeleteAsync(id);
            return Constant.SUCCESS;
        }

        private bool IsGuid(string input)
        {
            Guid guidOutput;
            return Guid.TryParse(input, out guidOutput);
        }
    }
}