using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using MailKit;
using Medallion.Threading;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Options;
using MimeKit;

namespace IRaCIS.Core.Application.Service
{
    public interface IMailVerificationService
    {

        Task AnolymousSendEmail(string researchProgramNo, string emailAddress, int verificationCode);

        Task SendEmailVerification(string emailAddress, int verificationCode);

        Task SiteSurveyRejectEmail(MimeMessage messageToSend, TrialSiteSurvey trialSiteSurvey, string routeUrl, User? user = null);

        Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode, UserMFAType mfaType = UserMFAType.Login);

        Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode);

        Task AnolymousSendEmailForResetAccount(string emailAddress, int verificationCode);

        Task AddUserSendEmailAsync(Guid userId, string baseUrl, string routeUrl);

        Task AdminResetPwdSendEmailAsync(Guid userId, string pwdNotMd5 = "123456");

        Task SiteSurveyUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl);

        Task ExternalUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl);

        Task<Guid> DoctorJoinTrialEmail(Guid trialId, Guid doctorId, string baseUrl, string rootUrl);

        Task UserFeedBackMail(Guid feedBackId);
    }

    public class MailVerificationService(IRepository<VerificationCode> _verificationCodeRepository,
      IRepository<SystemBasicData> _systemBasicDatarepository,
      IRepository<VisitTask> _visitTaskRepository,
      IRepository<TrialSite> _trialSiteRepository,
      IRepository<User> _userRepository,
      IRepository<UserFeedBack> _userFeedBackRepository,
      ITokenService _tokenService,
      IRepository<SubjectVisit> _subjectVisitRepository,
      IRepository<Trial> _trialRepository,
      IRepository<UserType> _userTypeRepository,
      IRepository<Doctor> _doctorTypeRepository,
      IRepository<Dictionary> _dictionaryRepository,
      IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
      IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
      IDistributedLockProvider _distributedLockProvider, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IMailVerificationService
    {
        private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;


        private async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario scenario, MimeMessage messageToSend,
            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc)
        {
            var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).FirstOrDefaultAsync();

            if (configInfo == null)
            {
                throw new BusinessValidationFailedException("系统未找到当前场景邮件配置信息，请联系运维人员核查");
            }


            var (topicStr, htmlBodyStr) = _userInfo.IsEn_Us ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);

            try
            {
                //每个场景修改主题 和body的逻辑不一样
                (topicStr, htmlBodyStr) = emailFunc((topicStr, htmlBodyStr));
            }
            catch (Exception ex)
            {

                throw new BusinessValidationFailedException("邮件模板内容有误，填充内容出现问题，请联系运维人员核查");
            }


            messageToSend.Subject = topicStr;

            var builder = new BodyBuilder();

            builder.HtmlBody = htmlBodyStr;

            messageToSend.Body = builder.ToMessageBody();

            return configInfo;
        }

        public async Task<EmailNoticeConfig> GetEmailConfigInfoAsync(EmailBusinessScenario scenario)
        {
            var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).Include(t => t.EmailNoticeUserTypeList).FirstOrDefaultAsync();

            if (configInfo == null)
            {
                throw new BusinessValidationFailedException("系统未找到当前场景邮件配置信息，请联系运维人员核查");
            }

            return configInfo;
        }


        private EventHandler<MessageSentEventArgs> GetEmailSuccessHandle(Guid userId, int verificationCode, string email = "")
        {
            EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
            {
                // args.Response 
                var code = verificationCode.ToString();
                _ = _verificationCodeRepository.AddAsync(new VerificationCode()
                {
                    CodeType = VerifyType.Email,
                    HasSend = true,
                    Code = code,
                    UserId = userId,
                    EmailOrPhone = email,
                    ExpirationTime = DateTime.Now.AddMinutes(3)
                }).Result;
                _ = _verificationCodeRepository.SaveChangesAsync().Result;

            };

            return sucessHandle;
        }

        private string ReplaceCompanyName(string needDealtxt)
        {
            var str = needDealtxt.Replace("{company}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN)
                .Replace("{company abbreviation}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN);
            return str;
        }

        //MFA 
        public async Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode, UserMFAType mfaType = UserMFAType.Login)
        {
            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
            //收件地址
            messageToSend.To.Add(new MailboxAddress(userName, emailAddress));
            //主题---[来自{0}] 关于MFA邮箱验证的提醒

            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
                    userName,
                    verificationCode
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(mfaType == UserMFAType.Login ? EmailBusinessScenario.MFALogin : EmailBusinessScenario.MFAUnlock, messageToSend, emailConfigFunc);


            var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress);


            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
        }

        //用户重置邮箱 
        public async Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode)
        {

            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
            //收件地址
            messageToSend.To.Add(new MailboxAddress(userName, emailAddress));
            //主题
            //---[来自展影IRC] 关于重置邮箱的提醒

            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),

                    userName,
                    //---您正在进行邮箱重置操作
                    verificationCode
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UserResetEmail, messageToSend, emailConfigFunc);


            var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress);

            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);


        }



        //不登录  通过邮箱重置密码
        public async Task AnolymousSendEmailForResetAccount(string emailAddress, int verificationCode)
        {
            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
            //收件地址
            messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));


            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),

                       "Sir/Madam",
                //---您正在进行邮箱重置密码操作
                    verificationCode
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UnloginUseEmailResetPassword, messageToSend, emailConfigFunc);

            ////此时不知道用户
            var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);


            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);
        }

        /// <summary>
        /// Reviewer简历录入 发送验证码
        /// </summary>
        /// <param name="emailAddress"></param>
        /// <param name="verificationCode"></param>
        /// <returns></returns>
        public async Task SendEmailVerification(string emailAddress, int verificationCode)
        {

            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
            //收件地址
            messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
            //主题
            //---[来自展影IRC]的提醒

            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),

                   "Sir/Madam",
                //---您正在参与展影医疗IRC项目
                    companyName,
                    verificationCode
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.ReviewerLogin, messageToSend, emailConfigFunc);

            //此时不知道用户
            var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);


            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);


        }


        //中心调研 登陆
        public async Task AnolymousSendEmail(string researchProgramNo, string emailAddress, int verificationCode)
        {

            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
            //收件地址
            messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
            //主题
            //$"[来自展影IRC] [{researchProgramNo}] 关于中心调研的提醒";

            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName, researchProgramNo);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),

                    "Sir/Madam",
                //---您正在参与展影医疗IRC项目中心调研工作
                companyName,
                    verificationCode
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurveyLogin, messageToSend, emailConfigFunc);

            //此时不知道用户
            var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);


            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle);

        }

        public async Task SiteSurveyRejectEmail(MimeMessage messageToSend, TrialSiteSurvey trialSiteSurvey, string routeUrl, User? user)
        {

            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));


            var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialSiteSurvey.TrialId);

            var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialSiteSurvey.TrialId && t.Id == trialSiteSurvey.TrialSiteId, true);


            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;


            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),

              (user == null ? trialSiteSurvey.UserName : user.LastName + "/ " + user.FirstName),
                     trialInfo.TrialCode,
                     trialInfo.ResearchProgramNo,
                    trialInfo.ExperimentName,
                siteInfo.TrialSiteCode,
                siteInfo.TrialSiteAliasName,
                   trialSiteSurvey.LatestBackReason,
                routeUrl,
                   (trialSiteSurvey.State == TrialSiteSurveyEnum.ToSubmit ? "inline - block" : "none")
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurveyReject, messageToSend, emailConfigFunc);



            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);

        }

        //添加用户发送邮件
        public async Task AddUserSendEmailAsync(Guid userId, string baseUrl, string routeUrl)
        {

            var sysUserInfo = (await _userRepository.Where(t => t.Id == userId).Include(t => t.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();


            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
            //收件地址
            messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail));
            //主题
            //---[来自展影IRC] 关于创建账户的提醒


            var token = _tokenService.GetToken(IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo)));

            await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });

            routeUrl = routeUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;

            var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));

            var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";


            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),

                  sysUserInfo.FullName,
                   sysUserInfo.UserName,
                   sysUserInfo.UserTypeRole.UserTypeShortName,
                    redirectUrl
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysCreateUser, messageToSend, emailConfigFunc);


            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
        }

        //管理员重置密码发送邮件
        public async Task AdminResetPwdSendEmailAsync(Guid userId, string pwdNotMd5 = "123456")
        {
            var sysUserInfo = (await _userRepository.Where(t => t.Id == userId).Include(t => t.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();

            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
            //收件地址
            messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail));
            //主题
            //---[来自展影IRC] 关于重置账户密码的提醒

            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),

                    sysUserInfo.FullName,
                   sysUserInfo.UserName,
                   sysUserInfo.UserTypeRole.UserTypeShortName,
                   pwdNotMd5
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysResetPassword, messageToSend, emailConfigFunc);

            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
        }


        //Site调研 用户加入项目
        public async Task SiteSurveyUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl)
        {
            var sysUserInfo = (await _userRepository.Where(t => t.Id == userId).Include(t => t.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();

            var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);

            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
            //收件地址
            messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail));
            //主题
            // $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";


            var token = _tokenService.GetToken(IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo)));

            if (sysUserInfo.IsFirstAdd)
            {
                await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
            }

            var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;

            var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));

            var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";


            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),

                    sysUserInfo.FullName,
                    trialInfo.ExperimentName,
                    trialInfo.ResearchProgramNo,
                    trialInfo.TrialCode,
                    sysUserInfo.UserName,
                    sysUserInfo.UserTypeRole.UserTypeShortName,
                    sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc);


            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);


        }

        //外部用户 加入项目
        public async Task ExternalUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl)
        {
            var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId)).IfNullThrowException();

            var sysUserInfo = (await _userRepository.Where(t => t.Id == userId).Include(t => t.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();


            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
            //收件地址
            messageToSend.To.Add(new MailboxAddress(String.Empty, sysUserInfo.EMail));
            //主题
            // $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";



            var token = _tokenService.GetToken(IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo)));
            if (sysUserInfo.IsFirstAdd)
            {
                await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
            }

            var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));

            var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;

            var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";


            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),

                    sysUserInfo.FullName,
                    trialInfo.ExperimentName,
                    trialInfo.ResearchProgramNo,
                    trialInfo.TrialCode,
                   sysUserInfo.UserName,
                    sysUserInfo.UserTypeRole.UserTypeShortName,
                   sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc);


            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, null);

        }


        //医生生成账号加入  或者已存在账号加入到项目中
        public async Task<Guid> DoctorJoinTrialEmail(Guid trialId, Guid doctorId, string baseUrl, string rootUrl)
        {
            var doctor = await _doctorTypeRepository.FindAsync(doctorId);
            User sysUserInfo = new User();

            var userType = await _userTypeRepository.FirstAsync(t => t.UserTypeEnum == UserTypeEnum.IndependentReviewer);

            var @lock = _distributedLockProvider.CreateLock($"UserCode");

            using (await @lock.AcquireAsync())
            {
                var isDoctorHaveAccount = await _userRepository.AnyAsync(t => t.DoctorId == doctorId);


                if (!isDoctorHaveAccount)
                {

                    var saveItem = new User() { FirstName = doctor.FirstName, LastName = doctor.LastName, EMail = doctor.EMail };

                    var trialType = await _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialType).FirstOrDefaultAsync();

                    if (trialType == TrialType.NoneOfficial)
                    {
                        saveItem.IsTestUser = true;
                    }


                    saveItem.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1;

                    saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User));

                    saveItem.UserName = saveItem.UserCode;

                    saveItem.UserTypeEnum = UserTypeEnum.IndependentReviewer;

                    saveItem.DoctorId = doctorId;
                    saveItem.UserTypeId = userType.Id;

                    var savedUser = await _userRepository.AddAsync(saveItem);

                    //下面获取Token 需要这部分信息
                    sysUserInfo = savedUser.Clone();

                    sysUserInfo.UserTypeRole = userType;

                    await _userRepository.SaveChangesAsync();

                }
                else
                {
                    sysUserInfo = (await _userRepository.Where(t => t.DoctorId == doctorId).Include(t => t.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();
                }
            }


            var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);

            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
            //收件地址
            messageToSend.To.Add(new MailboxAddress(doctor.FullName, doctor.EMail));



            var basicInfo = IRaCISClaims.Create(_mapper.Map<UserBasicInfo>(sysUserInfo));

            ////第一次添加的时候  注意赋值
            //basicInfo.PermissionStr = userType.PermissionStr;
            //basicInfo.UserTypeShortName = userType.UserTypeShortName;

            var token = _tokenService.GetToken(basicInfo);

            if (sysUserInfo.IsFirstAdd)
            {
                await _userRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new User() { EmailToken = token });
            }

            var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + userType.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;

            var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));

            var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";

            //主题
            // $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";


            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
            {
                var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);

                var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),

                   sysUserInfo.FullName,
                    trialInfo.ExperimentName,
                    trialInfo.ResearchProgramNo,
                    trialInfo.TrialCode,
                    sysUserInfo.UserName,
                    userType.UserTypeShortName,
                    sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
                    );

                return (topicStr, htmlBodyStr);
            };


            await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.DoctorUserFirstJoinTrial : EmailBusinessScenario.DoctorUserExistJoinTrial, messageToSend, emailConfigFunc);


            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, null);

            return sysUserInfo.Id;
        }


        //用户反馈邮件

        public async Task UserFeedBackMail(Guid feedBackId)
        {
            var feedBack = await _userFeedBackRepository.Where(t => t.Id == feedBackId).Include(t => t.CreateUser).ThenInclude(t => t.UserTypeRole).FirstNotNullAsync();

            var messageToSend = new MimeMessage();
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));

            var isHaveTrialId = feedBack.TrialId != null;

            var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

            var emialScenario = feedBack.VisitTaskId != null ? EmailBusinessScenario.IRImageError : (feedBack.SubjectVisitId != null ? EmailBusinessScenario.TrialSubjectVisitFeedBack : (feedBack.TrialId != null ? EmailBusinessScenario.TrialFeedBack : EmailBusinessScenario.SysFeedBack));

            var emailConfigInfo = await GetEmailConfigInfoAsync(emialScenario);

            var userTypeEnumList = emailConfigInfo.EmailNoticeUserTypeList.Where(t => t.EmailUserType == EmailUserType.To).Select(t => t.UserType).ToList();

            var emailList = await _userRepository.Where(t => userTypeEnumList.Contains(t.UserTypeEnum) &&
             (isHaveTrialId ? t.UserTrials.Any(t => t.TrialId == feedBack.TrialId) : true)).Select(t => new { t.EMail, t.UserTypeEnum, t.FullName }).ToListAsync();


            foreach (var email in emailList)
            {
                messageToSend.To.Add(new MailboxAddress(email.FullName, email.EMail));
            }

            var userNames = string.Join(',', emailList.Select(t => t.FullName));

            //影像阅片反馈 pm
            if (feedBack.VisitTaskId != null)
            {

                var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.IRImageError).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();


                var info = await _visitTaskRepository.Where(t => t.Id == feedBack.VisitTaskId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.SourceSubjectVisit.VisitName }).FirstNotNullAsync();

                Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
                {
                    var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName);

                    var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
                         userNames,
                        info.TrialCode,
                        info.SubejctCode,
                        info.VisitName,
                        feedBack.CreateUser.UserTypeRole.UserTypeShortName,
                         feedBack.CreateUser.FullName,
                         emailType,
                         feedBack.QuestionDescription,
                         _systemEmailConfig.SiteUrl
                        );

                    return (topicStr, htmlBodyStr);
                };


                await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IRImageError, messageToSend, emailConfigFunc);

            }
            else if (feedBack.SubjectVisitId != null)
            {
                var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialSubjectVisitFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();


                var info = await _subjectVisitRepository.Where(t => t.Id == feedBack.SubjectVisitId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.VisitName }).FirstNotNullAsync();

                Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
                {
                    var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName);

                    var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
                         userNames,
                        info.TrialCode,
                        info.SubejctCode,
                        info.VisitName,
                        feedBack.CreateUser.UserTypeRole.UserTypeShortName,
                         feedBack.CreateUser.FullName,
                         emailType,
                         feedBack.QuestionDescription,
                         _systemEmailConfig.SiteUrl
                        );

                    return (topicStr, htmlBodyStr);
                };


                await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialSubjectVisitFeedBack, messageToSend, emailConfigFunc);
            }
            //项目相关的反馈  pm  admin
            else if (feedBack.TrialId != null)
            {

                var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();


                var info = await _trialRepository.Where(t => t.Id == feedBack.TrialId).Select(t => new { t.ResearchProgramNo, t.TrialCode }).FirstNotNullAsync();

                Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
                {
                    var topicStr = string.Format(input.topicStr, info.ResearchProgramNo);

                    var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
                       userNames,
                        info.TrialCode,
                        feedBack.CreateUser.UserTypeRole.UserTypeShortName,
                        feedBack.CreateUser.FullName,
                         emailType,
                         feedBack.QuestionDescription,
                         _systemEmailConfig.SiteUrl
                        );

                    return (topicStr, htmlBodyStr);
                };


                await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialFeedBack, messageToSend, emailConfigFunc);

            }
            //项目无关的反馈  admin  
            else
            {


                Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
                {
                    var topicStr = string.Format(input.topicStr);

                    var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
                        userNames,
                        feedBack.CreateUser.UserTypeRole.UserTypeShortName,
                         feedBack.CreateUser.FullName,
                         feedBack.QuestionDescription,
                         _systemEmailConfig.SiteUrl
                        );

                    return (topicStr, htmlBodyStr);
                };


                await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysFeedBack, messageToSend, emailConfigFunc);
            }

            await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);

        }
    }
}
