package cn.com.qmth.stmms.ms.marking.api;

import cn.com.qmth.stmms.ms.commons.utils.specification.PagingAndSortingDTO;
import cn.com.qmth.stmms.ms.core.domain.MarkLog;
import cn.com.qmth.stmms.ms.core.domain.MarkLogOperType;
import cn.com.qmth.stmms.ms.core.domain.Paper;
import cn.com.qmth.stmms.ms.core.domain.Work;
import cn.com.qmth.stmms.ms.core.domain.task.MarkTask;
import cn.com.qmth.stmms.ms.core.domain.user.Role;
import cn.com.qmth.stmms.ms.core.repository.MarkLogRepo;
import cn.com.qmth.stmms.ms.core.repository.MarkTaskRepo;
import cn.com.qmth.stmms.ms.core.repository.PaperRepo;
import cn.com.qmth.stmms.ms.core.repository.WorkRepo;
import cn.com.qmth.stmms.ms.marking.assembler.PaperAssembler;
import cn.com.qmth.stmms.ms.marking.dto.PaperDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author by xf
 * @date 2019/11/5.
 */
@RestController
@RequestMapping("/api/task")
public class TaskApi {

    @Autowired
    private PaperAssembler paperAssembler;

    @Autowired
    private PaperRepo paperRepo;

    @Autowired
    private MarkTaskRepo markTaskRepo;

    @Autowired
    private MarkLogRepo markLogRepo;

    @Autowired
    private WorkRepo workRepo;

    /**
     * 任务管理查询
     *
     * @param workId
     * @param secretNumber
     * @param type
     * @return
     */
    @RequestMapping("/search")
    public PagingAndSortingDTO searchBySecretNumber(@RequestParam("workId") Long workId,
                                         @RequestParam(required = false) String secretNumber,
                                         @RequestParam("type") String type,
                                        @RequestParam(required = false) Long startNumber,
                                        @RequestParam(required = false) Long endNumber,
                                        @RequestParam(required = false) Boolean missing,
                                         @RequestParam("page") Integer page,
                                         @RequestParam("size") Integer size) {
        if ("paper".equals(type)) {
            Specification<Paper> specification = (root, query, builder) -> {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(builder.equal(root.get("workId"), workId));
                if (secretNumber != null) {
                    predicates.add(builder.equal(root.get("secretNumber"), secretNumber));
                }
                if (startNumber != null && endNumber != null) {
                    predicates.add(builder.between(root.get("examNumber"), startNumber, endNumber));
                } else if (startNumber != null) {
                    predicates.add(builder.equal(root.get("examNumber"), startNumber));
                }
                if (Objects.nonNull(missing)) {
                    predicates.add(builder.equal(root.get("isMissing"), missing));
                }
                return builder.and(predicates.toArray(new Predicate[predicates.size()]));
            };
            Page<Paper> paperOptional = paperRepo.findAll(specification, new PageRequest(page, size));
            List<PaperDTO> list = new ArrayList<>();
            for (Paper paper : paperOptional) {
                list.add(paperAssembler.toDTO(paper));
            }
            return new PagingAndSortingDTO(paperOptional.getNumber(), paperOptional.getSize(), paperOptional.getTotalPages(),
                    paperOptional.getTotalElements(), list);
        } else if ("task".equals(type)) {
            Specification<MarkTask> specification = (root, query, builder) -> {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(builder.equal(root.get("workId"), workId));
                if (secretNumber != null) {
                    predicates.add(builder.equal(root.get("secretNumber"), secretNumber));
                }
                return builder.and(predicates.toArray(new Predicate[predicates.size()]));
            };
            Page<MarkTask> taskOptional = markTaskRepo.findAll(specification, new PageRequest(page, size));
            List<PaperDTO> list = new ArrayList<>();
            for (MarkTask markTask : taskOptional) {
                PaperDTO paperDto = paperAssembler.toDTO(markTask.getPaper());
                //设置为任务的密号
                paperDto.setSn(markTask.getSecretNumber());
                list.add(paperDto);
            }
            return new PagingAndSortingDTO(taskOptional.getNumber(), taskOptional.getSize(), taskOptional.getTotalPages(),
                    taskOptional.getTotalElements(), list);
        }
        return null;

    }

    /**
     * 重评
     *
     * @param paperId
     * @param ranges
     * @return
     */
    @Transactional
    @RequestMapping("/reevaluation")
    public boolean reevaluation(@RequestParam("paperId") Long paperId,
                                @RequestParam("ranges") String ranges) {
        Paper paper = paperRepo.findOne(paperId);
        paper.reject(null);
        //重评后撤销标准卷
//        paper.setSample(false);
        String[] range = ranges.split(",");
        for (String markId : range) {
            MarkTask markTask = markTaskRepo.findByPaperIdAndMarkerId(paperId, Long.valueOf(markId));
            if (markTask != null) {
                markTask.setRejected(true);
                markTask.setOriginLevel(markTask.getResult());
                markTask.setResult(null);
            }
            markTaskRepo.save(markTask);
            paperRepo.save(paper);

            //加入重评日志
            String operResult = "-";
            MarkLog markLogPrev = markLogRepo.findTopByCreateUserIdAndOperTypeAndSubjectAndExamNumberOrderByCreateTimeDesc(markTask.getMarkerId(), MarkLogOperType.REEVALUATION_LEVEl.getId(), markTask.getSubject().toString(), paper.getExamNumber());
            if (Objects.nonNull(markLogPrev)) {
                operResult = Optional.ofNullable(markLogPrev.getOperDataAfter()).orElse("-");
            }
            Work work = workRepo.findOne(paper.getWorkId());
            MarkLog markLog = new MarkLog(markTask.getMarkerId(), markTask.getMarkerName(), Role.MARKER, markTask.getSubject(), paper.getExamNumber(), paper.getStudentName(), MarkLogOperType.REEVALUATION_LEVEl.getId(), paper.getWorkId(), paper.getId(), markTask.getStage(), operResult, markTask.getOriginLevel(), MarkLogOperType.REEVALUATION_LEVEl.getName(), work.getName());
            markLogRepo.save(markLog);
        }

        return true;
    }

}
