package com.qmth.distributed.print.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.distributed.print.business.bean.params.analyze.AbleAnalyzePaperParam;
import com.qmth.distributed.print.business.bean.params.analyze.GradeBatchPaperParam;
import com.qmth.distributed.print.business.bean.result.analyze.GradeBatchPaperResult;
import com.qmth.distributed.print.business.entity.GradeBatch;
import com.qmth.distributed.print.business.entity.GradeBatchPaper;
import com.qmth.distributed.print.business.mapper.GradeBatchPaperMapper;
import com.qmth.distributed.print.business.service.GradeBatchPaperService;
import com.qmth.distributed.print.business.service.GradeBatchService;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysOrg;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.GradeAnalyzePaperStatusEnum;
import com.qmth.teachcloud.common.enums.OrgTypeEnum;
import com.qmth.teachcloud.common.service.SysOrgService;
import com.qmth.teachcloud.common.service.TeachcloudCommonService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 分析-批次试卷关联关系表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2022-05-20
 */
@Service
public class GradeBatchPaperServiceImpl extends ServiceImpl<GradeBatchPaperMapper, GradeBatchPaper> implements GradeBatchPaperService {
    @Resource
    SysOrgService sysOrgService;
    @Resource
    TeachcloudCommonService teachcloudCommonService;
    @Resource
    GradeBatchService gradeBatchService;

    @Override
    public IPage<GradeBatchPaperResult> findGradeBatchPaperPage(Long batchId, Long examId, String courseCode, int pageNumber, int pageSize, SysUser requestUser) {
        Long schoolId = requestUser.getSchoolId();
        IPage<GradeBatchPaperResult> datasource = this.baseMapper.findGradeBatchPaperPage(new Page<>(pageNumber, pageSize), batchId, examId, courseCode, schoolId);
        for (GradeBatchPaperResult record : datasource.getRecords()) {
            Long teachingRoomId = record.getTeachingRoomId();
            SysOrg teachCollege = this.findTeachCollegeByOrgId(teachingRoomId);
            record.setTeachCollegeId(teachCollege.getId());
            record.setTeachCollegeName(teachCollege.getName());
        }
        return datasource;
    }

    @Override
    public List<GradeBatchPaperResult> findAbleAnalyzePaperList(Long batchId, Long examId, Long collegeId, String courseCode, String teacherName, SysUser requestUser) {
        Long schoolId = requestUser.getSchoolId();
        Set<Long> orgIds = teachcloudCommonService.listSubOrgIds(null);
        GradeBatch gradeBatch = gradeBatchService.getById(batchId);
        if (Objects.isNull(gradeBatch)) {
            throw ExceptionResultEnum.ERROR.exception("教研分析批次不存在");
        }
        List<GradeBatchPaperResult> datasource = this.baseMapper.findAbleAnalyzePaper(gradeBatch.getSemesterId(), examId, collegeId, courseCode, teacherName, orgIds, schoolId);
        List<GradeBatchPaperResult> needAddList = new ArrayList<>();
        for (GradeBatchPaperResult gradeBatchPaperResult : datasource) {
            // 额外处理开课学院
            Long teachingRoomId = gradeBatchPaperResult.getTeachingRoomId();
            SysOrg teachCollege = this.findTeachCollegeByOrgId(teachingRoomId);
            if (SystemConstant.longNotNull(collegeId) && !collegeId.equals(teachCollege.getId())) {
                continue;
            }
            gradeBatchPaperResult.setTeachCollegeId(teachCollege.getId());
            gradeBatchPaperResult.setTeachCollegeName(teachCollege.getName());

            // 需要拆分的试卷类型
            String paperType = gradeBatchPaperResult.getPaperType();
            for (String paperTypeCell : paperType.split(",")) {
                GradeBatchPaperResult needAdd = new GradeBatchPaperResult();
                BeanUtils.copyProperties(gradeBatchPaperResult, needAdd);
                needAdd.setPaperType(paperTypeCell);
                needAdd.setPaperName(needAdd.getCourseName() + "-" + paperTypeCell);
                needAddList.add(needAdd);
            }
        }
        return needAddList.stream().sorted(Comparator.comparing(GradeBatchPaperResult::getSemesterName)
                .thenComparing(GradeBatchPaperResult::getExamName)
                .thenComparing(GradeBatchPaperResult::getTeachCollegeId)
                .thenComparing(GradeBatchPaperResult::getCourseCode)
                .thenComparing(GradeBatchPaperResult::getPaperNumber)
                .thenComparing(GradeBatchPaperResult::getPaperType)).collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveGradeBatchPaper(GradeBatchPaperParam gradeBatchPaperParam, SysUser requestUser) {
        Long batchId = gradeBatchPaperParam.getBatchId();
        Long schoolId = requestUser.getSchoolId();
        List<AbleAnalyzePaperParam> ableAnalyzePaperParamList = gradeBatchPaperParam.getAbleAnalyzePaperList();

        // 是否需要更新批次状态
        AtomicBoolean updateBatchStatus = new AtomicBoolean(false);
        List<GradeBatchPaper> gradeBatchPaperList = ableAnalyzePaperParamList.stream().flatMap(e -> {
            String paperNumber = e.getPaperNumber();
            String paperType = e.getPaperType();
            Long teachCollegeId = e.getTeachCollegeId();
            String teachCollegeName = e.getTeachCollegeName();
            String paperName = e.getPaperName();

            GradeBatchPaper gradeBatchPaper = new GradeBatchPaper();
            gradeBatchPaper.setSchoolId(schoolId);
            gradeBatchPaper.setBatchId(batchId);
            gradeBatchPaper.setPaperNumber(paperNumber);
            gradeBatchPaper.setPaperType(paperType);
            gradeBatchPaper.setPaperName(e.getPaperName());
            gradeBatchPaper.setTeachCollegeId(teachCollegeId);
            gradeBatchPaper.setTeachCollegeName(teachCollegeName);


            GradeBatchPaper dbBatchPaper = this.getOne(new QueryWrapper<GradeBatchPaper>().lambda()
                    .eq(GradeBatchPaper::getSchoolId, schoolId)
                    .eq(GradeBatchPaper::getBatchId, batchId)
                    .eq(GradeBatchPaper::getPaperNumber, paperNumber)
                    .eq(GradeBatchPaper::getPaperType, paperType));
            if (Objects.isNull(dbBatchPaper)) {
                // 新增
                gradeBatchPaper.insertInfo(requestUser.getId());
                gradeBatchPaper.setStatus(GradeAnalyzePaperStatusEnum.PUSH_GRADE_BATCH);
                gradeBatchPaper.setEnable(true);
                gradeBatchPaper.setPublishStatus(false);
                updateBatchStatus.set(true);

                // 更新批次状态为PUSH_GRADE_BATCH
                UpdateWrapper<GradeBatch> updateWrapper = new UpdateWrapper<>();
                updateWrapper.lambda().set(GradeBatch::getStatus, GradeAnalyzePaperStatusEnum.PUSH_GRADE_BATCH).eq(GradeBatch::getId, batchId);
                gradeBatchService.update(updateWrapper);
            } else {
                // 编辑（计算中的不允许被编辑，其他状态下的只要开课学院和试卷名称有变化，状态就更新为需要重新推送）
                GradeAnalyzePaperStatusEnum dbStatus = dbBatchPaper.getStatus();
                if (GradeAnalyzePaperStatusEnum.CALCULATING.equals(dbStatus)) {
                    throw ExceptionResultEnum.ERROR.exception("试卷编号为【" + paperNumber + "】，试卷类型为【" + paperType + "】的分析试卷正在计算中请稍后再试");
                }
                if (!teachCollegeId.equals(dbBatchPaper.getTeachCollegeId()) || !teachCollegeName.equals(dbBatchPaper.getTeachCollegeName()) || !paperName.equals(dbBatchPaper.getPaperName())) {
                    gradeBatchPaper.setStatus(GradeAnalyzePaperStatusEnum.PUSH_GRADE_BATCH);
                    updateBatchStatus.set(true);
                }
                gradeBatchPaper.setId(dbBatchPaper.getId());
                gradeBatchPaper.setStatus(dbBatchPaper.getStatus());
                gradeBatchPaper.setPublishStatus(dbBatchPaper.getPublishStatus());
                gradeBatchPaper.updateInfo(requestUser.getId());
            }
            return Stream.of(gradeBatchPaper);
        }).collect(Collectors.toList());

        this.saveOrUpdateBatch(gradeBatchPaperList);

        // 更新批次状态
        if (updateBatchStatus.get()) {
            UpdateWrapper<GradeBatch> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().set(GradeBatch::getStatus, GradeAnalyzePaperStatusEnum.PUSH_GRADE_BATCH).eq(GradeBatch::getId, batchId);
            gradeBatchService.update(updateWrapper);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteGradeBatchPaper(Long batchId, List<Long> idList) {
        for (Long id : idList) {
            GradeBatchPaper gradeBatchPaper = this.getById(id);
            if (GradeAnalyzePaperStatusEnum.CALCULATING.equals(gradeBatchPaper.getStatus())) {
                throw ExceptionResultEnum.ERROR.exception("试卷编号为【" + gradeBatchPaper.getPaperNumber() +
                        "】，试卷类型为【" + gradeBatchPaper.getPaperType() + "】的分析试卷正在计算中请稍后再试");
            }
            if (gradeBatchPaper.getPublishStatus()) {
                throw ExceptionResultEnum.ERROR.exception("试卷编号为【" + gradeBatchPaper.getPaperNumber() +
                        "】，试卷类型为【" + gradeBatchPaper.getPaperType() + "】的分析试卷已发布，不能删除");
            }
        }
        // 更新批次状态为status=PUSH_GRADE_BATCH
        UpdateWrapper<GradeBatch> gradeBatchUpdateWrapper = new UpdateWrapper<>();
        gradeBatchUpdateWrapper.lambda().set(GradeBatch::getStatus, GradeAnalyzePaperStatusEnum.PUSH_GRADE_BATCH).eq(GradeBatch::getId, batchId);
        gradeBatchService.update(gradeBatchUpdateWrapper);

        // 更新enale=false
        UpdateWrapper<GradeBatchPaper> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(GradeBatchPaper::getEnable, false).in(GradeBatchPaper::getId, idList);
        return this.update(updateWrapper);
    }

    @Override
    public GradeBatchPaper findByThirdExamIdAndGradeCourseCode(Long schoolId, String thirdExamId, String gradeCourseCode) {
        return this.baseMapper.findByThirdExamIdAndGradeCourseCode(schoolId, thirdExamId, gradeCourseCode);
    }

    @Transactional
    @Override
    public void checkOperateAuth(Long schoolId, String paperNumber, String paperType) {
        List<GradeBatchPaper> gradeBatchPaperList = this.list(new QueryWrapper<GradeBatchPaper>().lambda()
                .eq(GradeBatchPaper::getSchoolId, schoolId)
                .eq(GradeBatchPaper::getPaperNumber, paperNumber)
                .eq(GradeBatchPaper::getPaperType, paperType));
        if (gradeBatchPaperList.stream().anyMatch(e -> GradeAnalyzePaperStatusEnum.CALCULATING.equals(e.getStatus()))) {
            throw ExceptionResultEnum.ERROR.exception("选择的试卷有正在计算的分析课程");
        }
        List<Long> batchIdList = gradeBatchPaperList.stream().map(GradeBatchPaper::getBatchId).distinct().collect(Collectors.toList());
        if (batchIdList.size() > 0) {
            if (gradeBatchService.list(new QueryWrapper<GradeBatch>().lambda().in(GradeBatch::getId, batchIdList)).stream().anyMatch(e -> GradeAnalyzePaperStatusEnum.CALCULATING.equals(e.getStatus()))) {
                throw ExceptionResultEnum.ERROR.exception("所选择的试卷所属的批次正在计算中不能更改");
            }
        }

        // 更新批次科目状态
        for (GradeBatchPaper gradeBatchPaper : gradeBatchPaperList) {
            gradeBatchPaper.setStatus(GradeAnalyzePaperStatusEnum.READY_TO_CALCULATE);
            this.updateById(gradeBatchPaper);

            // 更新批次状态
            GradeBatch gradeBatch = gradeBatchService.getById(gradeBatchPaper.getBatchId());
            // 批次未推送成功，不更新状态
            if(GradeAnalyzePaperStatusEnum.PUSH_GRADE_BATCH.equals(gradeBatch.getStatus())){
                continue;
            }
            if (GradeAnalyzePaperStatusEnum.FINISH_CALCULATE.equals(gradeBatch.getStatus())) {
                gradeBatch.setStatus(GradeAnalyzePaperStatusEnum.READY_TO_CALCULATE);
                gradeBatchService.updateById(gradeBatch);
            } else {
                QueryWrapper<GradeBatchPaper> queryWrapperList = new QueryWrapper<>();
                queryWrapperList.lambda().eq(GradeBatchPaper::getBatchId, gradeBatchPaper.getBatchId());
                List<GradeBatchPaper> gradeBatchPaperAll = this.list(queryWrapperList);
                if (!gradeBatchPaperAll.isEmpty()) {
                    long count = gradeBatchPaperAll.stream().filter(m -> !GradeAnalyzePaperStatusEnum.READY_TO_CALCULATE.equals(m.getStatus())).count();
                    if (count == 0) {
                        // 更新批次状态
                        UpdateWrapper<GradeBatch> updateWrapper = new UpdateWrapper<>();
                        updateWrapper.lambda().set(GradeBatch::getStatus, GradeAnalyzePaperStatusEnum.READY_TO_CALCULATE).eq(GradeBatch::getId, gradeBatchPaper.getBatchId());
                        gradeBatchService.update(updateWrapper);
                    }
                }
            }
        }
    }

    /**
     * 根据机构id查询开课学院
     *
     * @param orgId 机构id（课程所在教研室）
     * @return 开课学院
     */
    @Override
    public SysOrg findTeachCollegeByOrgId(Long orgId) {
        if (!SystemConstant.longNotNull(orgId)) {
            throw ExceptionResultEnum.ERROR.exception("机构id不存在");
        }

        List<SysOrg> collegeList = sysOrgService.findParentsByOrgId(orgId).stream().filter(e -> OrgTypeEnum.COLLEGE.equals(e.getType())).distinct().collect(Collectors.toList());
        if (collegeList.size() != 1) {
            throw ExceptionResultEnum.ERROR.exception("未找到开课学院");
        }
        return collegeList.get(0);
    }
}
