package com.rongwei.trainingcommon.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rongwei.rwadmincommon.system.domain.SysUserDo;
import com.rongwei.rwadmincommon.system.service.SysUserOrgService;
import com.rongwei.rwadmincommon.system.vo.SysUserVo;
import com.rongwei.rwcommon.base.BaseDo;
import com.rongwei.rwcommon.base.R;
import com.rongwei.rwcommon.utils.StringUtils;
import com.rongwei.safecommon.utils.JSCommonUtils;
import com.rongwei.training.domain.*;
import com.rongwei.trainingcommon.sys.service.EmpExamService;
import com.rongwei.trainingcommon.sys.service.PlanPaperService;
import com.rongwei.trainingcommon.sys.service.PlanService;
import com.rongwei.trainingcommon.sys.service.TrainingSendNotifyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.rongwei.safecommon.utils.SaveConstans.NotifyContent.*;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyTitle.*;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyType.*;

/**
 * SendNotifyService class
 *
 * @author XH
 * @date 2023/12/15
 */
@Service
public class TrainingSendNotifyServiceImpl implements TrainingSendNotifyService {
    // 培训计划已发布
    private static final String TRAINING_PLAN_PUBLISH = "y";
    private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
    @Autowired
    private PlanService planService;
    @Autowired
    private PlanPaperService planPaperService;
    @Autowired
    private SendMailServiceImpl sendMailService;
    @Autowired
    private EmpExamService empExamService;
    @Autowired
    private SysUserOrgService userOrgService;
    @Autowired
    private TrainingDemandSurveyBackupsServiceImpl demandSurveyBackupsService;
    @Autowired
    private PlanCourseServiceImpl planCourseService;
    @Autowired
    private EmpCourseServiceImpl empCourseService;

    @Override
    public R endReminderEmail() {
        // 获取培训计划
        List<PlanDo> planDoList = planService.list(new LambdaQueryWrapper<PlanDo>().eq(BaseDo::getDeleted, "0")
                .eq(PlanDo::getPublish, TRAINING_PLAN_PUBLISH)
                .last("and( DATEDIFF(TRAININGENDTIMT, NOW()) =3 or DATEDIFF(TRAININGENDTIMT, NOW()) =0)"));
        if (planDoList.isEmpty()) {
            return R.ok();
        }
        log.info("获取到培训计划：{}", planDoList);
        List<String> planId = planDoList.stream().map(PlanDo::getId).collect(Collectors.toList());
        List<PlanCourseDo> planCourseDoList = planCourseService.list(new LambdaQueryWrapper<PlanCourseDo>()
                .eq(BaseDo::getDeleted, "0")
                .in(PlanCourseDo::getTrainingplanid, planId));

        // 根据培训计划获取对应的试卷信息
//        List<PlanPaperDo> planPaperList = planPaperService.list(new LambdaQueryWrapper<PlanPaperDo>()
//                .eq(BaseDo::getDeleted, "0")
//                .in(PlanPaperDo::getTrainingplanid, planDoList.stream().map(PlanDo::getId).collect(Collectors.toSet())));

        log.info("获取到的课程信息：{}", planCourseDoList);
        // 筛选出距离截止日期还有3天的试卷信息
//        List<PlanPaperDo> closePlanPaper = planPaperList
//                .parallelStream()
//                .filter(planPaper -> planPaper.getDeadline() != null && sendMailService.aFewDaysApart(planPaper.getDeadline()) == 3)
//                .collect(Collectors.toList());
//        if (closePlanPaper.isEmpty()) {
//            return;
//        }
        // 即将截止的试卷Id
//        Set<String> paperId = closePlanPaper.stream().map(PlanPaperDo::getPaperid).collect(Collectors.toSet());
//        // 试卷所属的培训计划
//        Set<String> planId = closePlanPaper.stream().map(PlanPaperDo::getTrainingplanid).collect(Collectors.toSet());
        /*****获取没有参与课程培训的培训员工******/
        List<EmpCourseDo> toTestInfoList = empCourseService.list(new LambdaQueryWrapper<EmpCourseDo>()
                .eq(BaseDo::getDeleted, "0")
                .in(EmpCourseDo::getPlanid, planId)
                .in(EmpCourseDo::getPlancourseid, planCourseDoList.stream().map(PlanCourseDo::getId).collect(Collectors.toList()))
                .last("and COURSETIME*60 <> ifnull(COURSEUSETIME,0)")
        );
        if (toTestInfoList.isEmpty()) {
            return R.ok();
        }
        // 对数据按照 培训计划已经课程信息进行分组
        Map<String, Map<String, List<String>>> collect = toTestInfoList.stream()
                .collect(Collectors.groupingBy(EmpCourseDo::getPlanid, Collectors.groupingBy(EmpCourseDo::getCoursename,
                        Collectors.mapping(EmpCourseDo::getEmpid, Collectors.toList()))));

        // 发送培训课程截止提醒邮件
        collect.forEach((k, v) -> {
            PlanDo planDo = planDoList.stream().filter(info -> info.getId().equals(k)).findFirst().get();
            v.forEach((courseName, infos) -> {
                log.info("准备发送课程截止提醒邮件");
                JSCommonUtils.sendNotify(CUT_OFF_TRAIN_TITLE, String.format(CUT_OFF_TRAIN_CONTENT, planDo.getCoursename(), planDo.getTrainingendtimt()), "",
                        infos.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList())
                        , planDo.getId(), COURSE);
            });
        });
        return R.ok();
    }

    /**
     * 培训试卷截止提醒
     *
     * @return
     */
    @Override
    public R endReminderPaperMail() {
        // 获取培训计划
        List<PlanDo> planDoList = planService.list(new LambdaQueryWrapper<PlanDo>().eq(BaseDo::getDeleted, "0")
                .eq(PlanDo::getPublish, TRAINING_PLAN_PUBLISH));
        if (planDoList.isEmpty()) {
            return R.ok();
        }
        List<String> planIds = planDoList.stream().map(PlanDo::getId).collect(Collectors.toList());
        // 获取培训计划中 截止日期在3天和0填的试卷信息
        List<PlanPaperDo> planPaperDos = planPaperService.list(new LambdaQueryWrapper<PlanPaperDo>()
                .in(PlanPaperDo::getTrainingplanid, planIds)
                .eq(BaseDo::getDeleted, "0")
                .last("and( DATEDIFF(deadline, NOW()) =3 or DATEDIFF(deadline, NOW()) =0)")
        );
        List<String> planPaperIds = planPaperDos.stream().map(PlanPaperDo::getId).collect(Collectors.toList());
        // 获取所有未考试的用户信息
        List<EmpExamDo> examDoList = empExamService.list(new LambdaQueryWrapper<EmpExamDo>().eq(BaseDo::getDeleted, "0")
                .in(EmpExamDo::getPlanid, planIds)
                .in(EmpExamDo::getPlanpaperid, planPaperIds)
                .eq(EmpExamDo::getExamstatus, "待考试")
        );
        Map<String, List<String>> paperMap = new HashMap<>();
        // 对试卷按照试卷名称分组
        Map<String, List<EmpExamDo>> collect = examDoList.stream().collect(Collectors.groupingBy(info -> info.getPaperid() + info.getPlanpaperid(), Collectors.toList()));
        collect.forEach((k, v) -> {
            EmpExamDo empExamDo = v.get(0);
            JSCommonUtils.sendNotify(CUT_OFF_PAPER_TITLE, String.format(CUT_OFF_PAPER_CONTENT, empExamDo.getPapername(), empExamDo.getExamdeadtime()), "",
                    v.stream().map(EmpExamDo::getEmpid).distinct().collect(Collectors.toList()), empExamDo.getPlanid(), TRAINING);
        });

        return R.ok();
    }


    /**
     * 定时提醒为产于培训人员产于培训
     *
     * @param
     * @return
     * @date 2023/12/19 17:58
     * @author shangmi
     */

    @Override
    public void trainingPlan() {
        List<PlanDo> planDos = planService.list(new QueryWrapper<PlanDo>().lambda().eq(BaseDo::getDeleted, "0"));
        Map<PlanDo, Set<String>> planDoSetHashMap = new HashMap<>();
        planDos.forEach(planDo -> {
            // 参与部门
            String orgIds = planDo.getIncludingorgids();
            // 参与员工
            String empids = planDo.getTrainingempids();
            // 排除员工
            String excludeempids = planDo.getExcludeempids();
            Set<String> empIdSet = new HashSet<>();
            if (StringUtils.isNotBlank(orgIds)) {
                // 根据组织机构获取 该机构下的所有员工信息
                List<SysUserVo> deptUsersByDeptIds = userOrgService.getDeptUsersByDeptIds(Arrays.asList(orgIds.split(",")));
                // 取出员工id
                empIdSet = deptUsersByDeptIds.stream().map(SysUserDo::getId).collect(Collectors.toSet());
            }
            if (StringUtils.isNotBlank(empids)) {
                // 将参与员工的组织机构加入
                empIdSet.addAll(Arrays.asList(empids.split(",")));
            }
            if (StringUtils.isNotBlank(excludeempids)) {
                empIdSet.removeAll(Arrays.asList(excludeempids.split(",")));
            }
            planDoSetHashMap.put(planDo, empIdSet);
        });
        /**
         * 发送提醒通知
         */
        sendTrainingPlanNotify(planDoSetHashMap);
    }

    /**
     * 提示产于问卷调查
     *
     * @param
     * @return
     * @date 2023/12/19 17:58
     * @author shangmi
     */

    @Override
    public void questionnaireSurvey() {
        List<TrainingDemandSurveyBackupsDo> list = demandSurveyBackupsService.list(new LambdaQueryWrapper<TrainingDemandSurveyBackupsDo>()
                .eq(BaseDo::getDeleted, 0)
                .isNotNull(TrainingDemandSurveyBackupsDo::getNoparticipatinguserid)
                .apply("DATE(DEADLINE) >= curdate()"));
        sendQuestionnaireSurveyNotify(list);
    }

    /**
     * 问卷调查提现
     *
     * @param
     */
    @Async
    @Override
    public void sendQuestionnaireSurveyNotify(List<TrainingDemandSurveyBackupsDo> saveDemandSurveyBackupsDos) {
        // 获取用户id
        saveDemandSurveyBackupsDos.forEach((info) -> {
            List<String> userIds = Arrays.asList(info.getNoparticipatinguserid().split(","));
            JSCommonUtils.sendNotify(QUESTIONNAIRE_SURVEY_TITLE, String.format(QUESTIONNAIRE_SURVEY_CONTENT, info.getYear(),
                    info.getName()), "", userIds, info.getId(), TRAININGFORM);
        });
    }


    /**
     * 培训计划提醒
     *
     * @param planAndUserIdMap
     */
    public void sendTrainingPlanNotify(Map<PlanDo, Set<String>> planAndUserIdMap) {
        // 获取用户id
        planAndUserIdMap.forEach((k, v) -> {
//            CXCommonUtils.sendNotify(TRAIN_NOTIFY_TITLE, String.format(TRAIN_NOTIFY_CONTENT, k.getCoursename(),
//                            k.getTrainingstarttime(), k.getTrainingendtimt()), "", new ArrayList<>(v),
//                    k.getId(), TRAINING);
//            CXCommonUtils.sendNotify(COURSE_NOTIFY_TITLE, String.format(TRAIN_NOTIFY_CONTENT, k.getCoursename(),
//                            k.getTrainingstarttime(), k.getTrainingendtimt()), "", new ArrayList<>(v),
//                    k.getId(), COURSE);
        });

    }

    /**
     * 培训计划取消提醒
     *
     * @param courseMap
     * @param paperMap
     */
    @Override
    public void sendTrainingPlanCancelNotify(Map<String, List<String>> courseMap,
                                             Map<String, List<String>> paperMap) {
        courseMap.forEach((k, v) -> {
            JSCommonUtils.sendNotify(CANCEL_TRAIN_TITLE, String.format(CANCEL_TRAIN_CONTENT, k), "",
                    v, null, COURSE);
        });
        paperMap.forEach((k, v) -> {
            JSCommonUtils.sendNotify(CANCEL_TRAIN_TITLE, String.format(CANCEL_TRAIN_CONTENT, k), "",
                    v, null, TRAINING);
        });
    }


}
