package com.bcxin.message.scheduled.message;

import cn.hutool.core.date.DateUtil;
import com.bcxin.message.entity.messagecenter.MsgSendLogEntity;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;

/**
 * description：发送重试任务调度
 * author：linchunpeng
 * date：2023/11/22
 */
@Slf4j
@Component
public class SendRetryScheduler {

    @Autowired
    private Scheduler scheduler;
    
    //失败重试间隔 秒
    @Value("${message.retry.interval}")
    private Integer retryInterval;

    /**
     * description：调度发送重试任务
     * author：linchunpeng
     * date：2023/11/22
     */
    public void scheduleSendRetry(MsgSendLogEntity msgSendLogEntity) {
        try {
            log.info("调度发送重试任务，requestId：{}", msgSendLogEntity.getRequestId());
            JobDetail jobDetail = createSendRetryJobDetail(msgSendLogEntity);
            Trigger trigger = createSendRetryTrigger(msgSendLogEntity);
            if (trigger != null) {
                log.info("放入调度线程，requestId：{}", msgSendLogEntity.getRequestId());
                scheduler.scheduleJob(jobDetail, trigger);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * description：重新调度发送重试任务
     * author：linchunpeng
     * date：2023/11/22
     */
    public void reScheduleSendRetry(MsgSendLogEntity msgSendLogEntity) {
        try {
            log.info("重新调度发送重试任务，requestId：{}", msgSendLogEntity.getRequestId());
            JobDetail jobDetail = scheduler.getJobDetail(this.makeSendRetryJobKey(msgSendLogEntity.getId()));
            Trigger trigger = TriggerBuilder.newTrigger()
                    .forJob(jobDetail)
                    .startAt(DateUtil.offsetSecond(new Date(), retryInterval))
                    .build();
            scheduler.scheduleJob(trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * description：创建发送重试任务
     * author：linchunpeng
     * date：2023/11/22
     */
    private JobDetail createSendRetryJobDetail(MsgSendLogEntity msgSendLogEntity) {
        log.info("创建发送重试任务，requestId：{}", msgSendLogEntity.getRequestId());
        return JobBuilder.newJob(SendRetryJob.class)
                .withIdentity(this.makeSendRetryJobKey(msgSendLogEntity.getId()))
                .usingJobData("jobId", msgSendLogEntity.getId())
                .storeDurably()
                .build();
    }

    /**
     * description：创建发送重试任务触发器
     * author：linchunpeng
     * date：2023/11/22
     */
    private Trigger createSendRetryTrigger(MsgSendLogEntity msgSendLogEntity) {
        log.info("创建发送重试任务触发器，requestId：{}", msgSendLogEntity.getRequestId());
        Calendar startTime = Calendar.getInstance();
        startTime.setTime(new Date());
        startTime.add(Calendar.SECOND, retryInterval);
        return TriggerBuilder.newTrigger()
                .withIdentity(this.makeSendRetryTriggerKey(msgSendLogEntity.getId()))
                .startAt(startTime.getTime())
                .build();
    }

    /**
     * description：取消发送重试任务
     * author：linchunpeng
     * date：2023/11/22
     */
    public void cancelSendRetryJob(MsgSendLogEntity msgSendLogEntity) {
        try {
            log.info("取消发送重试任务，requestId：{}", msgSendLogEntity.getRequestId());
            scheduler.pauseTrigger(this.makeSendRetryTriggerKey(msgSendLogEntity.getId()));
            scheduler.pauseJob(this.makeSendRetryJobKey(msgSendLogEntity.getId()));
            scheduler.deleteJob(this.makeSendRetryJobKey(msgSendLogEntity.getId()));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * description：生成发送重试任务key
     * author：linchunpeng
     * date：2023/11/22
     */
    private JobKey makeSendRetryJobKey(Long jobId) {
        return JobKey.jobKey(jobId.toString(), "SEND_RETRY");
    }

    /**
     * description：生成发送重试任务触发器key
     * author：linchunpeng
     * date：2023/11/22
     */
    private TriggerKey makeSendRetryTriggerKey(Long jobId) {
        return TriggerKey.triggerKey(jobId.toString(), "SEND_RETRY");
    }

}
