package com.qmth.themis.backend.api;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qmth.themis.business.annotation.ApiJsonObject;
import com.qmth.themis.business.annotation.ApiJsonProperty;
import com.qmth.themis.business.cache.bean.ExamCourseCacheBean;
import com.qmth.themis.business.config.SystemConfig;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.MqDto;
import com.qmth.themis.business.dto.response.RoomCodeQueryDto;
import com.qmth.themis.business.dto.response.TEExamStudentDto;
import com.qmth.themis.business.entity.*;
import com.qmth.themis.business.enums.*;
import com.qmth.themis.business.service.*;
import com.qmth.themis.business.util.ServletUtil;
import com.qmth.themis.common.enums.ExceptionResultEnum;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.util.Result;
import com.qmth.themis.common.util.ResultUtil;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: 考生库 前端控制器
 * @Param:
 * @returnß:
 * @Author: wangliang
 * @Date: 2020/6/25
 */
@Api(tags = "考生库Controller")
@RestController
@RequestMapping("/${prefix.url.admin}/examStudent")
public class TEExamStudentController {
    private final static Logger log = LoggerFactory.getLogger(TEExamStudentController.class);

    @Resource
    TEExamStudentService teExamStudentService;

    @Resource
    TBAttachmentService tbAttachmentService;

    @Resource
    TBTaskHistoryService taskHistoryService;

    @Resource
    TEExamService teExamService;

    @Resource
    TEExamActivityService teExamActivityService;

    @Resource
    TBExamInvigilateUserService tbExamInvigilateUserService;

    @Resource
    MqDtoService mqDtoService;

    @Resource
    SystemConfig systemConfig;

    @Resource
    TEStudentService teStudentService;

    @Resource
    TEExamCourseService teExamCourseService;

    @ApiOperation(value = "考生导出")
    @RequestMapping(value = "/export", method = RequestMethod.POST)
    public Result export(@ApiParam(value = "考试批次id", required = true) @RequestParam Long examId,
                         @ApiParam(value = "考试场次id", required = false) @RequestParam(required = false) Long activityId,
                         @ApiParam(value = "证件号", required = false) @RequestParam(required = false) String identity,
                         @ApiParam(value = "姓名", required = false) @RequestParam(required = false) String name,
                         @ApiParam(value = "考场代码", required = false) @RequestParam(required = false) String roomCode,
                         @ApiParam(value = "科目代码", required = false) @RequestParam(required = false) String courseCode,
                         @ApiParam(value = "年级", required = false) @RequestParam(required = false) String grade,
                         @ApiParam(value = "是否启用", required = false) @RequestParam(required = false) Integer enable,
                         @ApiParam(value = "教学班级", required = false) @RequestParam(required = false) String classNo,
                         @ApiParam(value = "底照是否上传", required = false) @RequestParam(required = false) Integer hasPhoto) throws Exception {
        TBTaskHistory tbTaskHistory = null;
        Map<String, Object> transMap = new HashMap<String, Object>();
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        //往任务表里插一条数据
        tbTaskHistory = new TBTaskHistory(TaskTypeEnum.EXPORT_EXAM_STUDENT, TaskStatusEnum.INIT, SystemConstant.EXPORT_INIT, 0d, tbUser.getId());
        taskHistoryService.save(tbTaskHistory);
        transMap.put("tbTaskHistory", tbTaskHistory);

        transMap.put("examId", examId);
        transMap.put("activityId", activityId);
        transMap.put("identity", identity);
        transMap.put("name", name);
        transMap.put("roomCode", roomCode);
        transMap.put("courseCode", courseCode);
        transMap.put("grade", grade);
        transMap.put("enable", enable);
        transMap.put("classNo", classNo);
        transMap.put("hasPhoto", hasPhoto);

        transMap.put("createId", tbUser.getId());

        //mq发送消息start
        MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_STUDENT_EXPORT.name(), transMap, MqTagEnum.EXAM_STUDENT_EXPORT, String.valueOf(tbTaskHistory.getId()), tbUser.getName());

        mqDtoService.assembleSendOneWayMsg(mqDto);
        //mq发送消息end
        Map<String, Long> map = new HashMap<String, Long>();
        map.put(SystemConstant.TASK_ID, tbTaskHistory.getId());
        return ResultUtil.ok(map);

    }

    @ApiOperation(value = "考生查询接口")
    @RequestMapping(value = "/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "考生信息", response = TEExamStudentDto.class)})
    public Result query(@ApiParam(value = "考试批次id", required = true) @RequestParam Long examId,
                        @ApiParam(value = "考试场次id", required = false) @RequestParam(required = false) Long activityId,
                        @ApiParam(value = "证件号", required = false) @RequestParam(required = false) String identity,
                        @ApiParam(value = "姓名", required = false) @RequestParam(required = false) String name,
                        @ApiParam(value = "考场代码", required = false) @RequestParam(required = false) String roomCode,
                        @ApiParam(value = "科目代码", required = false) @RequestParam(required = false) String courseCode,
                        @ApiParam(value = "年级", required = false) @RequestParam(required = false) String grade,
                        @ApiParam(value = "是否启用", required = false) @RequestParam(required = false) Integer enable,
                        @ApiParam(value = "教学班级", required = false) @RequestParam(required = false) String classNo,
                        @ApiParam(value = "底照是否上传", required = false) @RequestParam(required = false) Integer hasPhoto,
                        @ApiParam(value = "分页页码", required = true) @RequestParam int pageNumber,
                        @ApiParam(value = "分页数", required = true) @RequestParam int pageSize) {
        if (Objects.isNull(examId) || Objects.equals(examId, "")) {
            throw new BusinessException(ExceptionResultEnum.EXAM_ID_IS_NULL);
        }
        IPage<TEExamStudentDto> teExamStudentIPage = teExamStudentService.examStudentQuery(
                new Page<>(pageNumber, pageSize), examId, activityId, identity, name, roomCode, courseCode, grade,
                enable, classNo, hasPhoto);
        if (teExamStudentIPage.getRecords() != null && teExamStudentIPage.getRecords().size() > 0) {
            for (TEExamStudentDto dto : teExamStudentIPage.getRecords()) {
                if (StringUtils.isNotBlank(dto.getBasePhotoUrl())) {
                    dto.setBasePhotoUrl(systemConfig.getProperty("aliyun.oss.url") + "/" + dto.getBasePhotoUrl());
                }
            }
        }
        return ResultUtil.ok(teExamStudentIPage);
    }

    @ApiOperation(value = "考生停用/启用接口")
    @RequestMapping(value = "/toggle", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @Transactional
    public Result examStudentToggle(@ApiJsonObject(name = "examStudentToggle", value = {
            @ApiJsonProperty(key = "id", type = "long", example = "1", description = "考生ID"),
            @ApiJsonProperty(key = "enable", type = "int", example = "1", description = "是否启用")}) @ApiParam(value = "考生信息", required = true) @RequestBody List<Map<String, Object>> mapParameter) {
        if (Objects.isNull(mapParameter) || mapParameter.size() == 0) {
            throw new BusinessException(ExceptionResultEnum.EXAM_STUDENT_INFO_IS_NULL);
        }
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        List<TEExamStudent> teExamStudentList = new ArrayList<>();
        for (int i = 0; i < mapParameter.size(); i++) {
            Map map = mapParameter.get(i);
            TEExamStudent teExamStudent = teExamStudentService.getById(Long.parseLong(String.valueOf(map.get("id"))));
            if (Objects.isNull(teExamStudent)) {
                throw new BusinessException(ExceptionResultEnum.EXAM_STUDENT_NO);
            }
            teExamStudent.setEnable(Integer.parseInt(String.valueOf(map.get("enable"))));
            teExamStudent.setUpdateId(tbUser.getId());
            teExamStudentList.add(teExamStudent);
        }
        teExamStudentService.updateBatchById(teExamStudentList);
        teExamStudentList.forEach(s -> {
            teExamStudentService.updateExamStudentCacheBean(s.getId());
        });
        return ResultUtil.ok(Collections.singletonMap("success", true));
    }

    @ApiOperation(value = "考生修改接口")
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @Transactional
    public Result save(@ApiParam(value = "考生信息", required = true) @RequestBody List<TEExamStudent> teExamStudentList) {
        if (Objects.isNull(teExamStudentList) || teExamStudentList.size() == 0) {
            throw new BusinessException(ExceptionResultEnum.EXAM_STUDENT_INFO_IS_NULL);
        }
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        TBOrg tbOrg = (TBOrg) ServletUtil.getRequestOrg();
        teExamStudentList.forEach(s -> {
            if (Objects.isNull(s.getId())) {
                QueryWrapper<TEStudent> teExamStudentQueryWrapper = new QueryWrapper<>();
                teExamStudentQueryWrapper.lambda().eq(TEStudent::getName, s.getName())
                        .eq(TEStudent::getIdentity, s.getIdentity()).eq(TEStudent::getOrgId, tbOrg.getId());
                int count = teStudentService.count(teExamStudentQueryWrapper);
                if (count == 0) {
                    TEStudent teStudent = new TEStudent(tbOrg.getId(), s.getIdentity(), s.getName(), tbUser.getId());
                    teStudentService.save(teStudent);
                    s.setStudentId(teStudent.getId());
                    s.setCreateId(tbUser.getId());
                }
            } else {
                UpdateWrapper<TEExamStudent> teExamStudentUpdateWrapper = new UpdateWrapper<>();
                teExamStudentUpdateWrapper.lambda().set(TEExamStudent::getName, s.getName())
                        .eq(TEExamStudent::getIdentity, s.getIdentity());
                teExamStudentService.update(teExamStudentUpdateWrapper);

                UpdateWrapper<TEStudent> teStudentUpdateWrapper = new UpdateWrapper<>();
                teStudentUpdateWrapper.lambda().set(TEStudent::getName, s.getName()).eq(TEStudent::getIdentity,
                        s.getIdentity());
                teStudentService.update(teStudentUpdateWrapper);
                s.setUpdateId(tbUser.getId());
            }
            ExamCourseCacheBean examCourseCacheBean = teExamCourseService.getExamCourseCacheBean(s.getExamId(), s.getCourseCode());
            if (Objects.isNull(examCourseCacheBean)) {
                throw new BusinessException("考试科目不存在");
            }
            s.setCourseName(examCourseCacheBean.getCourseName());
            List<RoomCodeQueryDto> roomCodeQueryDtoList = teExamStudentService.examRoomQuery(null);
            if (Objects.nonNull(roomCodeQueryDtoList)) {
                Map<String, RoomCodeQueryDto> roomCodeQueryDtoMap = roomCodeQueryDtoList.stream()
                        .collect(Collectors.toMap(RoomCodeQueryDto::getRoomCode, Function.identity(), (dto1, dto2) -> dto1));
                String roomName = roomCodeQueryDtoMap.get(s.getRoomCode()).getRoomName();
                if (Objects.isNull(roomName)) {
                    throw new BusinessException("考场不存在");
                }
                s.setRoomName(roomCodeQueryDtoMap.get(s.getRoomCode()).getRoomName());
            }
            teExamStudentService.saveOrUpdate(s);
        });
        for(TEExamStudent es:teExamStudentList){
            teExamStudentService.updateExamStudentCacheBean(es.getId());
        }
        return ResultUtil.ok(Collections.singletonMap("success", true));
    }

    @ApiOperation(value = "考生删除接口")
    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @Transactional
    public Result delete(@ApiParam(value = "考生id", required = true) @RequestBody List<Long> ids) {
        if (Objects.isNull(ids) || ids.size() == 0) {
            throw new BusinessException(ExceptionResultEnum.EXAM_STUDENT_ID_IS_NULL);
        }
        teExamStudentService.removeByIds(ids);
        ids.forEach(s -> {
            teExamStudentService.deleteExamStudentCacheBean(s);
        });
        return ResultUtil.ok(Collections.singletonMap("success", true));
    }

    @ApiOperation(value = "考生导入接口")
    @RequestMapping(value = "/import", method = RequestMethod.POST)
    @Transactional
    @ApiResponses({@ApiResponse(code = 200, message = "{\"taskId\":0}", response = Result.class)})
    public Result importData(@ApiParam(value = "上传文件", required = true) @RequestParam MultipartFile file,
                             @ApiParam(value = "考试批次id", required = true) @RequestParam Long examId) throws IOException {
        if (Objects.isNull(file) || Objects.equals(file, "")) {
            throw new BusinessException(ExceptionResultEnum.ATTACHMENT_IS_NULL);
        }
        if (Objects.isNull(examId) || Objects.equals(examId, "")) {
            throw new BusinessException(ExceptionResultEnum.EXAM_ID_IS_NULL);
        }
        Map<String, Object> mapParameter = systemConfig.getOssEnv(UploadFileEnum.file.getId());
        TBAttachment tbAttachment = null;
        TBTaskHistory tbTaskHistory = null;
        Map transMap = new HashMap();
        try {
            TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
            tbAttachment = tbAttachmentService.saveAttachment(file, ServletUtil.getRequestMd5(),
                    ServletUtil.getRequestPath(), mapParameter, tbUser.getOrgId(), tbUser.getId());
            if (Objects.isNull(tbAttachment)) {
                throw new BusinessException(ExceptionResultEnum.ATTACHMENT_ERROR);
            } else {
                // 往任务表里插一条数据
                tbTaskHistory = new TBTaskHistory(TaskTypeEnum.IMPORT_EXAM_STUDENT, examId, TaskStatusEnum.INIT,
                        SystemConstant.IMPORT_INIT, 0d, tbAttachment.getName(), tbAttachment.getRemark(),
                        tbUser.getId());
                taskHistoryService.save(tbTaskHistory);
                transMap.put("tbTaskHistory", tbTaskHistory);
            }
            transMap.put("examId", examId);
            transMap.put("createId", tbUser.getId());

            // 先查询考试相关信息
            TEExam teExam = teExamService.getById(examId);
            if (Objects.isNull(teExam)) {
                throw new BusinessException(ExceptionResultEnum.EXAM_NO);
            }
            transMap.put("mode", teExam.getMode());
            transMap.put("orgId", teExam.getOrgId());
            transMap.put("examCount", teExam.getExamCount());

            // 获取该批次下的所有考场，校验考场id是否存在
            QueryWrapper<TEExamActivity> teExamActivityQueryWrapper = new QueryWrapper<>();
            teExamActivityQueryWrapper.lambda().eq(TEExamActivity::getExamId, examId);
            List<TEExamActivity> teExamActivityList = teExamActivityService.list(teExamActivityQueryWrapper);
            if (Objects.isNull(teExamActivityList) || teExamActivityList.size() == 0) {
                throw new BusinessException(ExceptionResultEnum.EXAM_ACTIVITY_NO);
            }
            Map<String, TEExamActivity> teExamActivityMap = teExamActivityList.stream()
                    .collect(Collectors.toMap(TEExamActivity::getCode, Function.identity(), (dto1, dto2) -> dto1));
            transMap.put("teExamActivityMap", teExamActivityMap);

            // 获取考场代码和考场名称
            QueryWrapper<TBExamInvigilateUser> tbExamInvigilateUserQueryWrapper = new QueryWrapper<>();
            tbExamInvigilateUserQueryWrapper.lambda().eq(TBExamInvigilateUser::getOrgId, teExam.getOrgId()).eq(TBExamInvigilateUser::getExamId, examId);
            List<TBExamInvigilateUser> tbExamInvigilateUserList = tbExamInvigilateUserService.list(tbExamInvigilateUserQueryWrapper);
            if (Objects.nonNull(tbExamInvigilateUserList) && tbExamInvigilateUserList.size() > 0) {
                Map<String, TBExamInvigilateUser> tbExamInvigilateUserMap = tbExamInvigilateUserList.stream()
                        .collect(Collectors.toMap(TBExamInvigilateUser::getRoomCode, Function.identity(), (dto1, dto2) -> dto1));
                transMap.put("tbExamInvigilateUserMap", tbExamInvigilateUserMap);
            }
            transMap.put("remark", tbAttachment.getRemark());
            // mq发送消息start
            MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_STUDENT_IMPORT.name(), transMap,
                    MqTagEnum.EXAM_STUDENT_IMPORT, String.valueOf(tbTaskHistory.getId()), tbUser.getName());
            mqDtoService.assembleSendOneWayMsg(mqDto);
            // mq发送消息end
        } catch (Exception e) {
            log.error("请求出错", e);
            if (Objects.nonNull(tbAttachment)) {
                tbAttachmentService.deleteAttachment(mapParameter, tbAttachment);
            }
            if (e instanceof BusinessException) {
                throw new BusinessException(e.getMessage());
            } else {
                throw new RuntimeException(e);
            }
        }
        Map map = new HashMap();
        map.put(SystemConstant.TASK_ID, tbTaskHistory.getId());
        return ResultUtil.ok(map);
    }
}
