package com.njcn.msgpush.module.push.client.sender.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dm20151123.Client;
import com.aliyun.dm20151123.models.SingleSendMailRequest;
import com.aliyun.dm20151123.models.SingleSendMailResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.njcn.msgpush.module.push.client.sender.EmailSender;
import com.njcn.msgpush.module.push.client.sender.Sender;
import com.njcn.msgpush.module.push.client.setting.impl.AliYunMailSetting;
import com.njcn.msgpush.module.push.constant.MsgPushConstant;
import com.njcn.msgpush.module.push.dal.dataobject.channel.ProviderErrorCodeMappingDO;
import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Map;

import static com.aliyun.teautil.Common.toJSONString;

/**
 * @author caozehui
 * @data 2026-02-11
 */
@Slf4j
public class AliyunEmailSender implements EmailSender {

    private Sender sender;

    public static final String ACCOUNT_NAME = "accountName";
    public static final String REPLY_TO_ADDRESS = "replyToAddress";

    public static final String FROM_ALIAS = "fromAlias";

    public static final String SUBJECT = "subject";
    public static final String HTML_BODY = "htmlBody";
    public static final String TEXT_BODY = "textBody";
    private Client emailClient;

    public AliyunEmailSender(AliYunMailSetting aliYunMailSetting, Sender sender) {
        this.sender = sender;
        if (ObjectUtil.isNotNull(aliYunMailSetting)) {
            Config config = new Config()
                    .setAccessKeyId(aliYunMailSetting.getAccessKeyId())
                    .setAccessKeySecret(aliYunMailSetting.getAccessKeySecret())
                    .setRegionId(aliYunMailSetting.getRegionId())
                    .setEndpoint(aliYunMailSetting.getEndpoint());

            try {
                this.emailClient = new com.aliyun.dm20151123.Client(config);
            } catch (Exception e) {
                log.error("阿里云-邮件服务初始化失败，请检查配置信息");
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public boolean sendEmail(MessageRecordDO message, Map<String, Object> params) {
        RuntimeOptions runtimeOptions = new RuntimeOptions();
        runtimeOptions.autoretry = true;

        String extraInfo = message.getExtraInfo();
        JSONObject jsonObject = JSON.parseObject(extraInfo);
        SingleSendMailRequest request = new SingleSendMailRequest()
                .setAccountName(jsonObject.get(ACCOUNT_NAME).toString())
                .setAddressType(1)
                .setReplyToAddress((boolean) jsonObject.get(REPLY_TO_ADDRESS))
                .setToAddress(message.getReceiver()) //目标地址，多个 email 地址可以用逗号分隔，最多 100 个地址（支持邮件组）。
                .setSubject(message.getTitle())
                .setHtmlBody(message.getContent()) //HtmlBody 和 TextBody 是针对不同类型的邮件
                .setTextBody("")
                .setFromAlias(jsonObject.get(FROM_ALIAS).toString());

        try {
            LocalDateTime now = LocalDateTime.now();
            long start = now.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            message.setSendTime(now);
            SingleSendMailResponse response = this.emailClient.singleSendMailWithOptions(request, runtimeOptions);
            LocalDateTime end = LocalDateTime.now();
            message.setCostTime((int) (end.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - start));
            System.out.println(toJSONString(response));
            if (HttpStatus.OK.value() == response.getStatusCode()) {
                this.sender.channelProviderConfigService.successUpdate(message.getProviderType(), message.getChannel());
                return true;
            } else {
                message.setErrorCode(response.getStatusCode() + "");
                ProviderErrorCodeMappingDO providerErrorCode = this.sender.providerErrorCodeMappingService.getByProviderErrorCode(message.getProviderType(), message.getChannel(), response.getStatusCode() + "");
                if (ObjectUtil.isNotNull(providerErrorCode)) {
                    message.setErrorMsg(providerErrorCode.getOriginalMessage());
                } else {
                    message.setErrorMsg(MsgPushConstant.ERROR_MSG_UNKNOWN);
                }
                this.sender.messageRetryQueueService.saveOrUpdateRetryMessage(message);
                this.sender.channelProviderConfigService.failureUpdate(message.getProviderType(), message.getChannel());
                return false;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
