package com.testor.module.train.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.testor.biz.sys.org.model.domain.SysOrg;
import com.testor.biz.sys.org.service.SysOrgService;
import com.testor.biz.sys.user.model.domain.SysUser;
import com.testor.biz.sys.user.service.SysUserService;
import com.testor.common.core.utils.StringUtils;
import com.testor.common.util.DateUtil;
import com.testor.module.duty.model.dto.Person;
import com.testor.module.train.course.model.domain.TTrainCourse;
import com.testor.module.train.course.model.domain.TTrainSection;
import com.testor.module.train.course.model.domain.TTrainSmallNode;
import com.testor.module.train.course.service.TTrainCourseService;
import com.testor.module.train.course.service.TTrainSectionService;
import com.testor.module.train.course.service.TTrainSmallNodeService;
import com.testor.module.train.examinationManage.model.dto.TTrainExaminationManageParam;
import com.testor.module.train.examinationManage.service.TTrainExaminationManageService;
import com.testor.module.train.myManagement.model.domain.TTrainGrade;
import com.testor.module.train.myManagement.model.domain.TTrainMyManagement;
import com.testor.module.train.myManagement.service.TTrainGradeService;
import com.testor.module.train.myManagement.service.TTrainMyManagementService;
import com.testor.module.train.paper.service.TTrainPaperService;
import com.testor.module.train.project.dao.TTrainProjectDao;
import com.testor.module.train.project.model.domain.TTrainProject;
import com.testor.module.train.project.model.dto.MyManagement;
import com.testor.module.train.project.model.dto.TTrainProjectDelParam;
import com.testor.module.train.project.model.dto.TTrainProjectParam;
import com.testor.module.train.project.model.stat.ProjectScoreStatVo;
import com.testor.module.train.project.model.stat.ProjectStatPara;
import com.testor.module.train.project.service.TTrainProjectService;
import com.testor.module.train.project.service.TrainProjectStatisticsDetailService;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import com.tongtech.tfw.backend.common.biz.models.BaseResponse;
import com.tongtech.tfw.backend.common.biz.models.BizGeneralResponse;
import com.tongtech.tfw.backend.common.context.ContextUtils;
import com.tongtech.tfw.backend.common.exception.BusinessException;
import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl;
import com.tongtech.tfw.backend.common.models.sys.UserInfo;
import com.tongtech.tfw.backend.core.helper.IdHelper;
import com.tongtech.tfw.backend.core.helper.ObjectHelper;
import com.tongtech.tfw.backend.core.helper.StringHelper;
import com.tongtech.tfw.backend.core.helper.TypeHelper;
import com.tongtech.tfw.backend.core.helper.bean.BeanHelper;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;


import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 教育培训计划—安全培训教育Service业务层处理
 *
 * @author testor-framework
 * @date 2022-07-28 15:15:20
 */
@Service
public class TTrainProjectServiceImpl extends SuperServiceImpl<TTrainProjectDao, TTrainProject> implements TTrainProjectService {
    @Autowired(required = false)
    private TTrainProjectDao tTrainProjectDao;

    @Autowired
    private SysOrgService sysOrgService;

    @Autowired
    private TTrainMyManagementService tTrainMyManagementService;

    @Autowired
    private TTrainCourseService tTrainCourseService;

    @Autowired
    private TTrainPaperService tTrainPaperService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private TTrainExaminationManageService tTrainExaminationManageService;

    @Autowired
    private TTrainGradeService tTrainGradeService;

    @Autowired
    private TTrainSmallNodeService tTrainSmallNodeService;

    @Autowired
    private TTrainSectionService tTrainSectionService;
    @Autowired
    private TrainProjectStatisticsDetailService projectStatisticsDetailService;


    @Override
    public BaseResponse<TTrainProject> addEntity(TTrainProjectParam addRequest) throws Exception {
        UserInfo loginUser = ContextUtils.getLoginUser();
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        BaseResponse<TTrainProject> baseResponse = new BaseResponse<>();
        if (ObjectHelper.isNotEmpty(addRequest)) {
            String id = addRequest.getId();
            if (ObjectHelper.isEmpty(id)) {
                id = IdHelper.getId32bit();
            } else {
                TTrainProject management = this.getById(id);
                // 培训计划开始时间
               // String startTime = management.getVisitStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

                String startTime = DateUtil.convertDateToStr(management.getVisitStartTime(), "yyyy-MM-dd HH:mm:ss");
                // 当前时间
                String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                if (currentTime.compareTo(startTime) > 0) {
                    throw new BusinessException("培训计划已经开始不能修改");
                }
                tTrainMyManagementService.deletePerson(addRequest.getId());
            }

            // 获取培训计划人员调用人员接口进行存储
            List<MyManagement> myManagements = addRequest.getMyManagements();
            // 存储考试计划
            Map<String, String> examId = null;
            if ("1".equals(addRequest.getIsAddExam())) {
                TTrainExaminationManageParam examinationManageParam = new TTrainExaminationManageParam();
                List<MyManagement> list = addRequest.getMyManagements();
                examinationManageParam.setMyManagements(list);
                examinationManageParam.setExamDuration(addRequest.getExamDuration()).setExamEndTime(addRequest.getExamEndTime())
                        .setExamName(addRequest.getExamName()).setExamSite(addRequest.getExamSite()).setExamStartTime(addRequest.getExamStartTime())
                        .setExamType(addRequest.getVisitType()).setExamWay(addRequest.getExamType()).setPaperId(addRequest.getTestPaperId())
                        .setMakeupExamOptions(addRequest.getMakeupExamOptions());
                // 考试计划id
                examId = tTrainExaminationManageService.addEntity(examinationManageParam).getData();

                // 如果添加考试设置考试计划和培训计划关联关系
                Map<String, String> finalExamId = examId;
                myManagements.forEach(item -> {
                    for (String key : finalExamId.keySet()) {
                        if (item.getPersonId().equals(key)) {
                            item.setParentId(finalExamId.get(key));
                        }
                    }
                });
            }

            if (myManagements.size() == 0) {
                throw new BusinessException("请添加参训人员");
            }

            String temp = id;
//            String exam = examId;
            myManagements.stream().forEach(item -> {
                item.setId("");
                item.setTaskId(temp);
                item.setTabStatus("1");
//                item.setParentId(exam);
                item.setVisitStartTime(addRequest.getVisitStartTime());
                item.setVisitEndTime(addRequest.getVisitEndTime());
                item.setTaskName(addRequest.getProjectName());
                item.setLearnWay(addRequest.getVisitWay());
                item.setTaskType(addRequest.getVisitType());
                item.setTestPaperId(addRequest.getTestPaperId());
                item.setIsAddExam(addRequest.getIsAddExam());
                item.setCurrentStatus("0");
            });
            tTrainMyManagementService.addEntity(myManagements);
            TTrainProject data = BeanHelper.beanToBean(addRequest, TTrainProject.class);
            data.setOrgName(sysOrg.getOrgName());
            data.setOrgId(loginUser.getOrgId());
            data.setShouldLearnNumber(Integer.toString(myManagements.size()));
            data.setId(id);
            boolean result = this.saveOrUpdate(data);
            if (result) {
                TTrainProject newEntity = new TTrainProject();
                newEntity.setId(id);
                baseResponse.setData(newEntity);
            }
        }
        return baseResponse;
    }

    @Override
    public BaseResponse<TTrainProjectParam> getByIds(String id) {
        BaseResponse<TTrainProjectParam> baseResponse = new BaseResponse<>();
        if (StringHelper.isNotEmpty(id)) {
            TTrainProject s = this.getById(id);
            TTrainProjectParam tTrainProjectParam = BeanHelper.beanToBean(s, TTrainProjectParam.class);
            // 培训计划id
            String projectParamId = tTrainProjectParam.getId();
            // 课程id
            String courseId = tTrainProjectParam.getCourseId();
            // 试卷id
            String testPaperId = tTrainProjectParam.getTestPaperId();
            // 获取人员集合
            List<TTrainMyManagement> personList = tTrainMyManagementService.getPerson(projectParamId);
            //ToDo 动态查询培训状态
            if (!CollectionUtils.isEmpty(personList) && personList.size() > 0) {
                int count = 0;
                for (TTrainMyManagement tTrainMyManagement : personList) {
                    updateStatus(tTrainMyManagement, courseId);
                    if ("3".equals(tTrainMyManagement.getCurrentStatus())) {
                        count++;
                    }
                }
                tTrainProjectParam.setShouldLearnNumber(String.valueOf(personList.size()));
                tTrainProjectParam.setFinishNumber(String.valueOf(count));
                BigDecimal divide = new BigDecimal(tTrainProjectParam.getFinishNumber()).divide(new BigDecimal(tTrainProjectParam.getShouldLearnNumber()), 6, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP);
                ;
                tTrainProjectParam.setPercentage(divide.toString() + "%");
            }
            List<MyManagement> collect = personList.stream()
                    .map(bean -> bean.beanToBean(MyManagement.class))
                    .sorted(Comparator.comparing(MyManagement::getCurrentStatus).reversed())
                    .collect(Collectors.toList());
            collect.forEach(item -> item.setOrgName(item.getCompany()));
            // 获取课程集合
            List<TTrainCourse> courseList = tTrainCourseService.getCourse(courseId);
            // 获取试卷名称
            String testPaperName = "";
            if (StringHelper.isNotEmpty(testPaperId)) {
                testPaperName = tTrainPaperService.getTestPaperName(testPaperId);
            }
            // 获取评价人数及评价平均分
            List<TTrainGrade> list = tTrainGradeService.list(new QueryWrapper<TTrainGrade>().eq(TTrainGrade.TASK_ID, id));
            if (ObjectHelper.isNotEmpty(list)) {
                // 评价人数
                int size = list.size();
                List<TTrainGrade> filterList = list.stream().filter(temp -> temp != null).collect(Collectors.toList());
                // 评分
                int total = filterList.stream().mapToInt(TTrainGrade::getAssessMinute).sum();
                // 平均分
                double avg = total / size;
                tTrainProjectParam.setEvaluationAvg(String.format("%.1f", avg).toString());
                tTrainProjectParam.setEvaluationPerson(Integer.toString(size));
            }
            tTrainProjectParam.setTrainCourses(courseList);

            tTrainProjectParam.setMyManagements(collect);
            tTrainProjectParam.setTestPaperName(testPaperName);
            baseResponse.setData(tTrainProjectParam);
        }

        detailStatics(baseResponse, id);
        return baseResponse;
    }


    @Override
    @SneakyThrows
    public void updateStatus(TTrainMyManagement record, String courseId) {
        Date now = new Date();
        //todo{
        if ("1".equals(record.getTabStatus())) {
            //课程id
            String loginUserId = record.getPersonId();
            //获取所有章节id
            List<Object> sectionIds = tTrainSectionService.listObjs(new QueryWrapper<TTrainSection>().select("id").in("course_id", courseId).eq("status", "0"));
            if (sectionIds.size() == 0) {
                //设置已完成
                record.setCurrentStatus("3");
            }
            //获取所有小节，完成时间从小到大排序
            List<TTrainSmallNode> list = tTrainSmallNodeService.getExaminationInformation(sectionIds, loginUserId, record.getId());
            if (list != null && list.size() > 0) {
                //第一列数据
                TTrainSmallNode tTrainSmallNode = list.get(0);
                //最后一列数据
                TTrainSmallNode lastSmallNode = list.get(list.size() - 1);
                //如果当前时间还未到计划开始时间（在计划开始之前）
                if (now.compareTo(record.getVisitStartTime())>0) {
                    //设置未开始
                    record.setCurrentStatus("0");
                }
                //如果最后一列数据为空，证明没有学习完毕
                if (lastSmallNode.getFinishTime() == null) {
                    //如果当前时间在结束计划之后
                    if (now.compareTo(record.getVisitEndTime())>0) {
                        //设置逾期
                        record.setCurrentStatus("5");
                    } else {
                        //设置进行中
                        record.setCurrentStatus("1");
                    }
                }
                //如果最后一列不为空
                else {
                    //如果最后完成的小节时间在结束计划之后
                    Date finishTime = tTrainSmallNode.getFinishTime();
                    if (finishTime == null) {
                        if (new Date().compareTo(record.getVisitEndTime())>0) {
                            //设置逾期
                            record.setCurrentStatus("5");
                        }
                    } else {
                        if (finishTime.compareTo(record.getVisitEndTime())>0) {
                            //设置逾期
                            record.setCurrentStatus("5");
                        } else {
                            //设置已完成
                            record.setCurrentStatus("3");
                        }
                    }
                }
            }
        }
    }


    @Override
    public BaseResponse<BizGeneralResponse> updateEntity(TTrainProject updateRequest) throws Exception {
        BaseResponse<BizGeneralResponse> baseResponse = new BaseResponse<>();
        if (ObjectHelper.isNotEmpty(updateRequest) && StringHelper.isNotEmpty(updateRequest.getId())) {
            TTrainProject data = BeanHelper.beanToBean(updateRequest, TTrainProject.class);
            boolean result = this.updateById(data);
            baseResponse.setData(
                    BizGeneralResponse.builder().result(TypeHelper.castToString(result)).build());
        }
        return baseResponse;
    }

    @Override
    public BaseResponse<BizGeneralResponse> deleteEntity(TTrainProjectDelParam deleteRequest) throws Exception {
        BaseResponse<BizGeneralResponse> baseResponse = new BaseResponse<>();
        if (ObjectHelper.isNotEmpty(deleteRequest) && StringHelper.isNotEmpty(deleteRequest.getId())) {
            TTrainProject management = this.getById(deleteRequest.getId());
            // 培训计划开始时间
//            String startTime = management.getVisitStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            String startTime = DateUtil.convertDateToStr(management.getVisitStartTime(), "yyyy-MM-dd HH:mm:ss");

            // 当前时间
            String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            if (currentTime.compareTo(startTime) > 0) {
                throw new BusinessException("培训计划已经开始不能修改");
            }
            TTrainProject data = new TTrainProject();
            data.setId(deleteRequest.getId());
            data.setStatus(BizConstants.STATUS_DELETE);
            boolean result = this.updateById(data);
            baseResponse.setData(
                    BizGeneralResponse.builder().result(TypeHelper.castToString(result)).build());
        }
        return baseResponse;
    }

    @Override
    public IPage<TTrainProjectParam> getAffiliation(TTrainProjectParam param, String parentIds, String orgId) {
        Long page = StringHelper.isEmpty(param.getPage()) ? BizConstants.PAGE : Long.valueOf(1);
        Long limit = StringHelper.isEmpty(param.getLimit()) ? BizConstants.LIMIT : Long.valueOf(-1);
        Page<TTrainProjectParam> resultPage = new Page<>(page, limit);
        return tTrainProjectDao.getAffiliation(resultPage, param, parentIds, orgId);
    }

    /**
     * 获取培训计划
     *
     * @param dsName
     * @param datasetName
     * @param parameters
     * @return
     */
    public List<TTrainProjectParam> getExportTtrainProject(String dsName, String datasetName, Map<String, Object> parameters) {
        String id = parameters.get("id").toString();
        TTrainProjectParam data = getByIds(id).getData();
        data.setProjectName("培训项目名称：" + data.getProjectName());
        // 课程id
        String[] courseID = data.getCourseId().split(",");
        String courseName = "课程名称：";
        for (String s : courseID) {
            TTrainCourse course = tTrainCourseService.getById(s);
            courseName += course.getCourseName() + "、";
        }
        data.setCourseId(courseName);
        String isAddExam = data.getIsAddExam();
        switch (isAddExam) {
            case "1":
                data.setIsAddExam("是否有考试：是");
                break;
            case "0":
                data.setIsAddExam("是否有考试：否");
                break;
        }
        data.setTestPaperName("试卷名称：" + data.getTestPaperName());
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String start = df.format(data.getVisitStartTime());
        String end = df.format(data.getVisitEndTime());
        data.setVisitWay("参训时间:" + start + "-" + end);

        String examStart = df.format(data.getExamStartTime());
        String examEnd = df.format(data.getExamEndTime());

        data.setPercentage("考试时间：" + examStart + "-" + examEnd);

        data.setExamSite("考试地点:" + data.getExamSite());
        List<TTrainProjectParam> arrayList = new ArrayList<>();
        arrayList.add(data);
        return arrayList;
    }

    /**
     * 获取培训计划关联的人员
     *
     * @param dsName
     * @param datasetName
     * @param parameters
     * @return
     */
    public List<TTrainMyManagement> getExportTtrainProjectPerson(String dsName, String datasetName, Map<String, Object> parameters) {
        // 培训计划id
        String id = parameters.get("id").toString();
        TTrainProjectParam data = getByIds(id).getData();
        // 获取人员集合
        List<TTrainMyManagement> personList = tTrainMyManagementService.getPerson(id);
        int count = 0;
        for (TTrainMyManagement tTrainMyManagement : personList) {
            ++count;
            // 序号
            tTrainMyManagement.setErrorsNum(Integer.toString(count));
            String affiliation = tTrainMyManagement.getPersonAffiliation();
            switch (affiliation) {
                case "1":
                    tTrainMyManagement.setPersonAffiliation("本单位");
                    break;
                case "2":
                    tTrainMyManagement.setPersonAffiliation("相关方");
                    break;
            }
            SysUser person = sysUserService.getById(tTrainMyManagement.getPersonId());
            // 年龄
            tTrainMyManagement.setLearnWay(Integer.toString(person.getAge()));
            //  性别
            tTrainMyManagement.setTaskType(person.getSex().equals("0") ? "男" : "女");
        }
        return personList;
    }

    @Override
    public List<TTrainProjectParam> getProjectPerson(String s) {
        return tTrainProjectDao.getProjectPerson(s);
    }

    /**
     * 详情统计数据
     */
    private void detailStatics(BaseResponse<TTrainProjectParam> baseResponse, String id) {
        try {
            TTrainProjectParam data = baseResponse.getData();
            if (data == null) {
                return;
            }
            ProjectStatPara para = new ProjectStatPara();
            para.setProjectId(id);

            ProjectScoreStatVo scoreStatVo = new ProjectScoreStatVo();
            List<String> scoreList = projectStatisticsDetailService.findScoreStatByProjectId(para);
            scoreList.addAll(projectStatisticsDetailService.findScoreRepairTest(para));
            List<BigDecimal> doubleList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(scoreList)) {
                BigDecimal sum = BigDecimal.ZERO;
                for (String score : scoreList) {
                    if(StringUtils.isNotBlank(score)){
                        doubleList.add(new BigDecimal(score));
                        sum = sum.add(new BigDecimal(score));
                    }
                }
                // 获取最大值
                BigDecimal max = Collections.max(doubleList);
                // 获取最小值
                BigDecimal min = Collections.min(doubleList);
                // 计算平均值
                BigDecimal average = sum.divide(BigDecimal.valueOf(doubleList.size()), 1, RoundingMode.HALF_UP);
                scoreStatVo.setHighestScore(max.toString());
                scoreStatVo.setLowestScore(min.toString());
                scoreStatVo.setAverageScore(average.toString());
            }
            ProjectScoreStatVo examStates = projectStatisticsDetailService.findExamStates(para);
            if (examStates != null) {
                scoreStatVo.setExamNum(examStates.getExamNum());
                scoreStatVo.setExamFinishPercentage(examStates.getExamFinishPercentage());
                scoreStatVo.setExamNumFinish(examStates.getExamNumFinish());
            }

            data.setScoreStatByProjectId(scoreStatVo);
            baseResponse.setData(data);
        } catch (Exception e) {
            log.error("培训计划详情统计数据异常", e);
        }
    }


    public static void main(String[] args) {
        BigDecimal divide = new BigDecimal("1").divide(new BigDecimal("3"), 6, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.DOWN);

        System.out.println(divide);

    }


}
