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

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.distributed.print.business.bean.params.SingleExamStudentAddParam;
import com.qmth.distributed.print.business.entity.ExamDetail;
import com.qmth.distributed.print.business.entity.ExamDetailCourse;
import com.qmth.distributed.print.business.entity.ExamStudent;
import com.qmth.distributed.print.business.entity.ExamTask;
import com.qmth.distributed.print.business.enums.ExamDetailStatusEnum;
import com.qmth.distributed.print.business.enums.ExamStatusEnum;
import com.qmth.distributed.print.business.mapper.ExamDetailCourseMapper;
import com.qmth.distributed.print.business.service.ExamDetailCourseService;
import com.qmth.distributed.print.business.service.ExamDetailService;
import com.qmth.distributed.print.business.service.ExamStudentService;
import com.qmth.distributed.print.business.service.ExamTaskService;
import com.qmth.teachcloud.common.bean.result.TbTaskDetailResult;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicCourse;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.mark.MarkPaperStatus;
import com.qmth.teachcloud.common.util.ServletUtil;
import com.qmth.teachcloud.mark.entity.MarkPaper;
import com.qmth.teachcloud.mark.entity.MarkStudent;
import com.qmth.teachcloud.mark.service.MarkPaperService;
import com.qmth.teachcloud.mark.service.MarkStudentService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 考务数据（考场关联科目） 服务实现类
 * </p>
 *
 * @author xf
 * @since 2021-03-23
 */
@Service
public class ExamDetailCourseServiceImpl extends ServiceImpl<ExamDetailCourseMapper, ExamDetailCourse> implements ExamDetailCourseService {

    @Resource
    private ExamStudentService examStudentService;
    @Resource
    private ExamDetailService examDetailService;
    @Resource
    private MarkStudentService markStudentService;
    @Resource
    private MarkPaperService markPaperService;
    @Resource
    private ExamTaskService examTaskService;

    @Override
    public List<Map<String, Object>> listClientByExamDetailIdAndStatus(Long examDetailId) {
        return this.baseMapper.listClientByExamDetailIdAndStatus(examDetailId, ExamDetailStatusEnum.FINISH.name());
    }

    @Override
    public void updatePaperNumber(List<Long> examDetailCourseIds, String paperNumber, String relatePaperType) {
        UpdateWrapper<ExamDetailCourse> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(ExamDetailCourse::getPaperNumber, paperNumber)
                .set(ExamDetailCourse::getPaperType, relatePaperType)
                .in(ExamDetailCourse::getId, examDetailCourseIds);
        this.update(updateWrapper);
    }

    @Override
    public List<ExamDetailCourse> listByExamDetailIdAndStatus(Long examDetailId) {
        return this.baseMapper.listByExamDetailIdAndStatus(examDetailId, ExamStatusEnum.SUBMIT.name());
    }

    @Override
    public List<BasicCourse> listCoursesByPrintPlanId(String param, List<Long> printPlanIdList) {
        return this.baseMapper.listCoursesByPrintPlanId(SystemConstant.translateSpecificSign(param), printPlanIdList);
    }

    @Override
    public List<ExamDetailCourse> listByPrintPlanIdAndCourseCodeAndPaperNumber(Long schoolId, Long printPlanId, String courseCode, String paperNumber) {
        return this.baseMapper.listByPrintPlanIdAndCourseCodeAndPaperNumber(schoolId, printPlanId, courseCode, paperNumber);
    }

    @Override
    public List<ExamDetailCourse> listExamDetailByExamIdAndPaperNumber(Long schoolId, Long examId, String paperNumber) {
        return this.baseMapper.listExamDetailByExamIdAndPaperNumber(schoolId, examId, paperNumber);
    }

    @Override
    public TbTaskDetailResult getByExamDetailId(Long examDetailId) {
        return this.baseMapper.getByExamDetailId(examDetailId);
    }

    @Override
    public List<String> listPaperNumberByPrintPlanId(String param, List<Long> printPlanIdList, Set<Long> orgIds) {
        return this.baseMapper.listPaperNumberByPrintPlanId(SystemConstant.translateSpecificSign(param), printPlanIdList, orgIds);
    }

    @Override
    public List<ExamDetailCourse> listByExamDetailId(Long examDetailId) {
        QueryWrapper<ExamDetailCourse> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ExamDetailCourse::getExamDetailId, examDetailId);
        return this.list(queryWrapper);
    }

    @Override
    public List<JSONObject> listExamDetailPaperNumber(Long examDetailId) {
        QueryWrapper<ExamDetailCourse> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ExamDetailCourse::getExamDetailId, examDetailId)
                .orderByAsc(ExamDetailCourse::getCourseCode);
        List<ExamDetailCourse> examDetailCourseList = this.list(queryWrapper);
        List<JSONObject> jsonObjectList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(examDetailCourseList)) {
            for (ExamDetailCourse examDetailCourse : examDetailCourseList) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("examDetailCourseId", String.valueOf(examDetailCourse.getId()));
                jsonObject.put("courseCode", examDetailCourse.getCourseCode());
                jsonObject.put("courseName", examDetailCourse.getCourseName());
                List<String> paperTypes = new ArrayList<>();
                if (StringUtils.isNotBlank(examDetailCourse.getPaperType())) {
                    paperTypes = Arrays.asList(examDetailCourse.getPaperType().split(","));

                }
                jsonObject.put("paperTypes", paperTypes);
                jsonObjectList.add(jsonObject);
            }
        }
        return jsonObjectList;
    }

    @Transactional
    @Override
    public boolean addExamStudent(SingleExamStudentAddParam singleExamStudentAddParam) {
        ExamDetailCourse examDetailCourse = this.getById(singleExamStudentAddParam.getExamDetailCourseId());
        if (examDetailCourse == null) {
            throw ExceptionResultEnum.ERROR.exception("考场科目数据不存在");
        }
        ExamDetail examDetail = examDetailService.getById(examDetailCourse.getExamDetailId());
        if (examDetail == null) {
            throw ExceptionResultEnum.ERROR.exception("考场数据不存在");
        }
        // 打印完成，才可以新增
        if (!ExamDetailStatusEnum.FINISH.equals(examDetail.getStatus())) {
            throw ExceptionResultEnum.ERROR.exception("考场还未印刷，不能新增考生");
        }

        int count = examStudentService.countByExamDetailCourseIdAndStudentCode(examDetailCourse.getId(), singleExamStudentAddParam.getStudentCode());
        if (count > 0) {
            throw ExceptionResultEnum.ERROR.exception("考号在本考场已存在");
        }
        ExamTask examTask = examTaskService.getByExamIdAndCourseCodeAndPaperNumber(examDetail.getExamId(), examDetailCourse.getCourseCode(), examDetailCourse.getPaperNumber());
        if(examTask == null){
            throw ExceptionResultEnum.ERROR.exception("命题任务不存在");
        }
        MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examDetail.getExamId(), examDetailCourse.getPaperNumber());
        if (markPaper != null && MarkPaperStatus.FINISH.equals(markPaper.getStatus())) {
            throw ExceptionResultEnum.ERROR.exception("已结束阅卷，不能新增考生");
        }

        // 保存exam_student
        Long id = SystemConstant.getDbUuid();
        ExamStudent examStudent = new ExamStudent();
        examStudent.setId(id);
        examStudent.setSchoolId(examDetail.getSchoolId());
        examStudent.setExamDetailCourseId(examDetailCourse.getId());
        examStudent.setStudentCode(singleExamStudentAddParam.getStudentCode());
        examStudent.setStudentName(singleExamStudentAddParam.getStudentName());
        examStudent.setExamId(examDetail.getExamId());
        examStudent.setPaperNumber(examDetailCourse.getPaperNumber());
        examStudent.setCoursePaperId(examDetailCourse.getCoursePaperId());
        examStudent.setPaperType(singleExamStudentAddParam.getPaperType());
        examStudent.setCollegeName(singleExamStudentAddParam.getCollege());
        examStudent.setMajorName(singleExamStudentAddParam.getMajorName());
        examStudent.setClazzName(singleExamStudentAddParam.getClassName());
        examStudent.setCanDelete(true);
        examStudentService.save(examStudent);

        // 保存mark_student
        MarkStudent markStudent = new MarkStudent(id, examDetail.getExamId(), examDetailCourse.getCourseCode(),
                examDetailCourse.getCourseName(), examDetailCourse.getPaperNumber(),
                examDetailCourse.getCoursePaperId(), singleExamStudentAddParam.getPaperType(),
                singleExamStudentAddParam.getStudentCode(), singleExamStudentAddParam.getStudentName(),
                examDetail.getPackageCode(), examDetail.getExamPlace(), examDetail.getExamRoom(),
                singleExamStudentAddParam.getCollege(), singleExamStudentAddParam.getMajorName(), singleExamStudentAddParam.getClassName(),
                null, null, examDetail.getExamStartTime(), examDetail.getExamEndTime(), examTask.getUserId());
        if (markStudent.getSecretNumber() == null) {
            markStudent.randomSecretNumber();
            while (markStudentService.countByExamIdAndSecretNumber(markStudent.getExamId(), markStudent.getSecretNumber()) > 0) {
                markStudent.randomSecretNumber();
            }
        }
        markStudentService.save(markStudent);
        markPaperService.updateStudentCountByExamIdAndPaperNumberAndPaperType(markPaper.getExamId(), markPaper.getPaperNumber(), markPaper.getPaperType());

        return true;
    }

    @Override
    public List<ExamDetailCourse> listByExamDetailIds(List<Long> edIds) {
        QueryWrapper<ExamDetailCourse> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<ExamDetailCourse> lw = wrapper.lambda();
        lw.in(ExamDetailCourse::getExamDetailId, edIds);
        return this.list(wrapper);
    }

    @Transactional
    @Override
    public boolean deleteExamStudent(Long id) {
        ExamStudent examStudent = examStudentService.getById(id);
        if (examStudent == null || !examStudent.getCanDelete()) {
            throw ExceptionResultEnum.ERROR.exception("考生不能删除");
        }
        MarkStudent markStudent = markStudentService.getById(id);
        if (markStudent.getUpload() != null && markStudent.getUpload()) {
            throw ExceptionResultEnum.ERROR.exception("考生题卡已扫描，不能删除");
        }
        examStudentService.removeById(id);
        markStudentService.removeById(id);
        markPaperService.updateStudentCountByExamIdAndPaperNumberAndPaperType(markStudent.getExamId(), markStudent.getPaperNumber(), markStudent.getPaperType());
        return true;
    }
}
