//--------------------------------------------------------------------
//     此代码由T4模板自动生成  byzhouhang 20210918
//	   生成时间 2022-03-04 13:33:56 
//     对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using Medallion.Threading;
using Microsoft.AspNetCore.Mvc;
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Application.Contracts;
using MassTransit;
namespace IRaCIS.Core.Application.Service
{
    /// 
    /// 项目外部人员  录入流程相关
    /// 	
    [ApiExplorerSettings(GroupName = "Trial")]
    public class TrialExternalUserService(IRepository _trialExternalUseRepository,
        IRepository _userRoleRepository,
         IRepository _identityUserRepository,
        IRepository _trialUserRoleRepository,
         IRepository _trialIdentityUserRepository,
        IRepository _trialRepository,
        IRepository _userTypeRepository,
        IMailVerificationService _mailVerificationService,
        IDistributedLockProvider _distributedLockProvider, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ITrialExternalUserService
    {
        [HttpPost]
        public async Task> GetTrialExternalUserList(TrialExternalUserQuery queryTrialExternalUser)
        {
            var trialExternalUserQueryable = _trialExternalUseRepository.Where(t => t.TrialId == queryTrialExternalUser.TrialId)
                .WhereIf(!string.IsNullOrEmpty(queryTrialExternalUser.Phone), t => t.Phone.Contains(queryTrialExternalUser.Phone))
                .WhereIf(!string.IsNullOrEmpty(queryTrialExternalUser.Email), t => t.Email.Contains(queryTrialExternalUser.Email))
                .WhereIf(!string.IsNullOrEmpty(queryTrialExternalUser.Name), t => (t.LastName + " / " + t.FirstName).Contains(queryTrialExternalUser.Name))
            .ProjectTo(_mapper.ConfigurationProvider);
            return await trialExternalUserQueryable.ToListAsync();
        }
        /// 
        /// 添加和更新接口   已验证邮箱和账户类型不允许添加重复项
        /// 
        /// 
        /// 
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        [UnitOfWork]
        [TrialGlobalLimit("AfterStopCannNotOpt")]
        public async Task AddOrUpdateTrialExternalUser(TrialExternalUserAddAndSendEmail addOrEditTrialExternalUser)
        {
            if (addOrEditTrialExternalUser.Id == null)
            {
                var @lock = _distributedLockProvider.CreateLock($"UserCode");
                using (await @lock.AcquireAsync())
                {
                    var existSysUser = await _identityUserRepository.Where(t => t.EMail == addOrEditTrialExternalUser.Email, true).Include(t => t.UserRoleList).FirstOrDefaultAsync();
                    if (existSysUser != null)
                    {
                        if (existSysUser.LastName != addOrEditTrialExternalUser.LastName || existSysUser.FirstName != addOrEditTrialExternalUser.FirstName)
                        {
                            //$"该用户在系统中的用户名为:{existSysUser.LastName + " / " + existSysUser.FirstName} 电话:{existSysUser.Phone},与填写信息存在不一致项, 请将界面信息修改为与系统一致,再进行保存",
                            return ResponseOutput.NotOk(_localizer["TrialExternalUser_Inconsistency", existSysUser.LastName + " / " + existSysUser.FirstName, existSysUser.Phone], new { existSysUser.LastName, existSysUser.FirstName, existSysUser.Phone, existSysUser.OrganizationName, existSysUser.IsZhiZhun, existSysUser.IsTestUser }, ApiResponseCodeEnum.NeedTips);
                        }
                    }
                    //处理  生成账户
                    if (await _trialExternalUseRepository.AnyAsync(t =>
                            t.Email == addOrEditTrialExternalUser.Email &&
                            t.UserTypeId == addOrEditTrialExternalUser.UserTypeId && t.TrialId == addOrEditTrialExternalUser.TrialId))
                    {
                        //---系统已经存在与列表中填写的邮箱和用户类型相同的账户,请确认。
                        return ResponseOutput.NotOk(_localizer["TrialExternalUser_EmailTypeDuplicate"]);
                    }
                    var addEntity = _mapper.Map(addOrEditTrialExternalUser);
                    await _trialExternalUseRepository.AddAsync(addEntity);
                    if (existSysUser != null)
                    {
                        addEntity.IsSystemUser = true;
                        addEntity.SystemUserId = existSysUser.Id;
                    }
                    var trialType = await _trialRepository.Where(t => t.Id == addOrEditTrialExternalUser.TrialId).Select(t => t.TrialType).FirstOrDefaultAsync();
                    #region 验证用户 能否加入
                    if (trialType == TrialType.OfficialTrial || trialType == TrialType.Training)
                    {
                        if (existSysUser != null && existSysUser.IsTestUser)
                        {
                            //---正式类型 、培训类型的项目 不允许加入测试用户 
                            throw new BusinessValidationFailedException(_localizer["TrialExternalUser_TestUserNotAllowed"]);
                        }
                    }
                    if (trialType == TrialType.NoneOfficial)
                    {
                        if (existSysUser != null && existSysUser.IsTestUser == false)
                        {
                            //---测试项目  不允许加入正式用户 
                            throw new BusinessValidationFailedException(_localizer["TrialExternalUser_FormalUserNotAllowed"]);
                        }
                    }
                    #endregion
                    await _trialExternalUseRepository.SaveChangesAsync();
                    //添加的时候就发邮件  现在省略
                    if (addOrEditTrialExternalUser.IsSendEmail)
                    {
                        await SendExternalUserJoinEmail(new TrialExternalUserSendEmail()
                        {
                            BaseUrl = addOrEditTrialExternalUser.BaseUrl,
                            RouteUrl = addOrEditTrialExternalUser.RouteUrl,
                            TrialId = addOrEditTrialExternalUser.TrialId,
                            SendUsers = new List()
                        {
                            new UserEmail()
                            {
                                Id = addEntity.Id,
                                Email=addEntity.Email,
                                IsSystemUser=addEntity.IsSystemUser,
                                //SystemUserId=addEntity.SystemUserId,
                                UserTypeId=addOrEditTrialExternalUser.UserTypeId
                            }
                        }
                        });
                    }
                    return ResponseOutput.Ok(addEntity.Id.ToString());
                }
            }
            else
            {
                //---人员信息不支持编辑,请删除后重新添加。
                return ResponseOutput.NotOk(_localizer["TrialExternalUser_NotEditable"]);
            }
        }
        [HttpDelete("{trialExternalUserId:guid}/{isSystemUser:bool}/{systemUserId}")]
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        public async Task DeleteTrialExternalUser(Guid trialExternalUserId, bool isSystemUser, Guid systemUserId)
        {
            var trialExternalUser = await _trialExternalUseRepository.FirstOrDefaultAsync(t => t.Id == trialExternalUserId);
            if (await _trialIdentityUserRepository.AnyAsync(t => t.TrialId == trialExternalUser.TrialId && t.IdentityUserId == trialExternalUser.SystemUserId))
            {
                //---当前用户已参与到项目,不允许删除
                return ResponseOutput.NotOk(_localizer["TrialExternalUser_CannotDelete"]);
            }
            var success = await _trialExternalUseRepository.BatchDeleteNoTrackingAsync(t => t.Id == trialExternalUserId);
            return ResponseOutput.Result(success);
        }
        //New  省掉邀请流程
        [HttpPost]
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
        [TrialGlobalLimit("AfterStopCannNotOpt")]
        [UnitOfWork]
        public async Task SendExternalUserJoinEmail(TrialExternalUserSendEmail sendEmail)
        {
            var trialId = sendEmail.TrialId;
            var trialType = await _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialType).FirstOrDefaultAsync();
            foreach (var item in sendEmail.SendUsers.GroupBy(t => t.Email))
            {
                var userEmail = item.Key;
                var userTypeIdList = item.Select(t => t.UserTypeId).ToList();
                var itemFirst = item.FirstOrDefault();
                var externalIdList = item.Select(t => t.Id).ToList();
                //var identityUserId = item.Key;
                var existSysUser = await _identityUserRepository.Where(t => t.EMail == userEmail, true).Include(t => t.UserRoleList).FirstOrDefaultAsync();
                if (existSysUser != null)
                {
                    //账号状态设置为启用
                    existSysUser.Status = UserStateEnum.Enable;
                    foreach (var userTypeId in userTypeIdList)
                    {
                        var findRole = existSysUser.UserRoleList.FirstOrDefault(t => t.UserTypeId == userTypeId);
                        if (findRole != null)
                        {
                            //存在该角色,设置为启用
                            findRole.IsUserRoleDisabled = false;
                        }
                        else
                        {
                            //不存在该角色,那么就添加
                            var addRole = _mapper.Map(existSysUser);
                            addRole.UserTypeEnum = _userTypeRepository.Where(t => t.Id == userTypeId).Select(t => t.UserTypeEnum).First();
                            addRole.UserTypeId = userTypeId;
                            addRole.IsUserRoleDisabled = false;
                            existSysUser.UserRoleList.Add(addRole);
                        }
                    }
                    //防止已经生成账号的信息与外部人员信息不一致 在此默认批量更一下
                    await _trialExternalUseRepository.BatchUpdateNoTrackingAsync(t => externalIdList.Contains(t.Id), u => new TrialExternalUser()
                    {
                        FirstName = existSysUser.FirstName,
                        LastName = existSysUser.LastName,
                        Phone = existSysUser.Phone,
                        OrganizationName = existSysUser.OrganizationName
                    });
                }
                else
                {
                    //生成账户  并插入
                    var externalUser = await _trialExternalUseRepository.FirstOrDefaultAsync(t => t.Id == itemFirst.Id);
                    var generateUser = _mapper.Map(externalUser);
                    if (trialType == TrialType.NoneOfficial)
                    {
                        generateUser.IsTestUser = true;
                    }
                    // 外部人员生成账号 都是外部的
                    generateUser.IsZhiZhun = false;
                    generateUser.Code = _identityUserRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1;
                    generateUser.UserCode = AppSettings.GetCodeStr(generateUser.Code, nameof(IdentityUser));
                    //generateUser.UserName = generateUser.UserCode;
                    generateUser.Password = MD5Helper.Md5(IRCEmailPasswordHelper.GenerateRandomPassword(10));
                    generateUser.Status = UserStateEnum.Enable;
                    generateUser.UserRoleList = new List() { };
                    foreach (var userTypeId in userTypeIdList)
                    {
                        var addRole = _mapper.Map(generateUser);
                        addRole.Id = NewId.NextSequentialGuid();
                        addRole.UserTypeEnum = _userTypeRepository.Where(t => t.Id == userTypeId).Select(t => t.UserTypeEnum).First();
                        addRole.UserTypeId = userTypeId;
                        generateUser.UserRoleList.Add(addRole);
                    }
                    var newAddUser = await _identityUserRepository.AddAsync(generateUser);
                   
                    existSysUser = newAddUser;
                    await _trialExternalUseRepository.BatchUpdateNoTrackingAsync(t => externalIdList.Contains(t.Id), u => new TrialExternalUser()
                    {
                        IsSystemUser = false,
                        SystemUserId = newAddUser.Id,
                        FirstName = existSysUser.FirstName,
                        LastName = existSysUser.LastName,
                        OrganizationName = existSysUser.OrganizationName,
                        Phone = existSysUser.Phone,
                    });
                }
                await _identityUserRepository.SaveChangesAsync();
                var identityUserId = existSysUser.Id;
                var userTypeList = await _identityUserRepository.Where(t => t.Id == identityUserId).SelectMany(t => t.UserRoleList).Select(t => new { t.UserTypeId, t.UserTypeRole.UserTypeName, t.UserTypeRole.UserTypeShortName }).ToListAsync();
                var userHaveUserTypeIdList = userTypeList.Select(t => t.UserTypeId).ToList();
                if (userTypeIdList.Except(userHaveUserTypeIdList).Any())
                {
                    return ResponseOutput.NotOk("database dirty data ");
                }
                var findTrialUser = await _trialIdentityUserRepository.Where(t => t.TrialId == trialId && t.IdentityUserId == identityUserId, true, true).Include(t => t.TrialUserRoleList).ThenInclude(t => t.UserRole).FirstOrDefaultAsync();
                if (findTrialUser == null)
                {
                    //没有项目参与人员
                    findTrialUser = await _trialIdentityUserRepository.AddAsync(new TrialIdentityUser()
                    {
                        IdentityUserId = identityUserId,
                        TrialId = trialId,
                        JoinTime = DateTime.Now,
                        TrialUserRoleList = userTypeIdList.Select(u => new TrialUserRole()
                        {
                            TrialId = trialId,
                            UserId = existSysUser.UserRoleList.FirstOrDefault(t => t.UserTypeId == u).Id,
                        }).ToList()
                    });
                }
                else
                {
                    //有该人员
                    if (findTrialUser.IsDeleted == true)
                    {
                        findTrialUser.IsDeleted = false;
                        findTrialUser.DeletedTime = null;
                        findTrialUser.RemoveTime = null;
                        findTrialUser.JoinTime = DateTime.Now;
                    }
                    //是否有该角色
                    foreach (var userTypeId in userTypeIdList)
                    {
                        var findTrialUserRole = findTrialUser.TrialUserRoleList.Where(t => t.UserRole.UserTypeId == userTypeId).FirstOrDefault();
                        if (findTrialUserRole == null)
                        {
                            //添加该角色
                            findTrialUser.TrialUserRoleList.Add(new TrialUserRole() { TrialUserId = findTrialUser.Id, TrialId = trialId, UserId = existSysUser.UserRoleList.FirstOrDefault(t => t.UserTypeId == userTypeId).Id });
                        }
                        else
                        {
                            //如果禁用,那么启用
                            if (findTrialUserRole.IsDeleted == true)
                            {
                                findTrialUserRole.IsDeleted = false;
                                findTrialUserRole.DeletedTime = null;
                            }
                        }
                    }
                }
                await _trialIdentityUserRepository.SaveChangesAsync();
                var usertyps = string.Join(',', userTypeList.Where(t => userTypeIdList.Contains(t.UserTypeId)).Select(t => $"{t.UserTypeShortName} ({t.UserTypeName})"));
                await _mailVerificationService.ExternalUserJoinEmail(trialId, identityUserId, usertyps, sendEmail.BaseUrl, sendEmail.RouteUrl);
                await _trialExternalUseRepository.BatchUpdateNoTrackingAsync(t => externalIdList.Contains(t.Id), u => new TrialExternalUser() { IsJoin = true });
            }
            return ResponseOutput.Ok();
        }
    }
}