package com.yihu.wlyy.statistics.service;

import com.yihu.wlyy.statistics.dao.DoctorPatientGroupInfoDao;
import com.yihu.wlyy.statistics.dao.QuartzJobConfigDao;
import com.yihu.wlyy.statistics.dao.QuotaDao;
import com.yihu.wlyy.statistics.dao.SignFamilyDao;
import com.yihu.wlyy.statistics.etl.model.CacheModel;
import com.yihu.wlyy.statistics.etl.mycache.CachePool;
import com.yihu.wlyy.statistics.job.business.QuartzHelper;
import com.yihu.wlyy.statistics.job.cache.CacheCleanJob;
import com.yihu.wlyy.statistics.job.check.CheckSignJob;
import com.yihu.wlyy.statistics.job.check.ReportAllLogJob;
import com.yihu.wlyy.statistics.job.message.FollowupPlanJob;
import com.yihu.wlyy.statistics.job.message.HealthMessageJob;
import com.yihu.wlyy.statistics.job.message.NoticeJob;
import com.yihu.wlyy.statistics.model.doctor.DoctorPatientGroupInfo;
import com.yihu.wlyy.statistics.model.job.QuartzJobConfig;
import com.yihu.wlyy.statistics.model.job.WlyyQuota;
import com.yihu.wlyy.statistics.model.signfamily.SignFamily;
import com.yihu.wlyy.statistics.vo.WlyyJobConfigVO;
import com.yihu.wlyy.statistics.vo.WlyyQuotaVO;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author chenweida
 */
@Service
public class JobService {
    @Autowired
    private QuartzHelper quartzHelper;

    @Autowired
    private QuartzJobConfigDao wlyyJobConfigDao;

    @Autowired
    private QuotaDao quotaDao;

    @Autowired
    private SignFamilyDao signFamilyDao;

    @Autowired
    private DoctorPatientGroupInfoDao doctorPatientGroupInfoDao;
    @Autowired
    private CachePool cachePool;

    @Transactional
    public void stopById(String id) throws Exception {
        QuartzJobConfig quartzJobConfig = wlyyJobConfigDao.findById(id, "1");
        if (quartzJobConfig != null) {
            quartzHelper.removeJob(quartzJobConfig.getId());
            quartzJobConfig.setStatus("0");
        } else {
            throw new Exception("任务已经停止");
        }
    }

    @Transactional
    public void startById(String id) throws Exception {
        QuartzJobConfig quartzJobConfig = wlyyJobConfigDao.findById(id, "0");
        if (quartzJobConfig != null) {
            startOneJob(quartzJobConfig);
        } else {
            throw new Exception("任务已经启动");
        }
    }


    @Transactional
    public void stopAll() throws Exception {
        List<QuartzJobConfig> quartzJobConfigs = wlyyJobConfigDao.findByAll("1");
        if (quartzJobConfigs != null && quartzJobConfigs.size() > 0) {
            for (QuartzJobConfig quartzJobConfig : quartzJobConfigs) {
                quartzHelper.removeJob(quartzJobConfig.getId());
                quartzJobConfig.setStatus("0");
            }
        } else {
            throw new Exception("任务已经全部停止");
        }
    }

    @Transactional
    public void startAll() throws Exception {
        List<QuartzJobConfig> quartzJobConfigs = wlyyJobConfigDao.findByAll("0");
        if (quartzJobConfigs != null && quartzJobConfigs.size() > 0) {
            for (QuartzJobConfig quartzJobConfig : quartzJobConfigs) {
                startOneJob(quartzJobConfig);
            }
        } else {
            throw new Exception("任务已经全部启动");
        }
    }

    /**
     * 启动单个任务
     *
     * @param quartzJobConfig
     * @throws Exception
     */
    private void startOneJob(QuartzJobConfig quartzJobConfig) throws Exception {
        WlyyQuota wlyyQuota = quotaDao.findOne(quartzJobConfig.getQuotaId());

        WlyyQuotaVO wlyyQuotaVO = new WlyyQuotaVO();
        WlyyJobConfigVO wlyyJobConfigVO = new WlyyJobConfigVO();
        BeanUtils.copyProperties(wlyyQuota, wlyyQuotaVO);
        BeanUtils.copyProperties(quartzJobConfig, wlyyJobConfigVO);

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("quota", wlyyQuotaVO);
        params.put("jobConfig", wlyyJobConfigVO);
        if (!StringUtils.isEmpty(quartzJobConfig.getJobClass())) {
            //往quartz框架添加任务
            quartzHelper.addJob(getRightClass(quartzJobConfig), quartzJobConfig.getQuartzCron(), quartzJobConfig.getId(), params);
            quartzJobConfig.setStatus("1");//设置任务状态是启动
        }
    }

    public void startNowById(String id) throws Exception {
        QuartzJobConfig quartzJobConfig = wlyyJobConfigDao.findOne(id);
        WlyyQuota wlyyQuota = quotaDao.findOne(quartzJobConfig.getQuotaId());

        WlyyQuotaVO wlyyQuotaVO = new WlyyQuotaVO();
        WlyyJobConfigVO wlyyJobConfigVO = new WlyyJobConfigVO();
        BeanUtils.copyProperties(wlyyQuota, wlyyQuotaVO);
        BeanUtils.copyProperties(quartzJobConfig, wlyyJobConfigVO);

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("quota", wlyyQuotaVO);
        params.put("jobConfig", wlyyJobConfigVO);

        //往quartz框架添加任务
        if (!StringUtils.isEmpty(quartzJobConfig.getJobClass())) {
            quartzHelper.startNow(getRightClass(quartzJobConfig), quartzJobConfig.getId() + UUID.randomUUID().toString().replace("-", ""), params);
        }
    }


    public void productDataByDay(Integer day) throws Exception {
        List<QuartzJobConfig> quartzJobConfigs = wlyyJobConfigDao.findByIds();
        for (QuartzJobConfig quartzJobConfig : quartzJobConfigs) {
            WlyyQuota wlyyQuota = quotaDao.findOne(quartzJobConfig.getQuotaId());

            WlyyQuotaVO wlyyQuotaVO = new WlyyQuotaVO();
            WlyyJobConfigVO wlyyJobConfigVO = new WlyyJobConfigVO();
            BeanUtils.copyProperties(wlyyQuota, wlyyQuotaVO);
            BeanUtils.copyProperties(quartzJobConfig, wlyyJobConfigVO);

            Map<String, Object> params = new HashMap<String, Object>();
            params.put("quota", wlyyQuotaVO);
            params.put("jobConfig", wlyyJobConfigVO);
            for (int i = 1; i <= day; i++) {
                //往quartz框架添加任务
                params.put("daybefore", getYesterday(0 - i - 1));
                params.put("yesterday", getYesterday(0 - i));
                if (!StringUtils.isEmpty(quartzJobConfig.getJobClass())) {
                    quartzHelper.startNow(getRightClass(quartzJobConfig), quartzJobConfig.getId() + UUID.randomUUID().toString().replace("-", ""), params);
                    Thread.sleep(10000L);
                }
            }
        }
    }

    public static String getYesterday(Integer day) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, day);
        String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
        return yesterday;
    }

    public void productDataByOneDay(String yesterday) throws Exception {
        SimpleDateFormat dataSimple = new SimpleDateFormat("yyyy-MM-dd");

        Date date = dataSimple.parse(yesterday);
        if (date == null) {
            throw new Exception("时间格式错误");
        }
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, -1);//把日期往后增加一天.整数往后推,负数往前移动
        Date nowDate = calendar.getTime();   //这个时间就是日期往后推一天的结果
        String daybefore = new SimpleDateFormat("yyyy-MM-dd").format(nowDate.getTime());
        List<QuartzJobConfig> quartzJobConfigs = wlyyJobConfigDao.findByIds();
        for (QuartzJobConfig quartzJobConfig : quartzJobConfigs) {
            WlyyQuota wlyyQuota = quotaDao.findOne(quartzJobConfig.getQuotaId());

            WlyyQuotaVO wlyyQuotaVO = new WlyyQuotaVO();
            WlyyJobConfigVO wlyyJobConfigVO = new WlyyJobConfigVO();
            BeanUtils.copyProperties(wlyyQuota, wlyyQuotaVO);
            BeanUtils.copyProperties(quartzJobConfig, wlyyJobConfigVO);

            Map<String, Object> params = new HashMap<String, Object>();
            params.put("quota", wlyyQuotaVO);
            params.put("jobConfig", wlyyJobConfigVO);
            //往quartz框架添加任务
            params.put("daybefore", daybefore);
            params.put("yesterday", yesterday);
            if (!StringUtils.isEmpty(quartzJobConfig.getJobClass())) {
                quartzHelper.startNow(getRightClass(quartzJobConfig), quartzJobConfig.getId() + UUID.randomUUID().toString().replace("-", ""), params);
                Thread.sleep(40000L);
            }

        }
    }

    /**
     * @param quartzJobConfig
     * @return
     * @throws ClassNotFoundException
     */
    private Class getRightClass(QuartzJobConfig quartzJobConfig) throws ClassNotFoundException {
        return Class.forName(quartzJobConfig.getJobClass());
    }

    public void productDataByOneDayWithId(String yesterday, String id) throws Exception {
        SimpleDateFormat dataSimple = new SimpleDateFormat("yyyy-MM-dd");
        Date date = dataSimple.parse(yesterday);
        if (date == null) {
            throw new Exception("时间格式错误");
        }
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, -1);//把日期往后增加一天.整数往后推,负数往前移动
        Date nowDate = calendar.getTime();   //这个时间就是日期往后推一天的结果
        String daybefore = new SimpleDateFormat("yyyy-MM-dd").format(nowDate.getTime());

        QuartzJobConfig quartzJobConfig = wlyyJobConfigDao.findById(id);
        if (quartzJobConfig == null) {
            throw new Exception("id不存在");
        }
        WlyyQuota wlyyQuota = quotaDao.findOne(quartzJobConfig.getQuotaId());
        WlyyQuotaVO wlyyQuotaVO = new WlyyQuotaVO();
        WlyyJobConfigVO wlyyJobConfigVO = new WlyyJobConfigVO();
        BeanUtils.copyProperties(wlyyQuota, wlyyQuotaVO);
        BeanUtils.copyProperties(quartzJobConfig, wlyyJobConfigVO);

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("quota", wlyyQuotaVO);
        params.put("jobConfig", wlyyJobConfigVO);

        //往quartz框架添加任务
        params.put("daybefore", daybefore);
        params.put("yesterday", yesterday);
        if (!StringUtils.isEmpty(quartzJobConfig.getJobClass())) {
            quartzHelper.startNow(getRightClass(quartzJobConfig), quartzJobConfig.getId() + UUID.randomUUID().toString().replace("-", ""), params);
            Thread.sleep(40000L);
        }
    }

    @Transactional
    @Async("dbExtractExecutor")
    public void startaaaa() throws Exception {
        quartzHelper.startNow(HealthMessageJob.class, UUID.randomUUID().toString().replace("-", ""), new HashMap<>());
    }

    public void productDataByDayAndId(Integer day, String id) throws Exception {
        QuartzJobConfig quartzJobConfig = wlyyJobConfigDao.findById(id);
        if (quartzJobConfig == null) {
            throw new Exception("id不存在");
        }
        WlyyQuota wlyyQuota = quotaDao.findOne(quartzJobConfig.getQuotaId());

        WlyyQuotaVO wlyyQuotaVO = new WlyyQuotaVO();
        WlyyJobConfigVO wlyyJobConfigVO = new WlyyJobConfigVO();
        BeanUtils.copyProperties(wlyyQuota, wlyyQuotaVO);
        BeanUtils.copyProperties(quartzJobConfig, wlyyJobConfigVO);

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("quota", wlyyQuotaVO);
        params.put("jobConfig", wlyyJobConfigVO);
        for (int i = 1; i <= day; i++) {
            //往quartz框架添加任务
            params.put("daybefore", getYesterday(0 - i - 1));
            params.put("yesterday", getYesterday(0 - i));
            if (!StringUtils.isEmpty(quartzJobConfig.getJobClass())) {
                quartzHelper.startNow(getRightClass(quartzJobConfig), quartzJobConfig.getId() + UUID.randomUUID().toString().replace("-", ""), params);
                Thread.sleep(40000L);
            }
        }
    }

    public void startCheckSignJob() throws Exception {
        if (!quartzHelper.isExistJob(CheckSignJob.jobKey)) {
            quartzHelper.addJob(CheckSignJob.class, CheckSignJob.cron, CheckSignJob.jobKey, new HashMap<>());
        }
    }

    public void stopCheckSignJob() throws Exception {
        if (quartzHelper.isExistJob(CheckSignJob.jobKey)) {
            quartzHelper.removeJob(CheckSignJob.jobKey);
        }
    }

    public void productDataByDayToDay(String start, String end) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date startDate = sdf.parse(start);
        Date endDate = sdf.parse(end);
        if (startDate.after(endDate)) {
            throw new Exception("日期参数错误");
        }
        int day = daysBetween(startDate, endDate);
        for (int i = 0; i < day; i++) {
            productDataByOneDay(getYesterday(i, startDate));

        }
    }

    public static String getYesterday(Integer day, Date startDate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(startDate);
        cal.add(Calendar.DAY_OF_MONTH, day);
        String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
        return yesterday;
    }

    public static int daysBetween(Date smdate, Date bdate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        smdate = sdf.parse(sdf.format(smdate));
        bdate = sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }


    public void productDataByDayToDayAndId(String start, String end, String id) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date startDate = sdf.parse(start);
        Date endDate = sdf.parse(end);
        if (startDate.after(endDate)) {
            throw new Exception("日期参数错误");
        }
        int day = daysBetween(startDate, endDate);
        for (int i = 0; i < day; i++) {
            productDataByOneDayWithId(getYesterday(i, startDate), id);
        }
    }

    public void startCleanCacheJob() throws Exception {
        if (!quartzHelper.isExistJob(CacheCleanJob.jobKey)) {
            quartzHelper.addJob(CacheCleanJob.class, CacheCleanJob.cron, CacheCleanJob.jobKey, new HashMap<>());
        } else {
            throw new Exception("已经启动");
        }
    }

    public void stopCleanCacheJob() throws Exception {
        if (quartzHelper.isExistJob(CacheCleanJob.jobKey)) {
            quartzHelper.removeJob(CacheCleanJob.jobKey);
        } else {
            throw new Exception("已经停止");
        }
    }

    public void cleanCache() {
        CachePool.cleanAllCache();
    }

    public String seeCache() {
        Map<String, CacheModel> cacheModesCache = CachePool.getArriveSignFamilyExpenseStatus1Map();
        Map<String, String> patientGroupCache = CachePool.getPatientGroup();
        Map<String, String> healthGroupCache = CachePool.getHealthGroup();
        Map<String, List<String>> diseaseGroupCache = CachePool.getDiseaseGroup();
        String returnMessage = " 签约缓存:缓存存在" + cacheModesCache.size() + "天的缓存,";
        for (Map.Entry<String, CacheModel> entry : cacheModesCache.entrySet()) {
            returnMessage += entry.getKey() + ",";
        }
        returnMessage += "patientGroupCache" + (patientGroupCache.size() > 0 ? "有缓存" : "没有缓存");
        returnMessage += "healthGroupCache" + (healthGroupCache.size() > 0 ? "有缓存" : "没有缓存");
        returnMessage += "diseaseGroupCache" + (diseaseGroupCache.size() > 0 ? "有缓存" : "没有缓存");
        return returnMessage;
    }

    public void startHealthMessageJob() throws Exception {
        if (!quartzHelper.isExistJob(HealthMessageJob.jobKey)) {
            quartzHelper.addJob(HealthMessageJob.class, HealthMessageJob.cron, HealthMessageJob.jobKey, new HashMap<>());
        } else {
            throw new Exception("已经启动");
        }
    }

    public void stopHealthMessageJob() throws Exception {
        if (quartzHelper.isExistJob(HealthMessageJob.jobKey)) {
            quartzHelper.removeJob(HealthMessageJob.jobKey);
        } else {
            throw new Exception("已经停止");
        }
    }

    public void productHealthDataByOneDay(String day) throws Exception {
        SimpleDateFormat dataSimple = new SimpleDateFormat("yyyy-MM-dd");

        Date date = dataSimple.parse(day);
        if (date == null) {
            throw new Exception("时间格式错误");
        }
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, 1);//把日期往后增加一天.整数往后推,负数往前移动
        Date nowDate = calendar.getTime();   //这个时间就是日期往后推一天的结果
        String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(nowDate.getTime());
        Map<String, Object> params = new HashMap<String, Object>();
        //往quartz框架添加任务
        params.put("now", yesterday);
        params.put("yesterday", day);
        quartzHelper.startNow(HealthMessageJob.class, HealthMessageJob.jobKey + UUID.randomUUID().toString().replace("-", ""), params);
        Thread.sleep(40000L);
    }

    public void productHealthDataByDayToDay(String start, String end) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date startDate = sdf.parse(start);
        Date endDate = sdf.parse(end);
        if (startDate.after(endDate)) {
            throw new Exception("日期参数错误");
        }
        int day = daysBetween(startDate, endDate);
        for (int i = 0; i < day; i++) {
            productHealthDataByOneDay(getYesterday(i, startDate));
        }
    }

    public static void main(String[] args) throws Exception {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date startDate = sdf.parse("2016-10-20");
        Date endDate = sdf.parse("2016-10-28");
        System.out.println(daysBetween(startDate, endDate));
        System.out.println(getYesterday(0, startDate));
    }


    public void startEveryDayReportJob() throws Exception {
        if (!quartzHelper.isExistJob(ReportAllLogJob.jobKey)) {
            quartzHelper.addJob(ReportAllLogJob.class, ReportAllLogJob.cron, ReportAllLogJob.jobKey, new HashMap<>());
        } else {
            throw new Exception("已经启动");
        }
    }

    public void stopEveryDayReportJob() throws Exception {
        if (quartzHelper.isExistJob(ReportAllLogJob.jobKey)) {
            quartzHelper.removeJob(ReportAllLogJob.jobKey);
        } else {
            throw new Exception("已经停止");
        }
    }

    public void startNoticeJob() throws Exception {
        if (!quartzHelper.isExistJob(NoticeJob.jobKey)) {
            quartzHelper.addJob(NoticeJob.class, NoticeJob.jobCron, NoticeJob.jobKey, new HashMap<>());
            // quartzHelper.startNow(NoticeJob.class, UUID.randomUUID().toString().replace("-", ""), new HashMap<>());

        } else {
            throw new Exception("已经启动");
        }
    }

    public void stopNoticeJob() throws Exception {
        if (quartzHelper.isExistJob(NoticeJob.jobKey)) {
            quartzHelper.removeJob(NoticeJob.jobKey);
        } else {
            throw new Exception("已经停止");
        }
    }

    /*******************************
     * 随访计划任务
     *******************************************************/
    @Value("${spring.followupMessage.jobId}")
    private String followupJob;
    @Value("${spring.followupMessage.cron}")
    private String followupJobCron;

    public void startFollowupPlantJob() throws Exception {
        if (!quartzHelper.isExistJob(followupJob)) {
            quartzHelper.addJob(FollowupPlanJob.class, followupJobCron, followupJob, new HashMap<>());
        } else {
            throw new Exception("已经启动");
        }
    }

    public void stopFollowupPlantJob() throws Exception {
        if (quartzHelper.isExistJob(followupJob)) {
            quartzHelper.removeJob(followupJob);
        } else {
            throw new Exception("已经停止");
        }
    }

    public void startNoticeJobNow() throws Exception {
        quartzHelper.startNow(NoticeJob.class, UUID.randomUUID().toString(), new HashMap<>());

    }

    public void startHealthMessageJobNow() throws Exception {
        quartzHelper.startNow(HealthMessageJob.class, UUID.randomUUID().toString(), new HashMap<>());
    }
}
