package com.qmth.jkserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.dao.*;
import com.qmth.jkserver.dto.ExamKjProgressDto;
import com.qmth.jkserver.enums.ExamType;
import com.qmth.jkserver.model.*;
import com.qmth.jkserver.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

/**
 * 汇总统计service
 *
 * @author tianjun
 */
@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
public class ExamKjHZServiceImpl implements ExamKjHZService {

    @Resource
    private ExamPlanDao examPlanDao;

//	@Autowired
//	private MongoTemplate mongoTemplate;

    @Resource
    @Lazy
    private JkExamPlanService examPlanService;

    @Resource
    ExamRoomDao examRoomDao;

    @Resource
    ExamStageDao examStageDao;

    @Resource
    JkExamKjProgressService jkExamKjProgressService;

    @Resource
    JkKjOriginalFileHistoryService jkKjOriginalFileHistoryService;

    @Resource
    JkKjUploadHistoryService jkKjUploadHistoryService;

    @Resource
    JkExamRoomService jkExamRoomService;

    @Resource
    @Lazy
    ExamStudentService examStudentService;

    @Resource
    ExamStudentAnswerDao examStudentAnswerDao;

    @Resource
    JkExamSolfegeRecordDao jkExamSolfegeRecordDao;

    @Resource
    AttachmentService attachmentService;

    private static final DecimalFormat FORMAT = new DecimalFormat("0.00%");

    @Override
    public List<Map<String, Object>> getPlaceByExamCode(String examCode) {
        List<ExamPlan> list = examPlanDao.findByExamCode(examCode);
        if (list.size() == 0) {
            throw new JkServerException("错误的考试识别码:" + examCode);
        }
//		AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
//		TypedAggregation<ExamRoom> aggregation = Aggregation.newAggregation(ExamRoom.class,
//				Aggregation.match(Criteria.where("examCode").is(examCode)),
//				Aggregation.group("placeCode", "placeName").count().as("count"),
//				Aggregation.sort(Direction.ASC, "placeCode"),
//				Aggregation.project("placeCode", "placeName")).withOptions(aggregationOptions);
//		AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamRoom.class, DBObject.class);
//		List<DBObject> results = map.getMappedResults();
//		List<Map<String, Object>> result = new ArrayList<>();
//		for (DBObject object : results) {
//			Map<String, Object> data = new HashMap<>();
//			data.put("name", object.get("placeName"));
//			data.put("value", object.get("placeCode"));
//			result.add(data);
//		}
        List<Map<String, Object>> result = new ArrayList<>();
        List<Map> results = examRoomDao.findPlaceCodeAndPlaceNameAndCount(examCode);
        if (!CollectionUtils.isEmpty(results)) {
            for (Map m : results) {
                Map<String, Object> data = new HashMap<>();
                data.put("name", m.get("placeName"));
                data.put("value", m.get("placeCode"));
                result.add(data);
            }
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getRoomByPlaceCode(String examCode, String placeCode) {
        List<ExamPlan> list = examPlanDao.findByExamCode(examCode);
        if (list.size() == 0) {
            throw new JkServerException("错误的考试识别码:" + examCode);
        }
//        Criteria criteria = Criteria.where("examCode").is(examCode);
//        if (StringUtils.isNotEmpty(placeCode)) {
//            criteria = criteria.and("placeCode").is(placeCode);
//        }
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
//        TypedAggregation<ExamRoom> aggregation = Aggregation.newAggregation(ExamRoom.class,
//                Aggregation.match(criteria),
//                Aggregation.group("roomCode", "roomName").count().as("count"),
//                Aggregation.sort(Direction.ASC, "roomCode"),
//                Aggregation.project("roomCode", "roomName")).withOptions(aggregationOptions);
//        AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamRoom.class, DBObject.class);
//        List<DBObject> results = map.getMappedResults();
//        List<Map<String, Object>> result = new ArrayList<>();
//        for (DBObject object : results) {
//            Map<String, Object> data = new HashMap<>();
//            data.put("name", object.get("roomName"));
//            data.put("value", object.get("roomCode"));
//            result.add(data);
//        }
        List<Map<String, Object>> result = new ArrayList<>();
        List<Map> results = examRoomDao.findRoomCodeAndRoomNameAndCount(examCode);
        if (!CollectionUtils.isEmpty(results)) {
            for (Map m : results) {
                Map<String, Object> data = new HashMap<>();
                data.put("name", m.get("roomName"));
                data.put("value", m.get("roomCode"));
                result.add(data);
            }
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getBatchesByExamCode(String examCode) {
        List<ExamPlan> list = examPlanDao.findByExamCode(examCode);
        if (list.size() == 0) {
            throw new JkServerException("错误的考试识别码:" + examCode);
        }

        ExamPlan examPlan = list.get(0);
//        AggregationOptions aggregationOptions = new AggregationOptions.Builder().allowDiskUse(true).build();
        if (ExamType.NORMAL.equals(examPlan.getExamType()) || ExamType.UTEST.equals(examPlan.getExamType()) ||
                ExamType.SOLFEGE.equals(examPlan.getExamType())) {
//            TypedAggregation<ExamStage> aggregation = Aggregation.newAggregation(ExamStage.class,
//                    Aggregation.match(Criteria.where("examCode").is(examCode)),
//                    Aggregation.group("batchId", "batchName"), Aggregation.sort(Direction.ASC, "batchStartTime")).withOptions(aggregationOptions);
//            AggregationResults<DBObject> map = mongoTemplate.aggregate(aggregation, ExamStage.class, DBObject.class);
//            List<DBObject> results = map.getMappedResults();
//            List<Map<String, Object>> result = new ArrayList<>();
//            for (DBObject object : results) {
//                Map<String, Object> data = new HashMap<>();
//                data.put("name", object.get("batchName"));
//                data.put("value", object.get("batchId"));
//                result.add(data);
//            }
            List<Map<String, Object>> result = new ArrayList<>();
            List<Map> results = examStageDao.findBatchIdAndBatchName(examCode);
            if (!CollectionUtils.isEmpty(results)) {
                for (Map m : results) {
                    Map<String, Object> data = new HashMap<>();
                    data.put("name", m.get("batchName"));
                    data.put("value", m.get("batchId"));
                    result.add(data);
                }
            }
            return result;
        }
        throw new JkServerException("未知的考试任务类型:" + examPlan.getExamType());
    }

    @Override
    public ExamKjProgress findProgress(String examCode, String placeCode, String roomCode) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("placeCode").is(placeCode));
//        query.addCriteria(Criteria.where("roomCode").is(roomCode));
//        List<ExamKjProgress> examKjProgresses = mongoTemplate.find(query, ExamKjProgress.class);
        QueryWrapper<ExamKjProgress> examKjProgressQueryWrapper = new QueryWrapper<>();
        examKjProgressQueryWrapper.lambda().eq(ExamKjProgress::getExamCode, examCode)
                .eq(ExamKjProgress::getPlaceCode, placeCode)
                .eq(ExamKjProgress::getRoomCode, roomCode);
        List<ExamKjProgress> examKjProgresses = jkExamKjProgressService.list(examKjProgressQueryWrapper);
        return examKjProgresses.size() > 0 ? examKjProgresses.get(0) : null;
    }

    @Override
    public ExamKjProgress saveProgress(ExamKjProgress examKjProgress) {
//        return examKjProgressDao.save(examKjProgress);
        jkExamKjProgressService.saveOrUpdate(examKjProgress);
        return examKjProgress;
    }

    @Override
    public Page<ExamKjProgressDto> pageQueryProgress(ExamKjProgressDto examKjProgressDto, Boolean already,
                                                     String placeName, int pageNo, int pageSize) {
        ExamPlan examPlan = examPlanService.findByExamCode(examKjProgressDto.getExamCode());
        if (examPlan == null) {
            throw new JkServerException("错误的考试识别码:" + examKjProgressDto.getExamCode());
        }
//        Query query = new Query();
//        if (StringUtils.isNotEmpty(examKjProgressDto.getExamCode())) {
//            query.addCriteria(Criteria.where("examCode").is(examKjProgressDto.getExamCode()));
//        }
//        if (StringUtils.isNotEmpty(examKjProgressDto.getPlaceCode())) {
//            query.addCriteria(Criteria.where("placeCode").is(examKjProgressDto.getPlaceCode()));
//        }
//        if (StringUtils.isNotEmpty(examKjProgressDto.getRoomCode())) {
//            query.addCriteria(Criteria.where("roomCode").is(examKjProgressDto.getRoomCode()));
//        }
//        if (StringUtils.isNotEmpty(placeName)) {
//            query.addCriteria(Criteria.where("placeName").regex(examKjProgressDto.getPlaceName()));
//        }
//        if (already != null) {
//            query.addCriteria(Criteria.where("kjAlready").is(already.booleanValue()));
//        }
//        long count = mongoTemplate.count(query, ExamRoom.class);
        QueryWrapper<ExamRoom> examRoomQueryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(examKjProgressDto.getExamCode())) {
            examRoomQueryWrapper.lambda().eq(ExamRoom::getExamCode, examKjProgressDto.getExamCode());
        }
        if (StringUtils.isNotEmpty(examKjProgressDto.getPlaceCode())) {
            examRoomQueryWrapper.lambda().eq(ExamRoom::getPlaceCode, examKjProgressDto.getPlaceCode());
        }
        if (StringUtils.isNotEmpty(examKjProgressDto.getRoomCode())) {
            examRoomQueryWrapper.lambda().eq(ExamRoom::getRoomCode, examKjProgressDto.getRoomCode());
        }
        if (StringUtils.isNotEmpty(placeName)) {
            examRoomQueryWrapper.lambda().like(ExamRoom::getPlaceName, placeName);
        }
        if (already != null) {
            examRoomQueryWrapper.lambda().eq(ExamRoom::getKjAlready, already);
        }
//        Long count = Long.valueOf(jkExamRoomService.count(examRoomQueryWrapper));

//        Sort.Order order1 = new Sort.Order(Direction.ASC, "placeCode");
//        Sort.Order order2 = new Sort.Order(Direction.ASC, "roomCode");
//        Sort sort = new Sort(order1, order2);
//        query.with(sort);
//        query.limit(pageSize);
//        query.skip((pageNo - 1) * pageSize);
//        List<ExamRoom> examRooms = mongoTemplate.find(query, ExamRoom.class);
        List<ExamKjProgressDto> results = new ArrayList<ExamKjProgressDto>();
        IPage<ExamRoom> examRoomIPage = examRoomDao.listPage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNo, pageSize), examKjProgressDto.getExamCode()
                , examKjProgressDto.getPlaceCode(), examKjProgressDto.getRoomCode(), placeName, already);
        if (!CollectionUtils.isEmpty(examRoomIPage.getRecords())) {
            for (ExamRoom examRoom : examRoomIPage.getRecords()) {
                ExamKjProgressDto dto = new ExamKjProgressDto();
                dto.setExamCode(examRoom.getExamCode());
                dto.setPlaceCode(examRoom.getPlaceCode());
                dto.setPlaceName(examRoom.getPlaceName());
                dto.setRoomCode(examRoom.getRoomCode());
                dto.setRoomName(examRoom.getRoomName());
                // 查询当前考场的数据包是否上传
                ExamKjProgress examKjProgress = findProgress(examRoom.getExamCode(), examRoom.getPlaceCode(),
                        examRoom.getRoomCode());
                if (examKjProgress != null) {
                    if (Objects.nonNull(examKjProgress.getAttachmentId())) {
                        dto.setAttachmentId(examKjProgress.getAttachmentId());
                        Attachment attachment = attachmentService.getById(examKjProgress.getAttachmentId());
                        dto.setAttachment(attachment);
                    }
                    dto.setTime(examKjProgress.getStartTime());
                    dto.setType(examKjProgress.getType());
                }
                results.add(dto);
            }
        }
        PageImpl<ExamKjProgressDto> pageResult = new PageImpl<ExamKjProgressDto>(results,
                PageRequest.of(pageNo - 1, pageSize), examRoomIPage.getTotal());
        return pageResult;
    }

    @Override
    public KjOriginalFileHistory saveOriginalHistory(KjOriginalFileHistory history) {
//        return kjOriginalFileHistoryDao.save(history);
        jkKjOriginalFileHistoryService.saveOrUpdate(history);
        return history;
    }

    @Override
    public KjUploadHistory saveHistory(KjUploadHistory history) {
//        if (history.getFile() == null) {
//            throw new JkServerException("没有答案数据包实体文件");
//        }
        if (history.getAttachmentId() == null) {
            throw new JkServerException("没有答案数据包实体文件");
        }
        history.setTime(System.currentTimeMillis());
//        return kjUploadHistoryDao.save(history);
        jkKjUploadHistoryService.saveOrUpdate(history);
        return history;
    }

    @Override
    public Page<ExamKjProgressDto> pageQuerySolfegeProgress(ExamKjProgressDto examKjProgressDto, int pageNo,
                                                            int pageSize) {
        ExamPlan examPlan = examPlanService.findByExamCode(examKjProgressDto.getExamCode());
        if (examPlan == null) {
            throw new JkServerException("错误的考试识别码:" + examKjProgressDto.getExamCode());
        }
//        Query query = new Query();
//        if (StringUtils.isNotEmpty(examKjProgressDto.getExamCode())) {
//            query.addCriteria(Criteria.where("examCode").is(examKjProgressDto.getExamCode()));
//        }
//        if (StringUtils.isNotEmpty(examKjProgressDto.getPlaceCode())) {
//            query.addCriteria(Criteria.where("placeCode").is(examKjProgressDto.getPlaceCode()));
//        }
//        if (StringUtils.isNotEmpty(examKjProgressDto.getRoomCode())) {
//            query.addCriteria(Criteria.where("roomCode").is(examKjProgressDto.getRoomCode()));
//        }
//        long count = mongoTemplate.count(query, ExamRoom.class);
        QueryWrapper<ExamRoom> examRoomQueryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(examKjProgressDto.getExamCode())) {
            examRoomQueryWrapper.lambda().eq(ExamRoom::getExamCode, examKjProgressDto.getExamCode());
        }
        if (StringUtils.isNotEmpty(examKjProgressDto.getPlaceCode())) {
            examRoomQueryWrapper.lambda().eq(ExamRoom::getPlaceCode, examKjProgressDto.getPlaceCode());
        }
        if (StringUtils.isNotEmpty(examKjProgressDto.getRoomCode())) {
            examRoomQueryWrapper.lambda().eq(ExamRoom::getRoomCode, examKjProgressDto.getRoomCode());
        }
//        Long count = Long.valueOf(jkExamRoomService.count(examRoomQueryWrapper));

//        Sort.Order order1 = new Sort.Order(Direction.ASC, "placeCode");
//        Sort.Order order2 = new Sort.Order(Direction.ASC, "roomCode");
//        Sort sort = new Sort(order1, order2);
//        query.with(sort);
//        query.limit(pageSize);
//        query.skip((pageNo - 1) * pageSize);
//        List<ExamRoom> examRooms = mongoTemplate.find(query, ExamRoom.class);
        List<ExamKjProgressDto> results = new ArrayList<ExamKjProgressDto>();
        IPage<ExamRoom> examRoomIPage = examRoomDao.listPage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNo, pageSize), examKjProgressDto.getExamCode()
                , examKjProgressDto.getPlaceCode(), examKjProgressDto.getRoomCode(), null, null);
        if (!CollectionUtils.isEmpty(examRoomIPage.getRecords())) {
            for (ExamRoom examRoom : examRoomIPage.getRecords()) {
                ExamKjProgressDto dto = new ExamKjProgressDto();
                dto.setExamCode(examRoom.getExamCode());
                dto.setPlaceCode(examRoom.getPlaceCode());
                dto.setPlaceName(examRoom.getPlaceName());
                dto.setRoomCode(examRoom.getRoomCode());
                dto.setRoomName(examRoom.getRoomName());
                //查询当前考场的总人数
//                Query studentCountQuery = new Query();
//                studentCountQuery.addCriteria(Criteria.where("examCode").is(examRoom.getExamCode()));
//                studentCountQuery.addCriteria(Criteria.where("placeCode").is(examRoom.getPlaceCode()));
//                studentCountQuery.addCriteria(Criteria.where("roomCode").is(examRoom.getRoomCode()));
//                Long studentCount = mongoTemplate.count(studentCountQuery, ExamStudent.class);
                QueryWrapper<ExamStudent> examStudentQueryWrapper = new QueryWrapper<>();
                examStudentQueryWrapper.lambda().eq(ExamStudent::getExamCode, examRoom.getExamCode())
                        .eq(ExamStudent::getPlaceCode, examRoom.getPlaceCode())
                        .eq(ExamStudent::getRoomCode, examRoom.getRoomCode());
                Long studentCount = Long.valueOf(examStudentService.count(examStudentQueryWrapper));

                //查询当前考场已经考试的人数
//                Query examedCountQuery = new Query();
//                examedCountQuery.addCriteria(Criteria.where("examCode").is(examRoom.getExamCode()));
//                examedCountQuery.addCriteria(Criteria.where("student.placeCode").is(examRoom.getPlaceCode()));
//                examedCountQuery.addCriteria(Criteria.where("student.roomCode").is(examRoom.getRoomCode()));
//                Long examedCount = mongoTemplate.count(examedCountQuery, ExamStudentAnswer.class);
                Long examedCount = examStudentAnswerDao.findByExamCodeAndPlaceCodeAndRoomCodeCount(examRoom.getExamCode(),
                        examRoom.getPlaceCode(), examRoom.getRoomCode());

                dto.setTotal(studentCount.intValue());
                dto.setAnsweredCount(examedCount.intValue());
                BigDecimal bigDecimal = new BigDecimal((double) examedCount.intValue() / studentCount.intValue());
                dto.setAnsweredPercent(FORMAT.format(bigDecimal));
                //计算有答案的占比
//                examedCountQuery.addCriteria(Criteria.where("record").exists(true).ne(null));
//                Long answeredCount = mongoTemplate.count(examedCountQuery, ExamSolfegeRecord.class);
                Long answeredCount = jkExamSolfegeRecordDao.findByExamCodeAndPlaceCodeAndRoomCodeCount(examRoom.getExamCode(),
                        examRoom.getPlaceCode(), examRoom.getRoomCode());
                dto.setUploadedCount(answeredCount.intValue());
                bigDecimal = new BigDecimal((double) answeredCount.intValue() / studentCount.intValue());
                dto.setUploadedPercent(FORMAT.format(bigDecimal));
                results.add(dto);
            }
        }
        PageImpl<ExamKjProgressDto> pageResult = new PageImpl<ExamKjProgressDto>(results,
                PageRequest.of(pageNo - 1, pageSize), examRoomIPage.getTotal());
        return pageResult;
    }
}
