package com.bcxin.backend.configs;

import com.bcxin.backend.tasks.TaskAbstract;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.*;
import java.util.stream.Collectors;

@Configuration
@EnableScheduling
@Slf4j
public class ScheduleJob implements ApplicationContextAware {
    private final static Logger logger = LoggerFactory.getLogger(ScheduleJob.class);
    private ApplicationContext applicationContext;


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(50);
        return taskScheduler;
    }


    /**
     * 每日定时推送宁夏归集数据(每日凌晨1触发) cron = "0 0 1 * * ?
     */
    @Scheduled(cron = "${myapps.nxgjApi.nxgjschedule}") //5分钟执行一次
    public void SecuritySeviceK() {
        logger.error("保安服务许可审批");
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.SecuritySeviceK");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * 获取并且执行所有APP的定时任务，并且缓存到本地
     */
    @Scheduled(fixedDelay = 3 * 60 * 1000) // 60秒执行一次  测试，可以改
    public void executeAppJob() {
        logger.info("获取并且执行所有APP的定时任务已开启");
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.app.job");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }


    /**
     * 清除本地的APP信息缓存
     */

    @Scheduled(fixedDelay = 24 * 60 * 60 * 1000) // 一小时执行一次  测试，可以改  时间别跟 获取缓存时间成整数倍
    public void executeCleanAppJob() {
        logger.info("清除本地的APP信息缓存已开启");
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.clean.app.job");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    //实名认证每20分钟执行一次 测试环境1分钟一次
    @Scheduled(cron = "${myapps.authentication.timing}")
    public void authentication() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.RealName.authentication");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    @Scheduled(cron = "${myapps.message.send}")
    public void sendMessage() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("message.send");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * 30分钟执行一次
     */
    @Scheduled(fixedDelay = 30 * 60 * 1000)
    public void notifyOverDueAuditors() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("overDue.notice");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 检索证书管理记录生成符合条件的SignatureQueues签章记录 </b>
     * 5分钟执行一次
     * @author ZXF
     * @create 2022/10/20 0020 17:28
     * @version
     * @注意事项 </b>
     */
    @Scheduled(fixedRate = 1 * 60 * 1000)
    public void signatureToCreate() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.job.create_signature");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 模板加载生成pdf证书 </b>
     * 5分钟执行一次
     * @author ZXF
     * @create 2022/10/20 0020 17:28
     * @version
     * @注意事项 </b>
     */
    @Scheduled(cron = "${myapps.signature.create_pdf_schedule}") // 测试环境5分钟一次
    public void signatureToPDF() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.job.create_pdf");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 临时目录pdf剪切到in目录触发签章，结束电子签章流程 </b>
     * @author ZXF
     * @create 2023/01/07 0007 11:47
     * @version
     * @注意事项 </b>
     */
    @Scheduled(cron = "${myapps.signature.move_schedule}") // 测试环境3分钟一次
    public void signatureMovePDF() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.job.move");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 临时目录pdf剪切到in目录触发签章 </b>
     * @author ZXF
     * @create 2023/01/07 0007 11:47
     * @version
     * @注意事项 </b>
     */
    @Scheduled(cron = "${myapps.signature.cgi_schedule}") // 测试环境3分钟一次
    public void signQuicklyExCGI() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.job.cgi");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> in目录下的文件是否在out目录下存在，存在就删除in目录对应文件 </b>
     * @author ZXF
     * @create 2023/01/07 0007 11:47
     * @version
     * @注意事项 </b>
     */
    @Scheduled(cron = "${myapps.signature.del_schedule}") // 测试环境30秒一次
    public void signatureDelInPDF() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.job.del");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 扫描签章表中状态（status）为3（已生成pdf待签章的数据）且当前时间大于上一次更新时间（last_processed_time 3小时以上,将其状态改为0 </b>
     * @author LYM
     * @create 2023/05/06 0001 10:27
     * @version
     * @注意事项 </b>
     */
    @Scheduled(cron = "${myapps.signature.change_schedule}") // 测试环境1小时一次
    public void signatureChangeStatus() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.job.change");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }


    /**
     * <b> 北京内网初始生成京通靓证.bcx数据文件上传ftp </b>
     * @author ZXF
     * @create 2024/11/23 0023 15:09
     * @version
     * @注意事项 </b>
     */
    @Scheduled(fixedDelay = 1 * 60 * 1000)
    public void initSignatureJTLZ() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.jtlz.init");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 北京内网初始生成保安服务许可证京通靓证.bcx数据文件输出外网 </b>
     * @author ZXF
     * @create 2024/11/23 0023 15:09
     * @version
     * @注意事项 </b>
     */
    @Scheduled(fixedDelay = 5 * 60 * 1000)
    public void initSignatureJTLZDocument() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.jtlzdocument.init");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 北京内网读取ftp外到内.bcx数据文件解析处理结果 </b>
     * @author ZXF
     * @create 2024/11/23 0023 15:09
     * @version
     * @注意事项 </b>
     */
    @Scheduled(fixedDelay = 1 * 60 * 1000)
    public void useSignatureJTLZ() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.jtlz.use");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 北京内网京通靓证废止 </b>
     * @author ZXF
     * @create 2024/11/23 0023 15:09
     * @version
     * @注意事项 </b>
     */
    @Scheduled(fixedDelay = 1 * 60 * 1000)
    public void initSignatureJTLZFZ() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.jtlzfz.init");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 北京内网京通靓证废止读取ftp外到内.bcx数据文件解析处理结果 </b>
     * @author ZXF
     * @create 2024/11/23 0023 15:09
     * @version
     * @注意事项 </b>
     */
    @Scheduled(fixedDelay = 1 * 60 * 1000)
    public void useSignatureJTLZFZ() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.jtlzfz.use");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 北京内网初始生成文书签章数据 </b>
     * @author ZXF
     * @create 2024/11/23 0023 15:09
     * @version
     * @注意事项 </b>
     */
    @Scheduled(fixedDelay = 1 * 60 * 1000)
    public void initDocumentSignature() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.document.init");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 北京内网重置文书正副本签章数据 </b>
     * @author ZXF
     * @create 2024/11/23 0023 15:09
     * @version
     * @注意事项 </b>
     */
    @Scheduled(fixedDelay = 3 * 60 * 1000)
    public void resetDocumentSignature() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.document.reset");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    /**
     * <b> 北京内网文书签章结果数据同步更新 </b>
     * @author ZXF
     * @create 2024/11/23 0023 15:09
     * @version
     * @注意事项 </b>
     */
    @Scheduled(fixedDelay = 2 * 60 * 1000)
    public void useDocumentSignature() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.document.use");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    @Scheduled(fixedDelay = 2 * 60 * 1000)
    public void checkSignatureStatus() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.document.check");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    protected Collection<TaskAbstract> getTasks(String prefixBeanName) {
        Collection<TaskAbstract> tasks =
                this.applicationContext.getBeansOfType(TaskAbstract.class)
                        .values().stream().filter(ii -> ii.getTaskName().startsWith(prefixBeanName))
                        .collect(Collectors.toList());

        return tasks;
    }

    /**
     * 每日定时清除map缓存queuesId数据(每日凌晨两点执行一次) cron = "0 0 2 * * ?
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void cleanQueuesCache() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("sync.clean.queues.cache");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }
}
