using DocumentFormat.OpenXml;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.MassTransit.Consumer;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using MassTransit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MimeKit;
using System.Globalization;
using System.Linq.Dynamic.Core;

namespace IRaCIS.Core.Application.MassTransit.Recurring
{

    /// <summary>
    /// 定时过期提醒
    /// </summary>
    public class TrialDocumentErverDayEventConsumer(
        IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
        IRepository<VisitTask> _visitTaskRepository,
           IRepository<SystemDocument> _systemDocumentRepository,
             IRepository<IdentityUser> _identityUserRepository,
                   IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository,
         IRepository<Dictionary> _dictionaryRepository,
        IRepository<TrialUserRole> _trialUserRoleRepository, IRepository<TrialDocument> _trialDocumentRepository,
        IRepository<Trial> _trialRepository,
        ISystemDocumentService _systemDocumentService,
        IRepository<SystemDocNeedConfirmedUserType> _systemDocNeedConfirmedUserTypeRepository,
         IRepository<TrialDocNeedConfirmedUserType> _trialDocNeedConfirmedUserTypeRepository,
           IServiceScopeFactory serviceScopeFactory,
        IRepository<TrialIdentityUser> _trialIdentityUserRepository,
        IRepository<TrialDocConfirmedIdentityUser> _trialDocConfirmedUserRepository,
        IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
        IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,

        IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<TrialDocumentErverDayEvent>
    {
        private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;

        public async Task Consume(ConsumeContext<TrialDocumentErverDayEvent> context)
        {

            DateTime now = DateTime.Now;
            Console.WriteLine("发送定时项目过期提醒");
            var isEn_US = context.Message.CultureInfoName == StaticData.CultureInfo.en_US;
            //设置当前事件传递过来的语言
            var culture = context.Message.CultureInfoName;
            CultureInfo.CurrentCulture = new CultureInfo(culture);

            var trialDocQuery =
             from trialDoc in _trialDocumentRepository.AsQueryable(true)
             join trial in _trialRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trial.Id
             join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId
             join trialUserRole in _trialUserRoleRepository.Where(x => x.IsDeleted == false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
             join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
               on trialIdentityUser.IdentityUserId equals identityUser.Id
          

             join confirm in _trialDocConfirmedUserRepository.Where() on
             new { trialIdentityUser.IdentityUserId, TrialDocumentId = trialDoc.Id } equals new { IdentityUserId = confirm.ConfirmUserId, confirm.TrialDocumentId } into cc

             from confirm in cc.DefaultIfEmpty()
             where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted && trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
             select new TriaAndSystemlSignDocView()
            {

                TrialCode = trialDoc.Trial.TrialCode,
                ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
                ExperimentName = trialDoc.Trial.ExperimentName,
                CurrentStaffTrainDays = trialDoc.CurrentStaffTrainDays,
                NewStaffTrainDays = trialDoc.NewStaffTrainDays,
                Id = trialDoc.Id,
                TrialType=  trial.TrialType,
                 IsTestUser= identityUser.IsTestUser,
                TrialId = trialDoc.TrialId,
                IsSystemDoc = false,
                CreateTime = trialDoc.CreateTime,
                FullFilePath = trialDoc.Path,
                IsDeleted = trialDoc.IsDeleted,
                Name = trialDoc.Name,
                Path = trialDoc.Path,
                FileTypeId = trialDoc.FileTypeId,
                UpdateTime = trialDoc.UpdateTime,
                SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
                //IsConfirmed = confirm.ConfirmTime != null,
                ConfirmUserId = identityUser.Id,
                ConfirmTime = confirm.ConfirmTime,
                RealName = trialIdentityUser.IdentityUser.FullName,
                UserName = trialIdentityUser.IdentityUser.UserName,
                UserCreateTime= trialIdentityUser.CreateTime,
                IdentityUserTypeList = trialIdentityUser.TrialUserRoleList.Select(t => t.UserRole.UserTypeRole.UserTypeShortName).ToList(),

                DocNeedSignUserTypeList = trialDoc.NeedConfirmedUserTypeList.Select(t => t.UserTypeRole.UserTypeShortName).ToList(),
            };
            var datalist = await trialDocQuery.IgnoreQueryFilters().Where(t => t.IsDeleted == false && t.ConfirmTime == null&&t.ConfirmTime==null)
             .ToListAsync();


            datalist = datalist
                .Where(x=>((x.TrialType== TrialType.OfficialTrial|| x.TrialType== TrialType.Training) && !x.IsTestUser) || (x.TrialType==TrialType.NoneOfficial &&x.IsTestUser))
                .Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date)
                .ToList();
            var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
            var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();

            Console.WriteLine("发送定时项目过期提醒:人员数量" + userinfoList.Count);

            var scenario = EmailBusinessScenario.TrialTraining_ExpirationNotification;
            var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
            if (emailConfig == null)
            {
                return;
            }

            var userTrialIdList = datalist.Select(t => new { t.ConfirmUserId, t.TrialId }).Distinct().ToList();
            var userWithTrialList = (from ut in userTrialIdList
                                     join u in userinfoList on ut.ConfirmUserId equals u.Id
                                     select new { ut.TrialId, User = u }).ToList();

            var groupedList = userWithTrialList.GroupBy(x => new { x.TrialId, x.User.UserWorkLanguage }).ToList();
            foreach (var groupItem in groupedList)
            {
                var langUserInfoList = groupItem.Select(x => x.User).Distinct().ToList();
                if (!langUserInfoList.Any())
                {
                    continue;
                }

                Console.WriteLine($"发送定时过期提醒,数量：{langUserInfoList.Count}");

                var trialInfo = await _trialRepository.Where(x => x.Id == groupItem.Key.TrialId).FirstOrDefaultAsync();
                if (trialInfo == null)
                {
                    continue;
                }

                var workLanguage = groupItem.Key.UserWorkLanguage;
                var userIsEn_US = workLanguage == UserWorkLanguage.US;
                var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;

                foreach (var userinfo in langUserInfoList)
                {
                    try
                    {
                        var messageToSend = new MimeMessage();
                        messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
                        messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));

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

                            var htmlBodyStr = string.Format(
                               CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
                               userinfo.FullName,
                                     _systemEmailConfig.SiteUrl
                                );

                            return (topicStr, htmlBodyStr);
                        };

                        await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
                        await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);

                    }
                    catch (Exception)
                    {

                    }
                }

            }


        }
    }

    /// <summary>
    /// 生效通知
    /// </summary>
    public class TrialDocumentPublishEventConsumer(
     IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
     IRepository<VisitTask> _visitTaskRepository,
        IRepository<TrialDocument> _trialDocumentRepository,
          IRepository<IdentityUser> _identityUserRepository,
               IRepository<Trial> _trialRepository,
              IRepository<TrialIdentityUser> _trialIdentityUserRepository,
      IRepository<Dictionary> _dictionaryRepository,
     IRepository<TrialUserRole> _trialUserRoleRepository,
     IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,

     IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<TrialDocumentPublishEvent>
    {
        private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;

        public async Task Consume(ConsumeContext<TrialDocumentPublishEvent> context)
        {
            var isEn_US = context.Message.CultureInfoName == StaticData.CultureInfo.en_US;

            //设置当前事件传递过来的语言
            var culture = context.Message.CultureInfoName;
            CultureInfo.CurrentCulture = new CultureInfo(culture);

            // 记录是否只发送给新增角色的日志
            if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
            {
                Console.WriteLine($"只发送给新增项目的角色，角色数量: {context.Message.NewUserTypeIds.Count}");
            }
            // 构建查询
            IQueryable<TriaAndSystemlSignDocView> trialDocQuery;

            if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
            {
                // 只查询新增角色的用户
                trialDocQuery =
                from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
                join trial in _trialRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trial.Id
                join trialIdentityUser in _trialIdentityUserRepository.Where(x=>x.IsDeleted==false) on trialDoc.TrialId equals trialIdentityUser.TrialId
                join trialUserRole in _trialUserRoleRepository.Where(x => x.IsDeleted == false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
                join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
              on trialIdentityUser.IdentityUserId equals identityUser.Id
                where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted && context.Message.NewUserTypeIds.Contains(ur.UserRole.UserTypeId) && trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))

                select new TriaAndSystemlSignDocView()
                {
                    IsSystemDoc = true,
                    Id = trialDoc.Id,
                    TrialId= trialDoc.TrialId,
                    CreateTime = trialDoc.CreateTime,
                    IsDeleted = trialDoc.IsDeleted,
                    SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
                    TrialType = trial.TrialType,
                    IsTestUser = identityUser.IsTestUser,
                    Name = trialDoc.Name,
                    Path = trialDoc.Path,
                    FileTypeId = trialDoc.FileTypeId,
                    UpdateTime = trialDoc.UpdateTime,
                    ConfirmUserId = identityUser.Id,
                    RealName = identityUser.FullName,
                    UserName = identityUser.UserName,
                    IsNeedSendEmial = identityUser.IsZhiZhun,
                    FullFilePath = trialDoc.Path
                };
            }
            else
            {
                // 查询所有相关角色的用户
                trialDocQuery =
                from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))

                join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId
                join trialUserRole in _trialUserRoleRepository.Where(x=>x.IsDeleted==false) on trialIdentityUser.Id equals trialUserRole.TrialUserId

                join trial in _trialRepository.AsQueryable(false) on trialDoc.TrialId equals trial.Id
                join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
                 on trialIdentityUser.IdentityUserId equals identityUser.Id
                where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted &&trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))


                select new TriaAndSystemlSignDocView()
                {
                    IsSystemDoc = false,
                    Id = trialDoc.Id,
                    TrialId = trialDoc.TrialId,
                    EmailFromName =trial.EmailFromName,
                    CreateTime = trialDoc.CreateTime,
                    IsDeleted = trialDoc.IsDeleted,
                    SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
                    TrialType = trial.TrialType,
                    IsTestUser = identityUser.IsTestUser,
                    Name = trialDoc.Name,
                    Path = trialDoc.Path,
                    FileTypeId = trialDoc.FileTypeId,
                    UpdateTime = trialDoc.UpdateTime,
                    ConfirmUserId = identityUser.Id,
                    RealName = identityUser.FullName,
                    UserName = identityUser.UserName,
                    IsNeedSendEmial = identityUser.IsZhiZhun ,
                    FullFilePath = trialDoc.Path
                };
            }

            var datalist = await trialDocQuery.IgnoreQueryFilters().ToListAsync();
            datalist = datalist.Where(x => ((x.TrialType == TrialType.OfficialTrial || x.TrialType == TrialType.Training) && !x.IsTestUser) || (x.TrialType == TrialType.NoneOfficial && x.IsTestUser)).ToList();
              

            var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
            var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();

            var scenario = EmailBusinessScenario.TrialTraining_EffectiveNotification;
            var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable).FirstOrDefault();
            if (emailConfig == null)
            {
                return;
            }

            var userTrialIdList = datalist.Select(t => new { t.ConfirmUserId, t.TrialId }).Distinct().ToList();
            var userWithTrialList = (from ut in userTrialIdList
                                     join u in userinfoList on ut.ConfirmUserId equals u.Id
                                     select new { ut.TrialId, User = u }).ToList();

            foreach (var userWithTrial in userWithTrialList)
            {
                var userinfo = userWithTrial.User;
                string msg = $"{userinfo.UserName}项目生效通知,";
                try
                {
                    var messageToSend = new MimeMessage();
                    messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
                    messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));

                    var workLanguage = userinfo.UserWorkLanguage;
                    var userIsEn_US = workLanguage == UserWorkLanguage.US;
                    var companyName = userIsEn_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(
                           CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
                           userinfo.FullName,
                           _systemEmailConfig.SiteUrl
                            );

                        return (topicStr, htmlBodyStr);
                    };
                    await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);

                    var trialInfo = await _trialRepository.Where(x => x.Id == userWithTrial.TrialId).FirstOrDefaultAsync();
                    if (trialInfo == null)
                    {
                        continue;
                    }

                    await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
                    msg += "发送成功";

                }
                catch (Exception)
                {
                    msg += "发送失败";

                }


                Console.WriteLine(msg);
            }

        }
    }
}
