package cn.com.qmth.examcloud.core.questions.api.controller;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.google.gson.Gson;

import cn.com.qmth.examcloud.api.commons.enums.AdminOperateType;
import cn.com.qmth.examcloud.api.commons.enums.DataRuleType;
import cn.com.qmth.examcloud.api.commons.security.bean.User;
import cn.com.qmth.examcloud.api.commons.security.bean.UserDataRule;
import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.commons.util.PathUtil;
import cn.com.qmth.examcloud.core.basic.api.OrgCloudService;
import cn.com.qmth.examcloud.core.questions.base.BeanCopierUtil;
import cn.com.qmth.examcloud.core.questions.base.StringSimilarityUtils;
import cn.com.qmth.examcloud.core.questions.base.enums.ExportTemplateType;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperType;
import cn.com.qmth.examcloud.core.questions.base.excel.ExportUtils;
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
import cn.com.qmth.examcloud.core.questions.dao.ExportServiceManageRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.Paper;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetailUnit;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperSearchInfo;
import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
import cn.com.qmth.examcloud.core.questions.service.PaperService;
import cn.com.qmth.examcloud.core.questions.service.QuesService;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperDetailExp;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperDetailUnitExp;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperExp;
import cn.com.qmth.examcloud.core.questions.service.bean.paper.PaperAnswerDomain;
import cn.com.qmth.examcloud.core.questions.service.bean.paper.PreviewPaperHandler;
import cn.com.qmth.examcloud.core.questions.service.config.SysProperty;
import cn.com.qmth.examcloud.core.questions.service.export.ExportPaperAbstractService;
import cn.com.qmth.examcloud.core.questions.service.util.ExportTemplateUtil;
import cn.com.qmth.examcloud.core.questions.service.util.PaperUtil;
import cn.com.qmth.examcloud.reports.commons.bean.AdminOperateReport;
import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;
import cn.com.qmth.examcloud.support.cache.CacheHelper;
import cn.com.qmth.examcloud.web.security.DataRule;
import cn.com.qmth.examcloud.web.support.ControllerSupport;
import cn.com.qmth.examcloud.web.support.Naked;
import freemarker.template.TemplateException;
import io.swagger.annotations.ApiOperation;

/**
 * Created by songyue on 16/12/28.
 * updated by weiwenhai on 2018.9.28
 *
 * @code 160
 */
@Controller
@RequestMapping("${api_cqb}/")
public class PaperController extends ControllerSupport {

    private final static String BASE_PAGE = "base_page";

    @Autowired
    PaperService paperService;

    @Autowired
    PaperRepo paperRepo;

    @Autowired
    Gson gson;

    @Autowired
    SysProperty sysProperty;

    @Autowired
    QuesService quesService;

    @Autowired
    ExportServiceManageRepo exportServiceManageRepo;

    @Autowired
    OrgCloudService orgCloudService;

    @Autowired
    PaperDetailUnitRepo paperDetailUnitRepo;
    
    
    @ResponseBody
    @ApiOperation(value = "试卷审核")
    @GetMapping(value = "/paper/audit/{paperId}")
    public void audit(@PathVariable String paperId) {
    	User user=getAccessUser();
    	Paper paper = cn.com.qmth.examcloud.core.questions.base.Model.of(paperRepo.findById(paperId));
    	validateRootOrgIsolation(Long.valueOf(paper.getOrgId()));
    	paper.setAuditStatus(true);
    	paperRepo.save(paper);
    	StringBuilder paperInfo=new StringBuilder();
		paperInfo.append(" 课程:"+paper.getCourse().getName()+"("+paper.getCourse().getCode()+")");
		paperInfo.append(" 试卷名称:"+paper.getName());
    	ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE31.getDesc(),paperInfo.toString()));
    }
    
    /**
     * 根据Id获取试卷
     *
     * @param paperId
     * @return
     */
    @Naked
    @ResponseBody
    @ApiOperation(value = "根据Id获取试卷", notes = "根据Id获取试卷")
    @GetMapping(value = "/paper/{paperId}")
    public ResponseEntity<Object> getPaperById(@PathVariable String paperId) {
        return new ResponseEntity<>(paperService.getPaperDto(paperId), HttpStatus.OK);
    }

    /**
     * 保存试卷
     *
     * @param paper
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "保存试卷", notes = "保存试卷")
    @PutMapping(value = "/paper")
    public ResponseEntity<Object> savePaperById(@RequestBody PaperExp paper) {
        User user = getAccessUser();
        String changeInfo = getChangeInfo(paper);
        Map<String, Object> msgMap = paperService.savePaper(paper, user);
        if ("success".equals(msgMap.get("msg"))) {
            if (changeInfo != null) {
                if (PaperType.IMPORT.equals(paper.getPaperType())) {
                    ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE32.getDesc(), changeInfo));
                } else {
                    ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE33.getDesc(), changeInfo));
                }
            }
            return new ResponseEntity<>(msgMap, HttpStatus.OK);
        } else {
            throw new StatusException("1000", msgMap.get("msg").toString());
        }
    }

    private String getChangeInfo(PaperExp paper) {
        Paper old = cn.com.qmth.examcloud.core.questions.base.Model.of(paperRepo.findById(paper.getId()));
        if (old == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        if (!old.getName().equals(paper.getName())) {
            sb.append("试卷名称变动(" + old.getName() + "改为" + paper.getName() + ")");
        }

        if (sb.length() != 0) {
            return sb.toString();
        }
        return null;

    }

    /**
     * 查询所有导入试卷
     *
     * @param paperSearchInfo
     * @param curPage
     * @param pageSize
     * @return
     */
    @DataRule(type = DataRuleType.COURSE)
    @ResponseBody
    @ApiOperation(value = "查询所有导入试卷", notes = "查询所有导入试卷")
    @GetMapping(value = "/importPaper/{curPage}/{pageSize}")
    public ResponseEntity<Object> getImportPapers(@ModelAttribute PaperSearchInfo paperSearchInfo,
                                                  @PathVariable int curPage,
                                                  @PathVariable int pageSize) {
        User user = getAccessUser();
        UserDataRule userDataRule = super.getUserDataRule(DataRuleType.COURSE);

        paperSearchInfo.setOrgId(user.getRootOrgId().toString());

        return new ResponseEntity<>(paperService.getImportPapers(paperSearchInfo, curPage, pageSize, userDataRule), HttpStatus.OK);
    }

    @ResponseBody
    @ApiOperation(value = "查询所有待审核和审核不通过的导入试卷", notes = "查询所有待审核和审核不通过的导入试卷")
    @GetMapping(value = "/importPaperNotSuccess/{curPage}/{pageSize}")
    public ResponseEntity<Object> getImportPapersNotSuccess(@ModelAttribute PaperSearchInfo paperSearchInfo, @PathVariable int curPage, @PathVariable int pageSize) {
        User user = getAccessUser();
        paperSearchInfo.setOrgId(user.getRootOrgId().toString());
        return new ResponseEntity<>(paperService.getImportPapersNotSuccess(paperSearchInfo, curPage, pageSize),
                HttpStatus.OK);
    }

    @ResponseBody
    @ApiOperation(value = "根据条件查询导入试卷", notes = "根据条件查询导入试卷")
    @GetMapping(value = "/getImportPaper")
    public ResponseEntity<List<Paper>> getImportPapersBySearch(@ModelAttribute PaperSearchInfo paperSearchInfo) {
        User user = getAccessUser();
        paperSearchInfo.setOrgId(user.getRootOrgId().toString());
        return new ResponseEntity<List<Paper>>(paperService.getImportPapersBySearch(paperSearchInfo), HttpStatus.OK);
    }

    @ResponseBody
    @ApiOperation(value = "根据条件查询已组试卷", notes = "根据条件查询已组试卷")
    @GetMapping(value = "/getGenPaper")
    public ResponseEntity<List<Paper>> getGenPapersBySearch(@ModelAttribute PaperSearchInfo paperSearchInfo) {
        User user = getAccessUser();
        paperSearchInfo.setOrgId(user.getRootOrgId().toString());
        return new ResponseEntity<>(paperService.getGenPapersBySearch(paperSearchInfo), HttpStatus.OK);
    }

    /**
     * 查询所有已组试卷
     *
     * @param paperSearchInfo
     * @param curPage
     * @param pageSize
     * @return
     */
    @DataRule(type = DataRuleType.COURSE)
    @ResponseBody
    @ApiOperation(value = "查询所有已组试卷", notes = "查询所有已组试卷")
    @GetMapping(value = "/genPaper/{curPage}/{pageSize}")
    public ResponseEntity<Object> getGenPapers(@ModelAttribute PaperSearchInfo paperSearchInfo,
                                               @PathVariable int curPage, @PathVariable int pageSize) {
        User user = getAccessUser();
        UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
        paperSearchInfo.setOrgId(user.getRootOrgId().toString());
        return new ResponseEntity<>(paperService.getGenPapers(paperSearchInfo, curPage, pageSize,ud), HttpStatus.OK);
    }

    /**
     * @param paperSearchInfo
     * @param ids
     * @param curPage
     * @param pageSize
     * @return
     */
    @DataRule(type = DataRuleType.COURSE)
    @ResponseBody
    @ApiOperation(value = "查询所有导入试卷(not in paperIds)", notes = "查询所有导入试卷(not in paperIds)")
    @GetMapping(value = "/genPaper/huoge/{curPage}/{pageSize}")
    public ResponseEntity<Object> getGenPapersNotInIds(@ModelAttribute PaperSearchInfo paperSearchInfo,
                                                       @RequestParam String ids, @PathVariable int curPage, 
                                                       @PathVariable int pageSize) {
    	User user = getAccessUser();
    	UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
        paperSearchInfo.setOrgId(user.getRootOrgId().toString());
        Page<Paper> ret=null;
        if (StringUtils.isNotBlank(ids)) {
        	String[] idArr=ids.split(",");
            ret = paperService.getPapersNotInIds(paperSearchInfo, idArr, curPage, pageSize, PaperType.GENERATE,ud);
            if (ret.getContent().size() == 0 && ret.getTotalElements() > 0 && curPage > 1) {
                ret = paperService.getPapersNotInIds(paperSearchInfo, idArr, curPage - 1, pageSize, PaperType.GENERATE,ud);
            }
        } else {
            ret = paperService.getGenPapers(paperSearchInfo, curPage, pageSize,ud);
            if (ret.getContent().size() == 0 && ret.getTotalElements() > 0 && curPage > 1) {
                ret = paperService.getGenPapers(paperSearchInfo, curPage - 1, pageSize,ud);
            }
        }
        if(ret!=null&&CollectionUtils.isNotEmpty(ret.getContent())
        		&&paperSearchInfo.getFillCount()!=null&&paperSearchInfo.getFillCount()) {
        	setPaperQuesCountAndScore(ret.getContent());
        }
        return new ResponseEntity<>(ret, HttpStatus.OK);
    }

    /**
     * 删除试卷
     *
     * @param paperIds
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "删除试卷", notes = "删除试卷")
    @PostMapping(value = "/paper")
    public void delPaper(@RequestParam List<String> paperIds) {
        User user = getAccessUser();
        if(CollectionUtils.isEmpty(paperIds)) {
        	throw new StatusException("请选择试卷");
        }
        paperService.deletePapersPlus(paperIds, user);
    }

    /**
     * 批量通过试卷
     *
     * @param paperSearchInfo
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "批量通过试卷", notes = "批量通过试卷")
    @PutMapping(value = "/paper/pass")
    public ResponseEntity<Object> passPapers(@RequestBody PaperSearchInfo paperSearchInfo) {
        paperService.passPapers(Arrays.asList(paperSearchInfo.getPaperIds()));
        return new ResponseEntity<>(HttpStatus.OK);
    }

    /**
     * 批量不通过试卷
     *
     * @param paperSearchInfo
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "批量不通过试卷", notes = "批量不通过试卷")
    @PutMapping(value = "/paper/noPass")
    public ResponseEntity<Object> noPassPapers(@RequestBody PaperSearchInfo paperSearchInfo) {
        paperService.noPassPapers(Arrays.asList(paperSearchInfo.getPaperIds()));
        return new ResponseEntity<>(HttpStatus.OK);
    }

    /**
     * 批量待审核试卷
     *
     * @param paperSearchInfo
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "批量待审核试卷", notes = "批量待审核试卷")
    @PutMapping(value = "/paper/draft")
    public ResponseEntity<Object> initPapers(@RequestBody PaperSearchInfo paperSearchInfo) {
        paperService.backPapers(Arrays.asList(paperSearchInfo.getPaperIds()));
        return new ResponseEntity<>(HttpStatus.OK);
    }

    /**
     * 获取卷库考试试卷
     *
     * @param examId
     * @param courseCode
     * @param groupCode
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "获取卷库考试试卷", notes = "获取卷库考试试卷")
    @GetMapping(value = "/paper/list/{examId}/{courseCode}/{groupCode}")
    public List<Paper> listPaperById(@PathVariable String examId, @PathVariable String courseCode,
                                     @PathVariable String groupCode) {
        return paperService.listExamPapers(Long.parseLong(examId), courseCode, groupCode);
    }

    /**
     * 新增考试试卷
     *
     * @param examId
     * @param courseCode
     * @param groupCode
     * @param paperId
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "新增考试试卷", notes = "新增考试试卷")
    @PostMapping(value = "/paper/join/{examId}/{courseCode}/{groupCode}/{paperId}")
    public ResponseEntity<Object> joinExamPaper(@PathVariable String examId, @PathVariable String courseCode,
                                                @PathVariable String groupCode, @PathVariable String paperId) {
        paperService.joinToExamPaper(Long.parseLong(examId), courseCode, groupCode, paperId);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    /**
     * 删除考试试卷
     *
     * @param examId
     * @param courseCode
     * @param groupCode
     * @param paperId
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "删除考试试卷", notes = "删除考试试卷")
    @DeleteMapping(value = "/paper/release/{examId}/{courseCode}/{groupCode}/{paperId}")
    public ResponseEntity<Object> releaseExamPaper(@PathVariable String examId, @PathVariable String courseCode,
                                                   @PathVariable String groupCode, @PathVariable String paperId) {

        paperService.releaseExamPaper(Long.parseLong(examId), courseCode, groupCode, paperId);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    /**
     * 获取卷库考试试卷类型集合
     *
     * @param examId
     * @param courseCode
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "获取考试试卷类型集合", notes = "获取考试试卷类型集合")
    @GetMapping(value = "/paper/groupCode/{examId}/{courseCode}")
    public Set<String> listGroup(@PathVariable String examId, @PathVariable String courseCode) {
        return paperService.listGroupCodes(Long.parseLong(examId), courseCode);
    }

    /**
     * 删除考试试卷类型
     *
     * @param examId
     * @param courseCode
     * @param groupCode
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "删除考试试卷类型", notes = "删除考试试卷类型")
    @DeleteMapping(value = "/paper/groupCode/{examId}/{courseCode}/{groupCode}")
    public ResponseEntity<Object> deleteGroup(@PathVariable String examId, @PathVariable String courseCode,
                                              @PathVariable String groupCode) {
        paperService.deletGroupCode(Long.parseLong(examId), courseCode, groupCode);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    /**
     * 删除导入试卷中的试题
     *
     * @param questionId
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "删除试卷中的试题", notes = "删除试卷中的试题")
    @DeleteMapping(value = "/paper/deleteQuestion/{questionId}")
    public void deletePaperQuestion(@PathVariable String questionId) {
        User user = getAccessUser();
        paperService.deleteImportQuestionById(null, questionId, user);
    }

    /**
     * 删除导入试卷中的试题
     *
     * @param questionId
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "删除导入试卷中的试题", notes = "删除导入试卷中的试题")
    @DeleteMapping(value = "/paper/deleteQuestion/{detailUnitId}/{questionId}")
    public void deleteImportPaperQuestion(@PathVariable String detailUnitId, @PathVariable String questionId) {
        User user = getAccessUser();
        paperService.deleteImportQuestionById(detailUnitId, questionId, user);
    }

    /**
     * 向导入试卷中的新增试题
     *
     * @param paperId
     * @param paperDetailId
     * @param question
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "向导入试卷中的新增试题", notes = "向导入试卷中的新增试题")
    @PostMapping(value = "/paper/addQuestion/{paperId}/{paperDetailId}")
    public ResponseEntity<Object> insertQuestionToPaper(@PathVariable String paperId,
                                                        @PathVariable String paperDetailId, @RequestBody Question question) {
        User user = getAccessUser();
        return new ResponseEntity<>(paperService.insertQuestionToPaper(paperId, paperDetailId, question, user),
                HttpStatus.OK);

    }

    @ResponseBody
    @ApiOperation(value = "获取试卷的重复试题", notes = "获取试卷的重复试题")
    @GetMapping(value = "/paper/{paperId}/reduplicate-questions")
    public ResponseEntity<Object> reduplicateQuestions(@PathVariable String paperId) {
        List<PaperDetailUnitExp> allPaperDetailUnitList = new ArrayList<>();
        List<Set<String>> reduplicateId = new ArrayList<>();
        PaperExp paperExp = paperService.getPaperDto(paperId);
        List<PaperDetailExp> paperDetailExpList = paperExp.getPaperDetails();
        if (paperDetailExpList != null && paperDetailExpList.size() > 0) {
            for (PaperDetailExp paperDetailExp : paperDetailExpList) {
                if (paperDetailExp.getPaperDetailUnits() != null) {
                    allPaperDetailUnitList.addAll(paperDetailExp.getPaperDetailUnits());
                }
            }
        }
        int length = allPaperDetailUnitList.size();
        for (int i = 0; i < length - 1; i++) {
            PaperDetailUnitExp paperDetailUnitExp1 = allPaperDetailUnitList.get(i);
            String quesText1 = quesService.getExtractText(paperDetailUnitExp1.getQuestion());
            if (StringUtils.isEmpty(quesText1)) {
                continue;
            }
            for (int j = i + 1; j < length; j++) {
                PaperDetailUnitExp paperDetailUnitExp2 = allPaperDetailUnitList.get(j);
                String quesText2 = quesService.getExtractText(paperDetailUnitExp2.getQuestion());
                if (StringUtils.isEmpty(quesText2)) {
                    continue;
                }
                double similarity = StringSimilarityUtils.getSimilarityWithCosinesBySeg(quesText1, quesText2);
                if (similarity > sysProperty.getReduplicateSimilarity()) {
                    boolean found = false;
                    for (int k = 0; k < reduplicateId.size(); k++) {
                        if (reduplicateId.get(k).contains(paperDetailUnitExp1.getId())
                                && !reduplicateId.get(k).contains(paperDetailUnitExp2.getId())) {
                            found = true;
                            reduplicateId.get(k).add(paperDetailUnitExp2.getId());
                            break;
                        } else if (!reduplicateId.get(k).contains(paperDetailUnitExp1.getId())
                                && reduplicateId.get(k).contains(paperDetailUnitExp2.getId())) {
                            found = true;
                            reduplicateId.get(k).add(paperDetailUnitExp1.getId());
                            break;
                        } else if (reduplicateId.get(k).contains(paperDetailUnitExp1.getId())
                                && reduplicateId.get(k).contains(paperDetailUnitExp2.getId())) {
                            found = true;
                            // 两个题都在分组里，就不加了
                            break;
                        }
                    }
                    if (!found) {
                        Set<String> redupSet = new HashSet<>();

                        redupSet.add(paperDetailUnitExp1.getId());
                        redupSet.add(paperDetailUnitExp2.getId());
                        reduplicateId.add(redupSet);
                    }
                    // reduplicateId.add(paperDetailUnitExp1.getId());
                    // reduplicateId.add(paperDetailUnitExp2.getId());
                }
            }
        }
        return new ResponseEntity<>(reduplicateId, HttpStatus.OK);
    }

    /**
     * 根据试题获取试卷名称
     *
     * @param
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "获取试题所在的试卷名称", notes = "获取试题所在的试卷名称")
    @GetMapping(value = "/paper/listNames/{questionId}")
    public ResponseEntity<Object> getPaperNamesByQuesId(@PathVariable String questionId) {
        return new ResponseEntity<>(paperService.getPaperNamesByQuestionId(questionId), HttpStatus.OK);
    }

    /**
     * 根据试题获取试卷名称
     *
     * @param
     * @return
     */
    @DataRule(type = DataRuleType.COURSE)
    @ResponseBody
    @ApiOperation(value = "查询用于选题的试题列表", notes = "查询用于选题的试题列表")
    @GetMapping(value = "/paper/listQuestion/{paperId}/{curPage}/{pageSize}")
    public ResponseEntity<Object> listQuestionforSelect(@PathVariable String paperId,
                                                        @PathVariable int curPage,
                                                        @PathVariable int pageSize,
                                                        @RequestParam(name = "quesType") String quesType,
                                                        @RequestParam(name = "quesBody") String quesBody) {
        User user = getAccessUser();
        UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
        if (user == null) {
            return new ResponseEntity<>(new PageImpl<Question>(new ArrayList<>()), HttpStatus.OK);
        }
        QuesStructType quesStructType = null;
        if (StringUtils.isNotEmpty(quesType)) {
            quesStructType = QuesStructType.valueOf(quesType);
        }
        Page<Question> questionPageList = paperService.listQuestionforSelect(paperId, curPage, pageSize, quesStructType, user, quesBody,ud);
        return new ResponseEntity<>(questionPageList, HttpStatus.OK);
    }

    /**
     * 向试卷中某道大题插入多道试题（已存在的试题）
     *
     * @param paperId
     * @param paperDetailId
     * @param questions
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "向导入试卷中的新增试题", notes = "向导入试卷中的新增试题")
    @PostMapping(value = "/paper/selectQuestions/{paperId}/{paperDetailId}")
    public ResponseEntity<Object> selectQuestionsToPaper(@PathVariable String paperId,
                                                         @PathVariable String paperDetailId, @RequestBody List<Question> questions) {
        User user = getAccessUser();
        return new ResponseEntity<>(paperService.selectQuestionsToPaper(paperId, paperDetailId, questions, user),
                HttpStatus.OK);

    }

    /**
     * @param paperSearchInfo
     * @param ids
     * @param curPage
     * @param pageSize
     * @return
     */
    @DataRule(type = DataRuleType.COURSE)
    @ResponseBody
    @ApiOperation(value = "查询所有导入试卷(not in paperIds)", notes = "查询所有导入试卷(not in paperIds)")
    @GetMapping(value = "/importPaper/huoge/{curPage}/{pageSize}")
    public ResponseEntity<Object> getImportPapersNotInIds(@ModelAttribute PaperSearchInfo paperSearchInfo, @RequestParam String ids, @PathVariable int curPage,
                                                          @PathVariable int pageSize) {
    	User user = getAccessUser();
    	UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
        paperSearchInfo.setOrgId(user.getRootOrgId().toString());
        Page<Paper> ret=null;
        if (StringUtils.isNotBlank(ids)) {
        	String[] idArr=ids.split(",");
            ret = paperService.getPapersNotInIds(paperSearchInfo, idArr, curPage, pageSize, PaperType.IMPORT,ud);
            if (ret.getContent().size() == 0 && ret.getTotalElements() > 0 && curPage > 1) {
                ret = paperService.getPapersNotInIds(paperSearchInfo, idArr, curPage - 1, pageSize, PaperType.IMPORT,ud);
            }
        } else {
            ret = paperService.getImportPapers(paperSearchInfo, curPage, pageSize,ud);
            if (ret.getContent().size() == 0 && ret.getTotalElements() > 0 && curPage > 1) {
                ret = paperService.getImportPapers(paperSearchInfo, curPage - 1, pageSize,ud);
            }
        }
        if(ret!=null&&CollectionUtils.isNotEmpty(ret.getContent())
        		&&paperSearchInfo.getFillCount()!=null&&paperSearchInfo.getFillCount()) {
        	setPaperQuesCountAndScore(ret.getContent());
        }
        return new ResponseEntity<>(ret, HttpStatus.OK);
    }
    
    private void setPaperQuesCountAndScore(List<Paper> paperList) {
        if (paperList == null || paperList.size() == 0) {
            return;
        }
        for (Paper paper : paperList) {
            initQuesCountAndScore(paper);
            Map<String, Integer> quesCount = paper.getQuesCount();
            Map<String, Double> quesScore = paper.getQuesScore();
            List<PaperDetailUnit> units = paperDetailUnitRepo.findByPaper(paper);
            if (units != null && units.size() > 0) {
                for (PaperDetailUnit unit : units) {
                    if (unit.getQuestion().getPublicity() == null) {
                        unit.getQuestion().setPublicity(true);
                    }
                    if (unit.getQuestion().getDifficulty() == null) {
                        unit.getQuestion().setDifficulty("中");
                    }
                    String key = getKey(unit.getQuestion().getPublicity(), unit.getQuestion().getDifficulty());
                    quesCount.put(key, quesCount.get(key) + 1);
                    quesScore.put(key, BigDecimal.valueOf(quesScore.get(key)).add(BigDecimal.valueOf(unit.getScore())).doubleValue());
                }
            }
        }
    }

    private String getKey(Boolean publicity, String difficultyType) {
        String difficulty = null;
        if ("易".equals(difficultyType)) {
            difficulty = "1";
        } else if ("中".equals(difficultyType)) {
            difficulty = "2";
        } else {
            difficulty = "3";
        }
        if (publicity == null || publicity) {
            return "1-" + difficulty;
        } else {
            return "0-" + difficulty;
        }
    }

    private void initQuesCountAndScore(Paper paper) {
        Map<String, Integer> quesCount = new HashMap<>();
        quesCount.put("0-1", 0);
        quesCount.put("0-2", 0);
        quesCount.put("0-3", 0);
        quesCount.put("1-1", 0);
        quesCount.put("1-2", 0);
        quesCount.put("1-3", 0);
        Map<String, Double> quesScore = new HashMap<>();
        quesScore.put("0-1", 0.0);
        quesScore.put("0-2", 0.0);
        quesScore.put("0-3", 0.0);
        quesScore.put("1-1", 0.0);
        quesScore.put("1-2", 0.0);
        quesScore.put("1-3", 0.0);
        paper.setQuesCount(quesCount);
        paper.setQuesScore(quesScore);
    }

    /**
     * @param paperSearchInfo
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "查询该课程的所有导入试卷", notes = "查询该课程的所有导入试卷")
    @GetMapping(value = "/importPaper/course")
    public ResponseEntity<Object> getImportPapersByCourseNo(@ModelAttribute PaperSearchInfo paperSearchInfo) {
        User user = getAccessUser();
        paperSearchInfo.setOrgId(user.getRootOrgId().toString());
        paperService.formatPaperSearchInfo(paperSearchInfo);
        Paper importPaper = BeanCopierUtil.copyProperties(paperSearchInfo, Paper.class);
        importPaper.setPaperType(PaperType.IMPORT);
        return new ResponseEntity<>(paperRepo.findAll(Example.of(importPaper)), HttpStatus.OK);

    }

    /**
     * 使用原卷
     *
     * @param paperIds
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "使用原卷", notes = "使用原卷")
    @PutMapping(value = "/useBasePaper/{paperIds}")
    public ResponseEntity<Object> useBasePaper(@PathVariable String paperIds) {
        User user = getAccessUser();
        try {
            String[] paperIdArray = paperIds.split(",");
            StringBuilder paperInfo = new StringBuilder();
            for (int i = 0; i < paperIdArray.length; i++) {
                Paper oldpaper = cn.com.qmth.examcloud.core.questions.base.Model.of(paperRepo.findById(paperIdArray[i]));
                boolean result = paperService.checkPaperName(oldpaper.getName(), PaperType.GENERATE, user.getRootOrgId() + "");
                if (!result) {
                    throw new StatusException("160565", "考试试卷:" + oldpaper.getName() + "已经存在");
                }
                paperInfo.append(" 课程:" + oldpaper.getCourse().getName() + "(" + oldpaper.getCourse().getCode() + ") 试卷名称:" + oldpaper.getName());
            }
            paperService.useBasePaper(paperIds, user.getDisplayName());

            ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE34.getDesc(), paperInfo.toString()));
            return new ResponseEntity<>(HttpStatus.OK);
        } catch (Exception e) {
            throw new StatusException("160537", e.getMessage());
        }
    }

    /**
     * 上传音频文件检查
     *
     * @param paperId
     * @param filesName
     * @return
     */
    @ResponseBody
    @ApiOperation(value = "上传音频文件检查", notes = "上传音频文件检查")
    @PostMapping(value = "/checkRadioFile/{paperId}")
    public ResponseEntity<Object> checkRadioFile(@PathVariable String paperId, @RequestBody List<String> filesName) {
        Map<String, String> errorMessage = paperService.checkRadioFile(paperId, filesName);
        return new ResponseEntity<>(errorMessage, HttpStatus.OK);
    }

    @ResponseBody
    @ApiOperation(value = "上传音频文件", notes = "上传音频文件")
    @PostMapping(value = "/uploadRadio/{paperId}")
    public ResponseEntity<Object> uploadRadio(List<MultipartFile> files, @PathVariable String paperId) {
        User user = getAccessUser();
        paperService.uploadRadio(files, paperId, user);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @Naked
    @ApiOperation(value = "预览试卷页面")
    @GetMapping(value = "/paper/pdf/{paperId}")
    public String viewPaper(Model model, @PathVariable String paperId, @RequestParam(required = false) String examName) {
        Paper paper = cn.com.qmth.examcloud.core.questions.base.Model.of(paperRepo.findById(paperId));
        if (paper == null) {
            throw new StatusException("500", "试卷信息不存在！");
        }

        ExportPaperAbstractService exportPaperService = PaperUtil.getByRootOrgId(paper.getOrgId());
        PaperExp previewPaper = exportPaperService.previewPaperForPDF(paper);
        StringWriter result = new StringWriter();
        try {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("htmlList", PreviewPaperHandler.convertPaperHtml(previewPaper));
            map.put("orgName", CacheHelper.getOrg(Long.valueOf(paper.getOrgId())).getName());
            map.put("examName", examName);
            map.put("courseNo", previewPaper.getCourseNo());
            map.put("courseName", previewPaper.getCourseName());
            map.put("courseLevel", previewPaper.getCourseLevel());
            ExportTemplateUtil.getTemplate(Long.valueOf(paper.getOrgId()), ExportTemplateType.PAPER_VIEW).process(map, result);
            String content = result.toString();
            model.addAttribute("pageContent", content);
            return BASE_PAGE;
        } catch (NumberFormatException | TemplateException | IOException e) {
            throw new StatusException("500", "解析模板出错！");
        } finally {
            try {
                result.close();
            } catch (IOException e) {
            }
        }
    }

    @Naked
    @ApiOperation(value = "预览试卷答案页面")
    @GetMapping(value = "/paper/answer/pdf/{paperId}")
    public String viewPaperAnswer(Model model, @PathVariable String paperId, @RequestParam(required = false) String examName) {
        Paper paper = cn.com.qmth.examcloud.core.questions.base.Model.of(paperRepo.findById(paperId));
        if (paper == null) {
            throw new StatusException("500", "试卷答案信息不存在！");
        }

        ExportPaperAbstractService exportPaperService = PaperUtil.getByRootOrgId(paper.getOrgId());
        PaperExp previewPaper = exportPaperService.previewPaperForPDF(paper);


        StringWriter result = new StringWriter();
        try {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("htmlList", PreviewPaperHandler.convertPaperAnswerHtml(previewPaper));
            map.put("orgName", CacheHelper.getOrg(Long.valueOf(paper.getOrgId())).getName());
            map.put("examName", examName);
            map.put("courseNo", previewPaper.getCourseNo());
            map.put("courseName", previewPaper.getCourseName());
            map.put("courseLevel", previewPaper.getCourseLevel());
            ExportTemplateUtil.getTemplate(Long.valueOf(paper.getOrgId()), ExportTemplateType.ANWSER_VIEW).process(map, result);
            String content = result.toString();
            model.addAttribute("pageContent", content);
            return BASE_PAGE;
        } catch (NumberFormatException | TemplateException | IOException e) {
            throw new StatusException("500", "解析模板出错！");
        } finally {
            try {
                result.close();
            } catch (IOException e) {
            }
        }
    }

    @ApiOperation(value = "传送到印刷平台", notes = "传送到印刷平台")
    @GetMapping(value = "/sendPrint/{paperId}/{examId}/{orgId}")
    public ResponseEntity<Object> sendPrint(@PathVariable String paperId,
                                            @PathVariable String orgId,
                                            @PathVariable String examId) {
        paperService.sendPrint(paperId, orgId, examId);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @ResponseBody
    @ApiOperation(value = "根绝试卷id查询不同类型，题的数量")
    @GetMapping(value = "/paper/questionNumbers/{paperId}/{publicityType}/{difficultyType}")
    public ResponseEntity<Object> questionNumbers(@PathVariable String paperId,
                                                  @PathVariable Integer publicityType,
                                                  @PathVariable Integer difficultyType) {
        int total = paperService.getQuestionTypeNumbers(paperId, publicityType, difficultyType);
        return new ResponseEntity<>(total, HttpStatus.OK);
    }

    @ResponseBody
    @ApiOperation(value = "根绝试卷id查询不同类型，题的数量")
    @GetMapping(value = "/paper/questionScores/{paperId}/{publicityType}/{difficultyType}")
    public ResponseEntity<Object> questionScores(@PathVariable String paperId,
                                                 @PathVariable Integer publicityType,
                                                 @PathVariable Integer difficultyType) {
        double total = paperService.getQuestionTypeScore(paperId, publicityType, difficultyType);
        return new ResponseEntity<>(total, HttpStatus.OK);
    }

    @ApiOperation(value = "试卷答案导出")
    @RequestMapping(value = "/paper/answer/export/{paperId}", method = RequestMethod.GET)
    public void answerExport(@PathVariable String paperId, HttpServletResponse response) {
        User user = getAccessUser();
        Paper paper = cn.com.qmth.examcloud.core.questions.base.Model.of(paperRepo.findById(paperId));
        if (paper == null) {
            throw new StatusException("500", "未找到试卷");
        }
        if (!isSuperAdmin() && !paper.getOrgId().equals(String.valueOf(user.getRootOrgId()))) {
            throw new StatusException("500", "非法请求");
        }
        List<PaperAnswerDomain> dtos = paperService.answerExport(paper);
        ExportUtils.exportEXCEL("试卷答案", PaperAnswerDomain.class, dtos, response);
    }

    @DataRule(type = DataRuleType.COURSE)
    @ApiOperation(value = "试卷答案导入")
    @RequestMapping(value = "/paper/answer/import/{paperId}", method = RequestMethod.POST)
    @ResponseBody
    public void answerImport(@PathVariable String paperId, @RequestPart @NotNull(message = "上传文件不能为空！") MultipartFile dataFile) {
        User user = getAccessUser();
        UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
        if (ud.assertEmptyQueryResult()) {
        	throw new StatusException("500", "没有数据权限");
        }
        Paper paper = cn.com.qmth.examcloud.core.questions.base.Model.of(paperRepo.findById(paperId));
        if (paper == null) {
            throw new StatusException("500", "未找到试卷");
        }
        if (!isSuperAdmin() && !paper.getOrgId().equals(String.valueOf(user.getRootOrgId()))) {
            throw new StatusException("500", "非法请求");
        }
        if(ud.assertNeedQueryRefIds()&&!ud.stringRefIds().contains(paper.getCourse().getId())) {
        	throw new StatusException("500", "没有数据权限");
        }
        paperService.answerImport(paper, dataFile);
        StringBuilder paperInfo = new StringBuilder();
        paperInfo.append("课程:" + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ")");
        paperInfo.append(" 试卷名称:" + paper.getName());
        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE35.getDesc(), paperInfo.toString()));
    }

    @ApiOperation(value = "下载答案模板", notes = "下载答案模板")
    @GetMapping("/paper/answer/template")
    public void getImportTemplate(HttpServletResponse response) {
        String resoucePath = PathUtil.getResoucePath("templates/answerImportTemplate.xlsx");
        exportFile("答案导入模板.xlsx", new File(resoucePath));
    }

}
