package com.storlead.sales.mail.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.storlead.framework.common.constant.CommonConstant;
import com.storlead.framework.common.util.DateUtil;
import com.storlead.framework.common.util.DateUtils;
import com.storlead.framework.common.util.SpringContextUtils;
import com.storlead.framework.common.util.RandomGenerateHelper;
import com.storlead.framework.common.util.StringUtil;
import com.storlead.framework.common.util.encryptor.AccessKeyEncryptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.storlead.framework.redis.RedisService;
import com.storlead.sales.mail.connection.MailConnection;
import com.storlead.sales.mail.connection.client.MailConnectionUtil;
import com.storlead.sales.mail.connection.config.MailProperties;
import com.storlead.sales.mail.entity.*;
import com.storlead.sales.mail.enums.EmailBoxEnum;
import com.storlead.sales.mail.enums.SendStatus;
import com.storlead.sales.mail.mapper.EmailsMapper;
import com.storlead.sales.mail.pojo.MailDTO;
import com.storlead.sales.mail.pojo.MailListDTO;
import com.storlead.sales.mail.pojo.SendMailDTO;
import com.storlead.sales.mail.pojo.vo.*;
import com.storlead.sales.mail.properties.MailFileProperties;
import com.storlead.sales.mail.service.*;
import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
import com.storlead.sales.mail.util.EmailHelper;
import com.storlead.sales.mail.util.EmailSenderWithThreadLocal;
import com.storlead.sales.mail.util.ReceiveMailQueueThreadPool;
import com.sun.mail.imap.IMAPBodyPart;
import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.pop3.POP3Folder;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.FilenameUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.annotation.Resource;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.search.*;
import java.io.*;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

/**
 * <p>
 * 邮件表 服务实现类
 * </p>
 *
 * @author chenkq
 * @since 2024-05-28
 */
@Log4j2
@Service
public class EmailsServiceImpl extends MyBaseServiceImpl<EmailsMapper, EmailsEntity> implements EmailsService {


    private final ConcurrentMap<String, Boolean> processedMessages = new ConcurrentHashMap<>();

    private static final ConcurrentHashMap<Long, Lock> userLockMap = new ConcurrentHashMap<>();

    /**
     * 附件下载控制
     */
    private final ConcurrentMap<Long, Boolean> processedDownloadMailIds = new ConcurrentHashMap<>();

    @Resource
    private SmtpPopSettingsService popSettingsService;

    @Resource
    private MailFileProperties mailFileProperties;

    @Resource
    private MailAttachmentService mailAttachmentService;

    @Resource
    private MailTempAttachmentService tempAttachmentService;

    @Resource
    private MailDelayPullRecordService delayPullRecordService;

    @Resource
    private EmailSenderWithThreadLocal senderWithThreadLocal;

    @Resource
    private RedisService redisService;

    @Resource
    private EmailBlacklistRecordService blackListService;

    @Resource
    private EmailFolderRuleService folderRuleService;

    @Resource
    private Environment environment;

    @Override
    public void updateSelectBindCustomerMail() {
        //   this.baseMapper.updateCleanBindCustomerMail();
        //   this.baseMapper.updateBindLiaisonMail();
        //   this.baseMapper.updateBindCustomerMail();
    }

    @Override
    public SendStatus sendEmail(SendMailDTO dto,SmtpPopSettingsEntity smtpPop) {
//        String active = environment.getProperty("spring.profiles.active");
//        if("dev".equals(active)) {
//            return SendStatus.SUCCESS;
//        }
        try {
            if(Objects.isNull(dto.getRecipientCcls())) {
                dto.setRecipientCcls(new ArrayList<>());
            }
            if(Objects.isNull(dto.getRecipientBccls())) {
                dto.setRecipientBccls(new ArrayList<>());
            }
            if(Objects.isNull(dto.getRecipientls())) {
                dto.setRecipientls(new ArrayList<>());
            }
            String fromAddress = smtpPop.getEmailAddress();
            String fromNickName = smtpPop.getSenderNickName();

            Session session = getSendEmailsSession(smtpPop);
            InternetAddress [] froms = new InternetAddress[dto.getRecipientls().size()];
            for (int i = 0; i < dto.getRecipientls().size(); i++) {
                froms[i] = new InternetAddress(dto.getRecipientls().get(i));
            }
            InternetAddress [] fromsCC = new InternetAddress[dto.getRecipientCcls().size()];
            for (int i = 0; i < dto.getRecipientCcls().size(); i++) {
                fromsCC[i] = new InternetAddress(dto.getRecipientCcls().get(i));
            }

            InternetAddress [] fromsBCC = new InternetAddress[dto.getRecipientBccls().size()];
            for (int i = 0; i < dto.getRecipientBccls().size(); i++) {
                fromsBCC[i] = new InternetAddress(dto.getRecipientBccls().get(i));
            }
            Transport transport = session.getTransport("smtp");
            int sizeInBytes = 0;
            try {
                MimeMessage message = new MimeMessage(session);
                if (Objects.nonNull(froms) && froms.length > 0) {
                    message.setRecipients(Message.RecipientType.TO,froms);
                }
                if (Objects.nonNull(fromsCC) && fromsCC.length > 0) {
                    message.setRecipients(Message.RecipientType.CC,fromsCC);
                }
                if (Objects.nonNull(fromsBCC) && fromsBCC.length > 0) {
                    message.setRecipients(Message.RecipientType.BCC,fromsBCC);
                }
                if (CollectionUtils.isEmpty(dto.getFileIds()) && CollectionUtils.isEmpty(dto.getOldfileIds())) {
                    message.setFrom(new InternetAddress(fromAddress));
                    message.setSubject(dto.getSubject());

                    Multipart multipart = new MimeMultipart();
//                    // 消息正文
                    BodyPart messageBodyPart1 = new MimeBodyPart();
                    List<MimeBodyPart> imageParts = new ArrayList<>();
                    String updatedHtmlContent = EmailHelper.convertImageUrlsToCidBodyPart(dto.getContent(),imageParts,mailFileProperties.getPath().getJpeg(),multipart);
                    messageBodyPart1.setContent(updatedHtmlContent, "text/html; charset=UTF-8");
                    multipart.addBodyPart(messageBodyPart1);
                    // 发送完整的消息部分
                    message.setContent(multipart);
                    // 获取邮件大小
                    sizeInBytes = dto.getContent().length();

                } else {

                    message.setFrom(new InternetAddress(fromAddress));

                    message.setDescription(dto.getRemark());
                    // 设置邮件主题
                    message.setSubject(dto.getSubject());
                    // 创建消息部分
                    Multipart multipart = new MimeMultipart();
//                    // 消息正文
                    BodyPart messageBodyPart1 = new MimeBodyPart();

                    List<MimeBodyPart> imageParts = new ArrayList<>();
                    String updatedHtmlContent = EmailHelper.convertImageUrlsToCidBodyPart(dto.getContent(),imageParts,mailFileProperties.getPath().getJpeg(),multipart);
                    messageBodyPart1.setContent(updatedHtmlContent, "text/html; charset=UTF-8");
                    multipart.addBodyPart(messageBodyPart1);
                    // 设置文本消息部分
                    if (!CollectionUtils.isEmpty(dto.getFileIds())) {
                        LambdaQueryWrapper fileWrapper = new LambdaQueryWrapper<MailTempAttachmentEntity>().in(MailTempAttachmentEntity::getId,dto.getFileIds());
                        List<MailTempAttachmentEntity> tempAttachment = tempAttachmentService.list(fileWrapper);
                        for (MailTempAttachmentEntity attachment : tempAttachment) {
                            BodyPart messageBodyPart = new MimeBodyPart();
                            String filePath =  mailFileProperties.getPath().getPath() + attachment.getFilePath();
                            String fileName = attachment.getFileName()+"."+attachment.getFileExt();
                            DataSource fileSource = new FileDataSource(filePath);
                            messageBodyPart.setDataHandler(new DataHandler(fileSource));
                            messageBodyPart.setFileName(fileName);
                            multipart.addBodyPart(messageBodyPart);
                        }
                    }

                    if (!CollectionUtils.isEmpty(dto.getOldfileIds())) {
                        LambdaQueryWrapper fileMailWrapper = new LambdaQueryWrapper<MailTempAttachmentEntity>().in(MailTempAttachmentEntity::getId,dto.getOldfileIds());
                        List<MailAttachmentEntity> mailAttachments = mailAttachmentService.list(fileMailWrapper);
                        for (MailAttachmentEntity attachment : mailAttachments) {
                            BodyPart messageBodyPart = new MimeBodyPart();
                            String filePath =  mailFileProperties.getPath().getPath() + attachment.getFilePath();
                            String fileName = attachment.getFileName()+"."+attachment.getFileExt();
                            DataSource fileSource = new FileDataSource(filePath);
                            messageBodyPart.setDataHandler(new DataHandler(fileSource));
                            messageBodyPart.setFileName(fileName);
                            multipart.addBodyPart(messageBodyPart);
                        }
                    }
                    // 发送完整的消息部分
                    message.setContent(multipart);
                    // 获取邮件大小
                    sizeInBytes = dto.getContent().length();
                    // 发送消息
                }
                /**
                 * 发送成功,存储邮箱 replyEmailId null
                 */
                if (Integer.valueOf(1).equals(dto.getIsReceipt())) {
                    message.addHeader("Disposition-Notification-To", smtpPop.getEmailAddress());
                }
                Long replyMsgId = dto.getReplyMsgId();
                EmailsEntity email =  saveSendEmails(dto,fromAddress,fromNickName,replyMsgId,Long.valueOf(sizeInBytes));
                email.setIsOnlyHead(0);
                email.setSmtpPopId(smtpPop.getId());
                log.error("senderWithThreadLocal - saveOrUpdate----邮件");
                if(this.saveOrUpdate(email)) {
                    if (Objects.nonNull(email.getDelaySendTime())) {
                        if (!CollectionUtils.isEmpty(dto.getFileIds())) {
                            LambdaUpdateWrapper<MailTempAttachmentEntity> mt = new LambdaUpdateWrapper<>();
                            mt.set(MailTempAttachmentEntity::getEmailId, email.getId());
                            mt.in(MailTempAttachmentEntity::getId, dto.getFileIds());
                            tempAttachmentService.update(mt);
                        }
                    } else {
                        try {
                            CompletableFuture<SendStatus> resultFuture = senderWithThreadLocal.sendMailMessage(transport, message, email);
                            SendStatus result = resultFuture.get();
                            return result;
                        } catch (Exception e) {
                            log.error("email -address --"+smtpPop.getEmailAddress()+"--send - error -",e);
                            return SendStatus.SERVER_LOGIN_FAIL;
                        }
                    }
                }
            }catch (Exception e) {
                log.error("getSendEmailsSession -error",e);
                return SendStatus.FAILED;
            }
        } catch (Exception e) {
            log.error("send sendMail -error",e);
            return SendStatus.FAILED;
        }
        return SendStatus.SUCCESS;
    }

    @Override
    public List<UserClickTitleVO> selectUserClickTitle(Long ownerBy, String title) {
        return this.baseMapper.selectUserClickTitle(ownerBy,title);
    }

    @Override
    public Boolean sendEmail(EmailsEntity emails,SmtpPopSettingsEntity smtpPop) {
//        String active = environment.getProperty("spring.profiles.active");
//        if("dev".equals(active)) {
//            return true;
//        }
        try {

            List<String> recipientls = new ArrayList<>();
            if(StrUtil.isNotBlank(emails.getRecipient())) {
                recipientls = Arrays.asList(emails.getRecipient().split(","));
            }

            List<String> recipientCcls = new ArrayList<>();
            if(StrUtil.isNotBlank(emails.getRecipientCc())) {
                recipientCcls = Arrays.asList(emails.getRecipientCc().split(","));
            }
            List<String> recipientBccls = new ArrayList<>();
            if(StrUtil.isNotBlank(emails.getRecipientBcc())) {
                recipientBccls = Arrays.asList(emails.getRecipientBcc().split(","));
            }

            String fromAddress = smtpPop.getEmailAddress();

            Session session = getSendEmailsSession(smtpPop);
            InternetAddress [] froms = new InternetAddress[recipientls.size()];
            for (int i = 0; i < recipientls.size(); i++) {
                froms[i] = new InternetAddress(recipientls.get(i));
            }
            InternetAddress [] fromsCC = new InternetAddress[recipientCcls.size()];
            for (int i = 0; i < recipientCcls.size(); i++) {
                fromsCC[i] = new InternetAddress(recipientCcls.get(i));
            }
            InternetAddress [] fromsBCC = new InternetAddress[recipientBccls.size()];
            for (int i = 0; i < recipientBccls.size(); i++) {
                fromsBCC[i] = new InternetAddress(recipientBccls.get(i));
            }
            Transport transport = session.getTransport("smtp");
            int sizeInBytes = 0;
            try {
                Message message = new MimeMessage(session);
                if (Objects.nonNull(froms) && froms.length > 0) {
                    message.setRecipients(Message.RecipientType.TO,froms);
                }
                if (Objects.nonNull(fromsCC) && fromsCC.length > 0) {
                    message.setRecipients(Message.RecipientType.CC,fromsCC);
                }
                if (Objects.nonNull(fromsBCC) && fromsBCC.length > 0) {
                    message.setRecipients(Message.RecipientType.BCC,fromsBCC);
                }

                LambdaQueryWrapper fileWrapper = new LambdaQueryWrapper<MailTempAttachmentEntity>().in(MailTempAttachmentEntity::getEmailId,emails.getId());
                List<MailTempAttachmentEntity> tempAttachment = tempAttachmentService.list(fileWrapper);
                if (CollectionUtils.isEmpty(tempAttachment)) {
                    message.setFrom(new InternetAddress(fromAddress));
                    message.setSubject(emails.getSubject());

                    Multipart multipart = new MimeMultipart();
//                    // 消息正文
                    BodyPart messageBodyPart1 = new MimeBodyPart();
                    List<MimeBodyPart> imageParts = new ArrayList<>();
                    String updatedHtmlContent = EmailHelper.convertImageUrlsToCidBodyPart(emails.getContent(),imageParts,mailFileProperties.getPath().getJpeg(),multipart);
                    messageBodyPart1.setContent(updatedHtmlContent, "text/html; charset=UTF-8");
                    multipart.addBodyPart(messageBodyPart1);
                    // 发送完整的消息部分
                    message.setContent(multipart);
                } else {
                    message.setFrom(new InternetAddress(fromAddress));
                    message.setDescription(emails.getRemark());
                    // 设置邮件主题
                    message.setSubject(emails.getSubject());
                    Multipart multipart = new MimeMultipart();
//                    // 消息正文
                    BodyPart messageBodyPart1 = new MimeBodyPart();
                    List<MimeBodyPart> imageParts = new ArrayList<>();
                    String updatedHtmlContent = EmailHelper.convertImageUrlsToCidBodyPart(emails.getContent(),imageParts,mailFileProperties.getPath().getJpeg(),multipart);
                    messageBodyPart1.setContent(updatedHtmlContent, "text/html; charset=UTF-8");
                    multipart.addBodyPart(messageBodyPart1);
                    // 设置文本消息部分
                    for (MailTempAttachmentEntity attachment : tempAttachment) {
                        BodyPart messageBodyPart = new MimeBodyPart();
                        String filePath =  mailFileProperties.getPath().getPath() + attachment.getFilePath();
                        String fileName = attachment.getFileName()+"."+attachment.getFileExt();
                        DataSource fileSource = new FileDataSource(filePath);
                        messageBodyPart.setDataHandler(new DataHandler(fileSource));
                        messageBodyPart.setFileName(fileName);
                        multipart.addBodyPart(messageBodyPart);
                    }
                    // 发送完整的消息部分
                    message.setContent(multipart);
                }
                /**
                 * 发送成功,存储邮箱 replyEmailId null
                 */
                if (Integer.valueOf(1).equals(emails .getIsReceipt())) {
                    message.addHeader("Disposition-Notification-To", smtpPop.getEmailAddress());
                }
                if(this.saveOrUpdate(emails)) {
                    senderWithThreadLocal.sendMailMessage(transport,message,emails);
                }
                return true;
            }catch (Exception e) {
                log.error("getSendEmailsSession -error",e);
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("send sendMail -error",e);
            return false;
        }
    }
    @Override
    public void receiveEmails(SmtpPopSettingsEntity smtpPop,Boolean isBackTask) {
        String active = environment.getProperty("spring.profiles.active");
//        if("dev".equals(active)) {
//            return;
//        }
        String taskId = smtpPop.getEmailAddress()+"_"+smtpPop.getOwnerBy().toString();
        ReceiveMailQueueThreadPool instance = ReceiveMailQueueThreadPool.getInstance();
        if (instance.getTaskInProgressByMail(taskId)) {
            log.error("有任务正在进行--:>>>>>>>>>>>>>"+smtpPop.getEmailAddress());
            return;
        }
        instance.addTask(taskId,new Runnable() {
            @Override
            public void run() {
                receiveHeadEmails(smtpPop,isBackTask);
            }
        });

        addLoadMailContentTask(smtpPop);

        addLoadMailFilesTask(smtpPop);
    }

    @Override
    public void receiveHeadEmails(SmtpPopSettingsEntity smtpPop) {
        receiveHeadEmails(smtpPop,false);
    }

    @Override
    public void receiveEmails(SmtpPopSettingsEntity smtpPop) {
        receiveEmails(smtpPop,false);
    }

    @Override
    public void receiveHeadEmails(SmtpPopSettingsEntity smtpPop,Boolean isBackTask) {

        try {
            List<Message> inboxLs = getMessagels(smtpPop,"INBOX",EmailBoxEnum.INBOX,isBackTask);
            if (!CollectionUtils.isEmpty(inboxLs)) {
                List<EmailFolderRuleEntity> folderRules = folderRuleService.getUserFolderRules(smtpPop.getOwnerBy());
                Set<String> blackList = blackListService.getBlackEmaillist(smtpPop.getOwnerBy());
                pullHeadMail(inboxLs,smtpPop,EmailBoxEnum.INBOX,blackList,folderRules,isBackTask);
            }
//            if (!smtpPop.getEnabled()) {
//                return;
//            }
            List<Message> sentLs = getMessagels(smtpPop,"Sent Items", EmailBoxEnum.SENT,isBackTask);
            if (!CollectionUtils.isEmpty(sentLs)) {
                pullHeadMail(sentLs,smtpPop,EmailBoxEnum.SENT,null,null,isBackTask);
            }
        }catch (Exception e) {
            log.error("receiveHeadEmails - error ---"+smtpPop.getEmailAddress(),e);
        }
    }

    public List<Message> getMessagels(SmtpPopSettingsEntity smtpPop,String folderName, EmailBoxEnum boxEnum) {
        return getMessagels(smtpPop,folderName,boxEnum,false);
    }

    @Override
    public List<Message> getMessagels(SmtpPopSettingsEntity smtpPop,String folderName, EmailBoxEnum boxEnum,Boolean isBackTask) {
        try {
            QueryWrapper queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("smtp_pop_id", smtpPop.getId());
            queryWrapper.eq("folder", boxEnum.code);
            queryWrapper.select("max(recipient_date) as recipient_date");
            EmailsEntity email = this.getOne(queryWrapper);

            Date beginDate = null;
            MailProperties properties = new MailProperties(smtpPop);
            MailConnection mailConnection = MailConnectionUtil.receiveEmailsConnection(properties);
            if (Objects.isNull(mailConnection)) {
//                if(isBackTask) {
//                    // 处理异常，并发送通知
//                    if (Objects.nonNull(smtpPop.getId())) {
//                        LambdaUpdateWrapper<SmtpPopSettingsEntity> updateWrapper = new LambdaUpdateWrapper<>();
//                        updateWrapper.set(SmtpPopSettingsEntity::getEnabled,0);
//                        updateWrapper.eq(SmtpPopSettingsEntity::getId, smtpPop.getId())
//                                .setSql("connect_error_count = connect_error_count + 1"); // 原值 + 1
//                        popSettingsService.update(updateWrapper);
//                        // 禁止后续流程
////                        smtpPop.setEnabled(false);
//                    }
////                    // 发送消息通知提醒邮箱连接异常
////                    String[] argsArr = {"wecom"};
////                    Set<Long> userIds = new HashSet<>();
////                    userIds.add(smtpPop.getOwnerBy());
////
////                    Map<String,Object> messageMap = new HashMap<>();
////                    messageMap.put("messageContent","");
////                    messageMap.put("titleRemark","["+smtpPop.getEmailAddress()+"]");
////                    invokeSendMessage(messageMap,userIds,argsArr);
//                }
                return null;
            }
            Folder inbox = mailConnection.getFolder(folderName);
            if (Objects.isNull(inbox)) {
                return null;
            }
            inbox.open(Folder.READ_ONLY);
            if (Objects.nonNull(email)) {
                beginDate = email.getRecipientDate();
            }
            if (beginDate == null) {
                if (Integer.valueOf(0).equals(smtpPop.getPullDay()) || Objects.isNull(smtpPop.getPullDay())) {
                    LocalDate currentDate = LocalDate.now();
                    LocalDate datePullDayAgo = currentDate.minusYears(5);
                    beginDate = DateUtil.getDateByFormat(datePullDayAgo.toString(), "yyyy-MM-dd");
                } else {
                    LocalDate currentDate = LocalDate.now();
                    LocalDate datePullDayAgo = currentDate.minusDays(smtpPop.getPullDay());
                    beginDate = DateUtil.getDateByFormat(datePullDayAgo.toString(), "yyyy-MM-dd");
                }
            }

            SearchTerm searchTerm = new ReceivedDateTerm(ComparisonTerm.GT, beginDate);
            Message[] messages = inbox.search(searchTerm);

            List<Message> messagesList = Arrays.asList(messages);
            if (CollectionUtils.isEmpty(messagesList)) {
                return null;
            }
//            Date finalBeginDate = beginDate;
//            List<Message> messagels = messagesList.stream().filter(e -> {
//                try {
//                    return e.getReceivedDate().compareTo(finalBeginDate) > 0;
//                } catch (MessagingException ex) {
//                    return false;
//                }
//            }).collect(Collectors.toList());
//
//            if (Objects.isNull(messagels)) {
//                return messagels;
//            } else if (messagels.size() <= 100) {
//                return messagels;
//            } else if(messagels.size() > 100 && messagels.size() <= 1000) {
//                return messagels.stream().limit(500).collect(Collectors.toList());
//            } else {
//                return messagels.stream().limit(1000).collect(Collectors.toList());
//            }
            return messagesList;
        } catch (Exception e) {
            log.error("error", e);
            return  null;
        }
    }

    public void invokeSendMessage(Map messageMap,Set<Long> toUserIds,String[] argsArr ) {
        try {
            Object myClassInstance = SpringContextUtils.getBean("messageService");
            Class<?> clazz = myClassInstance.getClass();

//            Class<?> clazz = Class.forName("com.storlead.message.service.impl.MessageService");

            Method method = clazz.getMethod("autoMatchEventSendMessage",Map.class,String.class,String.class,Set.class,  String[].class);
            method.invoke(myClassInstance, messageMap,"999","EMAIL_SMTP_WARN",toUserIds,argsArr);
        } catch (Exception e) {
            log.error("invokeSendMessage - error",e);
        }

    }
    @Override
    public void pullHeadMail(List<Message> messages,SmtpPopSettingsEntity smtpPop, EmailBoxEnum boxEnum,Set<String> blackls,List<EmailFolderRuleEntity> folderRules,Boolean isBackTask) {
//        Lock lock = userLockMap.computeIfAbsent(smtpPop.getOwnerBy(), id -> new ReentrantLock());
        log.info("==========邮件入库开始=========="+boxEnum.code);

//        if (lock.tryLock()) {
            try {
                List<Message> messagels = messages;
                if (CollectionUtils.isEmpty(messagels)) {
                    return;
                }
                QueryWrapper queryMsgIdWp = new QueryWrapper<>();
                queryMsgIdWp.select("message_id");
                queryMsgIdWp.eq("folder", boxEnum.code);
                queryMsgIdWp.eq("smtp_pop_id", smtpPop.getId());
                queryMsgIdWp.last("order by recipient_date desc limit 100");
                List<String> ids = this.listObjs(queryMsgIdWp);
                List<String> mesageIds = new ArrayList<>();
                if (!CollectionUtils.isEmpty(ids)) {
                    mesageIds.addAll(ids);
                }
                List<String> messageIds = new ArrayList<>();
//                if (!CollectionUtils.isEmpty(messagels)) {
//                    List<String> varIdls = new ArrayList<>();
//                    for (Message message : messagels) {
//                        String [] varIds = message.getHeader("Message-ID");
//                        if (Objects.isNull(varIds)) {
//                            continue;
//                        }
//                        varIdls.add(varIds[0]);
//                    }
//                    if (!CollectionUtils.isEmpty(varIdls)) {
//                        messageIds = this.getEmailMessageIdsByMessageId(varIdls,boxEnum.code, smtpPop.getId());
//                        if (Objects.isNull(messageIds)) {
//                            messageIds = new ArrayList<>();
//                        }
//                    }
//                }
                List<EmailsEntity> entities = new ArrayList<>();
                for (Message message : messagels) {
                    String[] varIds = message.getHeader("Message-ID");
                    if (Objects.isNull(varIds)) {
                        continue;
                    }
                    String messageId = varIds[0];
                    // 如果 messageId 尚未处理，执行处理逻辑
                    if (!CollectionUtils.isEmpty(mesageIds) && mesageIds.contains(messageId)) {
                        continue;
                    }
                    String oldMessageId = this.getEmailMessageIdsByMessageId(messageId,boxEnum.code, smtpPop.getId());
//                    String[] inReplyTo = message.getHeader("In-Reply-To");
//                    if (inReplyTo != null) {
//                        String inReplyTo1 = message.getHeader("IN-REPLY-TO") != null ? message.getHeader("In-Reply-To")[0] : null;
//                        String references1 = message.getHeader("References") != null ? message.getHeader("References")[0] : null;
//                    }
//                    Boolean existMessageId = messageIds.contains(messageId);
                    EmailsEntity entity;
                    if (Objects.isNull(oldMessageId)) {
                        entity = convertMessageToEmailVo(message, true);
                        if (Objects.isNull(entity)) {
                            continue;
                        }
                        entity.setMessageId(messageId);
                        entity.setSmtpPopId(smtpPop.getId());
                        entity.setOwnerBy(smtpPop.getOwnerBy());
                    } else {
                        continue;
                    }
                    if (Objects.isNull(entity)) {
                        continue;
                    }
                    if (!CollectionUtils.isEmpty(folderRules)) {
                        /** 处理文件夹入栈规则 **/
                        folderRuleService.carveUpMailCustomFolder(entity, folderRules);
                    }
                    mesageIds.add(messageId);
                    if ("IMAP".equals(smtpPop.getProtocolType())) {
                        IMAPFolder folder = (IMAPFolder) message.getFolder();
                        Long msguid = folder.getUID(message);
                        entity.setMsgUid(msguid.toString());
                    } else if ("POP3".equals(smtpPop.getProtocolType())) {
                        POP3Folder folder = (POP3Folder) message.getFolder();
                        String msguid = folder.getUID(message);
                        entity.setMsgUid(msguid.toString());
                    }
                    if (!CollectionUtils.isEmpty(blackls)) {
                        if (blackls.contains(entity.getFrom())) {
                            entity.setIsTrash(1);
                        }
                    }
                    Boolean b = saveOrUpdate(entity);
                    if (b) {
                        entities.add(entity);
                        log.error("==========entity.getId()=========="+entity.getId());
                    }
                }
                log.info("==========邮件入库结束=========="+boxEnum.code);
                String finalboxCode = boxEnum.code;  // 提前取值
                Boolean finalIsBackTask = isBackTask;
                List<Long> finalIsMailIds = entities.stream().map(EmailsEntity::getId).collect(Collectors.toList());
                log.error("finalIsMailIds = "+finalIsMailIds);
                if (!CollectionUtils.isEmpty(finalIsMailIds)) {
                    CompletableFuture.runAsync(() -> {
                        updateFollowUpTime(entities, smtpPop.getOwnerBy());
                        // 发送新邮件提醒,绑定客户后，直接查询性能会好
                        log.error("操作完绑定客户"+ JSON.toJSON(finalIsMailIds)+"__"+isBackTask+"___EmailBoxEnum.code___"+finalboxCode+"____="+EmailBoxEnum.INBOX.code.equals(finalboxCode));
                        if (!CollectionUtils.isEmpty(finalIsMailIds) && finalIsBackTask && EmailBoxEnum.INBOX.code.equals(finalboxCode)) {
                            log.error("进入发送提醒");
                            sendNewMailRemind(finalIsMailIds,smtpPop.getOwnerBy(),smtpPop.getEmailAddress());
                        }
                    });
                    CompletableFuture.runAsync(() -> {
                        autoReplyMails(entities);
                    });
                }

            }catch(Exception e){
                log.error("pullHeadMail -- error---"+smtpPop.getEmailAddress(), e);
            }
    }

    public void sendNewMailRemind(List<Long> mailIds,Long userId,String mailAccount) {
        if (CollectionUtils.isEmpty(mailIds)) {
            return;
        }
        String messageContent = "您有"+mailIds.size()+"封新邮件，请前往查看！";
        // 获取新绑定的邮箱
        List<Long> cusIds = this.baseMapper.selectCusIdByMailId(mailIds);
        if (!CollectionUtils.isEmpty(cusIds)) {
            List<CustomerMailVO> customervos = this.baseMapper.selectCusInfoByCusId(cusIds);

            if (!CollectionUtils.isEmpty(customervos)) {
                StringBuilder sb = new StringBuilder();
                String moreCus = "";
                for (CustomerMailVO customer : customervos) {
                    if (sb.length() > 0) {
                        moreCus = "等";
                        sb.append("、");
                    }
                    sb.append("【");
                    sb.append(customer.getCountry());
                    sb.append("-");
                    sb.append(customer.getCustomerName());
                    sb.append("】");
                }
                messageContent = "您有来自"+sb+moreCus+"客户的"+mailIds.size()+"封新邮件，请前往查看！";
            }
        }
        try {
            Map<String,Object> messageMap = new HashMap<>();
            messageMap.put("messageContent",messageContent);

            Integer mailCount = this.baseMapper.countSmtpMailCount(userId);
            if (mailCount > 1) {
                messageMap.put("titleRemark","["+mailAccount+"]");
            } else {
                messageMap.put("titleRemark","");
            }
            Set<Long> toUserIds = new HashSet<>();
            toUserIds.add(userId);

           Object myClassInstance = SpringContextUtils.getBean("messageService");
            Class<?> clazz = myClassInstance.getClass();

//            Class<?> clazz = Class.forName("com.storlead.message.service.impl.MessageService");

            Method method = clazz.getMethod("autoMatchEventSendMessage",Map.class,String.class,String.class,Set.class,  String[].class);
            String[] argsArr = {"site","wecom","sms","mail"};
            method.invoke(myClassInstance, messageMap,"11","NEW_EMAIL",toUserIds,argsArr);
        }catch (Exception e) {
            log.error("autoMatchEventSendMessage error",e);
        }
    }

    public void autoReplyMails(List<EmailsEntity> entities){
        for (EmailsEntity entity : entities) {
            try {
                autoReplyMail(entity);
            }catch (Exception e) {
                log.error("---autoReplyMails error---",e);
            }
        }
    }

    public void updateFollowUpTime(List<EmailsEntity> entities,Long ownerBy){
        for (EmailsEntity entity : entities) {
            try {
                // 修改客户跟进实际
                if (Integer.valueOf(1).equals(entity.getInOutMark())) {
                    bindLiaisonMailCustomerIdByMailIdAndUserId(entity.getId(), entity.getFrom(), ownerBy, 1);
                } else {
                    String recipient = entity.getRecipient();
                    if (StrUtil.isNotBlank(entity.getRecipientCc())) {
                        if (StrUtil.isNotBlank(recipient)) {
                            recipient = recipient + "," + entity.getRecipientCc();
                        } else {
                            recipient = entity.getRecipientCc();
                        }
                    }
                    bindLiaisonMailCustomerIdByMailIdAndUserId(entity.getId(), recipient, ownerBy, 2);
                }

                if ("SENT".equals(entity.getFolder())) {
                    Object myClassInstance = SpringContextUtils.getBean("customerServiceImpl");
                    Class<?> clazz = myClassInstance.getClass();
                    Set<String> mailAddress = new HashSet<>();
                    if (StrUtil.isNotBlank(entity.getRecipient())) {
                        List<String> recipientls = Arrays.asList(entity.getRecipient().toLowerCase().split(","));
                        mailAddress.addAll(recipientls);
                    }
                    if (StrUtil.isNotBlank(entity.getRecipientCc())) {
                        List<String> recipientccls = Arrays.asList(entity.getRecipientCc().toLowerCase().split(","));
                        mailAddress.addAll(recipientccls);
                    }
                    if (!CollectionUtils.isEmpty(mailAddress)) {
                        LocalDateTime sentDate = (Objects.isNull(entity.getSentDate())) ? LocalDateTime.now() : entity.getSentDate().toInstant()
                                .atZone(ZoneId.systemDefault()) // 使用系统默认时区
                                .toLocalDateTime();
                        Method method = clazz.getMethod("updateFollowUpTimeByEmail", Set.class, LocalDateTime.class);
                        method.invoke(myClassInstance, mailAddress, sentDate);
                    }
                }
            } catch (Exception e) {
                log.error("updateFollowUpTimeByEmail --e", e);
            }
        }
    }

    public void autoReplyMail(EmailsEntity entity) {
        try {
            SmtpPopSettingsEntity smtpPop =  popSettingsService.getById(entity.getSmtpPopId());
            if (Integer.valueOf(1).equals(smtpPop.getIsAutoReply()) && smtpPop.getReplyOnTime().before(entity.getSentDate())) {
                if (entity.getFrom().equals(smtpPop.getEmailAddress())
                        || "system@storlead.com".equals(entity.getFrom())
                        || "system@storlead.com".equals(entity.getRecipient())) {
                    return;
                }
                // 发过了不用发
                String key = smtpPop.getEmailAddress()+"_"+entity.getFrom();
                Object object =redisService.getCacheObject(key);
                Long ttl = 0l;
                if (Objects.nonNull(object)) {
                     ttl = redisService.getCacheExpire(key, TimeUnit.SECONDS);
                }
                if ((Objects.isNull(object) || ttl <= 0) && StrUtil.isNotBlank(smtpPop.getReplyContent())) {
                    LocalDateTime now = LocalDateTime.now();
                    // 今天23:59:59
                    LocalDateTime endOfDay = now.toLocalDate().atTime(23, 59, 59);
                    // 计算剩余时间（秒）
                    long timeout = ChronoUnit.SECONDS.between(now, endOfDay);
                    redisService.setCacheObject(key,"reply",timeout, TimeUnit.SECONDS);

                    AccessKeyEncryptor accessKeyEncryptor = AccessKeyEncryptor.getAccessKeyEncryptor("");
                    String pass = accessKeyEncryptor.decrypt(smtpPop.getEmailPassword());
                    smtpPop.setEmailPassword(pass);
                    EmailsEntity repEmail = new EmailsEntity();
                    repEmail.setRecipient(entity.getFrom());
                    repEmail.setSubject(smtpPop.getReplyTitle());
                    repEmail.setContent(smtpPop.getReplyContent());
                    this.sendEmail(repEmail,smtpPop);
                }
            }
        }catch (Exception e) {
            log.error("autoReplyMail errpr ",e);
        }
    }
    @Override
    public NewMailCountTipVO countMailSummaryNum(Long smtpPopId, Long ownerBy) {
        return this.baseMapper.countMailSummaryNum(smtpPopId,ownerBy);
    }

    @Override
    public NewMailCountTipVO countCustomerAndClueNumber(Long smtpPopId, Long ownerBy) {
        return this.baseMapper.countCustomerAndClueNumber(smtpPopId,ownerBy);
    }

    @Override
    public NewMailCountTipVO countCustomerFollowUpMailNum(Long smtpPopId, Long ownerBy) {
        return this.baseMapper.countCustomerFollowUpMailNum(smtpPopId,ownerBy);
    }

    @Override
    public LocalDateTime getCustomerLastFollowUpTime(Long customerId) {
        return this.baseMapper.selectCustomerLastFollowUpTime(customerId);
    }

    @Override
    public List<EmailsEntity> getDelayDeleteMail() {
        return this.baseMapper.selectDelayDeleteMail();
    }

    @Override
    public IPage<CustomerEmailVo> selectCustomerEmailPage(Page<CustomerEmailVo> page, MailListDTO dto) {
        return this.baseMapper.selectCustomerEmailPage(page,dto);
    }


    @Override
    public void receiveBodyContentEmails(SmtpPopSettingsEntity smtpPop,List<EmailsEntity> emailsls,EmailBoxEnum boxEnum) {
        receiveBodyContent(smtpPop,emailsls,boxEnum);
    }

    @Override
    public InputStream loadEmailsFile(SmtpPopSettingsEntity smtpPop, EmailsEntity email,String attachmentName) {
        try {
            MailProperties properties = new MailProperties(smtpPop);
            MailConnection mailConnection = MailConnectionUtil.receiveEmailsConnection(properties);
            if (Objects.isNull(mailConnection)) {
                return null;
            }
            String folder = "Sent Items";
            if (EmailBoxEnum.INBOX.code.equals(email.getFolder())) {
                folder = "INBOX";
            }
            Message message = mailConnection.getMessageByUid(email.getMsgUid(),folder);
            if (Objects.isNull(message)) {
                return null;
            }
            Object content = message.getContent();
            if (content instanceof Multipart) {
                Multipart multipart = (Multipart) content;
                for (int i = 0; i < multipart.getCount(); i++) {
                    BodyPart bodyPart = multipart.getBodyPart(i);
                    if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) || bodyPart.isMimeType("application/octet-stream")) {
                        String fileName = bodyPart.getFileName();
                        fileName = MimeUtility.decodeText(fileName);
                        fileName = fileName.replace("\n", "").replace("\r", "");
                        if (fileName.equals(attachmentName)) {
                            return bodyPart.getInputStream();
                        }
                    }
                }
            }
        }catch (Exception e) {
            return null;
        }
        return null;
    }


    @Override
    public void loadEmailsFiles(SmtpPopSettingsEntity smtpPop, List<EmailsEntity> emails,List<MailAttachmentEntity> attachments) {
        try {
            MailProperties properties = new MailProperties(smtpPop);
            MailConnection mailConnection = MailConnectionUtil.receiveEmailsConnection(properties);
            if (Objects.isNull(mailConnection)) {
                return;
            }
            Map<Long,List<MailAttachmentEntity>> attachmentMap = attachments.stream().collect(Collectors.groupingBy(MailAttachmentEntity::getEmailId));
            for(EmailsEntity email : emails) {
                List<MailAttachmentEntity> mAttachments = attachmentMap.get(email.getId());
                if (CollectionUtils.isEmpty(mAttachments)) {
                    continue;
                }
                String folder = "Sent Items";
                if (EmailBoxEnum.INBOX.code.equals(email.getFolder())) {
                    folder = "INBOX";
                }
                mailConnection.getFolder(folder);
                Map<String, MailAttachmentEntity> attachmentMapName = mAttachments.stream()
                        .collect(Collectors.toMap(
                                attachment -> attachment.getFileName() + "." + attachment.getFileExt(), // 键：拼接 fileName 和 fileExt
                                attachment -> attachment,
                                (existing, replacement) -> existing
                        ));
                Message message = mailConnection.getMessageByUid(email.getMsgUid(),folder);
                if (Objects.isNull(message)) {
                    continue;
                }
                Object content = message.getContent();
                if (content instanceof Multipart) {
                    Multipart multipart = (Multipart) content;
                    for (int i = 0; i < multipart.getCount(); i++) {
                        BodyPart bodyPart = multipart.getBodyPart(i);
                        if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) || bodyPart.isMimeType("application/octet-stream")) {
                            String fileName = bodyPart.getFileName();
                            fileName = MimeUtility.decodeText(fileName);
                            fileName = fileName.replace("\n", "").replace("\r", "");
                            MailAttachmentEntity attachment = attachmentMapName.get(fileName);
                            if (Objects.isNull(attachment)) {
                                continue;
                            }
                            String filePath = mailFileProperties.getPath().getPath()+attachment.getFilePath();
                            if (new File(filePath).exists()) {
                                LambdaUpdateWrapper<MailAttachmentEntity> attachmentUpdate = new LambdaUpdateWrapper<>();
                                attachmentUpdate.set(MailAttachmentEntity::getDownload,Integer.valueOf(1));
                                attachmentUpdate.eq(MailAttachmentEntity::getId,attachment.getId());
                                mailAttachmentService.update(attachmentUpdate);
                            }
                            try {
                                File file = new File(filePath);
                                File parentDir = file.getParentFile();
                                // 如果父目录不存在，则递归创建
                                if (parentDir != null && !parentDir.exists()) {
                                    parentDir.mkdirs();  // mkdirs() 会创建所有必要的父目录
                                }
                                try (FileOutputStream output = new FileOutputStream(file)) {
                                    bodyPart.getInputStream().transferTo(output);
                                }
                                LambdaUpdateWrapper<MailAttachmentEntity> attachmentUpdate = new LambdaUpdateWrapper<>();
                                attachmentUpdate.set(MailAttachmentEntity::getDownload,Integer.valueOf(1));
                                attachmentUpdate.set(MailAttachmentEntity::getFileSize,file.length());
                                attachmentUpdate.eq(MailAttachmentEntity::getId,attachment.getId());
                                mailAttachmentService.update(attachmentUpdate);
                            }catch (Exception e) {
                                log.error("error --- ",e);
                            }
                        }
                    }
                }
            }
        }catch (Exception e) {
            log.error("loadEmailsFiles ---",e);
            return;
        }
        return;
    }


    public static Message[] mergeMessageArrays(Message[] array1, Message[] array2) {
        // 处理空数组的情况
        if (array1 == null && array2 == null) {
            return new Message[0]; // 两个数组都为空，返回空数组
        } else if (array1 == null) {
            return array2; // 如果第一个数组为空，返回第二个数组
        } else if (array2 == null) {
            return array1; // 如果第二个数组为空，返回第一个数组
        }
        // 如果两个数组都不为空，创建一个新的 Message[] 数组，大小为两个数组长度之和
        Message[] mergedArray = new Message[array1.length + array2.length];
        // 将第一个数组复制到新数组中
        System.arraycopy(array1, 0, mergedArray, 0, array1.length);
        // 将第二个数组复制到新数组的后半部分
        System.arraycopy(array2, 0, mergedArray, array1.length, array2.length);
        return mergedArray;
    }

    public void receiveBodyContent(SmtpPopSettingsEntity smtpPop,List<EmailsEntity> emailsls,EmailBoxEnum boxEnum) {
        try {
            MailProperties properties = new MailProperties(smtpPop);
            MailConnection mailConnection = MailConnectionUtil.receiveEmailsConnection(properties);
            if (Objects.isNull(mailConnection)) {
                return;
            }
            if (!CollectionUtils.isEmpty(emailsls)) {
                if (Objects.isNull(mailConnection)) {
                    return;
                }
                for (EmailsEntity email : emailsls) {
                    Message message = boxEnum.code.equals("INBOX") ? mailConnection.getMessageByUid(email.getMsgUid(),"INBOX") : mailConnection.getMessageByUid(email.getMsgUid(),"Sent Items");
                    if (Objects.isNull(message)) {
                        continue;
                    }
                    if (Integer.valueOf(0).equals(email.getIsOnlyHead())) {
                        continue;
                    }
                    String bodyContent = getEmailBodyContent(message);
                    LambdaUpdateWrapper<EmailsEntity> update = new LambdaUpdateWrapper<>();
                    update.set(EmailsEntity::getContent,bodyContent);
                    update.set(EmailsEntity::getIsOnlyHead,0);
                    update.eq(EmailsEntity::getId,email.getId());
                    update(update);
                    CompletableFuture.runAsync(() -> {
                        try {
                            pullMailAttachmentHead(email.getId(),email.getRecipientDate(),message.getContent(),smtpPop);
                        } catch (Exception e) {
                            log.error("get message content - error", e);
                        }
                    });
                }
            }
        }catch (Exception e) {
            log.error("receiveHeadContent -- error",e);
        }
    }

    @Override
    public void addLoadMailContentTask(SmtpPopSettingsEntity smtpPop) {

        ReceiveMailQueueThreadPool instance = ReceiveMailQueueThreadPool.getInstance();
        String taskName = smtpPop.getEmailAddress()+"_"+smtpPop.getOwnerBy().toString()+"_load_content";
        if (instance.getTaskInProgressByMail(taskName)) {
            log.error("有任务正在进行--:>>>>>>>>>>>>>"+taskName);
        } else {
            instance.addTask(taskName,new Runnable() {
                @Override
                public void run() {
                    loadMailContentTask(smtpPop);
                }
            });
        }
    }

    @Override
    public void loadMailContentTask(SmtpPopSettingsEntity smtpPop){
        try {
//            while (true) {
                LambdaQueryWrapper<EmailsEntity> wrapper = new LambdaQueryWrapper<>();
                wrapper.select(EmailsEntity::getId,EmailsEntity::getMsgUid,EmailsEntity::getFolder
                        ,EmailsEntity::getRecipientDate,EmailsEntity::getIsOnlyHead,EmailsEntity::getSmtpPopId);
                wrapper.eq(EmailsEntity::getIsOnlyHead, 1);
                wrapper.eq(EmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
                wrapper.eq(EmailsEntity::getSmtpPopId, smtpPop.getId());
                List<EmailsEntity> taskEntities = list(wrapper);
                if (CollectionUtils.isEmpty(taskEntities)) {
                    return;
                }
                List<EmailsEntity> inboxLs = taskEntities.stream().filter(e -> EmailBoxEnum.INBOX.code.equals(e.getFolder())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(inboxLs)) {
                    receiveBodyContentEmails(smtpPop, inboxLs, EmailBoxEnum.INBOX);
                }
                List<EmailsEntity> sentLs = taskEntities.stream().filter(e -> EmailBoxEnum.SENT.code.equals(e.getFolder())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(sentLs)) {
                    receiveBodyContentEmails(smtpPop, sentLs, EmailBoxEnum.SENT);
                }
//                if (CollectionUtils.isEmpty(sentLs) && CollectionUtils.isEmpty(sentLs)) {
//                    ret;
//                }
//            }
        } catch (Exception e) {
            log.error("Error in loadMailFiles", e);
        }
    }

    @Override
    public void addLoadMailFilesTask(SmtpPopSettingsEntity smtpPop) {

        ReceiveMailQueueThreadPool instance = ReceiveMailQueueThreadPool.getInstance();
        String taskName = smtpPop.getEmailAddress()+"_"+smtpPop.getOwnerBy()+"_load";
        if (instance.getTaskInProgressByMail(taskName)) {
            log.error("有任务正在进行--:>>>>>>>>>>>>>"+taskName);
        } else {
            instance.addTask(taskName,new Runnable() {
                @Override
                public void run() {
                    loadMailFiles(smtpPop);
                }
            });
        }
   }


    @Override
    public void loadMailFiles(SmtpPopSettingsEntity smtpPop) {
        try {
//            while (true) {
                // Query for undownloaded attachments
                LambdaQueryWrapper<MailAttachmentEntity> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(MailAttachmentEntity::getSmtpPopId, smtpPop.getId());
                wrapper.eq(MailAttachmentEntity::getDownload, 0);
                List<MailAttachmentEntity> attachments = mailAttachmentService.list(wrapper);

                // If no more attachments to download, break the loop
                if (CollectionUtils.isEmpty(attachments)) {
                    return;
                }

                // Get the corresponding email entities
                List<Long> mailIds = attachments.stream()
                        .map(MailAttachmentEntity::getEmailId)
                        .collect(Collectors.toList());

                LambdaQueryWrapper<EmailsEntity> mwrapper = new LambdaQueryWrapper<>();
                mwrapper.select(EmailsEntity::getId,EmailsEntity::getOwnerBy,EmailsEntity::getFolder,EmailsEntity::getContent,EmailsEntity::getMsgUid);
                mwrapper.in(EmailsEntity::getId, mailIds);
                List<EmailsEntity> entities = list(mwrapper);

                // If no corresponding emails, break the loop
                if (CollectionUtils.isEmpty(entities)) {
                    return;
                }
                // Download the attachments
                loadEmailsFiles(smtpPop, entities, attachments);
//            }
        } catch (Exception e) {
            log.error("Error in loadMailFiles", e);
        }
    }


    private static Map<String,String> decodeAndPrintAddresses(Address[] addresses) throws MessagingException, IOException {

        Map<String,String> map = new HashMap<>();
        if (addresses == null) return new HashMap<>();
        StringBuilder decodedAddresses = new StringBuilder();
        for (Address address : addresses) {
            InternetAddress internetAddress = (InternetAddress) address;
            String personal = internetAddress.getPersonal();
            String email = internetAddress.getAddress();
            if (personal != null) {
                personal = MimeUtility.decodeText(personal);
            }
            map.put(email,(personal != null ? personal : "N/A"));
//            decodedAddresses.append("[Name: ").append(personal != null ? personal : "N/A").append(", Email: ").append(email).append("] ");
        }
        return map;
    }

    private static String mapKeyToString(Map<String,String> map) {
        if (map == null) return "";
        String mapKey = map.entrySet().stream()
                .map(entry -> entry.getKey())
                .collect(Collectors.joining(","));
        if (("N/A").equals(mapKey)) {
            mapKey = "";
        }
        return mapKey;
    }

    private static String mapValueToString(Map<String,String> map) {
        if (map == null) return "";
        String mapKey = map.entrySet().stream()
                .map(entry -> entry.getValue())
                .collect(Collectors.joining(","));

        if (("N/A").equals(mapKey)) {
            mapKey = "";
        }
        return mapKey;
    }

    @Override
    public Boolean downloadMailAttachment(Long mailId, Date recipientDate,Object messageContent,SmtpPopSettingsEntity smtpPop) {
        try {
            String recipient = DateUtils.date2Str(recipientDate, DateUtils.yyyyMMdd);
            String downloadDir = mailFileProperties.getPath().getPath() + File.separator + smtpPop.getEmailAddress() + File.separator + recipient + File.separator;
            Object content = messageContent;
            if (content instanceof Multipart) {
                Multipart multipart = (Multipart) content;
                for (int i = 0; i < multipart.getCount(); i++) {
                    BodyPart bodyPart = multipart.getBodyPart(i);
                    if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
                        saveDownloadAttachment(bodyPart, downloadDir, smtpPop.getId(), mailId);
                    } else if (bodyPart.isMimeType("application/octet-stream")) {
                        saveDownloadAttachment(bodyPart, downloadDir, smtpPop.getId(), mailId);
                    }
                }
            }
        }catch (Exception e) {
            return false;
        }
        return true;
    }

    @Override
    public Boolean pullMailAttachmentHead(Long mailId, Date recipientDate,Object mailContent,SmtpPopSettingsEntity smtpPop) {
        try {
            if (processedDownloadMailIds.putIfAbsent(mailId, true) == null) {
                Integer mcount = mailAttachmentService.count(new LambdaQueryWrapper<MailAttachmentEntity>().eq(MailAttachmentEntity::getEmailId,mailId));
                if(mcount > 0) {
                    return Boolean.TRUE;
                }
                String recipient = DateUtils.date2Str(recipientDate,DateUtils.yyyyMMdd);
                String downloadDir = mailFileProperties.getPath().getPath()+ File.separator+smtpPop.getEmailAddress() +File.separator + recipient + File.separator;
                Object content =mailContent;
                if (content instanceof Multipart) {
                    Multipart multipart = (Multipart) content;
                    for (int i = 0; i < multipart.getCount(); i++) {
                        BodyPart bodyPart = multipart.getBodyPart(i);
                        if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) || bodyPart.isMimeType("application/octet-stream")) {
                            saveAttachmentRecord(bodyPart, downloadDir,smtpPop.getId(), mailId);
                        }
                    }
                }
            }
            processedDownloadMailIds.remove(mailId);
        }catch (Exception e) {
            processedDownloadMailIds.remove(mailId);
            return false;
        }
        return true;
    }

    @Override
    public IPage<EmailsEntity> pageWithScope(Page page, MailDTO dto) {
        return this.baseMapper.pageListNew(page,dto);
    }


    @Override
    public IPage<EmailsEntity> pageWithScopeCus(Page page, MailDTO dto) {
        return this.baseMapper.pageListCus(page,dto);
    }

    @Override
    public IPage<EmailsEntity> pageWithScopeAllCus(Page page, MailDTO dto) {
        return this.baseMapper.pageListNewAllCus(page,dto);
    }


    private void saveAttachmentRecord(BodyPart bodyPart,  String downloadDir,Long smtpPopId,Long emailId) throws MessagingException, IOException {
        String fileName = bodyPart.getFileName();
        fileName = MimeUtility.decodeText(fileName);
        fileName = fileName.replace("\n", "").replace("\r", "");
        String code =  RandomGenerateHelper.generateRandomString(6);
        // 如果不存在这创建路径
        if (!new File(downloadDir).exists()) {
            new File(downloadDir).mkdirs();
        }
        Integer size = bodyPart.getSize();
        fileName = fileName+"."+code;
        File file = new File(downloadDir +  File.separator + fileName);
        saveAttachmentToDatabase(file,code,size,smtpPopId, emailId);
    }

    public Boolean syncPullEmails(EmailsEntity entity, Message message,SmtpPopSettingsEntity smtpPop) {
        try {
            String recipient = DateUtils.date2Str(entity.getRecipientDate(),DateUtils.yyyyMMdd);
            String downloadDir = mailFileProperties.getPath().getPath()+ File.separator+smtpPop.getEmailAddress() +File.separator + recipient + File.separator;
            downloadAttachmentFromMessage(message,downloadDir,smtpPop.getId(),entity.getId());
        }catch (Exception e) {
            return false;
        }
        return true;
    }

    @Override
    public Boolean analysisDownLoadAttachment(EmailsEntity entity, Message message) {
        try {
            String recipient = DateUtils.date2Str(entity.getRecipientDate(),DateUtils.yyyyMMdd);
            String downloadDir = mailFileProperties.getPath().getPath()+ File.separator+entity.getFrom() +File.separator + recipient + File.separator;
            downloadAttachmentFromMessage(message,downloadDir,0L,entity.getId());
        }catch (Exception e) {
            return false;
        }
        return true;
    }

    @Override
    public EmailsEntity convertMessageToEmailVo(Message message,Boolean isPullHead) {

        try {
            EmailsEntity entity = new EmailsEntity();
            String subject = Objects.isNull(message.getSubject()) ? "" : MimeUtility.decodeText(message.getSubject());
            entity.setSubject(subject);
            if (subject.contains("回复")) {
                entity.setSubject(subject);
            }
            if (Objects.nonNull(message.getFolder())) {
                if (message.getFolder().getFullName().equals("INBOX")) {
                    entity.setFolder(EmailBoxEnum.INBOX.code);
                    entity.setInOutMark(1);
                }else {
                    entity.setFolder(EmailBoxEnum.SENT.code);
                    entity.setInOutMark(2);
                }
            }

            Map<String,String>  fromMap = decodeAndPrintAddresses(message.getFrom());

            entity.setFrom(mapKeyToString(fromMap));
            entity.setFromName(mapValueToString(fromMap));

            Map<String,String>  toMap = decodeAndPrintAddresses(message.getRecipients(Message.RecipientType.TO));
            entity.setRecipient(mapKeyToString(toMap));
            entity.setRecipientName(mapValueToString(toMap));

            Map<String,String>  toMapCC = decodeAndPrintAddresses(message.getRecipients(Message.RecipientType.CC));
            if (Objects.nonNull(toMapCC)) {
                entity.setRecipientCc(mapKeyToString(toMapCC));
                entity.setRecipientCcName(mapKeyToString(toMapCC));
            }
            entity.setEmailSize(Long.valueOf(message.getSize()));
            if (Objects.nonNull(message.getSentDate())) {
                entity.setSentDate(message.getSentDate());
            }
            if (Objects.nonNull(message.getReceivedDate())) {
                entity.setRecipientDate(message.getReceivedDate());
            }

            boolean isSeen = message.isSet(Flags.Flag.SEEN);
            entity.setIsRead(isSeen ? 1 : 0);
            if (isPullHead) {
                try {
                    Object content = message.getContent();
                    if (content instanceof String) {
                        entity.setIsOnlyHead(0);
                        entity.setContent(content.toString());
                    } else {
                        entity.setIsOnlyHead(1);
                    }
                } catch (Exception e){
                    log.error("message.getContent() -- error",e);
                    return entity;
                }

            } else {
                try {
                    Object content = message.getContent();
                    String argsStr = "";
                    if (content instanceof String) {
                        argsStr = message.getContent().toString();
                    } else if (content instanceof Multipart) {
                        Multipart multipart = (Multipart) content;
                        argsStr = parseMultipart(multipart);
                        argsStr = parseMultipartImage(argsStr,multipart);
                    }
                    entity.setIsOnlyHead(1);
                    entity.setContent(argsStr);
                }catch (Exception e) {
                    log.error("message.getContent() -- error",e);
                    return entity;
                }
            }
            return entity;
        }catch (Exception e) {
            log.error("convertMessageToEmailVo -- error",e);
            return null;
        }
    }

    @Override
    public Long getEmailIdByMessgeId(String messageId,Long smtpPopId) {
        return this.baseMapper.getEmailsIdByMessageId(messageId,smtpPopId);
    }

    @Override
    public EmailsEntity getEmailsByMessageId(String messageId,String folder,Long smtpPopId) {
        return this.baseMapper.getEmailsByMessageId(messageId,folder,smtpPopId);
    }

    @Override
    public List<String> getEmailMessageIdsByMessageIds(List<String> messageIds,String folder,Long smtpPopId) {
        return this.baseMapper.getEmailMessageIdsByMessageIds(messageIds,folder,smtpPopId);
    }

    @Override
    public String getEmailMessageIdsByMessageId(String messageId,String folder,Long smtpPopId) {
        return this.baseMapper.getEmailMessageIdsByMessageId(messageId,folder,smtpPopId);
    }

    @Override
    public Integer getEmailsByMessageId(String messageId,String fromAddress) {
        LambdaQueryWrapper<EmailsEntity> w = new LambdaQueryWrapper<>();
        w.eq(EmailsEntity::getMessageId,messageId);
        w.eq(EmailsEntity::getFrom,fromAddress);
        return this.baseMapper.selectCount(w);
    }


    @Override
    public String getEmailBodyContent(Message message) {
        try {
            Object content = message.getContent();
            String argsStr = "";
            if (content instanceof String) {
                argsStr = message.getContent().toString();
            } else if (content instanceof Multipart) {
                Multipart multipart = (Multipart) content;
                argsStr = parseMultipart(multipart);
                argsStr = parseMultipartImage(argsStr,multipart);
            }
            return argsStr;
        }catch (Exception e) {
            log.error("convertMessageToEmailVo -- error",e);
            return "";
        }
    }


    @Override
    public void bindLiaisonMailCustomerIdByMailIdAndUserId(Long mailId, String mailAddress, Long userId,Integer inOutMark) {
        try {
            if (StrUtil.isBlank(mailAddress)) {
                return;
            }
//            Runnable ttlRunnable = TtlRunnable.get(new Runnable() {
//                @Override
//                public void run() {
                   String lowerMailAddress = mailAddress.toLowerCase();
//                    Set<Long> cId = emailsMapper.getMailCustomerIdByMailIdAndUserId(mailId,lowerMailAddress,userId);
//                    Set<Long> lId = new HashSet<>();
//                    if (Objects.isNull(cId)) {
//                        new HashSet<>();
//                    }
//                    List<MailLiaisonVO> vos = emailsMapper.getLiaisonMailCustomerIdByMailIdAndUserId(mailId,lowerMailAddress,userId);
//                    if (!CollectionUtils.isEmpty(vos)) {
//                        Set<Long> mcId = vos.stream().map(e -> e.getCustomerId()).collect(Collectors.toSet());
//                        if (!CollectionUtils.isEmpty(mcId)) {
//                            cId.addAll(mcId);
//                        }
//                        Set<Long> lIds = vos.stream().map(e -> e.getLiaisonId()).collect(Collectors.toSet());
//                        if (!CollectionUtils.isEmpty(lIds)) {
//                            lId.addAll(lIds);
//                        }
//                    }
//                    if (!CollectionUtils.isEmpty(lId) || !CollectionUtils.isEmpty(cId)) {
//                        String customerId = CollectionUtils.isEmpty(cId) ? null : org.apache.commons.lang.StringUtils.join(cId,",");
//                        String liaisonIds = CollectionUtils.isEmpty(lId) ? null : org.apache.commons.lang.StringUtils.join(lId,",");
//                        emailsMapper.bindMailCustomerIdByMailId(mailId,customerId,liaisonIds);
//                    }

                    Object myClassInstance = SpringContextUtils.getBean("customerMailBingMarkServiceImpl");
                    Class<?> clazz = myClassInstance.getClass();
                    try {
                        Method method = clazz.getMethod("mateBindCustomerLiaisonMail",Long.class,Long.class,String.class,Integer.class);
                        method.invoke(myClassInstance,mailId,userId,lowerMailAddress,inOutMark);
                    } catch (Exception e) {
                        log.error("mateBindCustomerLiaisonFromMail --e",e);
                    }
                //}
//            });
//            ThreadPoolUtil.execute(ttlRunnable);
        }catch (Exception e) {
            log.error("bindLiaisonMailCustomerIdByMailIdAndUserId-------------------",e);
        }
    }

    private static Long getMessageId(Message message, Folder folder) throws MessagingException {
        if (folder instanceof IMAPFolder) {
            IMAPFolder imapFolder = (IMAPFolder) folder;
            return  imapFolder.getUID(message);
        } else {
            return null;
        }
    }



    private String parseMultipart(Multipart multipart) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            StringBuilder plainTextContent = new StringBuilder() ;
            StringBuilder plainHtmlContent = new StringBuilder() ;
            for (int i = 0; i < multipart.getCount(); i++) {
                BodyPart bodyPart = multipart.getBodyPart(i);
                if (bodyPart.isMimeType("text/plain")) {
                    plainTextContent.append((String) bodyPart.getContent());
                } else if (bodyPart.isMimeType("text/html")) {
                    String htmlContent = (String) bodyPart.getContent();
                    plainHtmlContent.append(htmlContent);
                } else if (bodyPart.isMimeType("multipart/alternative")) {
                    stringBuilder.append(parseMultipart((Multipart) bodyPart.getContent()));
                } else if (bodyPart.isMimeType("multipart/*")) {
                    stringBuilder.append(parseMultipart((Multipart) bodyPart.getContent()));
                }
            }
            if (StrUtil.isNotBlank(plainHtmlContent)) {
                stringBuilder.append(plainHtmlContent);
            } else {
                stringBuilder.append(plainTextContent);
            }
            return stringBuilder.toString();
        }catch (Exception e) {
            log.error("parseMultipart - error",e);
            return stringBuilder.toString();
        }
    }

    private String parseMultipartImage(String htmlContent,Multipart multipart) {
        try {
            for (int i = 0; i < multipart.getCount(); i++) {
                BodyPart bodyPart = multipart.getBodyPart(i);
                String contentType = bodyPart.getContentType();
                log.debug("contentType -="+contentType);
                if (Part.INLINE.equalsIgnoreCase(bodyPart.getDisposition()) || bodyPart.getContentType().toLowerCase().startsWith("image/")) {
                    htmlContent = processHtmlWithBase64Images(htmlContent, bodyPart);
                } else if (bodyPart.isMimeType("multipart/alternative")) {
                    htmlContent = parseMultipartImage(htmlContent,(Multipart) bodyPart.getContent());
                } else if (bodyPart.isMimeType("multipart/*")) {
                    htmlContent = parseMultipartImage(htmlContent,(Multipart) bodyPart.getContent());
                } else if (bodyPart.isMimeType("application/octet-stream")) {
                    htmlContent = processHtmlWithBase64Images(htmlContent, bodyPart);
               }
            }
        }catch (Exception e) {
           log.error("parseMultipartImage - ERROR",e);

        }
        return htmlContent;
    }

    // 处理 HTML 内容中的图片引用，替换为 base64
//    private String processHtmlWithBase64Images(String htmlContent, Multipart multipart) throws MessagingException, IOException {
//        // 找到所有 <img> 标签并处理 src="cid:"
//        String regex = "src=\"cid:(.*?)\"";
//        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regex);
//        java.util.regex.Matcher matcher = pattern.matcher(htmlContent);
//
//        while (matcher.find()) {
//            String contentId = matcher.group(1);
//            BodyPart imagePart = findImagePartByContentId(multipart, contentId);
//
//            if (imagePart != null) {
//                // 转换图片为 Base64 并替换 HTML 中的 src="cid:..."
//                String base64Image = convertImageToBase64(imagePart);
//                htmlContent = htmlContent.replace("cid:" + contentId, "data:image/png;base64," + base64Image);
//            }
//        }
//
//        return htmlContent;
//    }

    private String processHtmlWithBase64Images(String htmlContent, BodyPart bodyPart) throws MessagingException, IOException {
        // 找到所有 <img> 标签并处理 src="cid:"
        String contentId = ((MimeBodyPart) bodyPart).getContentID();
//        String contentId = ((IMAPBodyPart) bodyPart).getContentID();
        if (StrUtil.isBlank(contentId)) {
            if (bodyPart.getHeader("Content-ID") != null) {
                contentId = bodyPart.getHeader("Content-ID").toString();
            }
        }
        if (StrUtil.isNotBlank(contentId)) {
            BodyPart imagePart = bodyPart;
            if (imagePart != null) {
                // 转换图片为 Base64 并替换 HTML 中的 src="cid:..."
                contentId = contentId.replaceAll("^<(.+)>$", "$1");
                String base64Image = convertImageToBase64(imagePart);
                htmlContent = htmlContent.replace("cid:" + contentId, "data:image/png;base64," + base64Image);
            }
        }
        return htmlContent;
    }

    // 根据 Content-ID 查找对应的图片部分
    private BodyPart findImagePartByContentId(Multipart multipart, String contentId) throws MessagingException {
        for (int i = 0; i < multipart.getCount(); i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            if (bodyPart.getHeader("Content-ID") != null) {
                String[] contentIdHeader = bodyPart.getHeader("Content-ID");
                if (contentIdHeader[0].contains(contentId)) {
                    return bodyPart; // 找到匹配的图片
                }
            }
        }
        return null; // 未找到匹配的图片
    }

    // 将图片转换为 Base64 字符串
    private String convertImageToBase64(BodyPart bodyPart) throws IOException, MessagingException {
        InputStream inputStream = bodyPart.getInputStream();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }

        // 将图片转换为 Base64 编码
        byte[] imageBytes = outputStream.toByteArray();
        return Base64.getEncoder().encodeToString(imageBytes);
    }

    private void downloadAttachmentFromMessage(Message message, String downloadDir,Long smtpPopId,Long emailId) {
        try {
            Object content = message.getContent();
            if (content instanceof Multipart) {
                Multipart multipart = (Multipart) content;
                for (int i = 0; i < multipart.getCount(); i++) {
                    BodyPart bodyPart = multipart.getBodyPart(i);
                    if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) || bodyPart.isMimeType("application/octet-stream")) {
                        saveDownloadAttachment(bodyPart, downloadDir,smtpPopId,emailId);
                    }
                }
            }
        }catch (Exception e) {
            log.error("downloadAttachmentFromMessage -- error = ",e);
        }
    }

    private void saveDownloadAttachment(BodyPart bodyPart,  String downloadDir,Long smtpPopId,Long emailId) {
        try {
            String fileName = bodyPart.getFileName();
            fileName = MimeUtility.decodeText(fileName);
            fileName = fileName.replace("\n", "").replace("\r", "");
            String code =  RandomGenerateHelper.generateRandomString(6);
            // 如果不存在这创建路径
            Integer size = bodyPart.getSize();
            if (!new File(downloadDir).exists()) {
                new File(downloadDir).mkdirs();
            }
            fileName = fileName+"."+code;
            File file = new File(downloadDir +  File.separator + fileName);
            try (FileOutputStream output = new FileOutputStream(file)) {
                bodyPart.getInputStream().transferTo(output);
            }
            saveAttachmentToDatabase(file,code,size,smtpPopId,emailId);
        }catch (Exception e) {
            log.error("saveDownloadAttachment -- error",e);
        }

    }

    private void saveAttachmentHeader(BodyPart bodyPart,  String downloadDir,Long smtpPopId,Long emailId) throws MessagingException, IOException {
        String fileName = bodyPart.getFileName();
        fileName = MimeUtility.decodeText(fileName);
        fileName = fileName.replace("\n", "").replace("\r", "");
        String code =  RandomGenerateHelper.generateRandomString(6);
        // 如果不存在这创建路径
        Integer size = bodyPart.getSize();
        if (!new File(downloadDir).exists()) {
            new File(downloadDir).mkdirs();
        }
        fileName = fileName+"."+code;
        File file = new File(downloadDir +  File.separator + fileName);
        saveAttachmentToDatabase(file,code,size,smtpPopId,emailId);
    }


    private void saveAttachmentToDatabase(File file,String code,Integer size,Long smtpPopId,Long emailId) {
        String fileName = file.getName().replace("."+code,"");
        String fName = FilenameUtils.getBaseName(fileName);
        String fExt = FilenameUtils.getExtension(fileName);
        LambdaQueryWrapper<MailAttachmentEntity> l =  new LambdaQueryWrapper<>();
        l.eq(MailAttachmentEntity::getFileName,fName);
        l.eq(MailAttachmentEntity::getEmailId,emailId);
        l.eq(MailAttachmentEntity::getFileExt,fExt);
        l.eq(MailAttachmentEntity::getFileSize,Long.valueOf(size));
        l.eq(MailAttachmentEntity::getSmtpPopId,smtpPopId);
        l.last("limit 1");
        Integer c = mailAttachmentService.count(l);
        if (c == 0) {
            MailAttachmentEntity attachment = new MailAttachmentEntity();
            attachment.setEmailId(emailId);
            attachment.setSmtpPopId(smtpPopId);
            attachment.setFileCode(code);
            attachment.setFileName(fName);
            attachment.setFilePath(file.getAbsolutePath().replace(mailFileProperties.getPath().getPath(),""));
            attachment.setFileExt(fExt);
            attachment.setFileSize(Long.valueOf(size));
            mailAttachmentService.saveOrUpdate(attachment);
        }
    }

    private Session getSendEmailsSession(SmtpPopSettingsEntity smtpPop) {

        Properties properties = new Properties();
        properties.put("mail.smtp.host", smtpPop.getSmtpServer());
        properties.put("mail.smtp.port", smtpPop.getSmtpPort());
        properties.put("mail.smtp.auth", "true");
        properties.put("mail.user", smtpPop.getEmailAddress());
        properties.put("mail.smtp.starttls.enable",Integer.valueOf(1).equals(smtpPop.getSmtpTls()) ? "true" : "false");
        properties.put("mail.smtp.ssl.enable", Integer.valueOf(1).equals(smtpPop.getSmtpSsl()) ? "true" : "false");

        Session session = Session.getInstance(properties, new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(smtpPop.getEmailAddress(), smtpPop.getEmailPassword());
            }
        });
        return session;
    }

    private EmailsEntity saveSendEmails(SendMailDTO dto,String fromAddress,String fromNickname,Long replyMsgId,Long sizeInBytes) {
        try {
            EmailsEntity entity = new EmailsEntity();
            String subject =  MimeUtility.decodeText(dto.getSubject());
            entity.setSubject(subject);
            entity.setSentDate(new Date());
            entity.setIsRead(Integer.valueOf(1));
            if (Objects.nonNull(dto.getDelaySendTime())) {
                entity.setDelaySendTime(dto.getDelaySendTime());
                entity.setStatus(-1);
            } else {
                entity.setStatus(0);
            }
            if (Objects.nonNull(replyMsgId)) {
                entity.setReplyMsgId(replyMsgId);
            }
            if (Objects.nonNull(dto.getId())) {
                entity.setId(dto.getId());
            }
            if (Objects.nonNull(dto.getIsReceipt())) {
                entity.setIsReceipt(dto.getIsReceipt());
            }
            entity.setEmailSize(sizeInBytes);
            entity.setFromName(fromNickname);
            entity.setFrom(fromAddress);
            if (!CollectionUtils.isEmpty(dto.getRecipientls())) {
                entity.setRecipient(StringUtil.join(dto.getRecipientls(),","));
            }
            if (!CollectionUtils.isEmpty(dto.getRecipientCcls())) {
                entity.setRecipientCc(StringUtil.join(dto.getRecipientCcls(),","));
            }
            if (!CollectionUtils.isEmpty(dto.getRecipientBccls())) {
                entity.setRecipientBcc(StringUtil.join(dto.getRecipientBccls(),","));
            }
            entity.setSubject(dto.getSubject());
            entity.setContent(dto.getContent());
            entity.setFolder(EmailBoxEnum.SENTING.code);
            return entity;
        }catch (Exception e) {
            return null;
        }
    }

    private EmailsEntity updateSendEmailStatus(Long emailId) {
        try {
            EmailsEntity entity = new EmailsEntity();
            entity.setId(emailId);
            entity.setStatus(Integer.valueOf(1));
            entity.setFolder(EmailBoxEnum.SENT.code);
            updateById(entity);
            return entity;
        }catch (Exception e) {
            return null;
        }
    }

    @Override
    public void analysisMailEml(List<Message> messages,Set<String> cusMails,Long ownerBy) {
        if (CollectionUtils.isEmpty(messages) || CollectionUtils.isEmpty(cusMails)) {
            return;
        }   List<Message> messagels = messages;
        for (Message message : messagels) {
            Set<String> cusAddressls = cusMails;
            try {
                String[] r = message.getHeader("Message-ID");
                if (Objects.isNull(r)) {
                    continue;
                }
                String messageId = message.getHeader("Message-ID")[0];
                Map<String, String> fromMap = decodeAndPrintAddresses(message.getFrom());
                String fromAddress = mapKeyToString(fromMap);
                Integer count = this.getEmailsByMessageId(messageId, fromAddress);
                if (!Integer.valueOf(0).equals(count)) {
                    log.error("getEmailsByMessageId-----" + messageId);
                    continue;
                }
                EmailsEntity entity = convertMessageToEmailVo(message, false);
                if (Objects.isNull(entity)) {
                    continue;
                }
                entity.setMessageId(messageId);

                if (StrUtil.isBlank(entity.getFromName())) {
                    entity.setFromName(StringUtil.extractUsernames(entity.getFrom()));
                }
                if (StrUtil.isBlank(entity.getRecipientName())) {
                    entity.setRecipientName(StringUtil.extractUsernames(entity.getRecipient()));
                }
                if (StrUtil.isBlank(entity.getRecipientCcName())) {
                    entity.setRecipientCcName(StringUtil.extractUsernames(entity.getRecipientCc()));
                }
                if (cusAddressls.contains(entity.getFrom())) {
                    entity.setInOutMark(1);
                    entity.setFolder("INBOX");
                } else {
                    entity.setInOutMark(2);
                    entity.setFolder("SENT");
                }
                if (Objects.isNull(entity.getRecipientDate())) {
                    entity.setRecipientDate(entity.getSentDate());
                }
                entity.setSourceType(1);
                entity.setOwnerBy(ownerBy);
                entity.setUpdateBy(1L);
                entity.setCreateBy(1L);
                entity.setIsOnlyHead(0);

                Boolean b = saveOrUpdate(entity);
                if (b) {
                    analysisDownLoadAttachment(entity, message);
                    /**
                     * 加载附件
                     */
                    if (Integer.valueOf(1).equals(entity.getInOutMark())) {
                        bindLiaisonMailCustomerIdByMailIdAndUserId(entity.getId(), entity.getFrom(), 1L, 1);
                    } else {
                        String recipient = entity.getRecipient();
                        if (StrUtil.isNotBlank(entity.getRecipientCc())) {
                            if (StrUtil.isNotBlank(recipient)) {
                                recipient = recipient + "," + entity.getRecipientCc();
                            } else {
                                recipient = entity.getRecipientCc();
                            }
                        }
                        bindLiaisonMailCustomerIdByMailIdAndUserId(entity.getId(), recipient, 1L, 2);
                    }
                }
            } catch (Exception e) {
                log.error("analysisMailEml -- error:", e);
            }
        }

    }


    @Override
    public List<EmailsEntity> analysisMailEmlls(List<Message> messages,Set<String> internalMails,Long ownerBy) {

        List<EmailsEntity> entities = new ArrayList<>();

        if (CollectionUtils.isEmpty(messages) || CollectionUtils.isEmpty(internalMails)) {
           return  entities;
        }
        List<Message> messagels = messages;
        for (Message message : messagels) {

            try {
                String[] r = message.getHeader("Message-ID");
                if (Objects.isNull(r)) {
                    continue;
                }
                String messageId = message.getHeader("Message-ID")[0];
                Map<String, String> fromMap = decodeAndPrintAddresses(message.getFrom());
                String fromAddress = mapKeyToString(fromMap);
                Integer count = this.getEmailsByMessageId(messageId, fromAddress);
                if (!Integer.valueOf(0).equals(count)) {
                    log.error("getEmailsByMessageId-----" + messageId);
                    continue;
                }
                EmailsEntity entity = convertMessageToEmailVo(message, false);
                if (Objects.isNull(entity)) {
                    continue;
                }
                entity.setMessageId(messageId);

                if (StrUtil.isBlank(entity.getFromName())) {
                    entity.setFromName(StringUtil.extractUsernames(entity.getFrom()));
                }
                if (StrUtil.isBlank(entity.getRecipientName())) {
                    entity.setRecipientName(StringUtil.extractUsernames(entity.getRecipient()));
                }
                if (StrUtil.isBlank(entity.getRecipientCcName())) {
                    entity.setRecipientCcName(StringUtil.extractUsernames(entity.getRecipientCc()));
                }
                /**
                 * 如果发件箱是内部邮箱，则代表是发出去的邮件
                 */
                if (internalMails.contains(entity.getFrom())) {
                    entity.setInOutMark(2);
                    entity.setFolder("SENT");
                } else {
                    entity.setInOutMark(1);
                    entity.setFolder("INBOX");
                }
                if (Objects.isNull(entity.getRecipientDate())) {
                    entity.setRecipientDate(entity.getSentDate());
                }
                entity.setSourceType(1);
                entity.setOwnerBy(ownerBy);
                entity.setUpdateBy(1L);
                entity.setCreateBy(1L);
                entity.setIsOnlyHead(0);

                Boolean b = saveOrUpdate(entity);
                if (b) {
                    entities.add(entity);
                }
            } catch (Exception e) {
                log.error("analysisMailEml -- error:", e);
            }
        }
        return entities;
    }

//    public void pullMailRecord(SmtpPopSettingsEntity smtpPop, String folderName, EmailBoxEnum boxEnum, List<Integer> messageIds) {
//        MailProperties properties = new MailProperties(smtpPop);
//        MailConnection mailConnection = MailConnectionUtil.receiveEmailsConnection(properties);
//        if (Objects.isNull(mailConnection)) {
//            return;
//        }
//        try {
//            Store store = mailConnection.getStore();
//            Folder inbox = store.getFolder(folderName);
//            inbox.open(Folder.READ_WRITE);
//
//            int[] intArray = messageIds.stream().mapToInt(Integer::intValue).toArray();
//            Message[] messages  = inbox.getMessages(intArray);
//            for (Message message : messages) {
//                String messageId = message.getHeader("Message-ID")[0];
//                EmailsEntity entity = convertMessageToEmailVo(message,false);
//                if (Objects.isNull(entity)) {
//                    return;
//                }
//                entity.setSmtpPopId(smtpPop.getId());
//                entity.setMsgUid(messageId);
//                entity.setFolder(boxEnum.code);
//                Boolean b = this.save(entity);
//                if(b) {
//                    syncPullEmails(entity,message,folderName,smtpPop);
//                }
//            }
//            mailConnection.close();
//        }catch (Exception e) {
//            log.error("receiveEmails - error =",e);
//            mailConnection.close();
//        }
//    }

    public static void main(String[] args) {
        try {
            String baseDir = "D:/mail/attachment/rena@renice-tech.com/20240911";
            String fileName = "Datasheet(128G SLC)-Renice X5 2.5 SATAII SSD V1.2 Version.pdf.KrhPNh";
            Path filePath = Paths.get(baseDir, fileName);
            File file = new File(filePath.toUri());
            File parentDir = file.getParentFile();
            // 如果父目录不存在，则递归创建
            if (parentDir != null && !parentDir.exists()) {
                parentDir.mkdirs();  // mkdirs() 会创建所有必要的父目录
            }
            String content = "这是要写入文件的字符串内容";

            try (InputStream inputStream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
                 FileOutputStream output = new FileOutputStream(file)) {
                inputStream.transferTo(output); // 将字符串流写入文件
            }
            System.out.println("-----------------------"+filePath);
        }catch (Exception e) {
            log.error(e);
        }

    }
}
