package com.yushu.system.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yushu.common.config.YuShuConfig;
import com.yushu.common.utils.StringUtils;
import com.yushu.common.utils.file.FileUploadUtils;
import com.yushu.system.domain.SysMailConfig;
import com.yushu.system.domain.SysMailInbox;
import com.yushu.system.mapper.SysMailConfigMapper;
import com.yushu.system.mapper.SysMailInboxMapper;
import com.yushu.system.service.ISysMailInboxService;
import jakarta.mail.*;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMultipart;
import jakarta.mail.internet.MimeUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import jakarta.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 收件箱Service业务层处理
 * 
 * @author yushu
 * @date 2024-12-13
 */
@Service
public class SysMailInboxServiceImpl implements ISysMailInboxService {

    private static final Logger log = LoggerFactory.getLogger(SysMailInboxServiceImpl.class);
    

    @Autowired
    private SysMailInboxMapper sysMailInboxMapper;

    @Autowired
    private SysMailConfigMapper sysMailConfigMapper;

    @Override
    public SysMailInbox selectSysMailInboxByInboxId(Long inboxId) {
        return sysMailInboxMapper.selectSysMailInboxByInboxId(inboxId);
    }

    @Override
    public List<SysMailInbox> selectSysMailInboxList(SysMailInbox sysMailInbox) {
        return sysMailInboxMapper.selectSysMailInboxList(sysMailInbox);
    }

    @Override
    public int selectUnreadCount(Long configId) {
        return sysMailInboxMapper.selectUnreadCount(configId);
    }

    @Override
    public int markAsRead(Long inboxId) {
        return sysMailInboxMapper.markAsRead(inboxId);
    }

    @Override
    public int batchMarkAsRead(Long[] inboxIds) {
        return sysMailInboxMapper.batchMarkAsRead(inboxIds);
    }

    @Override
    public int toggleStar(Long inboxId) {
        return sysMailInboxMapper.toggleStar(inboxId);
    }

    @Override
    public int deleteSysMailInboxByInboxId(Long inboxId) {
        return sysMailInboxMapper.deleteSysMailInboxByInboxId(inboxId);
    }

    @Override
    public int deleteSysMailInboxByInboxIds(Long[] inboxIds) {
        return sysMailInboxMapper.deleteSysMailInboxByInboxIds(inboxIds);
    }

    @Override
    public int syncMails(Long configId) {
        SysMailConfig config = sysMailConfigMapper.selectSysMailConfigByConfigId(configId);
        if (config == null) {
            throw new RuntimeException("邮箱配置不存在");
        }
        if (!"1".equals(config.getEnableReceive())) {
            throw new RuntimeException("该配置未启用收信功能");
        }
        if (StringUtils.isEmpty(config.getImapHost())) {
            throw new RuntimeException("请先配置IMAP服务器");
        }

        int count = 0;
        Store store = null;
        Folder folder = null;

        try {
            // 连接IMAP服务器
            Properties props = new Properties();
            props.put("mail.store.protocol", "imap");
            props.put("mail.imap.host", config.getImapHost());
            props.put("mail.imap.port", config.getImapPort() != null ? config.getImapPort() : 993);
            
            if ("ssl".equals(config.getImapEncryption())) {
                props.put("mail.imap.ssl.enable", "true");
                props.put("mail.imap.ssl.trust", config.getImapHost());
            } else if ("tls".equals(config.getImapEncryption())) {
                props.put("mail.imap.starttls.enable", "true");
            }

            Session session = Session.getInstance(props);
            store = session.getStore("imap");
            store.connect(config.getUsername(), config.getPassword());

            // 打开收件箱
            folder = store.getFolder("INBOX");
            folder.open(Folder.READ_ONLY);

            // 获取所有邮件
            int messageCount = folder.getMessageCount();
            if (messageCount > 0) {
                Message[] messages = folder.getMessages(1, messageCount);

                for (Message message : messages) {
                    try {
                        String messageId = getMessageId(message);
                        
                        // 检查是否已存在
                        if (sysMailInboxMapper.selectByMessageId(configId, messageId) != null) {
                            continue;
                        }

                        SysMailInbox inbox = new SysMailInbox();
                        inbox.setConfigId(configId);
                        inbox.setMessageId(messageId);
                        inbox.setSubject(message.getSubject());
                        inbox.setReceiveTime(message.getReceivedDate());
                        inbox.setIsRead("0");
                        inbox.setIsStarred("0");
                        inbox.setFolder("INBOX");

                        // 发件人
                        Address[] from = message.getFrom();
                        if (from != null && from.length > 0) {
                            InternetAddress addr = (InternetAddress) from[0];
                            inbox.setFromAddress(addr.getAddress());
                            inbox.setFromName(addr.getPersonal());
                        }

                        // 收件人
                        Address[] to = message.getRecipients(Message.RecipientType.TO);
                        if (to != null) {
                            inbox.setToAddress(addressesToString(to));
                        }

                        // 抄送
                        Address[] cc = message.getRecipients(Message.RecipientType.CC);
                        if (cc != null) {
                            inbox.setCcAddress(addressesToString(cc));
                        }

                        // 内容
                        String content = getTextContent(message);
                        inbox.setContent(content);
                        // 根据内容判断类型（包含HTML标签则为html类型）
                        boolean isHtml = content != null && content.contains("<") && content.contains(">");
                        inbox.setContentType(isHtml ? "html" : "text");

                        // 提取附件信息（只记录元数据，不保存文件）
                        List<Map<String, Object>> attachmentList = getAttachmentInfo(message);
                        inbox.setHasAttachment(attachmentList.isEmpty() ? "0" : "1");
                        if (!attachmentList.isEmpty()) {
                            inbox.setAttachments(new ObjectMapper().writeValueAsString(attachmentList));
                        }

                        sysMailInboxMapper.insertSysMailInbox(inbox);
                        count++;
                    } catch (Exception e) {
                        log.error("处理邮件失败: {}", e.getMessage());
                    }
                }
            }

            log.info("同步邮件完成，共同步 {} 封新邮件", count);
            return count;
        } catch (Exception e) {
            log.error("同步邮件失败: {}", e.getMessage(), e);
            throw new RuntimeException("同步邮件失败: " + e.getMessage());
        } finally {
            try {
                if (folder != null && folder.isOpen()) {
                    folder.close(false);
                }
                if (store != null) {
                    store.close();
                }
            } catch (Exception e) {
                log.error("关闭连接失败", e);
            }
        }
    }

    /**
     * 提取附件元数据（不保存文件）
     */
    private List<Map<String, Object>> getAttachmentInfo(Message message) {
        List<Map<String, Object>> attachments = new ArrayList<>();
        try {
            if (message.isMimeType("multipart/*")) {
                extractAttachmentInfo((MimeMultipart) message.getContent(), attachments);
            }
        } catch (Exception e) {
            log.error("提取附件信息失败: {}", e.getMessage());
        }
        return attachments;
    }

    /**
     * 递归提取附件信息
     */
    private void extractAttachmentInfo(MimeMultipart multipart, List<Map<String, Object>> attachments) throws Exception {
        for (int i = 0; i < multipart.getCount(); i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            String disposition = bodyPart.getDisposition();
            String fileName = bodyPart.getFileName();
            
            if (Part.ATTACHMENT.equalsIgnoreCase(disposition) || Part.INLINE.equalsIgnoreCase(disposition)) {
                if (StringUtils.isNotEmpty(fileName)) {
                    Map<String, Object> att = new HashMap<>();
                    att.put("fileName", MimeUtility.decodeText(fileName));
                    att.put("size", bodyPart.getSize());
                    att.put("contentType", bodyPart.getContentType());
                    attachments.add(att);
                }
            } else if (bodyPart.getContent() instanceof MimeMultipart) {
                extractAttachmentInfo((MimeMultipart) bodyPart.getContent(), attachments);
            }
        }
    }

    /**
     * 获取邮件ID
     */
    private String getMessageId(Message message) throws Exception {
        String[] headers = message.getHeader("Message-ID");
        if (headers != null && headers.length > 0) {
            return headers[0];
        }
        return String.valueOf(message.hashCode());
    }

    /**
     * 地址数组转字符串
     */
    private String addressesToString(Address[] addresses) {
        StringBuilder sb = new StringBuilder();
        for (Address addr : addresses) {
            if (sb.length() > 0) sb.append(",");
            sb.append(((InternetAddress) addr).getAddress());
        }
        return sb.toString();
    }

    /**
     * 获取邮件文本内容
     */
    private String getTextContent(Message message) throws Exception {
        Object content = message.getContent();
        if (content instanceof String) {
            return (String) content;
        } else if (content instanceof MimeMultipart) {
            return getTextFromMimeMultipart((MimeMultipart) content);
        }
        return "";
    }

    private String getTextFromMimeMultipart(MimeMultipart mimeMultipart) throws Exception {
        String plainText = null;
        String htmlText = null;
        
        int count = mimeMultipart.getCount();
        for (int i = 0; i < count; i++) {
            BodyPart bodyPart = mimeMultipart.getBodyPart(i);
            if (bodyPart.isMimeType("text/plain")) {
                if (plainText == null) {
                    plainText = (String) bodyPart.getContent();
                }
            } else if (bodyPart.isMimeType("text/html")) {
                if (htmlText == null) {
                    htmlText = (String) bodyPart.getContent();
                }
            } else if (bodyPart.getContent() instanceof MimeMultipart) {
                String nested = getTextFromMimeMultipart((MimeMultipart) bodyPart.getContent());
                if (StringUtils.isNotEmpty(nested)) {
                    // 嵌套的multipart可能返回HTML或纯文本
                    if (nested.contains("<") && nested.contains(">")) {
                        if (htmlText == null) htmlText = nested;
                    } else {
                        if (plainText == null) plainText = nested;
                    }
                }
            }
        }
        
        // 优先返回HTML内容，没有HTML则返回纯文本
        if (StringUtils.isNotEmpty(htmlText)) {
            return htmlText;
        }
        return plainText != null ? plainText : "";
    }

    /**
     * 标记指定账户的所有未读邮件为已读
     */
    @Override
    public int markAllAsReadByConfig(Long configId) {
        // 使用SQL直接更新指定账户的所有未读邮件
        SysMailInbox inbox = new SysMailInbox();
        inbox.setConfigId(configId);
        inbox.setIsRead("0"); // 查询条件：未读邮件
        List<SysMailInbox> unreadMails = sysMailInboxMapper.selectSysMailInboxList(inbox);
        
        int count = 0;
        for (SysMailInbox mail : unreadMails) {
            mail.setIsRead("1");
            count += sysMailInboxMapper.updateSysMailInbox(mail);
        }
        return count;
    }
}
