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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.google.gson.JsonObject;
import com.qmth.distributed.print.business.bean.dto.*;
import com.qmth.distributed.print.business.bean.marking.ConvertJpgStorage;
import com.qmth.distributed.print.business.bean.params.ExamCardParams;
import com.qmth.distributed.print.business.bean.params.GenericExamCardParams;
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.distributed.print.business.util.CreatePdfUtil;
import com.qmth.distributed.print.business.util.HtmlToJpgUtil;
import com.qmth.distributed.print.business.util.HtmlToPdfUtil;
import com.qmth.teachcloud.common.bean.dto.DataPermissionRule;
import com.qmth.teachcloud.common.bean.params.ArraysParams;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicAttachment;
import com.qmth.teachcloud.common.entity.BasicCourse;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.CardCreateMethodEnum;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.PageSizeEnum;
import com.qmth.teachcloud.common.service.BasicAttachmentService;
import com.qmth.teachcloud.common.service.BasicCourseService;
import com.qmth.teachcloud.common.service.BasicRoleDataPermissionService;
import com.qmth.teachcloud.common.service.TeachcloudCommonService;
import com.qmth.teachcloud.common.util.ConvertUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

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

    @Resource
    private BasicExamRuleService basicExamRuleService;

    @Resource
    private ExamCardDetailService examCardDetailService;

    @Resource
    private ExamTaskDetailService examTaskDetailService;

    @Resource
    private ExamTaskService examTaskService;

    @Resource
    private BasicAttachmentService basicAttachmentService;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    @Resource
    BasicCourseService basicCourseService;

    @Resource
    HtmlToJpgUtil htmlToJpgUtil;

    @Resource
    CreatePdfUtil createPdfUtil;

    @Resource
    BasicRoleDataPermissionService basicRoleDataPermissionService;

    @Transactional
    @Override
    public String saveExamCard(ExamCardParams examCardParams) throws Exception {
        // ↓专卡
        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) {
            QueryWrapper<ExamCard> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(ExamCard::getSchoolId, schoolId)
                    .eq(ExamCard::getCourseCode, examCardParams.getCourseCode())
                    .eq(ExamCard::getTitle, examCardParams.getTitle());
            List<ExamCard> examCardList = this.list(queryWrapper);
            if (!examCardList.isEmpty()) {
                throw ExceptionResultEnum.ERROR.exception("题卡名称已存在");
            }

            examCard = new ExamCard();
            examCard.setSchoolId(schoolId);
            if (Objects.isNull(examCardParams.getTemplateId())) {
                examCard.setOrgId(basicCourseService.getOrgIdBySchoolIdAndCourseCode(schoolId, examCardParams.getCourseCode()));
            } else {
                examCard.setOrgId(user.getOrgId());
            }
            examCard.setCourseCode(examCardParams.getCourseCode());
            examCard.setCourseName(examCardParams.getCourseName());
            examCard.setTitle(examCardParams.getTitle());
            examCard.setMakeMethod(examCardParams.getMakeMethod());
            examCard.setStatus(examCardParams.getStatus());
            examCard.setType(examCardParams.getType());
            if (StringUtils.isNotBlank(examCardParams.getAttachmentId())) {
                examCard.setAttachmentId(Long.valueOf(examCardParams.getAttachmentId()));
            }
            examCard.insertInfo(user.getId());
            this.save(examCard);

            examCardDetail = new ExamCardDetail();
            examCardDetail.setCardId(examCard.getId());
            examCardDetail.setContent(examCardParams.getContent());
            String htmlContent = examCardParams.getHtmlContent();
            List<ConvertJpgStorage> convertJpgStorageList = htmlToJpgUtil.convertHtmlToJpgByCard(examCard.getTitle(), htmlContent, PageSizeEnum.A3);
            if (convertJpgStorageList.size() > 0) {
                examCardDetail.setJpgAttachmentInfo(JSON.toJSONString(convertJpgStorageList));
            }
            examCardDetail.setHtmlContent(htmlContent);
            examCardDetail.setAttachmentId(examCardParams.getAttachmentId());
            examCardDetail.insertInfo(user.getId());
            examCardDetailService.save(examCardDetail);
        }
        // 修改
        else {
            QueryWrapper<ExamCard> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(ExamCard::getSchoolId, schoolId)
                    .eq(ExamCard::getCourseCode, examCardParams.getCourseCode())
                    .eq(ExamCard::getTitle, examCardParams.getTitle())
                    .ne(ExamCard::getId, examCardParams.getId());
            List<ExamCard> examCardList = this.list(queryWrapper);
            if (!examCardList.isEmpty()) {
                throw ExceptionResultEnum.ERROR.exception("题卡名称已存在");
            }

            examCard = this.getById(examCardParams.getId());
            examCard.setTitle(examCardParams.getTitle());
//            if (CardTypeEnum.CUSTOM.equals(examCard.getType()) && !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());
            String htmlContent = examCardParams.getHtmlContent();
            List<ConvertJpgStorage> convertJpgStorageList = htmlToJpgUtil.convertHtmlToJpgByCard(examCard.getTitle(), htmlContent, PageSizeEnum.A3);
            if (convertJpgStorageList.size() > 0) {
                examCardDetail.setJpgAttachmentInfo(JSON.toJSONString(convertJpgStorageList));
            }
            examCardDetail.setHtmlContent(htmlContent);
            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::getAttachmentId, templateId);
        return this.getOne(queryWrapper);
    }

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

        // 通用题卡
        List<ExamCard> list = new ArrayList<>();
        List<ExamCard> genericCards = this.baseMapper.listGenericCard(schoolId, CardTypeEnum.GENERIC.name(), cardRuleId);
        if (!genericCards.isEmpty()) {
            list.addAll(genericCards);
        }
        // 专卡
        if (SystemConstant.ALL_CARD != cardRuleId) {
            // 只查自己创建的专卡(20230405已改为查询课程下所有题卡，允许复制，不能选择)
            List<ExamCard> customCards = this.baseMapper.listCustom(schoolId, courseCode, CardTypeEnum.CUSTOM.name());
            if (!customCards.isEmpty()) {
                list.addAll(customCards);
            }
        }

        // 命题任务未提交的任务，单独查询题卡
        List<ExamCard> customCards = this.baseMapper.listCustomByExamStage(schoolId, courseCode, paperNumber, CardTypeEnum.CUSTOM.name());
        if (!customCards.isEmpty()) {
            for (ExamCard customCard : customCards) {
                long count = list.stream().filter(m -> m.getId().equals(customCard.getId())).count();
                if (count == 0) {
                    list.add(customCard);
                }
            }
        }
        list.sort(Comparator.comparing(ExamCard::getType));
        return list;
    }

    @Override
    public void downloadFiles(HttpServletResponse response, ArraysParams arraysParams) throws Exception {
        // 路径规则：download-temp/{time}/{schoolId}/{courseCode}-{couseName}/{paperNumber}/{fileName}
        File fileTemp = null;
        String rootPath = null;
        try {
            long time = System.nanoTime();
            fileTemp = SystemConstant.getFileTempDirVar(String.valueOf(time) + File.separator + SystemConstant.getNanoId(), SystemConstant.TEMP_PREFIX);
            rootPath = fileTemp.getParent();
            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() + SystemConstant.HYPHEN + 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);
            }
            if (Objects.nonNull(fileTemp)) {
                fileTemp.delete();
            }
            // 压缩
            teachcloudCommonService.downloadFileAndZip(response, rootPath, time);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(fileTemp)) {
                fileTemp.delete();
            }
            if (Objects.nonNull(rootPath)) {
                ConvertUtil.delFolder(rootPath);
            }
        }
    }

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


    @Override
    public IPage<ExamCardPageDto> listPage(String type, String title, String createMethod, Boolean enable, Long createStartTime, Long createEndTime, Integer pageNumber, Integer pageSize) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        DataPermissionRule dpr = basicRoleDataPermissionService.findDataPermission(schoolId, requestUser.getId(), ServletUtil.getRequest().getServletPath());
        IPage<ExamCardPageDto> cardPageDtoIPage = this.baseMapper.listPage(new Page<>(pageNumber, pageSize), schoolId, type, title, createMethod, enable, createStartTime, createEndTime, dpr);
        for (ExamCardPageDto record : cardPageDtoIPage.getRecords()) {
            if (StringUtils.isNotBlank(record.getJpgAttachmentInfo())) {
                List<JSONObject> mapList = JSON.parseArray(record.getJpgAttachmentInfo(), JSONObject.class);
                List<String> imageUrls = new ArrayList<>();
                for (JSONObject object : mapList) {
                    imageUrls.add(teachcloudCommonService.filePreview(object.getLong("attachmentId")));
                }
                record.setImageUrls(imageUrls);
            }
        }
        return cardPageDtoIPage;
    }

    @Transactional
    @Override
    public Long saveGeneric(GenericExamCardParams params) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();

        QueryWrapper<ExamCard> checkTitleQueryWrapper = new QueryWrapper<>();
        checkTitleQueryWrapper.lambda().eq(ExamCard::getSchoolId, schoolId).eq(ExamCard::getType, CardTypeEnum.GENERIC).eq(ExamCard::getTitle, params.getTitle().trim());
        ExamCard checkTitleExamCardList = this.getOne(checkTitleQueryWrapper);

        ExamCard examCard = new ExamCard();
        ExamCardDetail examCardDetail = new ExamCardDetail();
        // 新增
        if (Objects.isNull(params.getId())) {
            // 保存题卡
            examCard.setId(SystemConstant.getDbUuid());
            examCard.setSchoolId(schoolId);
            examCard.setOrgId(sysUser.getOrgId());

            if (checkTitleExamCardList != null) {
                throw ExceptionResultEnum.ERROR.exception("题卡名称重复");
            }
            examCard.setTitle(params.getTitle());
            examCard.setMakeMethod(MakeMethodEnum.SELECT); // 默认值
            // 上传题卡，状态为提交
            examCard.setStatus(CardCreateMethodEnum.UPLOAD.equals(params.getCreateMethod()) ? CardStatusEnum.SUBMIT : CardStatusEnum.valueOf(params.getStatus()));
            examCard.setType(CardTypeEnum.GENERIC); // 默认值
            examCard.setCreateMethod(params.getCreateMethod());
            examCard.setAttachmentId(params.getAttachmentId());
            examCard.setEnable(true); // 默认值
            examCard.setCardRuleId(params.getCardRuleId());
            examCard.setRemark(params.getRemark());
            examCard.setCreateId(sysUser.getId());
            examCard.setCreateTime(System.currentTimeMillis());
            this.save(examCard);

            // 保存题卡内容
            examCardDetail.setId(SystemConstant.getDbUuid());
            examCardDetail.setCardId(examCard.getId());
            examCardDetail.setCreateId(sysUser.getId());
            examCardDetail.setCreateTime(System.currentTimeMillis());
            // 方式为上传
            String htmlContent = "";
            if (CardCreateMethodEnum.UPLOAD.equals(params.getCreateMethod())) {
                if (params.getAttachmentId() == null) {
                    throw ExceptionResultEnum.ERROR.exception("请上传模板文件");
                }
                BasicAttachment attachment = basicAttachmentService.getById(params.getAttachmentId());
                if (attachment == null) {
                    throw ExceptionResultEnum.ERROR.exception("无模板文件记录");
                }
                if (!SystemConstant.HTML_PREFIX.equalsIgnoreCase(attachment.getType())) {
                    throw ExceptionResultEnum.ERROR.exception("只能上传后缀为.html文件");
                }
                htmlContent = teachcloudCommonService.readFileContent(attachment.getPath());
                examCardDetail.setHtmlContent(htmlContent);
            }
            // 方式为自定义
            else if (CardCreateMethodEnum.STANDARD.equals(params.getCreateMethod()) || CardCreateMethodEnum.FREE.equals(params.getCreateMethod())) {
                examCardDetail.setContent(params.getContent());
                htmlContent = params.getHtmlContent();
                examCardDetail.setHtmlContent(htmlContent);
            } else {
                throw ExceptionResultEnum.ERROR.exception("题卡创建方式异常");
            }
            List<ConvertJpgStorage> convertJpgStorageList = htmlToJpgUtil.convertHtmlToJpgByCard(examCard.getTitle(), htmlContent, PageSizeEnum.A3);
            if (convertJpgStorageList.size() > 0) {
                examCardDetail.setJpgAttachmentInfo(JSON.toJSONString(convertJpgStorageList));
            }
            examCardDetailService.save(examCardDetail);
        }
        // 修改
        else {
            examCard = this.getById(params.getId());
            if (checkTitleExamCardList != null && !Objects.equals(params.getId(), examCard.getId())) {
                throw ExceptionResultEnum.ERROR.exception("题卡名称重复");
            }
            examCard.setTitle(params.getTitle());
            examCard.setAttachmentId(params.getAttachmentId());
            examCard.setCardRuleId(params.getCardRuleId());
            // 上传题卡，状态为提交
            examCard.setStatus(CardCreateMethodEnum.UPLOAD.equals(params.getCreateMethod()) ? CardStatusEnum.SUBMIT : CardStatusEnum.valueOf(params.getStatus()));
            examCard.setRemark(params.getRemark());
            examCard.setUpdateId(sysUser.getId());
            examCard.setUpdateTime(System.currentTimeMillis());
            this.updateById(examCard);

            examCardDetail = examCardDetailService.getByCardId(params.getId());
            examCardDetail.setUpdateId(sysUser.getId());
            examCardDetail.setUpdateTime(System.currentTimeMillis());
            String htmlContent = "";
            // 方式为上传
            if (CardCreateMethodEnum.UPLOAD.equals(params.getCreateMethod())) {
                if (params.getAttachmentId() == null) {
                    throw ExceptionResultEnum.ERROR.exception("请上传模板文件");
                }
                BasicAttachment attachment = basicAttachmentService.getById(params.getAttachmentId());
                if (attachment == null) {
                    throw ExceptionResultEnum.ERROR.exception("无模板文件记录");
                }
                if (!SystemConstant.HTML_PREFIX.equalsIgnoreCase(attachment.getType())) {
                    throw ExceptionResultEnum.ERROR.exception("只能上传后缀为.html文件");
                }
                htmlContent = teachcloudCommonService.readFileContent(attachment.getPath());
                examCardDetail.setHtmlContent(htmlContent);
                // 上传题卡，状态为提交
                examCard.setStatus(CardStatusEnum.SUBMIT);
            }
            // 方式为自定义
            else if (CardCreateMethodEnum.STANDARD.equals(params.getCreateMethod()) || CardCreateMethodEnum.FREE.equals(params.getCreateMethod())) {
                examCardDetail.setContent(params.getContent());
                htmlContent = params.getHtmlContent();
                examCardDetail.setHtmlContent(htmlContent);
            } else {
                throw ExceptionResultEnum.ERROR.exception("题卡创建方式异常");
            }
            List<ConvertJpgStorage> convertJpgStorageList = htmlToJpgUtil.convertHtmlToJpgByCard(examCard.getTitle(), htmlContent, PageSizeEnum.A3);
            if (convertJpgStorageList.size() > 0) {
                examCardDetail.setJpgAttachmentInfo(JSON.toJSONString(convertJpgStorageList));
            }
            examCardDetailService.updateById(examCardDetail);
        }
        return examCard.getId();
    }

    @Transactional
    @Override
    public Boolean deleteGeneric(Long id) {
        // 校验题卡是否被绑定
//        QueryWrapper<ExamTaskDetail> queryWrapper = new QueryWrapper<>();
//        queryWrapper.lambda().eq(ExamTaskDetail::getCardId, id);
//        List<ExamTaskDetail> examTaskDetails = examTaskDetailService.list(queryWrapper);
        List<ExamTaskDetail> examTaskDetails = examTaskDetailService.getExamTaskDetailByCardIdJson(id);
        if (examTaskDetails != null && examTaskDetails.size() > 0) {
            throw ExceptionResultEnum.ERROR.exception("题卡已绑定命题任务，不能删除");
        }

        examCardDetailService.removeByCardId(id);
        return this.removeById(id);
    }

    @Transactional
    @Override
    public Long copyCard(Long id, String courseCode) {
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();

        ExamCard examCard = this.getById(id);
        if (examCard == null) {
            throw ExceptionResultEnum.ERROR.exception("题卡不存在");
        }
        if (CardTypeEnum.CUSTOM.equals(examCard.getType()) && !courseCode.equals(examCard.getCourseCode())) {
            throw ExceptionResultEnum.ERROR.exception("复制的题卡不属于当前课程，无法复制");
        }

        // 复制题卡
        ExamCard copyExamCard = new ExamCard();
        BeanUtils.copyProperties(examCard, copyExamCard);
        String title = checkTitle(examCard, courseCode);
        copyExamCard.setTitle(title);
        copyExamCard.insertInfo(requestUser.getId());
        copyExamCard.setSyncStatus(null);
        if (CardTypeEnum.GENERIC.equals(examCard.getType()) && CardCreateMethodEnum.STANDARD.equals(examCard.getCreateMethod())) {
            BasicCourse basicCourse = basicCourseService.findByCourseCode(courseCode, requestUser.getSchoolId());
            copyExamCard.setCourseCode(courseCode);
            copyExamCard.setCourseName(basicCourse != null ? basicCourse.getName() : null);
            copyExamCard.setMakeMethod(MakeMethodEnum.SELF);
            copyExamCard.setCreateMethod(null);
            copyExamCard.setType(CardTypeEnum.CUSTOM);
        }
        copyExamCard.setRemark(String.format("来源题卡:%s(%s)", id, examCard.getTitle()));
        copyExamCard.setUsed(false);
        this.save(copyExamCard);
        Long copyExamCardId = copyExamCard.getId();

        ExamCardDetail examCardDetail = examCardDetailService.getByCardId(id);
        if (examCardDetail == null) {
            throw ExceptionResultEnum.ERROR.exception("题卡内容不存在");
        }
        // 复制题卡内容
        ExamCardDetail copyExamCardDetail = new ExamCardDetail();
        BeanUtils.copyProperties(examCardDetail, copyExamCardDetail);
        copyExamCardDetail.setId(SystemConstant.getDbUuid());
        copyExamCardDetail.setCardId(copyExamCardId);
        // 生成图片
        List<ConvertJpgStorage> convertJpgStorageList = htmlToJpgUtil.convertHtmlToJpgByCard(examCard.getTitle(), copyExamCardDetail.getHtmlContent(), PageSizeEnum.A3);
        if (!convertJpgStorageList.isEmpty()) {
            copyExamCardDetail.setJpgAttachmentInfo(JSON.toJSONString(convertJpgStorageList));
        } else {
            copyExamCardDetail.setJpgAttachmentInfo(null);
        }
        examCardDetailService.save(copyExamCardDetail);

        return copyExamCardId;
    }

    @Override
    public void convertImage(Long id) {
        ExamCard examCard = this.getById(id);
        ExamCardDetail examCardDetail = examCardDetailService.getByCardId(id);
        if (examCardDetail == null) {
            throw ExceptionResultEnum.ERROR.exception("题卡不存在");
        }

        List<ConvertJpgStorage> convertJpgStorageList = htmlToJpgUtil.convertHtmlToJpgByCard(examCard.getTitle(), examCardDetail.getHtmlContent(), PageSizeEnum.A3);
        if (convertJpgStorageList.size() > 0) {
            String jpgAttachmentIds = JSON.toJSONString(convertJpgStorageList);
            UpdateWrapper<ExamCardDetail> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().set(ExamCardDetail::getJpgAttachmentInfo, jpgAttachmentIds)
                    .eq(ExamCardDetail::getId, examCardDetail.getId());
            examCardDetailService.update(updateWrapper);
        }
    }

    @Override
    public void cardDownload(HttpServletResponse response, String id) {
        File tempFile = null;
        String rootPath = null;
        try {

            // 题卡
            ExamCard examCard = this.getById(id);
            // 本地保存目录
            tempFile = SystemConstant.getFileTempDirVar(String.valueOf(System.currentTimeMillis()) + File.separator + SystemConstant.getNanoId(), SystemConstant.TEMP_PREFIX);
            rootPath = tempFile.getParent();
            StringJoiner dirPath = new StringJoiner("");
            dirPath = dirPath.add(rootPath).add(File.separator)
                    .add(id).add(File.separator).add(SystemConstant.HYPHEN)
                    .add(examCard.getTitle()).add(File.separator);
            List<File> fileList = new ArrayList<>();

            String cardHtmlPath = dirPath + examCard.getTitle() + SystemConstant.HTML_PREFIX;
            String cardPdfPath = dirPath + examCard.getTitle() + SystemConstant.PDF_PREFIX;

            ExamCardDetail examCardDetail = examCardDetailService.getByCardId(examCard.getId());
            String htmlContent;
            // 通用模板
            if (MakeMethodEnum.SELECT.equals(examCard.getMakeMethod())) {
                htmlContent = createPdfUtil.resetHtmlTemplateBar(examCardDetail.getHtmlContent());
            } else {
//                BasicCardRule basicCardRule = basicCardRuleService.getById(examTask.getCardRuleId());
                htmlContent = createPdfUtil.replaceHtmlCard(examCardDetail, null);
            }

            // html
            File htmlFile = new File(cardHtmlPath);
            if (!htmlFile.exists()) {
                htmlFile.getParentFile().mkdirs();
                htmlFile.createNewFile();
            }
            // 生成html文件
            FileCopyUtils.copy(htmlContent.getBytes(StandardCharsets.UTF_8), htmlFile);
            fileList.add(htmlFile);
            // 转pdf文件
            File pdfFile = new File(cardPdfPath);
            if (!pdfFile.exists()) {
                pdfFile.getParentFile().mkdirs();
                pdfFile.createNewFile();
            }
            HtmlToPdfUtil.convert(cardHtmlPath, cardPdfPath, PageSizeEnum.A3);
            fileList.add(pdfFile);

            if (fileList.size() == 0) {
                throw ExceptionResultEnum.ERROR.exception("没有可导出文件");
            }
            if (Objects.nonNull(tempFile)) {
                tempFile.delete();
            }
            teachcloudCommonService.downloadFileAndZip(response, rootPath, rootPath);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (Objects.nonNull(tempFile)) {
                tempFile.delete();
            }
            if (Objects.nonNull(rootPath)) {
                ConvertUtil.delFolder(rootPath);
            }
        }
    }

    /**
     * 生成新的title
     *
     * @param examCard 题卡对象
     */
    private String checkTitle(ExamCard examCard, String courseCode) {
        String title;
        int i = 1;
        ExamCard newExamCard;
        do {
            title = examCard.getTitle() + "副本" + i;
            QueryWrapper<ExamCard> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(ExamCard::getSchoolId, examCard.getSchoolId())
                    .eq(ExamCard::getCourseCode, courseCode)
                    .eq(ExamCard::getTitle, title);
            newExamCard = this.getOne(queryWrapper);
            i++;
        } while (newExamCard != null);
        return title;
    }

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

        if (Objects.nonNull(examCardParams.getMakeMethod()) && StringUtils.isBlank(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内容不能为空");
                    }
                }
            }
        }
    }
}
