package com.qmth.jkserver.controller.system;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.jkserver.common.Constants;
import com.qmth.jkserver.constant.SystemConstant;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.dao.AttachmentDao;
import com.qmth.jkserver.dto.ExamPlanDto;
import com.qmth.jkserver.dto.ExamStudentDto;
import com.qmth.jkserver.dto.FaceVerify;
import com.qmth.jkserver.dto.excel.ExamStudentExportDto;
import com.qmth.jkserver.enums.*;
import com.qmth.jkserver.model.*;
import com.qmth.jkserver.service.*;
import com.qmth.jkserver.util.ExcelUtil;
import com.qmth.jkserver.util.ServletUtil;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/system/examPlan")
public class ExamPlanController extends BaseSystemController {

    private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(ExamPlanController.class);

    @Resource
    @Lazy
    JkExamPlanService examPlanService;

    @Resource
    @Lazy
    private KWService kWService;

//    @Autowired
//    private MongoTemplate mongoTemplate;

    @Resource
    private AttachmentDao attachmentDao;

    @Resource
    @Lazy
    private ExamStudentService examStudentService;

    @Resource
    AttachmentService attachmentService;

    @Resource
    JkExamRoomAddressService jkExamRoomAddressService;

    //创建考试识别码
    @RequestMapping(value = "/createExamCode", method = RequestMethod.POST)
    public Object getNotUsedExamCode() {
        return examPlanService.createExamCode();
    }

    @RequestMapping(value = "/addExamPlan", method = RequestMethod.POST)
    public Object add(HttpServletRequest request, ExamPlanDto examPlanDto) throws Exception {
        User user = super.getCachedUser(request);
        examPlanDto.setCreator(user);
        return examPlanService.save(examPlanDto);
    }

    @RequestMapping(value = "/findById", method = RequestMethod.POST)
    public Object findOne(String id) {
        ExamPlan examPlan = examPlanService.findById(Long.parseLong(id));
        ExamPlanDto examPlanDto = new ExamPlanDto();
        examPlanDto.setId(SystemConstant.getDbUuid());
        examPlanDto.setExamCode(examPlan.getExamCode());
        examPlanDto.setExamType(examPlan.getExamType());
        examPlanDto.setExamStatus(examPlan.getExamStatus());
        examPlanDto.setName(examPlan.getName());
        examPlanDto.setSimulation(examPlan.getSimulation());
        examPlanDto.setPaperRule(examPlan.getPaperRule());
        examPlanDto.setLoginRule(examPlan.getLoginRule());
        examPlanDto.setClientTheme(examPlan.getClientTheme());
        examPlanDto.setOpenMonitor(examPlan.getOpenMonitor());
//        examPlanDto.setFaceVerify(examPlan.getFaceVerify() == null ? new FaceVerify() : examPlan.getFaceVerify());
        FaceVerify faceVerify = new FaceVerify();
        if (examPlan.getFaceVerifyOpen() != null) {
            faceVerify.setOpen(examPlan.getFaceVerifyOpen());
        }
        if (examPlan.getFaceVerifyIntervalTime() != null) {
            faceVerify.setIntervalTime(examPlan.getFaceVerifyIntervalTime());
        }
        examPlanDto.setFaceVerify(faceVerify);
        examPlanDto.setSceneScore(examPlan.getSceneScore());
        KwFile kwFile = kWService.findKwFileByExamCode(examPlan.getExamCode());
        if (kwFile != null) {
//            examPlanDto.setKcFileName(kwFile.getRoomFile().getName());
//            examPlanDto.setKcFileId(kwFile.getRoomFileTemp().getId());
//            examPlanDto.setKwZipFileName(kwFile.getStudentFile().getName());
//            examPlanDto.setKwZipFileId(kwFile.getStudentFileTemp().getId());
//            examPlanDto.setPaperFileName(kwFile.getPaperFile().getName());
//            examPlanDto.setPaperFileId(kwFile.getPaperFileTemp().getId());
            Attachment attachment = attachmentService.getById(kwFile.getRoomFileId());
            examPlanDto.setKcFileName(attachment.getName());
            examPlanDto.setKcFileId(kwFile.getRoomFileTempId());
            attachment = attachmentService.getById(kwFile.getStudentFileId());
            examPlanDto.setKwZipFileName(attachment.getName());
            examPlanDto.setKwZipFileId(kwFile.getStudentFileTempId());
            attachment = attachmentService.getById(kwFile.getPaperFileId());
            examPlanDto.setPaperFileName(attachment.getName());
            examPlanDto.setPaperFileId(kwFile.getPaperFileTempId());
//            if (kwFile.getStudentAdditionalFile() != null) {
//                examPlanDto.setAdditionalFileName(kwFile.getStudentAdditionalFile().getName());
//                examPlanDto.setAdditionalFileId(kwFile.getStudentAdditionalFileTemp().getId());
//            }
            if (kwFile.getStudentAdditionalFileId() != null) {
                attachment = attachmentService.getById(kwFile.getStudentAdditionalFileId());
                examPlanDto.setAdditionalFileName(attachment.getName());
                examPlanDto.setAdditionalFileId(kwFile.getStudentAdditionalFileTempId());
            }
//            if (kwFile.getSceneScoreFile() != null) {
//                examPlanDto.setSceneScoreFileId(kwFile.getSceneScoreFileTemp().getId());
//                examPlanDto.setSceneScoreFileName(kwFile.getSceneScoreFile().getName());
//            }
            if (kwFile.getSceneScoreFileId() != null) {
                attachment = attachmentService.getById(kwFile.getSceneScoreFileId());
                examPlanDto.setSceneScoreFileId(kwFile.getSceneScoreFileTempId());
                examPlanDto.setSceneScoreFileName(attachment.getName());
            }
        }
        if (examPlan.getOpenMonitor().equals(OpenMonitor.YES)) {
//            Query query = new Query();
//            query.addCriteria(Criteria.where("examCode").is(examPlan.getExamCode()));
//            query.limit(1);
//            List<ExamRoomAddress> examRooms = mongoTemplate.find(query, ExamRoomAddress.class);
            QueryWrapper<ExamRoomAddress> examRoomAddressQueryWrapper = new QueryWrapper<>();
            examRoomAddressQueryWrapper.lambda().eq(ExamRoomAddress::getExamCode, examPlan.getExamCode())
                    .last(" limit 1 ");
            List<ExamRoomAddress> examRooms = jkExamRoomAddressService.list(examRoomAddressQueryWrapper);
            Long attachmentId = examRooms.get(0).getAttachmentId();
            examPlanDto.setRoomMonitorFileId(attachmentId);
            Attachment attachment = attachmentDao.findById(attachmentId);
            examPlanDto.setRoomMonitorFileName(attachment.getOriginalName());
        }
        return examPlanDto;
    }

    @RequestMapping(value = "/updateExamPlanStatus", method = RequestMethod.POST)
    public Object updateExamPlanStatus(String id, ExamStatus status) throws Exception {
        examPlanService.updateStatus(id, status);
        return true;
    }


    @RequestMapping(value = "/updateExamPlan", method = RequestMethod.POST)
    public Object updateExamPlan(ExamPlanDto examPlanDto) throws Exception {
        return examPlanService.update(examPlanDto);
    }

    @RequestMapping(value = "/pageQuery", method = RequestMethod.POST)
    public Object findAll(
            HttpServletRequest request,
            @RequestParam(required = false) String examType,
            @RequestParam(required = false) String examStatus,
            @RequestParam(required = false) Date startTime,
            @RequestParam(required = false) Date endTime,
            @RequestParam(required = false) String name,
            @RequestParam(required = false) Integer pageNo,
            @RequestParam(required = false) Integer pageSize
    ) throws ParseException, IOException {
        LOGGER.info("..........Examplan PageQuery Method......");
        pageNo = pageNo == null ? 1 : pageNo;
        pageSize = pageSize == null ? Constants.DEFAULT_PAGE_SIZE : pageSize;
        ExamPlanDto examPlanDto = new ExamPlanDto();
        if (StringUtils.isNotEmpty(examType)) {
            examPlanDto.setExamType(ExamType.valueOf(examType));
        }
        if (StringUtils.isNotEmpty(examStatus)) {
            examPlanDto.setExamStatus(ExamStatus.valueOf(examStatus));
        }
        if (StringUtils.isNotEmpty(name)) {
            examPlanDto.setName(name);
        }
        if (Objects.nonNull(startTime)) {
            examPlanDto.setStartTime(startTime.getTime());
        }
        if (Objects.nonNull(endTime)) {
            examPlanDto.setEndTime(endTime.getTime());
        }
        User user = super.getCachedUser(request);
        examPlanDto.setCreator(user);
        Long schoolId = (Long) ServletUtil.getRequestHeaderSchoolId();
        examPlanDto.setSchoolId(schoolId);
        long time1 = System.currentTimeMillis();
        Page<ExamPlan> pages = examPlanService.findAll(examPlanDto, pageNo, pageSize);
        long time2 = System.currentTimeMillis();
        LOGGER.info("--pageQuery examplan use:" + (time2 - time1) / 1000 + "s");
        return pages;
    }

    @RequestMapping(value = "/studentPageQuery", method = RequestMethod.POST)
    public Object findStudents(
            @RequestParam(required = true) String examCode,
            @RequestParam(required = true) String attachmentId,
            @RequestParam(required = false) String batchId,
            @RequestParam(required = false) String stageId,
            @RequestParam(required = false) String placeCode,
            @RequestParam(required = false) String roomCode,
            @RequestParam(required = false) String courseCode,
            @RequestParam(required = false) String queryKey,
            @RequestParam(required = false) Integer pageNo,
            @RequestParam(required = false) Integer pageSize
    ) {
        pageNo = pageNo == null ? 1 : pageNo;
        pageSize = pageSize == null ? Constants.DEFAULT_PAGE_SIZE : pageSize;
        ExamStudentDto examStudentDto = new ExamStudentDto();
        examStudentDto.setExamCode(examCode);
        examStudentDto.setAttachmentId(Long.parseLong(attachmentId));
        examStudentDto.setBatchId(batchId);
        examStudentDto.setStageId(stageId);
        examStudentDto.setPlaceCode(placeCode);
        examStudentDto.setRoomCode(roomCode);
        examStudentDto.setCourseCode(courseCode);
        examStudentDto.setQuerykey(queryKey);
        return examPlanService.queryExamStudetnsByPages(examStudentDto, pageNo, pageSize);
    }

    @RequestMapping(value = "/roomPageQuery", method = RequestMethod.POST)
    public Object findStudents(
            @RequestParam(required = false) String placeCode,
            @RequestParam(required = true) String examCode,
            @RequestParam(required = true) String attachmentId,
            @RequestParam(required = false) Integer pageNo,
            @RequestParam(required = false) Integer pageSize
    ) {
        pageNo = pageNo == null ? 1 : pageNo;
        pageSize = pageSize == null ? Constants.DEFAULT_PAGE_SIZE : pageSize;
        ExamRoomTemp examRoomTemp = new ExamRoomTemp();
        examRoomTemp.setAttachmentId(Long.parseLong(attachmentId));
        examRoomTemp.setExamCode(examCode);
        examRoomTemp.setPlaceCode(placeCode);
        return examPlanService.queryExamRoomsByPages(examRoomTemp, pageNo, pageSize);
    }

    @RequestMapping(value = "/deleteExamPlan", method = RequestMethod.POST)
    public Object updateExamStatus(String id) {
        ExamPlan examPlan = examPlanService.findById(Long.parseLong(id));
        if (ExamStatus.PUBLISHED.equals(examPlan.getExamStatus())) {
            throw new JkServerException("考试任务已经发布，不允许删除");
        }
        if (examPlan.getStartTime().compareTo(System.currentTimeMillis()) < 0) {
            throw new JkServerException("已经过了考试任务的开始时间,不允许删除");
        }
        examPlanService.deleteById(Long.parseLong(id));
        return true;
    }

    //数据导入--查看考生页面--  课程下拉
    @RequestMapping(value = "/findAllCourse", method = RequestMethod.POST)
    public Object findAllCourse(@RequestParam(required = true) String examCode, @RequestParam(required = true) ExamType examType, @RequestParam(required = true) String attachmentId) {
        return examPlanService.distinctCourseCodeStudentTemp(examCode, Long.parseLong(attachmentId), examType);
    }

    //数据导入--查看考生页面-- 批次下拉
    @RequestMapping(value = "/findAllBatch", method = RequestMethod.POST)
    public Object findAllBatch(@RequestParam(required = true) String examCode,
                               @RequestParam(required = true) ExamType examType, @RequestParam(required = true) String attachmentId) {
        return examPlanService.distinctBatchIdStudentTemp(examCode, Long.parseLong(attachmentId), examType);
    }

    //数据导入--查看考生页面-- 场次下拉
    @RequestMapping(value = "/findAllStage", method = RequestMethod.POST)
    public Object findAllStage(@RequestParam(required = true) String examCode, @RequestParam(required = true) ExamType examType, @RequestParam(required = true) String attachmentId, @RequestParam(required = false) String batchId) {
        return examPlanService.distinctStageIdStudentTemp(examCode, Long.parseLong(attachmentId), batchId, examType);
    }

    @RequestMapping(value = "/batchDeleteExamPlan", method = RequestMethod.POST)
    public Object batchDeleteExamPlan(String ids) {
        String[] idList = StringUtils.split(ids, ",");
        Set<String> idSet = new HashSet<>();
        if (idList.length > 0) {
            for (String id : idList) {
                ExamPlan examPlan = examPlanService.findById(Long.parseLong(id));
                if (ExamStatus.PUBLISHED.equals(examPlan.getExamStatus())) {
                    throw new JkServerException("考试任务:" + examPlan.getName() + " 已经发布，不允许删除");
                }
                if (examPlan.getStartTime().compareTo(System.currentTimeMillis()) < 0) {
                    throw new JkServerException("考试任务:" + examPlan.getName() + " 已经过了开始时间,不允许删除");
                }
                idSet.add(id);
            }
            for (String id : idSet) {
                examPlanService.deleteById(Long.parseLong(id));
            }
        }
        return true;
    }

    @RequestMapping(value = "/findAllPlace", method = RequestMethod.POST)
    public Object findAllPlace(String examCode, String attachmentId) {
        return examPlanService.distinctPlaceCodeExamRoomTemp(examCode, Long.parseLong(attachmentId));
    }

    @RequestMapping(value = "/findAllRoom", method = RequestMethod.POST)
    public Object findAllRoom(String examCode, String attachmentId) {
        return examPlanService.distinctRoomCodeExamRoomTemp(examCode, Long.parseLong(attachmentId));
    }

    @RequestMapping(value = "/findPlace", method = RequestMethod.POST)
    public Object findPlace(String examCode) {
        return examPlanService.distinctPlaceCodeExamStudentTemp(examCode);
    }

    @RequestMapping(value = "/findBatch", method = RequestMethod.POST)
    public Object findBatch(@RequestParam(required = true) String examCode) {
        return examPlanService.distinctBatchExamStudent(examCode);
    }

    @RequestMapping(value = "/findLoginRule", method = RequestMethod.POST)
    public Object findLoginRule(@RequestParam(required = true) String examCode) {
        return ExamLoginRule.toList();
    }

    @RequestMapping(value = "/findPaperRule", method = RequestMethod.POST)
    public Object findPaperRule(@RequestParam(required = true) String examCode) {
        return ExamPaperRule.toList();
    }

    @RequestMapping(value = "/findClientTheme", method = RequestMethod.POST)
    public Object findClientTheme(@RequestParam(required = true) String examCode) {
        return ExamClientTheme.toList();
    }

    @RequestMapping(value = "/findRoom", method = RequestMethod.POST)
    public Object findRoom(@RequestParam(required = true) String examCode,
                           @RequestParam(required = false) String placeCode) {
        return examPlanService.distinctRoomCodeExamStudentTemp(examCode, placeCode);
    }

    @ApiOperation(value = "考生数据导出")
    @RequestMapping(value = "/exam_student_export", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
    public void exportExamStudentInfo(@ApiParam(value = "考试识别码", required = true) @RequestParam String examCode) throws Exception {
        ExamPlan examPlan = examPlanService.findByExamCode(examCode);
        String examStartTime = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(examPlan.getStartTime());
        String examEndTime = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(examPlan.getEndTime());
        List<ExamStudent> examStudentList = examStudentService.findExamStudentByQuery(examCode, null, null, null, null, null, null, null, null);
        List<ExamStudentExportDto> examStudentExportDtoList = examStudentList.stream().map(e -> {
            ExamStudentExportDto cell = new ExamStudentExportDto();
            cell.setExamCode(e.getExamCode());
            cell.setBatchId(e.getBatchId());
            cell.setStageId(e.getStageId());
            cell.setPlaceCode(e.getPlaceCode());
            cell.setRoomCode(e.getRoomCode());
            cell.setTicketNo(e.getTicketNo());
            cell.setIdCard(e.getIdcard());
            cell.setStudentName(e.getName());
            cell.setCourseCode(e.getCourseCode());
            cell.setCourseName(e.getCourseName());
            cell.setExamStartTime(examStartTime);
            cell.setExamEndTime(examEndTime);
            return cell;
        }).collect(Collectors.toList());

        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        ExcelUtil.excelExport("考生列表", ExamStudentExportDto.class, examStudentExportDtoList, servletRequestAttributes.getResponse());
    }
}
