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

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
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.*;
import com.qmth.distributed.print.business.bean.params.DeleteParams;
import com.qmth.distributed.print.business.bean.params.PrintPlanParams;
import com.qmth.distributed.print.business.bean.params.SyncDataParam;
import com.qmth.distributed.print.business.bean.result.PrintPlanBrief;
import com.qmth.distributed.print.business.bean.result.PrintPlanResult;
import com.qmth.distributed.print.business.bean.result.TemplatePrintInfoResult;
import com.qmth.distributed.print.business.entity.*;
import com.qmth.distributed.print.business.enums.*;
import com.qmth.distributed.print.business.mapper.ExamPrintPlanMapper;
import com.qmth.distributed.print.business.service.*;
import com.qmth.distributed.print.business.templete.execute.AsyncCloudMarkingTaskService;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicAttachment;
import com.qmth.teachcloud.common.entity.BasicSchool;
import com.qmth.teachcloud.common.entity.SysOrg;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ClassifyEnum;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.service.*;
import com.qmth.teachcloud.common.sync.CloudMarkingTaskUtils;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

/**
 * <p>
 * 印刷计划管理 服务实现类
 * </p>
 *
 * @author xf
 * @since 2021-03-23
 */
@Service
public class ExamPrintPlanServiceImpl extends ServiceImpl<ExamPrintPlanMapper, ExamPrintPlan> implements ExamPrintPlanService {
    @Resource
    private ExamPrintPlanMapper examPrintPlanMapper;
    @Resource
    private ExamDetailService examDetailService;
    @Resource
    private SysOrgService sysOrgService;
    @Resource
    private BasicTemplateOrgService basicTemplateOrgService;
    @Resource
    private BasicSchoolService basicSchoolService;

    @Autowired
    private ExamTaskService examTaskService;

    @Autowired
    private BasicAttachmentService basicAttachmentService;

    @Resource
    private BasicExamRuleService basicExamRuleService;

    @Autowired
    private BasicMessageService basicMessageService;

    @Resource
    private TBTaskService tbTaskService;

    @Autowired
    private ClientPrintDataService clientPrintDataService;

    @Autowired
    private DataSyncService dataSyncService;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    @Autowired
    BasicClazzService basicClazzService;
    @Resource
    ExamDetailCourseService examDetailCourseService;

    @Resource
    ExamStudentService examStudentService;

    @Resource
    AsyncCloudMarkingTaskService asyncCloudMarkingTaskService;

    @Resource
    CloudMarkingTaskUtils cloudMarkingTaskUtils;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public IPage<PrintPlanResult> printPlanPage(Long schoolId, Long semesterId, Long examId, List<Long> printPlanIdList, PrintPlanStatusEnum status, Long startTime, Long endTime, int pageNumber, int pageSize) {
        Set<Long> orgIds = teachcloudCommonService.listSubOrgIds(null);
        IPage<PrintPlanResult> page = examPrintPlanMapper.findPrintPlanPage(new Page<>(pageNumber, pageSize), schoolId, semesterId, examId, printPlanIdList, status, startTime, endTime, orgIds);
        List<PrintPlanResult> list = page.getRecords();
        for (PrintPlanResult printPlanResult : list) {
            List<Map> variableContent = JSONObject.parseArray(printPlanResult.getVariableContentTemp(), Map.class);
            List<Map> ordinaryContent = JSONObject.parseArray(printPlanResult.getOrdinaryContentTemp(), Map.class);
            printPlanResult.setVariableContent(variableContent);
            printPlanResult.setOrdinaryContent(ordinaryContent);

            double totalSubjects = examDetailService.calculateTotalSubjects(printPlanResult.getId());
            double totalPackages = examDetailService.calculateTotalPackages(printPlanResult.getId());
            printPlanResult.setTotalSubjects((int) totalSubjects);
            printPlanResult.setTotalPackages((int) totalPackages);
        }
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public IPage<PrintPlanResult> printPlanSyncPage(Long schoolId, Long semesterId, Long examId, Long printPlanId, Long startTime, Long endTime, int pageNumber, int pageSize) {
        Set<Long> orgIds = teachcloudCommonService.listSubOrgIds(null);
        String[] status = {PrintPlanStatusEnum.PRINT_FINISH.name(), PrintPlanStatusEnum.END.name()};
        IPage<PrintPlanResult> page = examPrintPlanMapper.findPrintPlanSyncPage(new Page<>(pageNumber, pageSize), schoolId, semesterId, examId, status, printPlanId, startTime, endTime, orgIds);
        List<PrintPlanResult> list = page.getRecords();
        for (PrintPlanResult printPlanResult : list) {
            List<SyncExamStudentDto> examStudentDtos = examStudentService.listStudentByPrintPlanIdAndSyncStatus(printPlanResult.getId());
            printPlanResult.setCanPush(examStudentDtos != null && examStudentDtos.size() > 0);

            List<Map> variableContent = JSONObject.parseArray(printPlanResult.getVariableContentTemp(), Map.class);
            List<Map> ordinaryContent = JSONObject.parseArray(printPlanResult.getOrdinaryContentTemp(), Map.class);
            printPlanResult.setVariableContent(variableContent);
            printPlanResult.setOrdinaryContent(ordinaryContent);

            double totalSubjects = examDetailService.calculateTotalSubjects(printPlanResult.getId());
            double totalPackages = examDetailService.calculateTotalPackages(printPlanResult.getId());
            printPlanResult.setTotalSubjects((int) totalSubjects);
            printPlanResult.setTotalPackages((int) totalPackages);
        }
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<PrintPlanBrief> printPlanBriefQuery(String source, String module) {
        /*List<PrintPlanBrief> printPlanBriefList = new ArrayList<>();
        List<ExamPrintPlan> examPrintPlanList = this.list();
        for (ExamPrintPlan examPrintPlan : examPrintPlanList) {
            Long id = examPrintPlan.getId();
            String name = examPrintPlan.getName();
            PrintPlanStatusEnum status = examPrintPlan.getStatus();
            printPlanBriefList.add(new PrintPlanBrief(id, name ,status));
        }*/
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        List<PrintPlanBrief> list;
        if ("client".equals(source)) {
            SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
            String[] status = {PrintPlanStatusEnum.READY.name(), PrintPlanStatusEnum.PRINTING.name(), PrintPlanStatusEnum.PRINT_FINISH.name()};
            list = this.baseMapper.listToClient(schoolId, source, module, status, sysUser.getOrgId());
        } else {
            Set<Long> orgIds = teachcloudCommonService.listSubOrgIds(null);
            String[] status = {PrintPlanStatusEnum.READY.name(), PrintPlanStatusEnum.PRINTING.name(), PrintPlanStatusEnum.PRINT_FINISH.name()};
            list = this.baseMapper.list(schoolId, source, module, status, orgIds);
        }
        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> printPlanTemplateDatasource(Long requestSchoolId, Long userId) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        //1.根据userId，schoolId查出orgId(应该从requestUser 获取)
        Long schoolId = sysUser.getSchoolId();
        Long orgId = sysUser.getOrgId();

        //2.根据orgId查询他的所有叶子id 并把这些id放入List<Long> ids
        List<Long> orgIds;
        if ((orgId == null || orgId == 0) && (schoolId == null || schoolId == 0)) {
            // 超级管理员权限
            orgIds = sysOrgService.list().stream().map(SysOrg::getId).collect(Collectors.toList());
        } else if ((orgId == null || orgId == 0) && schoolId > 0) {
            // 学校管理员权限
            orgIds = sysOrgService.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSchoolId, schoolId)).stream().map(SysOrg::getId).collect(Collectors.toList());
        } else {
            // 普通权限
            List<Long> ids = new ArrayList<>();
            ids.add(orgId);
            orgIds = this.dp(ids, schoolId, new ArrayList<>());
        }

        //3.关联template和template_org表 查询出来orgIds所包含的所有模板并组装
        List<TemplatePrintInfoResult> templateInfoList = basicTemplateOrgService.findTemplateInfoByOrgIds(orgIds);
        templateInfoList = templateInfoList.stream().distinct().collect(Collectors.toList());
        System.out.println(JSONObject.toJSONString(templateInfoList));
        Map<String, Object> result = new HashMap<>();

        // 变量印品
        List<Map<String, Object>> variable = new ArrayList<>();
        List<TemplatePrintInfoResult> variableList = templateInfoList.stream()
                .filter(e -> TemplateTypeEnum.VARIABLE.equals(e.getTemplateType()))
                .collect(Collectors.toList());
        for (ClassifyEnum value : ClassifyEnum.values()) {
            Map<String, Object> variableMap = new HashMap<>();
            List<TemplatePrintInfoResult> sourceList = variableList.stream().filter(e -> value.equals(e.getTemplateClassify())).collect(Collectors.toList());
            List<Map<String, Object>> templateList = new ArrayList<>();
            for (TemplatePrintInfoResult templatePrintInfoResult : sourceList) {
                Map<String, Object> printMap = new HashMap<>();
                printMap.put("id", String.valueOf(templatePrintInfoResult.getTemplateId()));
                printMap.put("name", templatePrintInfoResult.getTemplateName());
                printMap.put("attachmentId", templatePrintInfoResult.getAttachmentId().toString());
                templateList.add(printMap);
            }
            if (templateList.size() > 0) {
                variableMap.put("type", value);
                variableMap.put("template", templateList);
                variable.add(variableMap);
            }
        }

        // 普通印品
        List<Map<String, Object>> ordinary = new ArrayList<>();
        List<TemplatePrintInfoResult> ordinaryList = templateInfoList.stream()
                .filter(e -> TemplateTypeEnum.ORDINARY.equals(e.getTemplateType()))
                .collect(Collectors.toList());
        Map<String, Object> ordinaryMap = new HashMap<>();
        for (ClassifyEnum value : ClassifyEnum.values()) {
            List<TemplatePrintInfoResult> sourceList = ordinaryList.stream().filter(e -> value.equals(e.getTemplateClassify())).collect(Collectors.toList());
            List<Map<String, Object>> templateList = new ArrayList<>();
            for (TemplatePrintInfoResult templatePrintInfoResult : sourceList) {
                Map<String, Object> printMap = new HashMap<>();
                printMap.put("id", String.valueOf(templatePrintInfoResult.getTemplateId()));
                printMap.put("name", templatePrintInfoResult.getTemplateName());
                printMap.put("attachmentId", templatePrintInfoResult.getAttachmentId().toString());
                templateList.add(printMap);
            }
            if (templateList.size() > 0) {
                ordinaryMap.put("type", value);
                ordinaryMap.put("template", templateList);
                ordinary.add(ordinaryMap);
            }
        }

        result.put("variable", variable);
        result.put("ordinary", ordinary);
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean savePrintPlan(PrintPlanParams printPlanParams) {
        boolean result;
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Long id = printPlanParams.getId();
        Long schoolId = printPlanParams.getSchoolId();
        if (basicSchoolService.list(new QueryWrapper<BasicSchool>().lambda().eq(BasicSchool::getId, schoolId).eq(BasicSchool::getEnable, true)).size() != 1) {
            throw ExceptionResultEnum.ERROR.exception("学校被禁用或不存在");
        }

        // 校验是否印试卷和题卡
        List<String> printContentList = printPlanParams.getPrintContent();
        BasicExamRule basicExamRule = basicExamRuleService.getBySchoolId(schoolId);
        if (Objects.isNull(basicExamRule)) {
            throw ExceptionResultEnum.ERROR.exception("未找到学校的通用规则");
        }
        /*if (basicExamRule.getIncludePaper() && !printContentList.contains("PAPER")) {
            throw ExceptionResultEnum.ERROR.exception("学校通用规则设置了强制包含试卷的必须选择试卷印品！");
        }*/
        if (printContentList.contains("PAPER") && !printContentList.contains("CARD")) {
            throw ExceptionResultEnum.ERROR.exception("如果试卷题卡印品选择了试卷，题卡必须被选择");
        }

        ExamPrintPlan examPrintPlan = new ExamPrintPlan();
        BeanUtils.copyProperties(printPlanParams, examPrintPlan);
        String printContent = StringUtils.join(printContentList, ",");
        examPrintPlan.setPrintContent(printContent);
        examPrintPlan.setCreateId(sysUser.getId());
        examPrintPlan.setUpdateId(sysUser.getId());
        examPrintPlan.setOrgId(sysUser.getOrgId());

        //印刷计划名称唯一性
        QueryWrapper<ExamPrintPlan> printPlanQueryWrapper = new QueryWrapper<>();
        printPlanQueryWrapper.lambda().eq(ExamPrintPlan::getSchoolId, schoolId).eq(ExamPrintPlan::getName, examPrintPlan.getName());
        ExamPrintPlan printPlan = this.getOne(printPlanQueryWrapper);
        if (id == null || id == 0) {
            // 没有印刷计划id -> 新增印刷计划
            if (printPlan != null) {
                throw ExceptionResultEnum.ERROR.exception("印刷计划名称已存在");
            }
            examPrintPlan.setId(SystemConstant.getDbUuid());
            examPrintPlan.setStatus(PrintPlanStatusEnum.NEW);
            examPrintPlan.setSyncStatus(ExamPrintPlanSyncStatusEnum.INIT);
            result = this.save(examPrintPlan);
        } else {
            // 包含印刷计划id -> 编辑印刷计划
            ExamPrintPlan tmp = this.getById(id);
            if (tmp == null) {
                throw ExceptionResultEnum.ERROR.exception("印刷计划id不存在");
            }
            if (printPlan != null && id.longValue() != printPlan.getId().longValue()) {
                throw ExceptionResultEnum.ERROR.exception("印刷计划名称已存在");
            }

            PrintPlanStatusEnum status = tmp.getStatus();
            if (!PrintPlanStatusEnum.NEW.equals(status) && !PrintPlanStatusEnum.READY.equals(status)) {
                throw ExceptionResultEnum.ERROR.exception("已经开始打印的印刷计划不能编辑");
            }
            // 学校id不能更改
            examPrintPlan.setSchoolId(tmp.getSchoolId());
            result = this.updateById(examPrintPlan);
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean removePrintPlan(DeleteParams deleteParams) {
        Long id = deleteParams.getId();
        ExamPrintPlan examPrintPlan = this.getById(id);
        if (examPrintPlan == null) {
            throw ExceptionResultEnum.ERROR.exception("要删除的项目计划不存在");
        }
        if (!PrintPlanStatusEnum.NEW.equals(examPrintPlan.getStatus())) {
            throw ExceptionResultEnum.ERROR.exception("只有'新建'状态的项目计划可以被删除");
        }
        if (!tbTaskService.countByPrintPlanIdAndEntityId(examPrintPlan.getSchoolId(), id, null)) {
            throw ExceptionResultEnum.ERROR.exception("要删除的印刷计划正在生成pdf中，无法删除");
        }
        examDetailService.deleteExaminationData(id, null);
        return this.removeById(id);
    }

    @Override
    public List<Map<String, String>> tempalteView(Long printPlanId) {
        ExamPrintPlan examPrintPlan = this.getById(printPlanId);
        String variableContent = examPrintPlan.getVariableContent();
        List<Map<String, String>> finalList = new ArrayList<>();
        List<Map> variableList = JSONObject.parseArray(variableContent, Map.class);
        for (Map variable : variableList) {
            finalList.add(getAttachment(variable));
        }

        String ordinaryContent = examPrintPlan.getOrdinaryContent();
        List<Map> ordinaryList = JSONObject.parseArray(ordinaryContent, Map.class);
        for (Map ordinary : ordinaryList) {
            finalList.add(getAttachment(ordinary));
        }
        return finalList;
    }

    @Override
    public IPage<ClientPrintTaskDto> listClientPrintTask(Page<ClientPrintTaskDto> page, Long schoolId, String machineCode, String printPlanId, String status, String courseCode, String paperNumber, String examPlace, String examRoom, Long examStartTime, Long examEndTime, Boolean isDownload, Boolean validate, Long orgId) {
        // 以下状态考场状态不可查询
        String[] examDetailStatus = new String[]{ExamDetailStatusEnum.NEW.name(), PrintPlanStatusEnum.READY.name()};
        IPage<ClientPrintTaskDto> clientPrintTaskDtoIPage = this.baseMapper.listClientPrintTask(page, schoolId, machineCode, printPlanId, status, courseCode, paperNumber, examPlace, examRoom, examStartTime, examEndTime, isDownload, validate, orgId, examDetailStatus);
        for (ClientPrintTaskDto record : clientPrintTaskDtoIPage.getRecords()) {
            // 试卷、题卡
            String printContent = record.getPrintContent();
            record.setIncluedPaper(!StringUtils.isBlank(printContent) && printContent.contains("PAPER"));
            record.setIncluedCard(!StringUtils.isBlank(printContent) && printContent.contains("CARD"));

            //印品
            String variableContent = record.getVariableContent();
            List<Map> variableList = JSONObject.parseArray(variableContent, Map.class);
            record.setIncluedSign(false);
            record.setIncluedPackage(false);
            for (Map map : variableList) {
                String type = map.get("type").toString();
                String templateId = map.get("templateId").toString();
                if (ClassifyEnum.SIGN.name().equals(type) && StringUtils.isNotBlank(templateId)) {
                    record.setIncluedSign(true);
                }
                if (ClassifyEnum.PACKAGE.name().equals(type) && StringUtils.isNotBlank(templateId)) {
                    record.setIncluedPackage(true);
                }
            }
            String ordinaryContent = record.getOrdinaryContent();
            List<Map> ordinaryList = JSONObject.parseArray(ordinaryContent, Map.class);
            record.setIncluedCheckin(false);
            for (Map map : ordinaryList) {
                String type = map.get("type").toString();
                String templateId = map.get("templateId").toString();
                if (ClassifyEnum.CHECK_IN.name().equals(type) && StringUtils.isNotBlank(templateId)) {
                    record.setIncluedCheckin(true);
                }
            }

            // 班级
            String className = examDetailService.findClazzNamesByClazzIds(record.getClassId(), ",");
            record.setClassName(className);
        }
        return clientPrintTaskDtoIPage;
    }


    @Override
    public List<ClientPrintTaskDto> listClientPrintTask(Long schoolId, String machineCode, String printPlanId, String status, String courseCode, String paperNumber, String examPlace, String examRoom, Long examStartTime, Long examEndTime, Boolean isDownload, Boolean validate, Long orgId) {
        // 以下状态考场状态不可查询
        String[] examDetailStatus = new String[]{ExamDetailStatusEnum.NEW.name(), PrintPlanStatusEnum.READY.name()};
        return this.baseMapper.listClientPrintTask(schoolId, machineCode, printPlanId, status, courseCode, paperNumber, examPlace, examRoom, examStartTime, examEndTime, isDownload, validate, orgId, examDetailStatus);
    }

    @Override
    public ClientPrintTaskTotalDto clientTaskTotalData(String printPlanId, Long orgId, String status, String courseCode, String paperNumber, String examPlace, String examRoom, Long examStartTime, Long examEndTime, Boolean isDownload, Boolean validate, String machineCode) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
//        Set<Long> orgIds = teachcloudCommonService.listSubOrgIds(null);
        // 以下状态考场状态不可查询
        String[] examDetailStatus = new String[]{ExamDetailStatusEnum.NEW.name(), PrintPlanStatusEnum.READY.name()};
        ClientPrintTaskTotalDto clientPrintTaskTotalDto = this.baseMapper.clientTaskTotalData(schoolId, printPlanId, status, courseCode, paperNumber, examPlace, examRoom, examStartTime, examEndTime, isDownload, validate, machineCode, orgId, examDetailStatus);

        if (clientPrintTaskTotalDto != null) {
            // 累计a3,a4
            List<ClientPrintData> list = clientPrintDataService.listBySchoolIdAndMachineCode(schoolId, machineCode);
            if (!list.isEmpty()) {
                int pagesA3 = list.stream().mapToInt(m -> m.getPagesA3()).sum();
                clientPrintTaskTotalDto.setHostPagesA3(pagesA3 / 2);
                int pagesA4 = list.stream().mapToInt(m -> m.getPagesA4()).sum();
                clientPrintTaskTotalDto.setHostPagesA4(pagesA4 / 2);
            }
        }

        return clientPrintTaskTotalDto;
    }

    @Override
    public IPage<ClientPrintStatisticsDto> listClientPrintStatistics(Page<ClientPrintStatisticsDto> page, Long schoolId, String printPlanId, String examPlace, Long examStartTime, Long examEndTime, String courseCode, String paperNumber, Long orgId) {
        // 以下状态考场状态不可查询
        String[] examDetailStatus = new String[]{ExamDetailStatusEnum.NEW.name(), PrintPlanStatusEnum.READY.name()};
        return this.baseMapper.listClientPrintStatistics(page, schoolId, printPlanId, examPlace, examStartTime, examEndTime, courseCode, paperNumber, orgId, examDetailStatus);
    }

    @Override
    public ClientPrintStatisticsTotalDto clientStatisticsTotalData(Long orgId, String printPlanId, String examPlace, Long examStartTime, Long examEndTime, String courseCode, String paperNumber) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
//        Set<Long> orgIds = teachcloudCommonService.listSubOrgIds(null);
        // 以下状态考场状态不可查询
        String[] examDetailStatus = new String[]{ExamDetailStatusEnum.NEW.name(), PrintPlanStatusEnum.READY.name()};
        ClientPrintStatisticsTotalDto clientPrintStatisticsTotalDto = this.baseMapper.clientStatisticsTotalData(schoolId, printPlanId, examPlace, examStartTime, examEndTime, courseCode, paperNumber, orgId, examDetailStatus);

        if (clientPrintStatisticsTotalDto != null) {
            String paperNumberStrs = clientPrintStatisticsTotalDto.getPaperNumberAndType();
            if (StringUtils.isNotBlank(paperNumberStrs)) {
                String[] paperNumbers = paperNumberStrs.split(",");
                Set<String> paperNumberSet = new HashSet<>(Arrays.asList(paperNumbers));
                clientPrintStatisticsTotalDto.setPaperCount(paperNumberSet.size());
            }
        }

        return clientPrintStatisticsTotalDto;
    }

    @Override
    public void syncDataCloud(Long printPlanId, Long thirdRelateId) {
        ExamPrintPlan examPrintPlan = this.getById(printPlanId);
        if (examPrintPlan == null) {
            throw ExceptionResultEnum.ERROR.exception("印刷计划数据异常");
        }
        if (!PrintPlanStatusEnum.END.equals(examPrintPlan.getStatus())
                && !PrintPlanStatusEnum.PRINT_FINISH.equals(examPrintPlan.getStatus())) {
            throw ExceptionResultEnum.ERROR.exception("印刷计划未打印完成或者未结束，不能同步数据");
        }
        asyncCloudMarkingTaskService.syncExamAndStudentAndCard(examPrintPlan, thirdRelateId, null);
    }

    @Override
    public void syncDataCloudBatch(SyncDataParam syncDataParam) {
        List<Long> ids = syncDataParam.getList();
        if (ids == null || ids.size() == 0) {
            throw ExceptionResultEnum.ERROR.exception("请选择操作数据");
        }
        QueryWrapper<ExamPrintPlan> queryWrapper = new QueryWrapper<>();
        List<PrintPlanStatusEnum> statusEnums = Arrays.asList(PrintPlanStatusEnum.END, PrintPlanStatusEnum.PRINT_FINISH);
        queryWrapper.lambda().in(ExamPrintPlan::getId, ids);
        List<ExamPrintPlan> examPrintPlans = this.list(queryWrapper);
        if (examPrintPlans != null && examPrintPlans.size() > 0) {
            long count = examPrintPlans.stream().filter(m -> statusEnums.indexOf(m.getStatus()) > 0).count();
            if (count > 0) {
                throw ExceptionResultEnum.ERROR.exception("印刷计划未打印完成或者未结束，不能同步数据");
            }
            for (ExamPrintPlan examPrintPlan : examPrintPlans) {
                asyncCloudMarkingTaskService.syncExamAndStudentAndCard(examPrintPlan, null, null);
            }
        }
    }

    @Override
    public void syncDataMerge(SyncDataParam syncDataParam) {
        List<Long> printPlans = syncDataParam.getList();
        if (CollectionUtils.isEmpty(printPlans)) {
            throw ExceptionResultEnum.ERROR.exception("请选择需要合并的印刷任务");
        }

        if (Objects.isNull(syncDataParam.getThirdRelateId()) && Objects.isNull(syncDataParam.getThirdRelateName())) {
            throw ExceptionResultEnum.ERROR.exception("考试ID、考试名称至少填一个");
        }

        // todo 校验印刷计划是否完成
        if (syncDataParam.getThirdRelateId() == null) {
            String time = String.valueOf(System.currentTimeMillis());
            QueryWrapper<ExamPrintPlan> printPlanQueryWrapper = new QueryWrapper<>();
            printPlanQueryWrapper.lambda().in(ExamPrintPlan::getId, syncDataParam.getList());
            List<ExamPrintPlan> examPrintPlans = this.list(printPlanQueryWrapper);
            ExamPrintPlan examPrintPlan = examPrintPlans.stream().max(Comparator.comparingLong(ExamPrintPlan::getExamEndTime)).get();
            String examTime = DateUtil.format(new Date(examPrintPlan.getExamEndTime()), CloudMarkingTaskUtils.DATE_FORMAT);
            syncDataParam.setThirdRelateId(cloudMarkingTaskUtils.syncExam(examPrintPlan.getSchoolId(), time, syncDataParam.getThirdRelateName(), examTime));
        }

        for (Long printPlanId : printPlans) {
            ExamPrintPlan examPrintPlan = this.getById(printPlanId);
            asyncCloudMarkingTaskService.syncExamAndStudentAndCard(examPrintPlan, syncDataParam.getThirdRelateId(), syncDataParam.getThirdRelateName());
        }
    }

    @Override
    public List<ThirdObjectDto> printSyncPlan(Long schoolId, Long semesterId, Long examId) {
        return this.baseMapper.listThirdObject(schoolId, semesterId, examId);
    }

    @Override
    public ExamPrintPlan findByExamDetailId(Long examDetailId) {
        ExamDetail examDetail = examDetailService.getById(examDetailId);
        if (Objects.isNull(examDetail)) {
            throw ExceptionResultEnum.ERROR.exception("未找到印刷考场数据");
        }
        ExamPrintPlan examPrintPlan = this.getById(examDetail.getPrintPlanId());
        if (Objects.isNull(examPrintPlan)) {
            throw ExceptionResultEnum.ERROR.exception("未找到印刷计划");
        }
        return examPrintPlan;
    }

    @Override
    public void sendNoticeUploadStructure(Long id, SysUser sysUser) {
        List<ExamDetailCourse> examDetailCourses = examDetailService.listSyncPaperNumberByPrintPlanId(id);
        for (ExamDetailCourse examDetailCours : examDetailCourses) {
            ExamTask examTask = examTaskService.getByCourseCodeAndPaperNumber(examDetailCours.getSchoolId(), examDetailCours.getCourseCode(), examDetailCours.getPaperNumber());
            basicMessageService.sendNoticeUploadStructure(examTask.getPaperNumber(), examTask.getCourseCode(), examTask.getCourseName(), examTask.getUserId(), MessageEnum.NOTICE_OF_UPLOAD_STRUCTURE, sysUser);
        }
    }

    @Override
    public List<ExamPrintPlan> findByPaperNumber(Long schoolId, String paperNumber) {
        Set<Long> examDetailIdSet = examDetailCourseService.list(new QueryWrapper<ExamDetailCourse>()
                        .lambda()
                        .eq(ExamDetailCourse::getSchoolId, schoolId)
                        .eq(ExamDetailCourse::getPaperNumber, paperNumber))
                .stream()
                .map(ExamDetailCourse::getExamDetailId)
                .collect(Collectors.toSet());

        Set<Long> examPrintPlanIdSet = new HashSet<>();
        if (examDetailIdSet.size() > 0) {
            examPrintPlanIdSet = examDetailService.list(new QueryWrapper<ExamDetail>()
                            .lambda()
                            .in(ExamDetail::getId, examDetailIdSet))
                    .stream()
                    .map(ExamDetail::getPrintPlanId)
                    .collect(Collectors.toSet());
        }

        List<ExamPrintPlan> examPrintPlanList = new ArrayList<>();
        if (examPrintPlanIdSet.size() > 0) {
            examPrintPlanList = this.list(new QueryWrapper<ExamPrintPlan>().lambda().in(ExamPrintPlan::getId, examPrintPlanIdSet));
        }
        return examPrintPlanList;
    }


    /**
     * 查找子机构
     *
     * @param ids        上级机构id集合
     * @param schoolId   学校id
     * @param resultList 已查询所有子机构id集合
     * @return 所有子机构id集合
     */
    private List<Long> dp(List<Long> ids, Long schoolId, List<Long> resultList) {
        resultList.addAll(ids);
        for (Long id : ids) {
            List<SysOrg> childList = sysOrgService.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getParentId, id).eq(SysOrg::getSchoolId, schoolId));
            if (childList.size() > 0) {
                List<Long> childIds = childList.stream().map(SysOrg::getId).collect(Collectors.toList());
                this.dp(childIds, schoolId, resultList);
            }
        }
        return resultList;
    }

    public Map<String, String> getAttachment(Map map) {
        Map<String, String> fMap = new HashMap<>();
        fMap.put("type", map.get("type").toString());
        String attachmentId = map.get("attachmentId").toString();
        BasicAttachment attachment = basicAttachmentService.getById(attachmentId);
        if (attachment.getType().equals(".ftl") || attachment.getType().equals(".html")) {
            String content = teachcloudCommonService.readFileContent(attachment.getPath());
            fMap.put("content", content);
            fMap.put("utl", null);
        } else if (attachment.getType().equals(".pdf")) {
            fMap.put("content", null);
            Map<String, String> stringMap = teachcloudCommonService.filePreviewByAttachmentId(Long.valueOf(attachmentId), false);
            fMap.putAll(stringMap);
        } else {
            throw ExceptionResultEnum.ERROR.exception("不支持的类型");
        }
        return fMap;
    }
}
