package com.qmth.distributed.print.api;

import com.qmth.boot.api.constant.ApiConstant;
import com.qmth.distributed.print.business.bean.dto.ExamTaskDetailCardDto;
import com.qmth.distributed.print.business.bean.params.ApproveFormParams;
import com.qmth.distributed.print.business.entity.ExamTask;
import com.qmth.distributed.print.business.entity.ExamTaskApplyTemp;
import com.qmth.distributed.print.business.entity.ExamTaskDetail;
import com.qmth.distributed.print.business.entity.TFFlowJoin;
import com.qmth.distributed.print.business.enums.ExamStatusEnum;
import com.qmth.distributed.print.business.service.*;
import com.qmth.teachcloud.common.annotation.OperationLogDetail;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.log.OperationTypeEnum;
import com.qmth.teachcloud.common.util.Result;
import com.qmth.teachcloud.common.util.ResultUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import io.swagger.annotations.*;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 入库申请 前端控制器
 * </p>
 *
 * @author xf
 * @since 2021-03-23
 */
@Api(tags = "入库申请Controller")
@RestController
@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + SystemConstant.PREFIX_URL_EXAM + "/task")
@Validated
public class ExamTaskApplyController {

    @Resource
    private ExamTaskService examTaskService;

    @Resource
    private PrintCommonService printCommonService;

    @Resource
    private ExamTaskPrintService examTaskPrintService;

    @Resource
    TaskService taskService;

    @Resource
    ActivitiService activitiService;

    @Resource
    TFFlowJoinService tfFlowJoinService;


    /**
     * 入库申请-查询
     *
     * @param auditStatus
     * @param cardRuleId
     * @param courseCode
     * @param paperNumber
     * @param startTime
     * @param endTime
     * @param userName    命题老师名称
     * @param pageNumber
     * @param pageSize
     * @return
     */
    @ApiOperation(value = "入库申请-分页查询")
    @RequestMapping(value = "/apply_list", method = RequestMethod.POST)
    public Result taskApplyList(@RequestParam(value = "semesterId", required = false) Long semesterId,
                                @RequestParam(value = "examId", required = false) Long examId,
                                @RequestParam(value = "auditStatus", required = false) String auditStatus,
                                @RequestParam(value = "cardRuleId", required = false) String cardRuleId,
                                @RequestParam(value = "courseCode", required = false) String courseCode,
                                @RequestParam(value = "paperNumber", required = false) String paperNumber,
                                @RequestParam(value = "startTime", required = false) Long startTime,
                                @RequestParam(value = "endTime", required = false) Long endTime,
                                @RequestParam(value = "userName", required = false) String userName,
                                @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
                                @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
        if (examId == null) {
            throw ExceptionResultEnum.EXAM_ID_IS_NULL.exception();
        }
        return ResultUtil.ok(examTaskService.listTaskApply(semesterId, examId, auditStatus, SystemConstant.convertIdToLong(cardRuleId), courseCode, paperNumber, startTime, endTime, userName, pageNumber, pageSize));
    }

    /**
     * 入库申请-删除
     */
    @ApiOperation(value = "入库申请-删除")
    @RequestMapping(value = "/apply_delete", method = RequestMethod.POST)
    @OperationLogDetail(operationType = OperationTypeEnum.DELETE, detail = "删除操作，命题任务ID：{{id}}")
    public Result applyDelete(@RequestParam Long id) {
        examTaskService.applyDelete(id);
        return ResultUtil.ok(true);
    }

    /**
     * 根据命题任务ID查询单个数据
     *
     * @param examTaskId 命题任务ID
     * @return Result
     */
    @ApiOperation(value = "根据命题任务ID查询任务详情数据")
    @RequestMapping(value = "/apply_get_one", method = RequestMethod.POST)
    public Result applyGetOne(@RequestParam(value = "examTaskId") Long examTaskId,
                              @RequestParam(value = "source", required = false) String source) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        ExamTaskDetailCardDto detail = examTaskService.applyGetOne(examTaskId, source);
        if (Objects.nonNull(detail) && Objects.nonNull(detail.getFlowId())) {
            Task task = taskService.createTaskQuery().processInstanceId(detail.getFlowId())
                    .taskCandidateOrAssigned(String.valueOf(sysUser.getId())).singleResult();
            if (Objects.nonNull(task)) {
                detail.setFlowTaskId(task.getId());
            } else {
                List<TFFlowJoin> tfFlowJoinList = tfFlowJoinService.findByObjectId(Long.parseLong(detail.getExamTaskId()));
                String flowId = null;
                TFFlowJoin tfFlowJoin = null;
                if (Objects.nonNull(tfFlowJoinList) && tfFlowJoinList.size() > 1) {
                    tfFlowJoin = tfFlowJoinList.get(tfFlowJoinList.size() - 1);
                } else if (Objects.nonNull(tfFlowJoinList) && tfFlowJoinList.size() == 1) {
                    tfFlowJoin = tfFlowJoinList.get(0);
                }
                flowId = Objects.nonNull(tfFlowJoin) ? String.valueOf(tfFlowJoin.getFlowId()) : flowId;
                task = taskService.createTaskQuery().processInstanceId(detail.getFlowId())
                        .taskCandidateOrAssigned(String.valueOf(sysUser.getId())).singleResult();
                if (Objects.nonNull(task)) {
                    detail.setFlowTaskId(task.getId());
                    detail.setFlowId(flowId);
                }
            }
        }
        return ResultUtil.ok(detail);
    }

    /**
     * 入库申请-立即申请-提交
     *
     * @param examTaskDetail 命题任务详情对象
     * @return Result
     */
    @ApiOperation(value = "入库申请-暂存/提交")
    @RequestMapping(value = "/apply_save", method = RequestMethod.POST)
    @OperationLogDetail(operationType = OperationTypeEnum.SAVE, detail = "提交操作，命题任务ID：{{examTaskDetail.examTaskId}}")
    public Result taskApplySave(@RequestBody ExamTaskDetail examTaskDetail) throws IOException {
        Map<String, Object> map = examTaskService.saveExamTaskDetail(examTaskDetail);
        ExamTask examTask = examTaskService.getById(examTaskDetail.getExamTaskId());
        if (examTaskDetail.getOperateType().equals(ExamStatusEnum.SUBMIT.name()) && (Objects.nonNull(examTask.getReview()) && !examTask.getReview())) {
            // 校验是否可以提交打印状态
            printCommonService.checkExamDataAndCreatePdfTask(examTask.getSchoolId(), examTask.getExamId(), examTask.getCourseCode(), examTask.getPaperNumber(), (SysUser) ServletUtil.getRequestUser());
        }
        Boolean sendFlowMq = (Boolean) map.get(SystemConstant.SEND_FLOW_MQ);
        if (Objects.nonNull(sendFlowMq) && sendFlowMq) {
            activitiService.sendFlowTaskApproveMsg(map);
        }
        return ResultUtil.ok(true);
    }


    /**
     * 入库申请-撤销申请
     *
     * @param examTask 命题任务对象
     * @return Result
     */
    @ApiOperation(value = "入库申请-撤回申请")
    @RequestMapping(value = "/apply_status", method = RequestMethod.POST)
    @OperationLogDetail(operationType = OperationTypeEnum.UPDATE, detail = "撤回申请操作，命题任务ID：{{examTask.id}}")
    public Result taskApplyStatus(@RequestBody ExamTask examTask) {
        Map<String, Object> map = examTaskService.status(examTask);
        activitiService.sendFlowTaskApproveMsg(map);
        return ResultUtil.ok(true);
    }


    /**
     * 入库申请-新建任务-保存
     *
     * @param examTaskApplyTemp
     * @return
     */
    @ApiOperation(value = "入库申请-新建任务-保存")
    @RequestMapping(value = "/submit_task_apply", method = RequestMethod.POST)
    @OperationLogDetail(operationType = OperationTypeEnum.ADD, detail = "入库申请新增了一条命题数据")
    public Result submitTaskApply(@RequestBody ExamTaskApplyTemp examTaskApplyTemp) throws IOException {
        Map<String, Object> map = examTaskService.submitTaskApply(examTaskApplyTemp);
        ExamTask examTask = (ExamTask) map.get(SystemConstant.EXAM_TASK);
        if (Objects.nonNull(examTask.getReview()) && !examTask.getReview()) {
            // 校验是否可以提交打印状态
            printCommonService.checkExamDataAndCreatePdfTask(examTask.getSchoolId(), examTask.getExamId(), examTask.getCourseCode(), examTask.getPaperNumber(), (SysUser) ServletUtil.getRequestUser());
        }
        Boolean sendFlowStartMq = (Boolean) map.get(SystemConstant.SEND_FLOW_START_MQ);
        Boolean sendFlowMq = (Boolean) map.get(SystemConstant.SEND_FLOW_MQ);
        if (Objects.nonNull(sendFlowStartMq) && sendFlowStartMq) {
            activitiService.sendFlowStartMsg(examTask.getFlowId());
        } else if (Objects.nonNull(sendFlowMq) && sendFlowMq) {
            activitiService.sendFlowTaskApproveMsg(map);
        }
        return ResultUtil.ok();
    }

    /**
     * 印刷室列表
     *
     * @return
     */
    @ApiOperation(value = "印刷室列表")
    @RequestMapping(value = "/list_task_print_house", method = RequestMethod.POST)
    public Result listTaskPrintHouse() {
        return ResultUtil.ok(examTaskPrintService.listHouse());
    }

    @ApiOperation(value = "题卡标题查询")
    @RequestMapping(value = "/find_card_title", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = Result.class)})
    public Result findCardTitle(@ApiParam(value = "题卡规则id", required = true) @RequestParam String cardRuleId) {
        return ResultUtil.ok((Object) examTaskService.findCardTitle(SystemConstant.convertIdToLong(cardRuleId)));
    }

    @ApiOperation(value = "命题任务-考试对象查询")
    @RequestMapping(value = "/find_exam_object", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = Result.class)})
    public Result findExamObject(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
                                 @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber) {
        return ResultUtil.ok(examTaskService.findExamObjectDtoByPaperNumber(examId, paperNumber));
    }

    @ApiOperation(value = "入库申请-考生对象查询")
    @RequestMapping(value = "/find_exam_task_student_object", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    public Result findExamTaskStudentObject(@RequestParam(required = false) String examId,
                                            @RequestParam(required = false) String courseCode,
                                            @RequestParam(required = false) String teacher,
                                            @RequestParam(required = false) String className) throws Exception {
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        return ResultUtil.ok(examTaskService.findExamTaskStudentObject(SystemConstant.convertIdToLong(examId), courseCode, teacher, className, requestUser));
    }

    @ApiOperation(value = "入库申请-导入考生对象")
    @RequestMapping(value = "/exam_task_exam_student_import", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @OperationLogDetail(operationType = OperationTypeEnum.IMPORT)
    public Result examTaskExamStudentImport(@RequestParam MultipartFile file) throws Exception {
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        return ResultUtil.ok(examTaskService.examTaskExamStudentImport(file, requestUser));
    }

    @ApiOperation(value = "入库申请-题库试卷列表")
    @RequestMapping(value = "/page_tiku_paper", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @OperationLogDetail(operationType = OperationTypeEnum.SELECT, detail = "查询题库试卷列表，课程代码：{{courseCode}}、试卷名称：{{paperName}}、教师工号：{{account}}")
    public Result pageTikuPaper(@ApiParam(value = "课程代码") @RequestParam(required = false) String courseCode,
                                @ApiParam(value = "试卷名称") @RequestParam(value = "paperName", required = false) String paperName,
                                @ApiParam(value = "教师工号") @RequestParam(value = "account", required = false) String account,
                                @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
                                @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
        return ResultUtil.ok(examTaskService.pageTikuPaper(courseCode, paperName, account, pageNumber, pageSize));
    }

    @ApiOperation(value = "入库申请-题库试卷包")
    @RequestMapping(value = "/get_tiku_paper_data", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @OperationLogDetail(operationType = OperationTypeEnum.SELECT, detail = "查询题库试卷包，考试ID：{{examId}}、题库试卷ID：{{paperId}}、唯一标识：{{uuid}}")
    public Result getTikuPaperData(@ApiParam(value = "考试ID", required = true) @RequestParam(value = "examId") Long examId,
                                   @ApiParam(value = "题库试卷ID", required = true) @RequestParam(value = "paperId") Long paperId,
                                   @ApiParam(value = "唯一标识") @RequestParam(value = "uuid", required = false) String uuid) {
        return ResultUtil.ok(examTaskService.getTikuPaperData(examId, paperId, uuid));
    }

    @ApiOperation(value = "入库申请-下载审批表-获取试卷审批表数据")
    @RequestMapping(value = "/find_approve_form_json", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = Result.class)})
    public Result findApproveFormJson(@ApiParam(value = "命题任务id") @RequestParam(required = false) String examTaskId,
                                      @ApiParam(value = "考试ID") @RequestParam(required = false) Long examId,
                                      @ApiParam(value = "试卷编号") @RequestParam(required = false) String paperNumber) {
        return ResultUtil.ok(examTaskService.findExamTaskApprovalForm(SystemConstant.convertIdToLong(examTaskId), examId, paperNumber));
    }

    @ApiOperation(value = "入库申请-下载审批表-下载审批表PDF")
    @RequestMapping(value = "/find_approve_form_pdf", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "下载成功", response = Result.class)})
    @OperationLogDetail(operationType = OperationTypeEnum.EXPORT, detail = "下载审批表PDF，命题任务ID：{{approveFormParams.examTaskId}}")
    public void findApproveFormPdf(@Valid @RequestBody ApproveFormParams approveFormParams, BindingResult bindingResult) throws Exception {
        if (bindingResult.hasErrors()) {
            throw ExceptionResultEnum.ERROR.exception(bindingResult.getAllErrors().get(0).getDefaultMessage());
        }
        HttpServletResponse response = ServletUtil.getResponse();
        examTaskService.findExamTaskApprovalPdf(response, approveFormParams.getExamTaskId(), approveFormParams.getHtmlContent());
    }
}

