package com.smppw.modaq.application.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.mail.JakartaUserPassAuthenticator;
import com.smppw.modaq.common.conts.EmailTypeConst;
import com.smppw.modaq.common.conts.PatternConsts;
import com.smppw.modaq.common.enums.ReportType;
import com.smppw.modaq.domain.dto.MailboxInfoDTO;
import com.sun.mail.imap.IMAPStore;
import jakarta.mail.MessagingException;
import jakarta.mail.Part;
import jakarta.mail.Session;
import jakarta.mail.Store;
import jakarta.mail.internet.MimeUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;

/**
 * @author mozuwen
 * @date 2024-09-04
 * @description 邮件解析工具
 */
public class EmailUtil {

    private static final Logger logger = LoggerFactory.getLogger(EmailUtil.class);

    private static final String POP3 = "pop3";
    private static final String IMAP = "imap";

    // 解码文件名（处理 RFC 2231 和 RFC 2047）
    public static String decodeFileName(Part part) throws UnsupportedEncodingException, MessagingException {
        String filename = part.getFileName();

        // 优先尝试 RFC 2231 的 filename*（如 "filename*=utf-8''%E4%B8%AD%E6%96%87.txt"）
        String[] values = part.getHeader("Content-Disposition");
        if (values != null) {
            for (String value : values) {
                if (value.startsWith("filename*")) {
                    filename = value.split("'")[2]; // 提取编码后的字符串
                    filename = MimeUtility.decodeText(filename);
                    return filename;
                }
            }
        }

        // 处理 RFC 2047 的多段编码（如 "=?utf-8?B?5Lit?= =?utf-8?B?5paH?=.txt"）
        if (filename != null && filename.contains("=?")) {
            return MimeUtility.decodeText(filename);
        }

        return filename;
    }

//    /**
//     * 采集邮件(多消息体)信息
//     *
//     * @param message      邮件
//     * @param emailAddress 邮箱地址
//     * @param path         存储路径
//     * @return 从邮箱采集到的信息
//     * @throws Exception 异常信息
//     */
//    public static List<EmailContentInfoDTO> collectMimeMultipart(Message message, String emailAddress, String path) throws Exception {
//        List<EmailContentInfoDTO> emailContentInfoDTOList = CollUtil.newArrayList();
//        String emailTitle = message.getSubject();
//        String emailDate = DateUtils.format(message.getSentDate(), DateConst.YYYYMMDDHHMMSS24);
//        String emailDateStr = DateUtils.format(message.getSentDate(), DateConst.YYYYMMDD);
//        String filePath = path + File.separator + emailAddress + File.separator + emailDateStr + File.separator;
//
//        MimeMultipart mimeMultipart = (MimeMultipart) message.getContent();
//        int length = mimeMultipart.getCount();
//        // 遍历邮件消息体 (我这里不要html正文)
//        for (int i = 0; i < length; i++) {
//            EmailContentInfoDTO emailContentInfoDTO = new EmailContentInfoDTO();
//            MimeBodyPart part = (MimeBodyPart) mimeMultipart.getBodyPart(i);
//            Object partContent = part.getContent();
//            String contentClass = part.getContent().getClass().getSimpleName();
//            // 1.邮件正文
//            switch (contentClass) {
//                case "String" -> {
//                    // 文件名 = 邮件主题 + 邮件日期
//                    String fileName = emailTitle + "_" + emailDate + ".html";
//                    String content = partContent.toString();
//                    emailContentInfoDTO = collectTextPart(part, content, filePath, fileName);
//                }
//                case "BASE64DecoderStream" -> {
//                    if (StrUtil.isNotBlank(part.getFileName())) {
//                        String fileName = MimeUtility.decodeText(part.getFileName());
//                        if (isSupportedFileType(fileName)) {
//                            continue;
//                        }
//                        emailContentInfoDTO.setFileName(fileName);
//
//                        String realPath = filePath + emailDate + fileName;
//
//                        File saveFile = cn.hutool.core.io.FileUtil.file(realPath);
//                        if (!saveFile.exists()) {
//                            if (!saveFile.getParentFile().exists()) {
//                                saveFile.getParentFile().mkdirs();
//                            }
//                            FileUtil.saveFile(saveFile, part);
//                        } else {
//                            cn.hutool.core.io.FileUtil.del(saveFile);
//                            FileUtil.saveFile(saveFile, part);
//                        }
//                        emailContentInfoDTO.setFilePath(realPath);
//                    }
//                }
//                case "MimeMultipart" -> {
//                    MimeMultipart contentPart = (MimeMultipart) partContent;
//                    int length2 = contentPart.getCount();
//                    for (int i2 = 0; i2 < length2; i2++) {
//                        part = (MimeBodyPart) contentPart.getBodyPart(i2);
//                        partContent = part.getContent();
//                        contentClass = partContent.getClass().getSimpleName();
//                        if ("String".equals(contentClass)) {
//                            // 文件名 = 邮件主题 + 邮件日期
//                            String fileName = emailTitle + "_" + emailDate + ".html";
//                            String content = partContent.toString();
//                            emailContentInfoDTO = collectTextPart(part, content, filePath, fileName);
//                        }
//                    }
//                }
//            }
//            String filepath = emailContentInfoDTO.getFilePath();
//            if (emailContentInfoDTO.getEmailContent() == null && filepath == null) {
//                continue;
//            }
//            emailContentInfoDTO.setEmailAddress(emailAddress);
//            emailContentInfoDTO.setEmailTitle(emailTitle);
//            emailContentInfoDTO.setEmailDate(DateUtils.format(message.getSentDate(), DateConst.YYYY_MM_DD_HH_MM_SS));
//            emailContentInfoDTOList.add(emailContentInfoDTO);
//        }
//
//        return emailContentInfoDTOList;
//    }

//    private static List<EmailContentInfoDTO> zipFile(String filepath) {
//        return null;
//    }

//    private static boolean isSupportedFileType(String fileName) {
//        if (StrUtil.isBlank(fileName)) {
//            return true;
//        }
//        return !ExcelUtil.isZip(fileName) && !ExcelUtil.isExcel(fileName) && !ExcelUtil.isPdf(fileName) && !ExcelUtil.isHTML(fileName) && !ExcelUtil.isRAR(fileName);
//    }

//    /**
//     * 根据日期过滤邮件
//     *
//     * @param messages  采集到的邮件
//     * @param startDate 邮件起始日期
//     * @param endDate   邮件截止日期
//     * @return 符合日期的邮件
//     */
//    public static List<Message> filterMessage(Message[] messages, Date startDate, Date endDate) {
//        long startTime = System.currentTimeMillis();
//        List<Message> messageList = CollUtil.newArrayList();
//        if (messages == null) {
//            return messageList;
//        }
//        for (Message message : messages) {
//            try {
//                if (message.getSentDate().compareTo(startDate) >= 0 && message.getSentDate().compareTo(endDate) <= 0) {
//                    messageList.add(message);
//                }
//            } catch (MessagingException e) {
//                throw new RuntimeException(e);
//            }
//        }
//        logger.info("根据日期过滤邮件耗时 -> {}ms", (System.currentTimeMillis() - startTime));
//        return messageList;
//    }

//    /**
//     * 采集邮件正文
//     *
//     * @param part        邮件消息体
//     * @param partContent 邮件消息内筒
//     * @param filePath    文件路径
//     * @param fileName    文件名
//     * @return 采集到邮件正文(html格式包含table标签)
//     */
//    public static EmailContentInfoDTO collectTextPart(MimeBodyPart part, String partContent, String filePath, String fileName) {
//        EmailContentInfoDTO emailContentInfoDTO = new EmailContentInfoDTO();
//        try {
//            if ((part.getContentType().contains("text/html") || part.getContentType().contains("TEXT/HTML"))) {
//                emailContentInfoDTO.setEmailContent(partContent);
//                String savePath = filePath + fileName;
//                File saveFile = new File(savePath);
//                if (!saveFile.exists()) {
//                    if (!saveFile.getParentFile().exists()) {
//                        saveFile.getParentFile().mkdirs();
//                        saveFile.getParentFile().setExecutable(true);
//                    }
//                }
//                //获取邮件编码
//                String contentType = part.getContentType();
//                String html = partContent.toString();
//                try {
//                    if (contentType.contains("charset=")) {
//                        contentType = contentType.substring(contentType.indexOf("charset=") + 8).replaceAll("\"", "");
//                        html = html.replace("charset=" + contentType.toLowerCase(), "charset=UTF-8");
//                        html = html.replace("charset=" + contentType.toUpperCase(), "charset=UTF-8");
//                    }
//                    if (savePath.contains(":")) {
//                        savePath = savePath.replaceAll(":", "");
//                    }
//                    cn.hutool.core.io.FileUtil.writeUtf8String(html, new File(savePath));
//                } catch (Exception e) {
//                    logger.error(e.getMessage(), e);
//                }
//                emailContentInfoDTO.setFileName(fileName);
//                emailContentInfoDTO.setFilePath(savePath);
//            } else {
//                try {
//                    if (part.getFileName() == null) {
//                        return emailContentInfoDTO;
//                    }
//                    String fileName1 = MimeUtility.decodeText(part.getFileName());
//                    if (isSupportedFileType(fileName1)) {
//                        return emailContentInfoDTO;
//                    }
//                    emailContentInfoDTO.setFileName(fileName1);
//                    String realPath = filePath + fileName1;
//                    File saveFile = new File(realPath);
//                    if (!saveFile.exists()) {
//                        if (!saveFile.getParentFile().exists()) {
//                            saveFile.getParentFile().mkdirs();
//                        }
//                        FileUtil.saveFile(saveFile, part);
//                    } else {
//                        cn.hutool.core.io.FileUtil.del(saveFile);
//                        FileUtil.saveFile(saveFile, part);
//                    }
//                    emailContentInfoDTO.setFilePath(realPath);
//                } catch (Exception e) {
//                    return emailContentInfoDTO;
//                }
//            }
//        } catch (MessagingException e) {
//            logger.info("邮件正文采集失败 -> 文件名:{}, 报错堆栈:{}", fileName, ExceptionUtil.stacktraceToString(e));
//            return emailContentInfoDTO;
//        }
//        return emailContentInfoDTO;
//    }

    public static Map<Integer, List<String>> getEmailType() {
        Map<Integer, List<String>> emailTypeMap = MapUtil.newHashMap(3, true);
        // 1.确认函
        emailTypeMap.put(EmailTypeConst.REPORT_LETTER_EMAIL_TYPE,
                ListUtil.toList(ReportType.LETTER.getPatterns()));
        // 2.周报
        emailTypeMap.put(EmailTypeConst.REPORT_WEEKLY_TYPE,
                ListUtil.toList(ReportType.WEEKLY.getPatterns()));
        // 3.其他
        emailTypeMap.put(EmailTypeConst.REPORT_OTHER_TYPE,
                ListUtil.toList(ReportType.OTHER.getPatterns()));
        // 4.定期报告的类型判断
        List<String> types = ListUtil.list(true);
        CollUtil.addAll(types, ReportType.QUARTERLY.getPatterns());
        CollUtil.addAll(types, ReportType.ANNUALLY.getPatterns());
        CollUtil.addAll(types, ReportType.MONTHLY.getPatterns());
        emailTypeMap.put(EmailTypeConst.REPORT_EMAIL_TYPE, types);
        return emailTypeMap;
    }

    /**
     * 判断邮件是否符合解析条件
     *
     * @param subject 邮件主题
     * @return 邮件类型:1-净值,2-估值表,3-定期报告 -> 兜底为净值类型
     */
    public static Integer getEmailTypeBySubject(String subject) {
        Map<Integer, List<String>> emailTypeMap = getEmailType();
        if (MapUtil.isEmpty(emailTypeMap) || StrUtil.isBlank(subject)) {
            return EmailTypeConst.NAV_EMAIL_TYPE;
        }
        for (Map.Entry<Integer, List<String>> emailTypeEntry : emailTypeMap.entrySet()) {
            for (String field : emailTypeEntry.getValue()) {
                if (subject.contains(field)) {
                    return emailTypeEntry.getKey();
                }
            }
        }
        // 特殊月报识别规则（没有月报或月度等关键字的月报）
        Matcher monthMatcher = PatternConsts.MONTHLY_PATTERN.matcher(subject);
        Matcher dayMatcher = PatternConsts.DAY_PATTERN.matcher(subject);
        if (monthMatcher.find() && !dayMatcher.find()) {
            return EmailTypeConst.REPORT_EMAIL_TYPE;
        }
        return EmailTypeConst.NAV_EMAIL_TYPE;
    }

    public static Store getStoreNew(MailboxInfoDTO mailboxInfoDTO) {
        // 配置连接邮件服务器参数
        Properties props = getMailProps(mailboxInfoDTO);
        // 创建Session实例对象
        Session session = Session.getInstance(props, new JakartaUserPassAuthenticator(mailboxInfoDTO.getAccount(), mailboxInfoDTO.getPassword()));
        Store store;
        try {
            String protocol = mailboxInfoDTO.getProtocol().equals(IMAP) ? "imaps" : "pop3";
            if (mailboxInfoDTO.getProtocol().contains(IMAP)) {
                IMAPStore imapStore = (IMAPStore) session.getStore(protocol);
                imapStore.connect(mailboxInfoDTO.getHost(), mailboxInfoDTO.getAccount(), mailboxInfoDTO.getPassword());
                // 网易邮箱需要带上身份标识,详情请看:https://www.hmail163.com/content/?404.html
                Map<String, String> clientParams = new HashMap<>(2);
                clientParams.put("name", "my-imap");
                clientParams.put("version", "1.0");
                imapStore.id(clientParams);
                return imapStore;
            } else {
                store = session.getStore(protocol);
                store.connect(mailboxInfoDTO.getHost(), mailboxInfoDTO.getAccount(), mailboxInfoDTO.getPassword());
                return store;
            }
        } catch (Exception e) {
            logger.error("邮箱信息:{},服务器参数:{}", mailboxInfoDTO, props);
            logger.error("连接邮箱报错堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
            return null;
        }
    }

    public static Properties getMailProps(MailboxInfoDTO mailboxInfoDTO) {
        Properties props = new Properties();
        if (mailboxInfoDTO.getProtocol().equalsIgnoreCase(POP3)) {
            props.put("mail.pop3.host", mailboxInfoDTO.getHost());
            props.put("mail.pop3.user", mailboxInfoDTO.getAccount());
            props.put("mail.pop3.socketFactory", mailboxInfoDTO.getPort());
            props.put("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            props.put("mail.pop3.port", mailboxInfoDTO.getPort());
            props.put("mail.store.protocol", mailboxInfoDTO.getProtocol());
        }
        if (mailboxInfoDTO.getProtocol().equalsIgnoreCase(IMAP)) {
            props.put("mail.store.protocol", "imaps");
            props.put("mail.imap.host", mailboxInfoDTO.getHost());
            props.put("mail.imap.port", mailboxInfoDTO.getPort());
            props.put("mail.imaps.ssl.enable", "true");
            props.put("mail.imaps.ssl.trust", "*");
            props.put("mail.imap.auth", "true");
            props.put("mail.imap.starttls.enable", "true");
            props.put("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            props.put("mail.imap.socketFactory.fallback", "false");
            // 关闭读取附件时分批获取 BASE64 输入流的配置
            props.put("mail.imap.partialfetch", false);
            props.put("mail.imaps.partialfetch", false);
        }
        return props;
    }

//    public static void senEmail(MailboxInfoDTO mailboxInfoDTO, String emails, File file, String htmlText, String host, String emailTitle) throws Exception {
//        logger.info("send email begin .........");
//        // 根据Session 构建邮件信息
//        MimeMessage message = new MimeMessage(getSession(mailboxInfoDTO));
//        // 创建邮件发送者地址
//        Address from = new InternetAddress(mailboxInfoDTO.getAccount() + host);
//        String[] emailArr = emails.split(";");
//        Address[] toArr = new Address[emailArr.length];
//        for (int idx = 0; idx < emailArr.length; idx++) {
//            if (StrUtil.isNotBlank(emailArr[idx])) {
//                Address to = new InternetAddress(emailArr[idx]);
//                toArr[idx] = to;
//            }
//        }
//        message.setFrom(from);
//        message.setRecipients(Message.RecipientType.TO, toArr);
//        // 邮件主题
//        message.setSubject(emailTitle);
//        // 邮件容器
//        MimeMultipart mimeMultiPart = new MimeMultipart();
//        // 设置HTML
//        BodyPart bodyPart = new MimeBodyPart();
//        logger.info("组装 htmlText.........");
//        // 邮件内容
//        bodyPart.setContent(htmlText, "text/html;charset=utf-8");
//        //设置附件
//        BodyPart filePart = new MimeBodyPart();
//        filePart.setFileName(file.getName());
//        filePart.setDataHandler(
//                new DataHandler(
//                        new ByteArrayDataSource(
//                                Files.readAllBytes(Paths.get(file.getAbsolutePath())), "application/octet-stream")));
//        mimeMultiPart.addBodyPart(bodyPart);
//        mimeMultiPart.addBodyPart(filePart);
//        message.setContent(mimeMultiPart);
//        message.setSentDate(new Date());
//        // 保存邮件
//        message.saveChanges();
//        // 发送邮件
//        Transport.send(message);
//    }

//    public static Session getSession(MailboxInfoDTO mailboxInfoDTO) {
//        try {
//            Properties properties = new Properties();
//            properties.put("mail.smtp.host", mailboxInfoDTO.getHost());
//            properties.put("mail.smtp.auth", true);
//            properties.put("mail.smtp.port", mailboxInfoDTO.getPort());
//            properties.put("mail.smtp.ssl.enable", true);
//            final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
//            properties.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
//            properties.setProperty("mail.smtp.socketFactory.fallback", "false");
//            properties.setProperty("mail.smtp.socketFactory.port", mailboxInfoDTO.getPort());
//            // 根据邮件的会话属性构造一个发送邮件的Session，
//            JakartaUserPassAuthenticator authenticator = new JakartaUserPassAuthenticator(mailboxInfoDTO.getAccount(), mailboxInfoDTO.getPassword());
//            return Session.getInstance(properties, authenticator);
//        } catch (Exception e) {
//            logger.error("getSession : {}", e.getMessage());
//        }
//        return null;
//    }

    public static void main(String[] args) {
        String text = "私募基金2024年04月度报告";
        System.out.println(getEmailTypeBySubject(text));
//
//        text = "私募基金202404月度报告";
//        System.out.println(matchReportDate(text));
//        System.out.println(matchReportType(3, text));
//
//        text = "私募基金2024_04月度报告";
//        System.out.println(matchReportDate(text));
//        System.out.println(matchReportType(3, text));
//
//        text = "私募基金2024_4月度报告";
//        System.out.println(matchReportDate(text));
//        System.out.println(matchReportType(3, text));
//
//        text = "私募基金2024-04月度报告";
//        System.out.println(matchReportDate(text));
//        System.out.println(matchReportType(3, text));
//
//        text = "私募基金2024_04月";
//        System.out.println(matchReportDate(text));
//        System.out.println(matchReportType(3, text));

        text = "私募基金2024年04月12号";
        System.out.println(getEmailTypeBySubject(text));

        text = "私募基金20240412";
        System.out.println(getEmailTypeBySubject(text));

        text = "私募基金2024041201";
        System.out.println(getEmailTypeBySubject(text));

        text = "私募基金_202404";
        System.out.println(getEmailTypeBySubject(text));
    }
}
