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();
        });
    }

    /**
     * 半小时执行一次
     */
    /*
    changed by lhc: 2023-01-15 临时去掉自动同步
    @Scheduled(fixedDelayString = "${scheduled.fixedDelay.sync.form}")
    public void executeFormMetaJob() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("sync.form");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }
     */

    /**
     * 半小时执行一次
     */
        /*
    changed by lhc: 2023-01-15 临时去掉自动同步
    @Scheduled(fixedDelayString = "${scheduled.fixedDelay.sync.data.ftp}")
    public void executeSyncDataViaFtpJob() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("sync.data.ftp");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }
         */

    /**
     * 20分钟执行一次
     */
            /*
    changed by lhc: 2023-01-15 临时去掉自动同步
    @Scheduled(fixedDelayString = "${scheduled.fixedDelay.sync.data.directly}")
    public void executeSyncDataJob() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("sync.data.directly");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

             */
            /*
    changed by lhc: 2023-01-15 临时去掉自动同步
    @Scheduled(fixedDelayString = "${scheduled.fixedDelay.sync.file.ftp}")
    public void executeSyncFileViaFtpJob() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("sync.file.ftp");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }



    @Scheduled(fixedDelayString = "${scheduled.fixedDelay.sync.file.directly}")
    public void executeSyncFileJob() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("sync.file.directly");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

    @Scheduled(fixedDelay = 20 * 60 * 1000)
    public void syncUser2DataExchange() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("data.exchange");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }*/

    /**
     * 对于失败的数据 20分钟一次
     */
    /*
        changed by lhc: 2023-01-15 临时去掉自动同步
    @Scheduled(fixedDelay = 20 * 60 * 1000)
    public void retrySyncData() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("retry.sync");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }

     */
        /*
        changed by lhc: 2023-01-15 临时去掉自动同步
    @Scheduled(fixedDelay = 30 * 60 * 1000)
    public void cleanSyncData() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("clean.sync");
        taskAbstracts.forEach(task -> {
            task.run();
        });
    }
         */

    /**
     * 2分钟执行一次下载
     */
        /*
        changed by lhc: 2023-01-15 临时去掉自动同步
    @Scheduled(fixedDelay = 2 * 60 * 1000)
    public void downloadSyncFile() {
        Collection<TaskAbstract> taskAbstracts = this.getTasks("sync.download");
        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();
        });
    }

//    @Scheduled(cron = "${myapps.screeninng.schedule.induction}") // 测试环境5分钟一次
//    public void inductionScreeningJob() {
//        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.Screening.job.induction");
//        taskAbstracts.forEach(task -> {
//            task.run();
//        });
//    }
//
//    @Scheduled(cron = "${myapps.screeninng.schedule.timing}") // 测试环境5分钟一次
//    public void timingScreeningJob() {
//        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.Screening.job.timing");
//        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(fixedDelay = 30 * 1000)
    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> 模板加载生成pdf证书 </b>
     * 5分钟执行一次
     * @author ZXF
     * @create 2022/10/20 0020 17:28
     * @version
     * @注意事项 </b>
     */
//    @Scheduled(cron = "${myapps.signature.schedule}") // 测试环境5分钟一次
    @Scheduled(fixedRate = 5 * 60 * 1000)
    public void signatureToPDF() {
        System.err.println("====> 电子签章（无章PDF生成）定时任务开始：5分钟一次................");
        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(fixedDelay = 3 * 60 * 1000)
    public void signatureMovePDF() {
        System.err.println("====> 电子签章（签章PDF上传FTP）定时任务开始：3分钟一次................");
        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(fixedDelay = 3 * 60 * 1000)
    public void signQuicklyExCGI() {
        System.err.println("====> 电子签章（临时目录pdf剪切到in目录触发签章）定时任务开始：3分钟一次................");
        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(fixedDelay = 30 * 1000)
    public void signatureDelInPDF() {
        System.err.println("====> 电子签章（删除in目录文件）定时任务开始：3分钟一次................");
        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(fixedDelay = 60 * 60 * 1000)
    public void signatureChangeStatus() {
        System.err.println("====> 电子签章修改状态定时任务开始：60分钟一次................");
        Collection<TaskAbstract> taskAbstracts = this.getTasks("execute.signature.pdf.job.change");
        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();
        });
    }
}
