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

import cn.hutool.core.util.ObjectUtil;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.njcn.msgpush.module.push.client.sender.SmsSender;
import com.njcn.msgpush.module.push.client.setting.impl.AliYunMailSetting;
import com.njcn.msgpush.module.push.constant.MessageStatusConstant;
import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

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

/**
 * @author caozehui
 * @data 2026-02-11
 */
@Slf4j
public class AliyunSmsSender implements SmsSender {
    public static final String SIGN_NAME = "signName";
    public static final String TEMPLATE_CODE = "templateCode";
    public static final String TEMPLATE_PARAM = "templateParam";
    public static final String OK = "OK";

    private Client smsClient;

    private final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
            5,
            5,
            1000,
            TimeUnit.MILLISECONDS,
            new java.util.concurrent.ArrayBlockingQueue<>(1000),
            r -> {
                Thread thread = new Thread(r);
                thread.setName("AliyunSmsSender-Pool-" + thread.getId());
                thread.setDaemon(false);
                return thread;
            },
            new ThreadPoolExecutor.CallerRunsPolicy()
    );

    public AliyunSmsSender(AliYunMailSetting aliYunSmsSetting) {
        if (ObjectUtil.isNotNull(aliYunSmsSetting)) {
            Config config = new Config()
                    .setAccessKeyId(aliYunSmsSetting.getAccessKeyId())
                    .setAccessKeySecret(aliYunSmsSetting.getAccessKeySecret())
                    .setRegionId(aliYunSmsSetting.getRegionId())
                    .setEndpoint(aliYunSmsSetting.getEndpoint());

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


    @Override
    public boolean sendSms(MessageRecordDO message) {
        Future<Boolean> future = THREAD_POOL_EXECUTOR.submit(() -> {
            message.setStatus(MessageStatusConstant.SENDING);
            RuntimeOptions runtimeOptions = new RuntimeOptions();
            // 设置自动重试，默认是不开启的。重试次数默认是3次
            runtimeOptions.autoretry = true;
            SendSmsRequest request = new SendSmsRequest()
                    .setPhoneNumbers(message.getReceiver())
                    .setSignName(message.getTitle())
                    .setTemplateCode(message.getTemplateCode())
                    .setTemplateParam(message.getTemplateParams());
            try {
                LocalDateTime now = LocalDateTime.now();
                long start = now.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                message.setSendTime(now);
                SendSmsResponse response = this.smsClient.sendSmsWithOptions(request, runtimeOptions);
                LocalDateTime end = LocalDateTime.now();
                message.setCostTime((int) (end.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - start));
                System.out.println(toJSONString(response));
                if (OK.equals(response.body.code)) {
                    return true;
                } else {
                    return false;
                }
            } catch (Exception e) {
                log.error("阿里云-短信服务发送失败");
                throw new Exception(e);
            }
        });
        Boolean b = null;
        try {
            b = future.get(3, TimeUnit.SECONDS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if (b) {
            message.setStatus(MessageStatusConstant.SUCCESS);
        } else {
            message.setStatus(MessageStatusConstant.FAILED);
        }
        return b;
    }

    @Override
    public boolean sendBatchSms(List<MessageRecordDO> messageIdList) {
        boolean res = true;
        for (MessageRecordDO message : messageIdList) {
            res &= this.sendSms(message);
        }
        return res;
    }
}
