package com.qmth.themis.admin.api;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qmth.themis.business.bean.admin.ExamInfoBean;
import com.qmth.themis.business.bean.admin.InvigilateListWarningBean;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.AuthDto;
import com.qmth.themis.business.dto.params.WarnInfoParams;
import com.qmth.themis.business.dto.response.TIeWarningNotifyDto;
import com.qmth.themis.business.entity.*;
import com.qmth.themis.business.enums.RoleEnum;
import com.qmth.themis.business.service.*;
import com.qmth.themis.business.util.ServletUtil;
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.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

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 + "/invigilate/warn")
@Validated
public class TIeInvigilateWarnInfoController {

    @Resource
    TIeInvigilateWarnInfoService tIeInvigilateWarnInfoService;

    @Resource
    TOeExamRecordService tOeExamRecordService;

    @Resource
    ThemisCacheService themisCacheService;

    @Resource
    TBExamInvigilateUserService tbExamInvigilateUserService;

    @Resource
    TEExamActivityService teExamActivityService;

    @Resource
    TEExamStudentService teExamStudentService;

    @Resource
    TEExamSummaryService teExamSummaryService;

    @ApiOperation(value = "预警提醒接口")
    @RequestMapping(value = "/notify", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"count\":1}", response = Result.class)})
//    @RedisLimitAnnotation(key = "warnNotify", period = 1, count = 1)
    public Result notify(@ApiParam(value = "考试批次id", required = false) @RequestParam(required = false) Long examId,
                         @ApiParam(value = "考试场次id", required = false) @RequestParam(required = false) Long examActivityId,
                         @ApiParam(value = "虚拟考场代码", required = false) @RequestParam(required = false) String roomCode) {
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        AuthDto authDto = themisCacheService.addAccountAuthCache(tbUser.getId());
        //如果有监考员角色，只能查看自己所监考的考场，巡考员和管理员则可以查看全部考场
        Integer count = null;
        Long userId = null;
        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name())) {
            userId = tbUser.getId();
            List<TBExamInvigilateUser> tbExamInvigilateUserList = tbExamInvigilateUserService.list(new QueryWrapper<TBExamInvigilateUser>().lambda()
                    .eq(TBExamInvigilateUser::getOrgId, tbUser.getOrgId())
                    .eq(TBExamInvigilateUser::getUserId, userId));
            if (!CollectionUtils.isEmpty(tbExamInvigilateUserList)) {
                List<TEExamSummary> teExamSummaryAllList = new ArrayList<>();
                for (TBExamInvigilateUser t : tbExamInvigilateUserList) {
                    List<TEExamActivity> teExamActivityList = teExamActivityService.list(new QueryWrapper<TEExamActivity>().lambda().eq(TEExamActivity::getExamId, t.getExamId()));
                    for (TEExamActivity teExamActivity : teExamActivityList) {
                        teExamSummaryAllList.addAll(themisCacheService.getExamSummaryCache(t.getExamId(), teExamActivity.getId(), t.getRoomCode()));
                    }
                }
                count = teExamSummaryAllList.stream().mapToInt(s -> s.getWarningUnread()).sum();
            }
        } else {
            //取当前用户机构id所属考试id集合
            List<ExamInfoBean> examInfoBeanList = teExamStudentService.getExamInfo(tbUser.getOrgId());
            if (!CollectionUtils.isEmpty(examInfoBeanList)) {
                List<TEExamSummary> teExamSummaryAllList = new ArrayList<>();
                for (ExamInfoBean t : examInfoBeanList) {
                    if (Objects.nonNull(t.getRoomCodes())) {
                        Set<String> roomCodeSet = new HashSet<>(Arrays.asList(t.getRoomCodes().split(", ")));
                        for (String s : roomCodeSet) {
                            teExamSummaryAllList.addAll(themisCacheService.getExamSummaryCache(t.getExamId(), t.getExamActivityId(), s));
                        }
                    }
                }
                count = teExamSummaryAllList.stream().mapToInt(s -> s.getWarningUnread()).sum();
            }
        }
        return ResultUtil.ok(Collections.singletonMap(SystemConstant.COUNT, Objects.isNull(count) ? 0 : count));
    }

    @ApiOperation(value = "预警提醒列表接口")
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "监考预警信息", response = InvigilateListWarningBean.class)})
    public Result list(@ApiParam(value = "考试批次id", required = false) @RequestParam(required = false) Long examId,
                       @ApiParam(value = "考试场次id", required = false) @RequestParam(required = false) Long examActivityId,
                       @ApiParam(value = "虚拟考场代码", required = false) @RequestParam(required = false) String roomCode,
                       @ApiParam(value = "审阅状态", required = false) @RequestParam(required = false) Integer approveStatus,
                       @ApiParam(value = "姓名", required = false) @RequestParam(required = false) String name,
                       @ApiParam(value = "证件号", required = false) @RequestParam(required = false) String identity,
                       @ApiParam(value = "陌生人脸min", required = false) @RequestParam(required = false) Integer minMultipleFaceCount,
                       @ApiParam(value = "陌生人脸max", required = false) @RequestParam(required = false) Integer maxMultipleFaceCount,
                       @ApiParam(value = "异常处理min", required = false) @RequestParam(required = false) Integer minExceptionCount,
                       @ApiParam(value = "异常处理max", required = false) @RequestParam(required = false) Integer maxExceptionCount,
                       @ApiParam(value = "预警量min", required = false) @RequestParam(required = false) Integer minWarningCount,
                       @ApiParam(value = "预警量max", required = false) @RequestParam(required = false) Integer maxWarningCount,
                       @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();
        AuthDto authDto = themisCacheService.addAccountAuthCache(tbUser.getId());
        //如果有监考员角色，只能查看自己所监考的考场，巡考员和管理员则可以查看全部考场
        Long userId = null;
        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name())) {
            userId = tbUser.getId();
        }
        return ResultUtil.ok(tOeExamRecordService.invigilatePageWarningList(new Page<>(pageNumber, pageSize), examId, examActivityId, roomCode, approveStatus, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount, maxExceptionCount, minWarningCount, maxWarningCount, userId, tbUser.getOrgId()));
    }

    @ApiOperation(value = "预警消息接口")
    @RequestMapping(value = "/message", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "预警通知信息", response = TIeWarningNotifyDto.class)})
//    @RedisLimitAnnotation(key = "warnMessage", period = 1, count = 1)
    public Result warningMessage(@ApiParam(value = "考试批次id", required = false) @RequestParam(required = false) Long examId) {
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        AuthDto authDto = themisCacheService.addAccountAuthCache(tbUser.getId());
        //如果有监考员角色，只能查看自己所监考的考场，巡考员和管理员则可以查看全部考场
        Long userId = null;
        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name())) {
            userId = tbUser.getId();
        }
        return ResultUtil.ok(tIeInvigilateWarnInfoService.warningMessage(examId, userId, tbUser.getOrgId()));
    }

    @ApiOperation(value = "预警修改阅读状态接口")
    @RequestMapping(value = "/save/status", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @Transactional
    public Result saveWarnStatus(@Validated @RequestBody WarnInfoParams warnInfoParams, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultUtil.error(bindingResult.getAllErrors().get(0).getDefaultMessage());
        }
        //2020/11/24新增管理员不清除预警状态
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        AuthDto authDto = themisCacheService.addAccountAuthCache(tbUser.getId());
        if (!authDto.getRoleCodes().toString().contains(RoleEnum.ADMIN.name())) {
            if (CollectionUtils.isEmpty(warnInfoParams.getWarningIds()) && Objects.isNull(warnInfoParams.getExamRecordId())) {
                throw new BusinessException("预警id数组或考试记录id不能同时为空");
            }
            UpdateWrapper<TIeInvigilateWarnInfo> tIeInvigilateWarnInfoUpdateWrapper = new UpdateWrapper<>();
            tIeInvigilateWarnInfoUpdateWrapper.lambda().set(TIeInvigilateWarnInfo::getApproveStatus, warnInfoParams.getApproveStatus());
            if (!CollectionUtils.isEmpty(warnInfoParams.getWarningIds())) {
                List<Long> warningTranIds = warnInfoParams.getWarningIds().stream().map(x -> Long.parseLong(x)).collect(Collectors.toList());
                tIeInvigilateWarnInfoUpdateWrapper.lambda().in(TIeInvigilateWarnInfo::getId, warningTranIds);
            } else if (Objects.nonNull(warnInfoParams.getExamRecordId())) {
                tIeInvigilateWarnInfoUpdateWrapper.lambda().eq(TIeInvigilateWarnInfo::getExamRecordId, warnInfoParams.getExamRecordId());
            }
            tIeInvigilateWarnInfoService.update(tIeInvigilateWarnInfoUpdateWrapper);
        }
        return ResultUtil.ok(true);
    }

    @ApiOperation(value = "预警提醒清除未阅列表接口")
    @RequestMapping(value = "/approveStatus/list/update", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "监考预警信息", response = InvigilateListWarningBean.class)})
    public Result approveStatusListUpdate(@ApiParam(value = "考试批次id", required = false) @RequestParam(required = false) Long examId,
                                          @ApiParam(value = "考试场次id", required = false) @RequestParam(required = false) Long examActivityId,
                                          @ApiParam(value = "虚拟考场代码", required = false) @RequestParam(required = false) String roomCode,
                                          @ApiParam(value = "审阅状态", required = false) @RequestParam(required = false) Integer approveStatus,
                                          @ApiParam(value = "姓名", required = false) @RequestParam(required = false) String name,
                                          @ApiParam(value = "证件号", required = false) @RequestParam(required = false) String identity,
                                          @ApiParam(value = "陌生人脸min", required = false) @RequestParam(required = false) Integer minMultipleFaceCount,
                                          @ApiParam(value = "陌生人脸max", required = false) @RequestParam(required = false) Integer maxMultipleFaceCount,
                                          @ApiParam(value = "异常处理min", required = false) @RequestParam(required = false) Integer minExceptionCount,
                                          @ApiParam(value = "异常处理max", required = false) @RequestParam(required = false) Integer maxExceptionCount,
                                          @ApiParam(value = "预警量min", required = false) @RequestParam(required = false) Integer minWarningCount,
                                          @ApiParam(value = "预警量max", required = false) @RequestParam(required = false) Integer maxWarningCount) {
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        AuthDto authDto = themisCacheService.addAccountAuthCache(tbUser.getId());
        //如果有监考员角色，只能查看自己所监考的考场，巡考员和管理员则可以查看全部考场
        Long userId = null;
        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name())) {
            userId = tbUser.getId();
        }
        //2020/11/24新增管理员不清除预警状态
        if (!authDto.getRoleCodes().toString().contains(RoleEnum.ADMIN.name())) {
            List<TOeExamRecord> tOeExamRecordList = tOeExamRecordService.findExamRecordByWarning(examId, examActivityId, roomCode, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount, maxExceptionCount, minWarningCount, maxWarningCount, userId, tbUser.getOrgId());
            for (TOeExamRecord t : tOeExamRecordList) {
                tOeExamRecordService.updateWarningUnreadCache(t.getId(), 0, true);
            }
            if (Objects.nonNull(examId)) {
                QueryWrapper<TEExamStudent> teExamStudentQueryWrapper = new QueryWrapper<>();
                teExamStudentQueryWrapper.lambda().eq(TEExamStudent::getExamId, examId);
                if (Objects.nonNull(examActivityId)) {
                    teExamStudentQueryWrapper.lambda().eq(TEExamStudent::getExamActivityId, examActivityId);
                }
                if (Objects.nonNull(roomCode)) {
                    teExamStudentQueryWrapper.lambda().eq(TEExamStudent::getRoomCode, roomCode);
                }
                List<TEExamStudent> teExamStudentList = teExamStudentService.list(teExamStudentQueryWrapper);
                if (!CollectionUtils.isEmpty(teExamStudentList)) {
                    Set<String> roomCodeSet = teExamStudentList.stream().map(s -> s.getRoomCode()).collect(Collectors.toSet());
                    for (String s : roomCodeSet) {
                        teExamSummaryService.updateExamSummaryWarningUnread(examId, examActivityId, s);
                        themisCacheService.updateExamSummaryCache(examId, examActivityId, s);
                    }
                    themisCacheService.updateExamSummaryCache(examId);
                    themisCacheService.updateExamSummaryCache(examId, examActivityId);
                }
            }
            tOeExamRecordService.approveStatusListUpdate(examId, examActivityId, roomCode, approveStatus, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount, maxExceptionCount, minWarningCount, maxWarningCount, userId, tbUser.getOrgId());
        }
        return ResultUtil.ok(true);
    }
}