package com.nokia.sms.service;

import com.alibaba.fastjson2.JSON;
import com.nokia.common.http.R;
import com.nokia.sms.dao.SmsDao;
import com.nokia.sms.pojo.Sms;
import com.nokia.sms.sgip.message.SendResult;
import com.nokia.sms.sgip.mt.client.MTClient;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;

@Slf4j
@Service
@Data
@ConfigurationProperties("sms")
public class SgipSmsService {
    static final LinkedBlockingQueue<Sms> QUEUE = new LinkedBlockingQueue<>();
    private final SmsDao smsDao;

    /**
     * 最大重试次数
     */
    private Integer maxRetry;

    public SgipSmsService(SmsDao smsDao) {
        this.smsDao = smsDao;
    }

    /**
     * 短信放入队列
     *
     * @param sms 短信
     * @return {@link R}
     */
    public R offer(Sms sms) {
        if (QUEUE.offer(sms)) {
            return R.ok();
        } else {
            log.error("入队失败");
            return R.error();
        }
    }

    public void sendMessage(Sms sms) {
        try {
            log.debug("准备发送短信: {}", JSON.toJSONString(sms));
            sms.setId(UUID.randomUUID().toString());
            sms.setSendTime(new Date());
            // 获取单例的MTClient
            MTClient client = MTClient.getInstance();
            // 发送短信
            SendResult[] results = client.sendMessage(sms.getPhoneNumbers(), sms.getContent(), sms.getScheduleTime());
            log.debug("短信已成功发送, 发送结果: {}", Arrays.toString(results));
            // 销毁应用
            client.dispose();
            sms.setResult(Arrays.toString(results));
//            if (ThreadLocalRandom.current().nextBoolean()) {
//                throw new RuntimeException("异常测试");
//            }
            sms.setStatus("已发送到短信网关");
            log.info("短信发送成功: {}", JSON.toJSONString(sms));
        } catch (Exception e) {
            sms.setStatus("发送到短信网关失败");
            log.error("短信发送失败, 短信: {}, 错误信息: {}", sms, e.getMessage());
            log.error(e.getMessage(), e);
            // 重试次数小于最大重试次数进行重试
            if (sms.getCount().getAndIncrement() < maxRetry) {
                retry(sms);
            }
        } finally {
            smsDao.insert(sms);
            log.debug("insert: {}", JSON.toJSONString(sms));
        }
    }

    /**
     * 消费队列发送短信
     */
    @PostConstruct
    public void consumer() {
        CompletableFuture.runAsync(() -> {
            while (true) {
                Sms sms = null;
                try {
                    sms = QUEUE.take();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.error(e.getMessage(), e);
                }
                if (sms == null) {
                    continue;
                }
                sendMessage(sms);
            }
        });
    }

    /**
     * 重试
     *
     * @param sms 短信
     */
    void retry(Sms sms) {
//        Instant startTime = Instant.now().plusSeconds(retryDelay);
//        scheduler.schedule(() -> sendMessage(sms), startTime);
        if (QUEUE.offer(sms)) {
            log.info("重新入队: {}", JSON.toJSONString(sms));
        } else {
            log.error("重新入队失败: {}", JSON.toJSONString(sms));
        }
    }
}
