package cn.reghao.tnb.file.app.zjob;

import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
import cn.reghao.tnb.file.app.zjob.db.JobDetailMapper;
import cn.reghao.tnb.file.app.zjob.model.constant.JobStatus;
import cn.reghao.tnb.file.app.zjob.model.po.JobDetail;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * @author reghao
 * @date 2024-09-14 16:01:30
 */
@Slf4j
@Service
public class JobContext {
    private final ScheduledExecutorService scheduler;
    private final Map<Long, Future<?>> jobMap = new HashMap<>();
    private final JobDetailMapper jobDetailMapper;

    public JobContext(JobDetailMapper jobDetailMapper) {
        this.scheduler = ThreadPoolWrapper.scheduledThreadPool("delay-job", 10);
        this.jobDetailMapper = jobDetailMapper;
    }

    public void addJob(DelayJob delayJob) {
        ScheduledFuture<?> future = scheduler.schedule(delayJob.getJob(), delayJob.getDelaySecond(), TimeUnit.SECONDS);
        jobMap.put(delayJob.getJobId(), future);
    }

    public void cancelJob(long jobId) {
        Future<?> future = jobMap.get(jobId);
        if (future != null && !future.isCancelled()) {
            future.cancel(true);
        }
    }

    public int getJobCount() {
        List<Long> jobIds = new ArrayList<>();
        jobMap.forEach((jobId, future) -> {
            if (!future.isDone()) {
                jobIds.add(jobId);
            }
        });
        return jobIds.size();
    }

    @PostConstruct
    public void sync() {
        scheduler.scheduleAtFixedRate(new SyncTask(), 0, 10, TimeUnit.SECONDS);
        List<JobDetail> list = jobDetailMapper.findByStatus(JobStatus.Prepare.getValue());
    }

    class SyncTask implements Runnable {
        @Override
        public void run() {
            List<Long> jobCompleted = new ArrayList<>();
            jobMap.forEach((jobId, future) -> {
                if (future.isDone()) {
                    log.info("延时任务 {} 已完成", jobId);
                    jobCompleted.add(jobId);
                }
            });
            jobCompleted.forEach(jobMap::remove);
        }
    }
}
