package com.testor.module.safeCheck.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.testor.common.util.cron.CheckFrequencyEnum;
import com.testor.common.util.cron.FrequencyDTO;
import com.testor.common.util.cron.FrequencyUtil;
import com.testor.module.safeCheck.dao.TSafeHazardCheckPeopleDao;
import com.testor.module.safeCheck.model.domain.TSafeHazardCheckPeople;
import com.testor.module.safeCheck.model.vo.SafeHazardCheckPeopleVO;
import com.testor.module.safeCheck.service.TSafeHazardCheckPeopleService;
import com.testor.xxl.job.task.util.CronUtil;
import com.testor.xxl.job.task.util.WeekdayEnum;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 巡检人员Service业务层处理
 *
 * @author testor-framework
 * @date 2022-08-04 11:07:50
 */
@Slf4j
@Service
public class TSafeHazardCheckPeopleServiceImpl extends SuperServiceImpl<TSafeHazardCheckPeopleDao, TSafeHazardCheckPeople> implements TSafeHazardCheckPeopleService {
    @Autowired(required = false)
    private TSafeHazardCheckPeopleDao tSafeHazardCheckPeopleDao;

    @Resource
    private FrequencyUtil frequencyUtil;

    /**
     * 根据 巡检计划 编辑 巡检人员（新增、修改、删除的处理）
     *
     * @param planId
     * @param CheckPeopleList
     * @return
     */
    @Transactional
    public boolean editBatchByPlan(String planId, Long advanceHour, LocalDateTime endDate, List<TSafeHazardCheckPeople> CheckPeopleList) {
        if (StrUtil.isBlank(planId) || CheckPeopleList == null || CheckPeopleList.size() == 0) {
            return false;
        }

        Map<String, List<TSafeHazardCheckPeople>> CheckPeopleMap = analysisCheckPeople(planId, CheckPeopleList);
        List<TSafeHazardCheckPeople> newCheckPeopleList = CheckPeopleMap.get("new");
        List<TSafeHazardCheckPeople> editCheckPeopleList = CheckPeopleMap.get("edit");
        List<TSafeHazardCheckPeople> deleteCheckPeopleList = CheckPeopleMap.get("delete");

        if (editCheckPeopleList == null) {
            editCheckPeopleList = new ArrayList<>();
        }

        // 新增
        if (newCheckPeopleList != null && newCheckPeopleList.size() > 0) {
            for (TSafeHazardCheckPeople checkPeople : newCheckPeopleList) {
                //   checkPeople.setCronExpression(generateCron(checkPeople));
                checkPeople.setPlanId(planId);
            }
            editCheckPeopleList.addAll(newCheckPeopleList);
        }

        // 生成cron表达式
        for (TSafeHazardCheckPeople checkPeople : editCheckPeopleList) {
            FrequencyDTO frequencyDTO = new FrequencyDTO();
            frequencyDTO.setFrequencyKey(checkPeople.getFrequencyKey());
            frequencyDTO.setTime(checkPeople.getStartTime());
            frequencyDTO.setDate(checkPeople.getStartDate());
            frequencyDTO.setDayNum(checkPeople.getStartDayNum());
            frequencyDTO.setMonthNum((checkPeople.getStartMonthNum()));
            //   frequencyDTO.setAdvanceHour(-advanceHour);
            String startCronStr = frequencyUtil.generateCronByNoAdvance(frequencyDTO);

            FrequencyDTO endFrequencyDTO = new FrequencyDTO();
            endFrequencyDTO.setFrequencyKey(checkPeople.getFrequencyKey());
            endFrequencyDTO.setTime(checkPeople.getEndTime());
            endFrequencyDTO.setDate(checkPeople.getEndDate());
            endFrequencyDTO.setDayNum(checkPeople.getEndDayNum());
            endFrequencyDTO.setMonthNum((checkPeople.getEndMonthNum()));
            //     endFrequencyDTO.setAdvanceHour(-advanceHour);
            String endCronStr = frequencyUtil.generateCronByNoAdvance(endFrequencyDTO);

            checkPeople.setStartCronExpression(startCronStr);
            checkPeople.setEndCronExpression(endCronStr);
        }

        // 删除
        if (deleteCheckPeopleList != null && deleteCheckPeopleList.size() > 0) {
            for (TSafeHazardCheckPeople CheckPeople : deleteCheckPeopleList) {
                CheckPeople.setStatus(BizConstants.STATUS_DELETE);
            }
            editCheckPeopleList.addAll(deleteCheckPeopleList);
        }

        boolean doResult = saveOrUpdateBatch(editCheckPeopleList, editCheckPeopleList.size());
        if (!doResult) {
            return doResult;
        }

        // 创建任务 并 更新 状态
//        List<TSafeHazardCheckPeople> updateList = new ArrayList<>();
//        for (TSafeHazardCheckPeople checkPeople : editCheckPeopleList) {
//            if (!BizConstants.STATUS_ENABLE.equals(checkPeople.getStatus())) {
//                continue;
//            }
//            String startCronStr = checkPeople.getStartCronExpression();
//            List<ZonedDateTime> zonedDateTimeList = CronUtil.calculateTimeList(startCronStr, LocalDateTimeUtil.offset(endDate, 1, ChronoUnit.DAYS));
//            if (zonedDateTimeList == null || zonedDateTimeList.size() == 0) {
//                continue;
//            }
//            ZonedDateTime zonedDateTime = zonedDateTimeList.get(0);
////            ZonedDateTime zonedDateTime = CronUtil.calculateTime(startCronStr, 2);
////            if (zonedDateTime == null) {
////                continue;
////            }
//
//            LocalDateTime startDate = zonedDateTime.toLocalDateTime();
//            LocalDateTime startTaskTime = LocalDateTimeUtil.offset(startDate, -advanceHour, ChronoUnit.HOURS);
//            // 如果 提前后 开始时间 < 当前时间 则 取 cron 下条数据的时间 进行 提前处理
//            // 即 提前时间不能大于两次任务的间隔时间
//            if(LocalDateTimeUtil.between(LocalDateTime.now(), startTaskTime, ChronoUnit.SECONDS) <= 0) {
//                if(zonedDateTimeList.size() < 2) {
//                    continue;
//                }
//                zonedDateTime = zonedDateTimeList.get(1);
//                startDate = zonedDateTime.toLocalDateTime();
//                startTaskTime = LocalDateTimeUtil.offset(startDate, -advanceHour, ChronoUnit.HOURS);
//            }
//            String taskCronStr = CronUtil.generateCronByOne(startTaskTime);
//            frequencyUtil.createTaskJob(checkPeople.getId(), taskCronStr, "巡检排查计划生成任务", "createCheckTask");
//
//            checkPeople.setGenerateTask("1");
//            updateList.add(checkPeople);
//        }
//
//        if (updateList.size() > 0) {
//            updateBatchById(updateList, updateList.size());
//        }
        return doResult;
    }

    /**
     * 根据巡检计划id 查询 巡检人员
     *
     * @param planId
     * @return
     */
    @Override
    public List<TSafeHazardCheckPeople> listByPlan(String planId) {
        if (StrUtil.isBlank(planId)) {
            return null;
        }

        LambdaQueryWrapper<TSafeHazardCheckPeople> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TSafeHazardCheckPeople::getStatus, BizConstants.STATUS_ENABLE)
                .eq(TSafeHazardCheckPeople::getPlanId, planId);
        List<TSafeHazardCheckPeople> CheckPeopleList = tSafeHazardCheckPeopleDao.selectList(queryWrapper);
        return CheckPeopleList;
    }

    /**
     * 解析、区分 巡检人员： 新增、 已存在编辑、 删除
     *
     * @param planId          计划id
     * @param CheckPeopleList
     * @return
     */
    @Override
    public Map analysisCheckPeople(String planId, List<TSafeHazardCheckPeople> CheckPeopleList) {

        if (StrUtil.isBlank(planId)) {
            return null;
        }

        Map<String, List<TSafeHazardCheckPeople>> resultMap = new HashMap<>();

        List<TSafeHazardCheckPeople> newCheckPeopleList = new ArrayList<>();
        List<TSafeHazardCheckPeople> editCheckPeopleList = new ArrayList<>();
        List<TSafeHazardCheckPeople> deleteCheckPeopleList = new ArrayList<>();

        List<TSafeHazardCheckPeople> oldCheckPeopleList = listByPlan(planId);
        if (oldCheckPeopleList == null || oldCheckPeopleList.size() == 0) {
            newCheckPeopleList = CheckPeopleList;
            resultMap.put("new", newCheckPeopleList);
            return resultMap;
        }

        Map<String, TSafeHazardCheckPeople> CheckPeopleMap = new HashMap<>();
        for (TSafeHazardCheckPeople CheckPeople : oldCheckPeopleList) {
            CheckPeopleMap.put(CheckPeople.getUserId(), CheckPeople);
        }

        for (TSafeHazardCheckPeople CheckPeople : CheckPeopleList) {
            if (CheckPeopleMap.get(CheckPeople.getUserId()) != null) {
                editCheckPeopleList.add(CheckPeople);
                CheckPeopleMap.remove(CheckPeople.getUserId());
                continue;
            }
            newCheckPeopleList.add(CheckPeople);
        }

        for (Map.Entry<String, TSafeHazardCheckPeople> entry : CheckPeopleMap.entrySet()) {
            deleteCheckPeopleList.add(entry.getValue());
        }

        resultMap.put("new", newCheckPeopleList);
        resultMap.put("edit", editCheckPeopleList);
        resultMap.put("delete", deleteCheckPeopleList);
        return resultMap;
    }

    @Override
    public List<SafeHazardCheckPeopleVO> listVOByPlan(String planId) {
        // todo 测试创建、启动任务
        //  createCheckTaskJob("44f76d5c5b8444daa8751731b23d07f3", null);

        return tSafeHazardCheckPeopleDao.listVOByPlan(planId);
    }

    /**
     * 生成cron表达式
     *
     * @param checkPeople
     * @return
     */
    public String generateCron(TSafeHazardCheckPeople checkPeople) {
        String frequencyKey = checkPeople.getFrequencyKey();
        if (StrUtil.isBlank(frequencyKey)) {
            return null;
        }

        String cronStr = null;
        // 单次
        if (CheckFrequencyEnum.one.getCode().equals(frequencyKey)) {
            String date = checkPeople.getStartDate();
            String time = checkPeople.getStartTime();
            String dateTimeStr = date + "T" + time;
            LocalDateTime dateTime = LocalDateTimeUtil.parse(dateTimeStr);
            cronStr = CronUtil.generateCronByOne(dateTime);
        }

        // 每日
        if (CheckFrequencyEnum.day.getCode().equals(frequencyKey)) {
            String time = checkPeople.getStartTime();
            cronStr = CronUtil.generateCronByEveryDay(time);
        }

        // 每周
        if (CheckFrequencyEnum.week.getCode().equals(frequencyKey)) {
            String time = checkPeople.getStartTime();
            Integer weekday = checkPeople.getStartDayNum();
            List<WeekdayEnum> weekdayEnumList = new ArrayList<>();
            if (weekday == 1) {
                weekdayEnumList.add(WeekdayEnum.MONDAY);
            } else if (weekday == 2) {
                weekdayEnumList.add(WeekdayEnum.TUESDAY);
            } else if (weekday == 3) {
                weekdayEnumList.add(WeekdayEnum.WEDNESDAY);
            } else if (weekday == 4) {
                weekdayEnumList.add(WeekdayEnum.THURSDAY);
            } else if (weekday == 5) {
                weekdayEnumList.add(WeekdayEnum.FRIDAY);
            } else if (weekday == 6) {
                weekdayEnumList.add(WeekdayEnum.SATURDAY);
            } else if (weekday == 7) {
                weekdayEnumList.add(WeekdayEnum.SUNDAY);
            } else {
                return null;
            }
            cronStr = CronUtil.generateCronByEveryWeek(weekdayEnumList, time);
        }

        // 每月
        if (CheckFrequencyEnum.month.getCode().equals(frequencyKey)) {
            Integer monthday = checkPeople.getStartDayNum();
            String time = checkPeople.getStartTime();

            if (monthday != 0) {
                List<Integer> monthdayList = new ArrayList<>();
                monthdayList.add(monthday);
                cronStr = CronUtil.generateCronByEveryMonth(monthdayList, time);
            } else {
                cronStr = CronUtil.generateCronByLastDay(null, time);
            }
        }

        // 每季
        if (CheckFrequencyEnum.quarter.getCode().equals(frequencyKey)) {
            Integer monthNum = checkPeople.getStartMonthNum();
            Integer monthday = checkPeople.getStartDayNum();
            String time = checkPeople.getStartTime();
            List<Integer> monthNumList = new ArrayList<>();
            if (monthNum == 1) { // 每季 第一个月
                monthNumList.add(1);
                monthNumList.add(4);
                monthNumList.add(7);
                monthNumList.add(10);
            } else if (monthNum == 2) { // 每季 第二个月
                monthNumList.add(2);
                monthNumList.add(5);
                monthNumList.add(8);
                monthNumList.add(11);
            } else if (monthNum == 3) { // 每季 第三个月
                monthNumList.add(3);
                monthNumList.add(6);
                monthNumList.add(9);
                monthNumList.add(12);
            } else {
                return null;
            }
            monthNumList.add(monthday);

            if (monthday != 0) {
                List<Integer> monthdayList = new ArrayList<>();
                monthdayList.add(monthday);
                cronStr = CronUtil.generateCronByEveryYear(monthNumList, monthdayList, time);
            } else {
                cronStr = CronUtil.generateCronByLastDay(monthNumList, time);
            }
        }

        // 每年
        if (CheckFrequencyEnum.year.getCode().equals(frequencyKey)) {
            Integer monthNum = checkPeople.getStartMonthNum();
            Integer monthday = checkPeople.getStartDayNum();
            String time = checkPeople.getStartTime();

            List<Integer> monthNumList = new ArrayList<>();
            monthNumList.add(monthNum);
            if (monthday != 0) {
                List<Integer> monthdayList = new ArrayList<>();
                monthdayList.add(monthday);
                cronStr = CronUtil.generateCronByEveryMonth(monthdayList, time);
            } else {
                cronStr = CronUtil.generateCronByLastDay(monthNumList, time);
            }

        }
        return cronStr;
    }

    /**
     * 查询指定时间 正在进行的 巡检计划 下的 巡检人员对象信息
     * @param doingDate 指定时间
     * @return
     */
    @Override
    public List<TSafeHazardCheckPeople> listDoingVOByPlanDate(LocalDateTime doingDate){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDate = doingDate.format(formatter);
        return tSafeHazardCheckPeopleDao.listDoingVOByPlanDate(formattedDate);
    }


}
