package com.qmth.themis.admin.api;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.constant.SystemConstant;
import com.qmth.themis.business.dto.InvigilateUserExportDto;
import com.qmth.themis.business.dto.MqDto;
import com.qmth.themis.business.dto.response.TBExamInvigilateUserDto;
import com.qmth.themis.business.entity.*;
import com.qmth.themis.business.enums.*;
import com.qmth.themis.business.excel.ExportUtils;
import com.qmth.themis.business.service.MqDtoService;
import com.qmth.themis.business.service.TBAttachmentService;
import com.qmth.themis.business.service.TBExamInvigilateUserService;
import com.qmth.themis.business.service.TBTaskHistoryService;
import com.qmth.themis.business.util.JacksonUtil;
import com.qmth.themis.business.util.MqUtil;
import com.qmth.themis.business.util.OssUtil;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 监考员设置 前端控制器
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/6/25
 */
@Api(tags = "监考员设置Controller")
@RestController
@RequestMapping(SystemConstant.PREFIX_URL_ADMIN + "/invigilateUser")
@Validated
public class TBExamInvigilateUserController {

    private final static Logger log = LoggerFactory.getLogger(TBExamInvigilateUserController.class);

    @Resource
    TBExamInvigilateUserService tbExamInvigilateUserService;

    @Resource
    MqDtoService mqDtoService;

    @Resource
    TBTaskHistoryService taskHistoryService;

    @Resource
    TBAttachmentService tbAttachmentService;

    @Resource
    OssUtil ossUtil;

    @Resource
    MqUtil mqUtil;

    @ApiOperation(value = "监考员查询接口")
    @RequestMapping(value = "/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "监考员信息", response = TBExamInvigilateUserDto.class)})
    public Result query(@ApiParam(value = "考试批次id", required = true) @RequestParam Long examId,
                        @ApiParam(value = "考场代码", required = false) @RequestParam(required = false) String roomCode,
                        @ApiParam(value = "用户id", required = false) @RequestParam(required = false) Long userId,
                        @ApiParam(value = "分页页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) int pageNumber,
                        @ApiParam(value = "分页数", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) int pageSize) {
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        return ResultUtil.ok(tbExamInvigilateUserService
                .examInvigilateUserQuery(new Page<>(pageNumber, pageSize), examId, roomCode, userId,
                        tbUser.getOrgId()));
    }

    @ApiOperation(value = "监考员修改接口")
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    @Transactional
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    public Result save(@ApiJsonObject(name = "saveInvigilateUser", value = {
            @ApiJsonProperty(key = "examId", type = "long", example = "1", description = "考试批次id", required = true),
            @ApiJsonProperty(key = "roomCode", description = "考场代码"),
            @ApiJsonProperty(key = "userIds", description = "用户id")}) @ApiParam(value = "监考员信息", required = true) @RequestBody Map<String, Object> mapParameter) {
        String roomCode = null;
        try {
            if (Objects.isNull(mapParameter.get(SystemConstant.EXAM_ID)) || Objects.equals(mapParameter.get(SystemConstant.EXAM_ID), "")) {
                throw new BusinessException(ExceptionResultEnum.EXAM_ID_IS_NULL);
            }
            Long examId = Long.parseLong(String.valueOf(mapParameter.get(SystemConstant.EXAM_ID)));
            if (Objects.isNull(mapParameter.get(SystemConstant.ROOM_CODE)) || Objects.equals(mapParameter.get(SystemConstant.ROOM_CODE), "")) {
                throw new BusinessException(ExceptionResultEnum.ROOMCODE_IS_NULL);
            }
            roomCode = String.valueOf(mapParameter.get(SystemConstant.ROOM_CODE));
            if (Objects.isNull(mapParameter.get("userIds")) || Objects.equals(mapParameter.get("userIds"), "")) {
                throw new BusinessException(ExceptionResultEnum.USER_ID_IS_NULL);
            }
            List<String> userIds = (List) mapParameter.get("userIds");
            if (userIds.size() > 3) {
                throw new BusinessException(ExceptionResultEnum.ERROR.getStatusCode(),
                        ExceptionResultEnum.ERROR.getCode(), "一个考场最多设置3名监考员");
            }
            TBOrg tbOrg = (TBOrg) ServletUtil.getRequestOrg();
            QueryWrapper<TBExamInvigilateUser> tbExamInvigilateUserQueryWrapper = new QueryWrapper<>();
            tbExamInvigilateUserQueryWrapper.lambda().eq(TBExamInvigilateUser::getRoomCode, roomCode)
                    .eq(TBExamInvigilateUser::getExamId, examId);
            if (Objects.nonNull(tbOrg) && Objects.isNull(tbOrg.getId())) {
                throw new BusinessException("监考员机构id不允许为空");
            }
            List<TBExamInvigilateUser> tbExamInvigilateUserList = tbExamInvigilateUserService
                    .list(tbExamInvigilateUserQueryWrapper);
            List<String> roomNameList = tbExamInvigilateUserList.stream().map(s -> s.getRoomName())
                    .collect(Collectors.toList());
            Long orgId = tbOrg.getId();
            tbExamInvigilateUserService.remove(tbExamInvigilateUserQueryWrapper);
            tbExamInvigilateUserList = new ArrayList<>();
            if (userIds.size() > 0) {
                for (int i = 0; i < userIds.size(); i++) {
                    TBExamInvigilateUser tbExamInvigilateUser = new TBExamInvigilateUser(examId, orgId,
                            Long.parseLong(userIds.get(i)), roomCode, roomNameList.get(0));
                    tbExamInvigilateUserList.add(tbExamInvigilateUser);
                }
            } else {
                TBExamInvigilateUser tbExamInvigilateUser = new TBExamInvigilateUser(examId, orgId,
                        null, roomCode, roomNameList.get(0));
                tbExamInvigilateUserList.add(tbExamInvigilateUser);
            }
            tbExamInvigilateUserService.saveBatch(tbExamInvigilateUserList);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length())
                        .replaceAll("'", "");
                throw new BusinessException(
                        "考场代码[" + roomCode + "]下的" + FieldUniqueEnum.convertToCode(columnStr) + "数据不允许重复插入");
            } else if (e instanceof BusinessException) {
                throw new BusinessException(e.getMessage());
            } else {
                throw new RuntimeException(e);
            }
        }
        return ResultUtil.ok(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) {
        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 = ossUtil.getAliYunOssPrivateDomain().getMap();
        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,
                            UploadFileEnum.file, tbUser.getOrgId(), tbUser.getId());
            if (Objects.isNull(tbAttachment)) {
                throw new BusinessException(ExceptionResultEnum.ATTACHMENT_ERROR);
            } else {
                //往任务表里插一条数据
                tbTaskHistory = new TBTaskHistory(TaskTypeEnum.IMPORT_INVIGILATE_USER, examId, TaskStatusEnum.INIT,
                        SystemConstant.IMPORT_INIT, 0d, tbAttachment.getName(), tbAttachment.getRemark(),
                        tbUser.getId(), tbUser.getOrgId());
                tbTaskHistory.setExamId(examId);
                taskHistoryService.save(tbTaskHistory);
                transMap.put("tbTaskHistory", tbTaskHistory);
            }
            transMap.put(SystemConstant.EXAM_ID, examId);
            transMap.put(SystemConstant.CREATE_ID, tbUser.getId());
            transMap.put(SystemConstant.ORG_ID, tbUser.getOrgId());
            transMap.put(SystemConstant.REMARK, tbAttachment.getRemark());
            //mq发送消息start
            MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.ROOM_CODE_IMPORT.name(), transMap,
                    MqTagEnum.ROOM_CODE_IMPORT, String.valueOf(tbTaskHistory.getId()), tbUser.getName());
            mqDtoService.assembleSendAsyncMsg(mqDto);
            //mq发送消息end
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (Objects.nonNull(tbAttachment)) {
                tbAttachmentService.deleteAttachment(mapParameter, UploadFileEnum.file, tbAttachment);
            }
            if (e instanceof BusinessException) {
                throw new BusinessException(e.getMessage());
            } else {
                throw new RuntimeException(e);
            }
        }
        return ResultUtil.ok(Collections.singletonMap(SystemConstant.TASK_ID, tbTaskHistory.getId()));
    }

    @ApiOperation(value = "监考员导出接口")
    @RequestMapping(value = "/export", method = RequestMethod.POST)
    @Transactional
    @ApiResponses({@ApiResponse(code = 200, message = "{\"taskId\":0}", response = Result.class)})
    public Result export(@ApiParam(value = "考试批次id", required = true) @RequestParam(required = false) Long examId,
                         @ApiParam(value = "考场代码", required = false) @RequestParam(required = false) String roomCode,
                         @ApiParam(value = "用户id", required = false) @RequestParam(required = false) Long userId) {
        TBTaskHistory tbTaskHistory = null;
        try {
            int count = tbExamInvigilateUserService.count();
            if (count > 0) {
                Map transMap = new HashMap();
                TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
                //往任务表里插一条数据
                tbTaskHistory = new TBTaskHistory(TaskTypeEnum.EXPORT_INVIGILATE_USER, TaskStatusEnum.INIT,
                        SystemConstant.EXPORT_INIT, 0d, tbUser.getId(), tbUser.getOrgId());
                tbTaskHistory.setExamId(examId);
                taskHistoryService.save(tbTaskHistory);
                transMap.put("tbTaskHistory", tbTaskHistory);
                transMap.put(SystemConstant.CREATE_ID, tbUser.getId());
                transMap.put(SystemConstant.ORG_ID, tbUser.getOrgId());
                transMap.put(SystemConstant.EXAM_ID, examId);
                transMap.put(SystemConstant.ROOM_CODE, roomCode);
                transMap.put(SystemConstant.USER_ID, userId);
                //mq发送消息start
                MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.ROOM_CODE_EXPORT.name(), transMap,
                        MqTagEnum.ROOM_CODE_EXPORT, String.valueOf(tbTaskHistory.getId()), tbUser.getName());
                mqDtoService.assembleSendAsyncMsg(mqDto);
                //mq发送消息end
            } else {
                return ResultUtil.ok(true);
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof BusinessException) {
                throw new BusinessException(e.getMessage());
            } else {
                throw new RuntimeException(e);
            }
        }
        return ResultUtil.ok(Collections.singletonMap(SystemConstant.TASK_ID, tbTaskHistory.getId()));
    }

    @ApiOperation(value = "监考员登录登出时间查询接口")
    @RequestMapping(value = "/login/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "监考员信息", response = TBExamInvigilateUserDto.class)})
    public void loginQuery(@ApiParam(value = "考试批次id", required = true) @RequestParam Long examId) throws Exception {
        List<InvigilateUserExportDto> invigilateUserExportDtoList = tbExamInvigilateUserService.examInvigilateUserLoginTimeExport(examId);
        if (!CollectionUtils.isEmpty(invigilateUserExportDtoList)) {
            List<InvigilateUserExportDto> invigilateUserExportDtoListTemp = new ArrayList<>(invigilateUserExportDtoList.size());
            for (InvigilateUserExportDto i : invigilateUserExportDtoList) {
                if (Objects.nonNull(i.getType()) && Objects.equals(i.getType(), "LOGIN")) {
                    i.setLoginTime(i.getCreateTime());
                    invigilateUserExportDtoListTemp.add(i);
                } else if (Objects.nonNull(i.getType()) && Objects.equals(i.getType(), "LOGOUT")) {
                    if (!CollectionUtils.isEmpty(invigilateUserExportDtoListTemp)) {
                        InvigilateUserExportDto invigilateUserExportDto = invigilateUserExportDtoListTemp.get(invigilateUserExportDtoListTemp.size() - 1);
                        invigilateUserExportDto.setLogoutTime(i.getCreateTime());
                    } else {
                        log.error("数据有误，没有登录时间:{}", JacksonUtil.parseJson(i));
                    }
                }
            }
            ExportUtils.exportEXCEL("监考员登录时间", InvigilateUserExportDto.class, invigilateUserExportDtoListTemp, ServletUtil.getResponse());
        }
    }
}
