package com.qqchen.deploy.backend.notification.adapter.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.notification.adapter.INotificationChannelAdapter;
import com.qqchen.deploy.backend.notification.entity.config.EmailNotificationConfig;
import com.qqchen.deploy.backend.notification.dto.EmailSendNotificationRequest;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Properties;

/**
 * 邮件通知渠道适配器
 *
 * @author qqchen
 * @since 2025-11-03
 */
@Slf4j
@Component
public class EmailChannelAdapter implements INotificationChannelAdapter<EmailNotificationConfig, EmailSendNotificationRequest> {

    @Override
    public void send(EmailNotificationConfig emailConfig, EmailSendNotificationRequest request) throws Exception {
        // 1. 校验配置
        validateEmailConfig(emailConfig);

        // 2. 创建JavaMailSender
        JavaMailSenderImpl mailSender = createMailSender(emailConfig);

        // 3. 校验收件人
        if (CollectionUtils.isEmpty(request.getToReceivers())) {
            throw new IllegalArgumentException("收件人列表不能为空");
        }

        // 4. 构建邮件
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");

        // 设置发件人
        if (emailConfig.getFromName() != null && !emailConfig.getFromName().isEmpty()) {
            helper.setFrom(new InternetAddress(emailConfig.getFrom(), emailConfig.getFromName(), "UTF-8"));
        } else {
            helper.setFrom(emailConfig.getFrom());
        }

        // 设置收件人
        helper.setTo(request.getToReceivers().toArray(new String[0]));

        // 设置抄送
        if (!CollectionUtils.isEmpty(request.getCcReceivers())) {
            helper.setCc(request.getCcReceivers().toArray(new String[0]));
        }

        // 设置密送
        if (!CollectionUtils.isEmpty(request.getBccReceivers())) {
            helper.setBcc(request.getBccReceivers().toArray(new String[0]));
        }

        // 设置主题（如果邮件没有设置subject且有标题，则使用标题作为主题）
        String subject = getEmailSubject(request);
        helper.setSubject(subject);

        // 设置内容（支持HTML）
        helper.setText(request.getContent(), request.getIsHtml() != null ? request.getIsHtml() : false);

        // 5. 发送邮件
        log.info("发送邮件通知 - 收件人: {}, 主题: {}", request.getToReceivers(), subject);
        mailSender.send(mimeMessage);
        log.info("邮件通知发送成功");
    }

    /**
     * 获取邮件主题
     */
    private String getEmailSubject(EmailSendNotificationRequest request) {
        // 如果已经设置了subject且不为空，直接使用
        if (request.getSubject() != null && !request.getSubject().trim().isEmpty()) {
            return request.getSubject();
        }
        
        // 如果没有设置subject但有标题，使用标题作为主题
        if (request.getTitle() != null && !request.getTitle().trim().isEmpty()) {
            return request.getTitle();
        }
        
        // 都没有则使用默认主题
        return "系统通知";
    }

    @Override
    public NotificationChannelTypeEnum supportedType() {
        return NotificationChannelTypeEnum.EMAIL;
    }

    @Override
    public String validateConfig(EmailNotificationConfig emailConfig) {
        try {
            validateEmailConfig(emailConfig);
            return "配置有效";
        } catch (Exception e) {
            return "配置验证失败: " + e.getMessage();
        }
    }

    @Override
    public void testConnection(EmailNotificationConfig emailConfig) throws Exception {
        // 1. 校验配置
        validateEmailConfig(emailConfig);

        // 3. 创建JavaMailSender
        JavaMailSenderImpl mailSender = createMailSender(emailConfig);

        // 4. 测试SMTP连接
        log.info("测试SMTP连接 - 服务器: {}:{}", emailConfig.getSmtpHost(), emailConfig.getSmtpPort());

        try {
            // 测试连接
            mailSender.testConnection();
            log.info("SMTP连接测试成功");
        } catch (Exception e) {
            log.error("SMTP连接测试失败: {}", e.getMessage());
            throw new Exception("SMTP连接失败: " + e.getMessage(), e);
        }

        // 5. 测试连接成功（不发送测试邮件，因为没有默认收件人）
        log.info("邮件通知渠道配置测试成功 - SMTP连接正常");
    }

    /**
     * 校验邮件配置
     */
    private void validateEmailConfig(EmailNotificationConfig config) {
        if (config.getSmtpHost() == null || config.getSmtpHost().isEmpty()) {
            throw new IllegalArgumentException("SMTP服务器地址不能为空");
        }

        if (config.getSmtpPort() == null) {
            throw new IllegalArgumentException("SMTP端口不能为空");
        }

        if (config.getUsername() == null || config.getUsername().isEmpty()) {
            throw new IllegalArgumentException("SMTP用户名不能为空");
        }

        if (config.getPassword() == null || config.getPassword().isEmpty()) {
            throw new IllegalArgumentException("SMTP密码不能为空");
        }

        if (config.getFrom() == null || config.getFrom().isEmpty()) {
            throw new IllegalArgumentException("发件人邮箱不能为空");
        }
    }

    /**
     * 创建JavaMailSender
     */
    private JavaMailSenderImpl createMailSender(EmailNotificationConfig config) {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost(config.getSmtpHost());
        mailSender.setPort(config.getSmtpPort());
        mailSender.setUsername(config.getUsername());
        mailSender.setPassword(config.getPassword());

        // 设置邮件属性
        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.debug", "false");

        // 如果使用SSL
        if (Boolean.TRUE.equals(config.getUseSsl())) {
            props.put("mail.smtp.ssl.enable", "true");
            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        }

        return mailSender;
    }

}

