package cn.com.ty.lift.business.framework.job;

import cn.com.ty.lift.business.maintenance.dao.entity.MaintenancePlan;
import cn.com.ty.lift.business.maintenance.dao.entity.model.MaintenanceTask;
import cn.com.ty.lift.business.maintenance.dao.mapper.MaintenancePlanMapper;
import cn.com.ty.lift.business.maintenance.service.MaintenancePlanService;
import cn.com.ty.lift.business.project.dao.entity.Project;
import cn.com.ty.lift.business.project.service.ProjectService;
import cn.com.ty.lift.business.push.entity.InspectionTips;
import cn.com.ty.lift.business.push.entity.RepairTips;
import cn.com.ty.lift.business.push.entity.TaskTips;
import cn.com.ty.lift.business.push.service.PushUserService;
import cn.com.ty.lift.common.constants.CommonEnum;
import cn.com.ty.lift.common.constants.WebSocketConstants;
import cn.com.ty.lift.common.model.PushMessage;
import cn.com.ty.lift.common.model.PushUserInfo;
import cn.com.ty.lift.common.utils.SendMessageUtil;
import cn.hutool.core.collection.IterUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 定时任务
 *
 * @author wcz
 * @since 2020/1/18 17:16
 */
@Slf4j
@Component
@EnableScheduling
@AllArgsConstructor
public class BusinessJob {

    private MaintenancePlanService maintenancePlanService;
    private JmsMessagingTemplate jmsMessagingTemplate;
    private PushUserService pushUserService;
    private MaintenancePlanMapper maintenancePlanMapper;
    private ProjectService projectService;

    /**
     * 更新维保计划过期状态job：每天1-3点，每10分钟执行一次
     */
    @Scheduled(cron = "0 0/10 1-3 * * ?")
    public void updateMtPlanJob() {
        log.info("Starting update maintenance plan overdue job...");
        long pageNum = 1;
        long pages;
        int size = 0;
        do {
            IPage<MaintenancePlan> planPages = maintenancePlanService.pageOverduePlan(new Page<>(pageNum, 100));
            pages = planPages.getPages();
            List<MaintenancePlan> records = planPages.getRecords();
            if (!records.isEmpty()) {
                records.forEach(record -> record.setStatus(-1));
                maintenancePlanService.updateBatchById(records);
            }
            pageNum++;
            size += records.size();
        } while (pageNum <= pages);
        log.info("update maintenance plan overdue job end, update size :" + size);
    }

    /**
     * 查询当天所有维保工的维保任务并提醒
     */
    @Scheduled(cron = "0 0 7 * * ?")
    public void sendMaintenanceTask() {
        log.info("开始执行维保任务提醒推送");
        //查询所有维保工当天的维保任务
        List<MaintenanceTask> maintenanceTasks = maintenancePlanMapper.queryMaintenanceTask();
        for (MaintenanceTask task : maintenanceTasks) {
            PushUserInfo userInfo = new PushUserInfo(task.getDeviceModel(), task.getDeviceFlag());
            //推送当天每个维保工的维保任务
            PushMessage.maintainHasTaskDaily(task.getNum())
                    .sendTokenOnPlatform(jmsMessagingTemplate, userInfo);
        }
        log.info("维保任务提醒推送执行完成");
    }


    /**
     * 批量更新项目状态为逾期，并发送提醒消息
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void updateProjectOverdueJob() {
        log.info("开始执行批量更新项目状态为逾期批处理");
        List<Project> projects = projectService.queryInServiceProjectList();
        projectService.updateBatch(projects, CommonEnum.ProjectStatus.OVERDUE.getCode());
        log.info("批量更新项目状态为逾期批处理执行成功");
        for (Project entry : projects) {
            projectService.sendOverdueMessage(entry.getId(), entry.getMtCompanyId());
        }
    }

    /**
     * 批量更新项目状态为服务中，并发送提醒消息
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void updateProjectInServiceJob() {
        log.info("开始执行批量更新项目状态为服务中批处理");
        List<Project> projects = projectService.queryNotStartProjectList();
        projectService.updateBatch(projects, CommonEnum.ProjectStatus.IN_SERVICE.getCode());
        log.info("批量更新项目状态为服务中批处理执行成功");
        for (Project entry : projects) {
            projectService.sendMessage(entry.getId(), entry.getMtCompanyId(), entry.getProjectStatus());
        }
    }

    /**
     * 年检到期提前45天提醒
     */
    @Scheduled(cron = "0 0 9 * * ?")
    public void inspection45days() {
        log.warn("Starting inspection 45days notice job...");
        sendAnnualInspection(45);
    }

    private void sendAnnualInspection(int days) {
        long pageNum = 1;
        long pages;
        do {
            IPage<InspectionTips> tips = pushUserService.pageMtCompanyByAnnualInspection(new Page<>(pageNum, 100), days);
            pages = tips.getPages();
            List<InspectionTips> records = tips.getRecords();
            if (records.isEmpty()) {
                continue;
            }
            if (days == 45) {
                for (InspectionTips record : records) {
                    List<PushUserInfo> pushUserInfos = pushUserService.listByUserIds(record.getMtCompanyId(), record.members());
                    if (IterUtil.isNotEmpty(pushUserInfos)) {
                        PushMessage pushMessage = PushMessage.inspectionAdvance45daysNotice(record.getProjectName(),
                                record.getDevicePosition(), record.getRegistrationCode());
                        pushMessage.sendTokenOnPlatform(jmsMessagingTemplate, pushUserInfos);
                        //推送消息到pc端
                        List<Long> userIds = pushUserInfos.stream().map(PushUserInfo::getUserId).collect(Collectors.toList());
                        SendMessageUtil.sendMessageToPC(jmsMessagingTemplate, userIds, pushMessage.getContent(),
                                WebSocketConstants.MessageType.INSPECTION_MSG);
                    }
                }
            } else {
                for (InspectionTips record : records) {
                    List<PushUserInfo> pushUserInfos = pushUserService.listByUserIds(record.getMtCompanyId(), record.members());
                    if (IterUtil.isNotEmpty(pushUserInfos)) {
                        PushMessage pushMessage = PushMessage.inspectionAdvance15daysNotice(record.getProjectName(),
                                record.getDevicePosition(), record.getRegistrationCode());
                        pushMessage.sendTokenOnPlatform(jmsMessagingTemplate, pushUserInfos);
                        //推送消息到pc端
                        List<Long> userIds = pushUserInfos.stream().map(PushUserInfo::getUserId).collect(Collectors.toList());
                        SendMessageUtil.sendMessageToPC(jmsMessagingTemplate, userIds, pushMessage.getContent(),
                                WebSocketConstants.MessageType.INSPECTION_MSG);
                    }
                }
            }
            pageNum++;
        } while (pageNum <= pages);
    }

    /**
     * 年检到期提前15天提醒
     */
    @Scheduled(cron = "0 0 10 * * ?")
    public void inspection15days() {
        log.warn("Starting inspection 15days notice job...");
        sendAnnualInspection(15);
    }

    @Scheduled(cron = "0 10 16 * * ?")
    public void taskTipsForRegion() {
        log.trace("Starting task report notice job...");
        List<RepairTips> repairTips = pushUserService.listMtCompanyByEmergencyRepairForRegion();
        if (repairTips.isEmpty()) {
            return;
        }

        Map<Long, TaskTips> taskTipsMap = new HashMap<>();
        List<TaskTips> taskTips = pushUserService.listMaintainForEnterpriseAdmin();
        for (TaskTips taskTip : taskTips) {
            taskTipsMap.put(taskTip.getMtCompanyId(), taskTip);
        }

        //区域主管（项目所属）
        for (RepairTips repairTip : repairTips) {
            long mtCompanyId = repairTip.getMtCompanyId();
            PushUserInfo director = pushUserService.listByUserId(mtCompanyId, repairTip.getDirectorId());
            int maintain = 0;
            TaskTips current = taskTipsMap.get(mtCompanyId);
            if (Objects.nonNull(current)) {
                maintain = current.getMaintainTotal();
            }
            PushMessage.managerTaskForRegionChargerDaily(repairTip.getAreaName(), repairTip.getTotal(), repairTip.getFinish(), repairTip.getRepairing(), maintain).sendTokenOnPlatform(jmsMessagingTemplate, director);
        }
    }

    @Scheduled(cron = "0 0 16 * * ?")
    public void taskTipsForDirector() {
        log.trace("Starting task report notice job...");
        List<RepairTips> repairTips = pushUserService.listMtCompanyByEmergencyRepairForDirector();
        if (repairTips.isEmpty()) {
            return;
        }

        Map<Long, TaskTips> taskTipsMap = new HashMap<>();
        List<TaskTips> taskTips = pushUserService.listMaintainForEnterpriseAdmin();
        for (TaskTips taskTip : taskTips) {
            taskTipsMap.put(taskTip.getMtCompanyId(), taskTip);
        }
        //总经理
        for (RepairTips repairTip : repairTips) {
            long mtCompanyId = repairTip.getMtCompanyId();
            List<PushUserInfo> pushUserInfos = pushUserService.listHighDirector(mtCompanyId);
            int maintain = 0;
            TaskTips current = taskTipsMap.get(mtCompanyId);
            if (Objects.nonNull(current)) {
                maintain = current.getMaintainTotal();
            }
            PushMessage.managerTaskForLeaderDaily(repairTip.getTotal(), repairTip.getFinish(), repairTip.getRepairing(), maintain).sendTokenOnPlatform(jmsMessagingTemplate, pushUserInfos);
        }
    }

    @Scheduled(cron = "0 0 8 * * ?")
    public void pageRepairAndMaintainForClerk() {
        log.info("Staring repair and maintain for clerk job...");
        long pageNum = 1;
        long pages;
        do {
            IPage<TaskTips> tipsIPage = pushUserService.pageRepairAndMaintainForClerk(new Page<>(pageNum, 100));
            pages = tipsIPage.getPages();
            List<TaskTips> records = tipsIPage.getRecords();
            if (!records.isEmpty()) {
                for (TaskTips record : records) {
                    PushUserInfo pushUserInfo = pushUserService.listByUserId(record.getMtCompanyId(), record.getUserId());
                    if (Objects.nonNull(pushUserInfo)) {
                        PushMessage.managerMaintainDaily(record.getMaintainTotal(), record.getRepairTotal());
                    }
                }
            }
            pageNum++;
        } while (pageNum <= pages);
    }
}
