using IRaCIS.Core.Domain.Share;
using MimeKit;
using IRaCIS.Core.Application.Helper;
using MailKit;
using Microsoft.AspNetCore.Hosting;
using IRaCIS.Core.Application.Auth;
using AutoMapper;
using IRaCIS.Application.Contracts;
using Nito.AsyncEx;
using Microsoft.Extensions.Options;

namespace IRaCIS.Application.Services
{
    public interface IMailVerificationService
    {

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

        Task SendEmailVerification(string emailAddress, int verificationCode);

        Task SiteSurveyRejectEmail(MimeMessage messageToSend);

        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);

     


    }

    public class MailVerificationService :  BaseService, IMailVerificationService
    {
        private readonly IRepository<VerificationCode> _verificationCodeRepository;

        private readonly IRepository<SystemBasicData> _systemBasicDatarepository;

        private readonly IWebHostEnvironment _hostEnvironment;
        private readonly IRepository<User> _userRepository;

        private readonly ITokenService _tokenService;

        private readonly IMapper _mapper;

        private readonly IRepository<Trial> _trialRepository;
        private readonly IRepository<UserType> _userTypeRepository;



        private readonly AsyncLock _mutex = new AsyncLock();

        private readonly SystemEmailSendConfig _systemEmailConfig;



        public MailVerificationService(IRepository<VerificationCode> verificationCodeRepository,
            IRepository<SystemBasicData> systemBasicDatarepository,
            IWebHostEnvironment hostEnvironment,
            IRepository<User> userRepository,
            ITokenService tokenService,
            IRepository<Trial> trialRepository,
             IRepository<UserType> userTypeRepository,
            IMapper mapper, IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig)
        {
            _systemEmailConfig = systemEmailConfig.CurrentValue;
            _verificationCodeRepository = verificationCodeRepository;
            _systemBasicDatarepository = systemBasicDatarepository;

            _hostEnvironment = hostEnvironment;

            _mapper = mapper;

            _tokenService = tokenService;
            _userRepository = userRepository;
            _trialRepository = trialRepository;

            _userTypeRepository = userTypeRepository;

        }

        //重置邮箱 
        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] 关于重置邮箱的提醒
            messageToSend.Subject = _localizer["Mail_EmailResetReminder"];

            var builder = new BodyBuilder();


            var pathToFile = _hostEnvironment.WebRootPath
                          + Path.DirectorySeparatorChar.ToString()
                          + "EmailTemplate"
                          + Path.DirectorySeparatorChar.ToString()
                          //+ "UserOptCommon.html";
            +(_userInfo.IsEn_Us ? "UserOptCommon_US.html" : "UserOptCommon.html");

            using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
            {
                var templateInfo = SourceReader.ReadToEnd();


                builder.HtmlBody = string.Format(templateInfo,

                  //---尊敬的
                  _localizer["Mail_Dear", userName],
                //---您正在进行邮箱重置操作
                    _localizer["Mail_ResettingEmail"],
                    verificationCode
                    );
            }


            messageToSend.Body = builder.ToMessageBody();



            EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
          {
              // args.Response 
              var code = verificationCode.ToString();
              _ = _verificationCodeRepository.AddAsync(new VerificationCode()
              {
                  CodeType = 0,
                  HasSend = true,
                  Code = code,
                  UserId = userId,
                  ExpirationTime = DateTime.Now.AddMinutes(3)
              }).Result;
              _ = _verificationCodeRepository.SaveChangesAsync().Result;

          };


            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));
            //主题
                //---[来自展影IRC] 关于重置密码的提醒
            messageToSend.Subject = _localizer["Mail_IRCResettingPassword "];



            var builder = new BodyBuilder();

            var pathToFile = _hostEnvironment.WebRootPath
                        + Path.DirectorySeparatorChar.ToString()
                        + "EmailTemplate"
                        + Path.DirectorySeparatorChar.ToString()
                         //+ "UserOptCommon.html";
                         + (_userInfo.IsEn_Us ? "UserOptCommon_US.html" : "UserOptCommon.html");

            using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
            {
                var templateInfo = SourceReader.ReadToEnd();


                builder.HtmlBody = string.Format(templateInfo,
                //---您正在进行邮箱重置密码操作
                   _localizer["Mail_ResettingPassword "],
                    verificationCode
                    );
            }



            messageToSend.Body = builder.ToMessageBody();


            EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
             {
                 var code = verificationCode.ToString();
                 _ = _verificationCodeRepository.AddAsync(new VerificationCode()
                 {
                     CodeType = Core.Domain.Share.VerifyType.Email,
                     HasSend = true,
                     Code = code,
                     UserId = Guid.Empty,//此时不知道用户
                     EmailOrPhone = emailAddress,
                     ExpirationTime = DateTime.Now.AddMinutes(3)
                 }).Result;
                 _ = _verificationCodeRepository.SaveChangesAsync().Result;
             };



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

        /// <summary>
        /// 发送验证码
        /// </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]的提醒
            messageToSend.Subject = _localizer["Mail_ImagingIRCReminder"];




            var builder = new BodyBuilder();

            var pathToFile = _hostEnvironment.WebRootPath
                      + Path.DirectorySeparatorChar.ToString()
                      + "EmailTemplate"
                      + Path.DirectorySeparatorChar.ToString()
                      + (_userInfo.IsEn_Us ? "UserOptCommon_US.html": "UserOptCommon.html" );

            using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
            {
                var templateInfo = SourceReader.ReadToEnd();


                builder.HtmlBody = string.Format(templateInfo,
                //---您正在参与展影医疗IRC项目
                   _localizer["Mail_IRCProject"],
                    verificationCode
                    );
            }

            messageToSend.Body = builder.ToMessageBody();



            EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
            {
                // args.Response 
                var code = verificationCode.ToString();
                _ = _verificationCodeRepository.AddAsync(new VerificationCode()
                {
                    CodeType = VerifyType.Email,
                    HasSend = true,
                    Code = code,
                    UserId = Guid.Empty,//此时不知道用户
                    EmailOrPhone = emailAddress,
                    ExpirationTime = DateTime.Now.AddMinutes(3)
                }).Result;
                _ = _verificationCodeRepository.SaveChangesAsync().Result;
            };



            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}] 关于中心调研的提醒";
            messageToSend.Subject = _localizer["Mail_ProjectParticipationReminder", researchProgramNo];




            var builder = new BodyBuilder();

            var pathToFile = _hostEnvironment.WebRootPath
                      + Path.DirectorySeparatorChar.ToString()
                      + "EmailTemplate"
                      + Path.DirectorySeparatorChar.ToString()
                       //+ "UserOptCommon.html";
                       + (_userInfo.IsEn_Us ? "UserOptCommon_US.html" : "UserOptCommon.html");

            using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
            {
                var templateInfo = SourceReader.ReadToEnd();


                builder.HtmlBody = string.Format(templateInfo,
                //---您正在参与展影医疗IRC项目中心调研工作
                   _localizer["Mail_CenterResearchReminder"],
                    verificationCode
                    );
            }

            messageToSend.Body = builder.ToMessageBody();



            EventHandler<MessageSentEventArgs> sucessHandle = (sender, args) =>
            {
                // args.Response 
                var code = verificationCode.ToString();
                _ = _verificationCodeRepository.AddAsync(new VerificationCode()
                {
                    CodeType = VerifyType.Email,
                    HasSend = true,
                    Code = code,
                    UserId = Guid.Empty,//此时不知道用户
                    EmailOrPhone = emailAddress,
                    ExpirationTime = DateTime.Now.AddMinutes(3)
                }).Result;
                _ = _verificationCodeRepository.SaveChangesAsync().Result;
            };



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


        }

        public async Task SiteSurveyRejectEmail(MimeMessage messageToSend)
        {
     
            //发件地址
            messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));



            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] 关于创建账户的提醒
            messageToSend.Subject = _localizer["Mail_AccountCreationReminder"];



            var builder = new BodyBuilder();

            var pathToFile = _hostEnvironment.WebRootPath
                        + Path.DirectorySeparatorChar.ToString()
                        + "EmailTemplate"
                        + Path.DirectorySeparatorChar.ToString()
                         //+ "AdminAddUser.html";
                         + (_userInfo.IsEn_Us ? "AdminAddUser_US.html" : "AdminAddUser.html");

            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)}";

            using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
            {
                var templateInfo = SourceReader.ReadToEnd();


                builder.HtmlBody = string.Format(templateInfo,
                   sysUserInfo.FullName,
                   sysUserInfo.UserName,
                   sysUserInfo.UserTypeRole.UserTypeShortName,
                    redirectUrl
                    );
            }



            messageToSend.Body = builder.ToMessageBody();


            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] 关于重置账户密码的提醒
            messageToSend.Subject = _localizer["Mail_AccountPasswordResetReminder"];



            var builder = new BodyBuilder();

            var pathToFile = _hostEnvironment.WebRootPath
                        + Path.DirectorySeparatorChar.ToString()
                        + "EmailTemplate"
                        + Path.DirectorySeparatorChar.ToString()
                         //+ "AdminResetUser.html";
                         + (_userInfo.IsEn_Us ? "AdminResetUser_US.html" : "AdminResetUser.html");


            using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
            {
                var templateInfo = SourceReader.ReadToEnd();


                builder.HtmlBody = string.Format(templateInfo,
                   sysUserInfo.FullName,
                   sysUserInfo.UserName,
                   sysUserInfo.UserTypeRole.UserTypeShortName,
                   pwdNotMd5
                    );
            }



            messageToSend.Body = builder.ToMessageBody();


            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}]邀请信";
            messageToSend.Subject = _localizer["Mail_InvitationEmail", trialInfo.ResearchProgramNo];



            var builder = new BodyBuilder();


            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 pathToFile = _hostEnvironment.WebRootPath
                     + Path.DirectorySeparatorChar.ToString()
                     + "EmailTemplate"
                     + Path.DirectorySeparatorChar.ToString()
                     + (sysUserInfo.IsFirstAdd ?  (_userInfo.IsEn_Us ? "TrialUserFirstJoin_US.html" : "TrialUserFirstJoin.html") : (_userInfo.IsEn_Us ? "TrialUserExistJoin_US.html" : "TrialUserExistJoin.html"));

            using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
            {
                var templateInfo = SourceReader.ReadToEnd();

                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)}";

                builder.HtmlBody = string.Format(templateInfo,
                    sysUserInfo.FullName,
                    trialInfo.ExperimentName,
                    trialInfo.ResearchProgramNo,
                    trialInfo.TrialCode,
                    sysUserInfo.UserName,
                    sysUserInfo.UserTypeRole.UserTypeShortName,
                    sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
                    );
            }

            messageToSend.Body = builder.ToMessageBody();

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


        }

        //外部用户 加入项目
        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}]邀请信";
            messageToSend.Subject = _localizer["Mail_InvitationEmail", trialInfo.ResearchProgramNo];


            var builder = new BodyBuilder();



            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 pathToFile = _hostEnvironment.WebRootPath
                        + Path.DirectorySeparatorChar.ToString()
                        + "EmailTemplate"
                        + Path.DirectorySeparatorChar.ToString()
                        + (sysUserInfo.IsFirstAdd ? (_userInfo.IsEn_Us ? "TrialUserFirstJoin_US.html" : "TrialUserFirstJoin.html")  : (_userInfo.IsEn_Us ? "TrialUserExistJoin_US.html" : "TrialUserExistJoin.html") );

            using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
            {
                var templateInfo = SourceReader.ReadToEnd();

                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)}";

                builder.HtmlBody = string.Format(templateInfo,
                    sysUserInfo.FullName,
                    trialInfo.ExperimentName,
                    trialInfo.ResearchProgramNo,
                    trialInfo.TrialCode,
                   sysUserInfo.UserName,
                    sysUserInfo.UserTypeRole.UserTypeShortName,
                   sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl
                    );
            }



            messageToSend.Body = builder.ToMessageBody();


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

        }





    }
}
