package com.qmth.distributed.print.business.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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.distributed.print.business.bean.dto.CardCustDto;
import com.qmth.distributed.print.business.bean.dto.CardDetailDto;
import com.qmth.distributed.print.business.bean.dto.SyncExamCardDto;
import com.qmth.distributed.print.business.bean.params.ExamCardParams;
import com.qmth.distributed.print.business.entity.*;
import com.qmth.distributed.print.business.enums.CardStatusEnum;
import com.qmth.distributed.print.business.enums.CardTypeEnum;
import com.qmth.distributed.print.business.enums.MakeMethodEnum;
import com.qmth.distributed.print.business.mapper.ExamCardMapper;
import com.qmth.distributed.print.business.service.*;
import com.qmth.teachcloud.common.bean.params.ArraysParams;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicAttachment;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.service.BasicAttachmentService;
import com.qmth.teachcloud.common.service.BasicCourseService;
import com.qmth.teachcloud.common.service.TeachcloudCommonService;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;

/**
 * <p>
 * 题卡 服务实现类
 * </p>
 *
 * @author xf
 * @since 2021-03-23
 */
@Service
public class ExamCardServiceImpl extends ServiceImpl<ExamCardMapper, ExamCard> implements ExamCardService {

    @Autowired
    private BasicExamRuleService basicExamRuleService;

    @Autowired
    private ExamCardDetailService examCardDetailService;

    @Autowired
    private ExamTaskDetailService examTaskDetailService;

    @Autowired
    private ExamTaskService examTaskService;

    @Autowired
    private BasicAttachmentService basicAttachmentService;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    @Autowired
    BasicCourseService basicCourseService;

    @Transactional
    @Override
    public String saveExamCard(ExamCardParams examCardParams) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser user = (SysUser) ServletUtil.getRequestUser();

        validateCardData(examCardParams);

        // 新增
        ExamCard examCard;
        ExamCardDetail examCardDetail;
        if (examCardParams.getTitle().getBytes().length > 80) {
            throw ExceptionResultEnum.ERROR.exception("标题最长只能输入80个字符");
        }
        if (examCardParams.getId() == null) {
            examCard = new ExamCard();
            examCard.setSchoolId(schoolId);
            examCard.setOrgId(basicCourseService.getOrgIdBySchoolIdAndCourseCode(schoolId, examCardParams.getCourseCode()));
            examCard.setCourseCode(examCardParams.getCourseCode());
            examCard.setCourseName(examCardParams.getCourseName());
            examCard.setTitle(examCardParams.getTitle());
            examCard.setMakeMethod(examCardParams.getMakeMethod());
            examCard.setStatus(examCardParams.getStatus());
            examCard.setType(examCardParams.getType());
            examCard.setTemplateId(examCardParams.getTemplateId());
            examCard.insertInfo(user.getId());
            this.save(examCard);

            examCardDetail = new ExamCardDetail();
            examCardDetail.setCardId(examCard.getId());
            examCardDetail.setContent(examCardParams.getContent());
            examCardDetail.setHtmlContent(examCardParams.getHtmlContent());
            examCardDetail.setAttachmentId(examCardParams.getAttachmentId());
            examCardDetail.insertInfo(user.getId());
            examCardDetailService.save(examCardDetail);
        }
        // 修改
        else {
            examCard = this.getById(examCardParams.getId());
            examCard.setTitle(examCardParams.getTitle());
            if (!examCardParams.getCourseCode().equals(examCard.getCourseCode())) {
                throw ExceptionResultEnum.ERROR.exception("课程不能更改");
            }
            if (!examCardParams.getMakeMethod().name().equals(examCard.getMakeMethod().name())) {
                throw ExceptionResultEnum.ERROR.exception("题卡制作方式不能更改");
            }
            examCard.setStatus(examCardParams.getStatus());
            examCard.setUpdateId(user.getId());
            examCard.setUpdateTime(System.currentTimeMillis());
            this.updateById(examCard);

            examCardDetail = examCardDetailService.getByCardId(examCardParams.getId());
            if (examCardDetail == null) {
                throw ExceptionResultEnum.ERROR.exception("题卡数据有误");
            }
            examCardDetail.setContent(examCardParams.getContent());
            examCardDetail.setHtmlContent(examCardParams.getHtmlContent());
            examCardDetail.setAttachmentId(examCardParams.getAttachmentId());
            examCardDetail.updateInfo(user.getId());
            examCardDetailService.updateById(examCardDetail);

        }

        // 绑定命题任务
        examTaskDetailService.bindCardId(examCardParams.getExamTaskId(), examCard);
        return String.valueOf(examCard.getId());
    }

    @Override
    public IPage<CardCustDto> listCardCust(String schoolId, String status, String paperNumber, String userId, Long applyStartTime, Long applyEndTime, Long finishStartTime, Long finishEndTime, Integer pageNumber, Integer pageSize) {
        Page<CardCustDto> page = new Page<>(pageNumber, pageSize);
        IPage<CardCustDto> cardCustDtoIPage = this.baseMapper.listCardCust(page, schoolId, status, paperNumber, userId, applyStartTime, applyEndTime, finishStartTime, finishEndTime);
        return cardCustDtoIPage;
    }

    @Transactional
    @Override
    public String saveExamCardCust(ExamCardParams examCardParams) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser user = (SysUser) ServletUtil.getRequestUser();

        if (!MakeMethodEnum.CUST.name().equals(examCardParams.getMakeMethod().name())) {
            throw ExceptionResultEnum.ERROR.exception("题卡制作类型错误");
        }
        if (StringUtils.isBlank(examCardParams.getCustAttachmentId())) {
            throw ExceptionResultEnum.ERROR.exception("客户制卡时，附件未上传");
        }

        ExamCard examCard = new ExamCard();
        examCard.setId(SystemConstant.getDbUuid());
        examCard.setSchoolId(schoolId);
        examCard.setOrgId(user.getOrgId());
        examCard.setCourseCode(examCardParams.getCourseCode());
        examCard.setCourseName(examCardParams.getCourseName());
        examCard.setMakeMethod(examCardParams.getMakeMethod());
        examCard.setTitle(examCardParams.getTitle());
        examCard.setStatus(examCardParams.getStatus());
        examCard.setType(CardTypeEnum.CUSTOM);
        examCard.setCreateId(user.getId());
        examCard.setCreateTime(System.currentTimeMillis());
        this.save(examCard);

        ExamCardDetail examCardDetail = new ExamCardDetail();
        examCardDetail.setId(SystemConstant.getDbUuid());
        examCardDetail.setCardId(examCard.getId());
        examCardDetail.setCustAttachmentId(examCardParams.getCustAttachmentId());
        examCardDetail.setCreateId(user.getId());
        examCardDetail.setCreateTime(System.currentTimeMillis());
        examCardDetailService.save(examCardDetail);

        // 绑定命题任务
        examTaskDetailService.bindCardId(examCardParams.getExamTaskId(), examCard);

        return String.valueOf(examCard.getId());
    }

    @Override
    public CardDetailDto getCardDetail(Long cardId) {
        ExamCard examCard = this.getById(cardId);
        if (!MakeMethodEnum.SELECT.equals(examCard.getMakeMethod())) {
            return this.baseMapper.getCardDetail(cardId);
        } else {
            return this.baseMapper.getCardDetailBySelect(cardId);
        }
    }

    @Override
    public ExamCard getOneByTemplateId(Long templateId) {
        QueryWrapper<ExamCard> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ExamCard::getTemplateId, templateId);
        return this.getOne(queryWrapper);
    }

    @Override
    public boolean usedCardByTemplateId(Long templateId) {
        List<ExamTaskDetail> list = examTaskDetailService.listByTemplateId(templateId);
        return !list.isEmpty();
    }

    @Override
    public List<ExamCard> listSelectCard(String courseCode, Long cardRuleId, String paperType) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();

        // 通用题卡
        List<ExamCard> list = new ArrayList<>();
        List<ExamCard> genericCards = this.baseMapper.listGenericCard(schoolId, sysUser.getOrgId(), CardTypeEnum.GENERIC.name());
        if (!genericCards.isEmpty()) {
            list.addAll(genericCards);
        }
        // 专卡
        if (SystemConstant.ALL_CARD != cardRuleId) {
            List<ExamCard> customCards = this.baseMapper.listCustom(schoolId, sysUser.getOrgId(), courseCode, CardTypeEnum.CUSTOM.name());
            if (!customCards.isEmpty()) {
                list.addAll(customCards);
            }
        }
        Collections.sort(list, Comparator.comparing(ExamCard::getType));
        return list;
    }

    @Override
    public void downloadFiles(HttpServletResponse response, ArraysParams arraysParams) throws Exception {
        // 路径规则：download-temp/{time}/{schoolId}/{courseCode}-{couseName}/{paperNumber}/{fileName}
        long time = System.nanoTime();
        String rootPath = SystemConstant.TEMP_FILES_DIR + File.separator + time;

        Long[] cardIds = arraysParams.getIds();
        // 根据题卡取命题任务
        for (Long cardId : cardIds) {
            List<ExamTask> examTasks = examTaskService.listExamTaskByCardId(cardId);
            if (examTasks.isEmpty() || examTasks.size() > 1) {
                throw ExceptionResultEnum.ERROR.exception("题卡数据异常");
            }
            ExamTask examTask = examTasks.get(0);
            StringJoiner sj = new StringJoiner(File.separator);
            sj.add(rootPath).add(examTask.getSchoolId().toString()).add(examTask.getCourseCode() + "-" + examTask.getCourseName()).add(examTask.getPaperNumber());

            // 附件ID
            ExamCardDetail examCardDetail = examCardDetailService.getByCardId(cardId);
            BasicAttachment attachment = basicAttachmentService.getById(examCardDetail.getCustAttachmentId());
            String fileName = attachment.getName() + attachment.getType();
            teachcloudCommonService.copyFile(sj.toString(), fileName, attachment);
        }
        // 压缩
        teachcloudCommonService.downloadFileAndZip(response, rootPath, time);
    }

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

    /**
     * 数据验证
     *
     * @param examCardParams
     */
    private void validateCardData(ExamCardParams examCardParams) {
        BasicExamRule basicExamRule = basicExamRuleService.getBySchoolId();
        if (basicExamRule == null) {
            throw ExceptionResultEnum.ERROR.exception("通用规则未设置");
        }

        if (StringUtils.isBlank(examCardParams.getMakeMethod().name())) {
            throw ExceptionResultEnum.ERROR.exception("题卡制作方式不能为空");
        }
        if (!basicExamRule.getCustomCard() && MakeMethodEnum.CUST.name().equals(examCardParams.getMakeMethod().name())) {
            throw ExceptionResultEnum.ERROR.exception("未启用客服制卡，不能选择该方式制作题卡");
        }
        if (examCardParams.getStatus() == null) {
            throw ExceptionResultEnum.ERROR.exception("提交方式不能为空");
        }
        if (CardTypeEnum.CUSTOM.name().equals(examCardParams.getType())) {
            if (examCardParams.getExamTaskId() == null) {
                throw ExceptionResultEnum.ERROR.exception("命题任务ID不能为空");
            }
            if (StringUtils.isBlank(examCardParams.getCourseCode())) {
                throw ExceptionResultEnum.ERROR.exception("课程代码不能为空");
            }
            if (StringUtils.isBlank(examCardParams.getCourseName())) {
                throw ExceptionResultEnum.ERROR.exception("课程名称不能为空");
            }
            if (MakeMethodEnum.SELECT.name().equals(examCardParams.getMakeMethod().name())) {
                if (examCardParams.getId() == null) {
                    throw ExceptionResultEnum.ERROR.exception("选择已有题卡时，题卡ID不能为空");
                }
                // 当前选择题卡是否已绑定
                List<ExamTaskDetail> list = examTaskDetailService.listByCardId(examCardParams.getId());
                if (list != null && list.size() > 0) {
                    throw ExceptionResultEnum.ERROR.exception("选择的题卡已被其它命题任务绑定");
                }

            } else if (MakeMethodEnum.SELF.name().equals(examCardParams.getMakeMethod().name())) {
                if (StringUtils.isBlank(examCardParams.getTitle())) {
                    throw ExceptionResultEnum.ERROR.exception("题卡标题不能为空");
                }
                if (StringUtils.isBlank(examCardParams.getContent())) {
                    throw ExceptionResultEnum.ERROR.exception("题卡内容不能为空");
                }
                if (CardStatusEnum.SUBMIT.name().equals(examCardParams.getStatus().name())) {
                    if (StringUtils.isBlank(examCardParams.getHtmlContent())) {
                        throw ExceptionResultEnum.ERROR.exception("提交题卡时，html内容不能为空");
                    }
                }
            } else if (MakeMethodEnum.CUST.name().equals(examCardParams.getMakeMethod().name())) {
                if (StringUtils.isBlank(examCardParams.getContent())) {
                    throw ExceptionResultEnum.ERROR.exception("题卡内容不能为空");
                }
                if (CardStatusEnum.SUBMIT.name().equals(examCardParams.getStatus().name())) {
                    if (StringUtils.isBlank(examCardParams.getHtmlContent())) {
                        throw ExceptionResultEnum.ERROR.exception("提交题卡时，html内容不能为空");
                    }
                }
            }
        }
    }
}
