package com.qmth.jkserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.dao.ExamStudentAnswerDao;
import com.qmth.jkserver.dao.JkExamSolfegeRecordDao;
import com.qmth.jkserver.model.ExamSolfegeRecord;
import com.qmth.jkserver.model.ExamStudent;
import com.qmth.jkserver.model.ExamStudentAnswer;
import com.qmth.jkserver.service.ExamStudentAnswerService;
import com.qmth.jkserver.service.ExamStudentService;
import com.qmth.jkserver.service.JkExamSolfegeRecordService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


/**
 * 考生答案相关服务
 *
 * @author tianjun
 */
@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
public class ExamStudentAnswerServiceImpl extends ServiceImpl<ExamStudentAnswerDao, ExamStudentAnswer> implements ExamStudentAnswerService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExamStudentAnswerServiceImpl.class);

    @Resource
    private ExamStudentAnswerDao examStudentAnswerDao;

//    @Autowired
//    private MongoOperations mongoTemplate;

    @Resource
    JkExamSolfegeRecordService jkExamSolfegeRecordService;

    @Resource
    @Lazy
    ExamStudentAnswerService examStudentAnswerService;

    @Resource
    @Lazy
    ExamStudentService examStudentService;

    @Resource
    JkExamSolfegeRecordDao jkExamSolfegeRecordDao;

    @Override
    public ExamStudentAnswer findAnswerByStudentId(Long studentId) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("student.id").is(new ObjectId(studentId)));
//        List<ExamStudentAnswer> examStudentAnswers = mongoTemplate.find(query, ExamStudentAnswer.class);
        QueryWrapper<ExamStudentAnswer> examStudentAnswerQueryWrapper = new QueryWrapper<>();
        examStudentAnswerQueryWrapper.lambda().eq(ExamStudentAnswer::getStudentId, studentId);
        List<ExamStudentAnswer> examStudentAnswers = examStudentAnswerService.list(examStudentAnswerQueryWrapper);
        if (examStudentAnswers.size() == 0 || examStudentAnswers == null) {
            return null;
        }
        if (examStudentAnswers.size() == 1) {
            return examStudentAnswers.get(0);
        }
        throw new JkServerException("一个考生考一个科目出现了多份答案，只能够有一份答案");

    }

    @Override
    public ExamStudentAnswer saveService(ExamStudentAnswer examStudentAnswer) {
        if (examStudentAnswer.getId() == null) {
            examStudentAnswer.setTime(System.currentTimeMillis());
        }
        if (StringUtils.isEmpty(examStudentAnswer.getExamCode())) {
            throw new JkServerException("考试识别码不能够为空");
        }
//        examStudentAnswer = examStudentAnswerDao.save(examStudentAnswer);
        examStudentAnswerService.saveOrUpdate(examStudentAnswer);
        return examStudentAnswer;
    }

    @Override
    public void deleteById(String id) {
        examStudentAnswerDao.deleteById(id);
    }

    @Override
    public List<ExamStudentAnswer> findObjectiveAnswerByExamCode(String examCode, int skip, int limit) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("objectiveAnswer").exists(true).ne("").ne(null));
//        query.addCriteria(Criteria.where("paperId").exists(true).ne("").ne(null));
//        query.addCriteria(Criteria.where("isAbsent").ne(true));
//        query.skip(skip);
//        query.limit(limit);
//        Order order1 = new Order(Direction.ASC, "paperId");
//        Order order2 = new Order(Direction.ASC, "student.ticketNo");
//        List<Order> orders = new ArrayList<>();
//        orders.add(order1);
//        orders.add(order2);
//        query.with(new Sort(orders));
//        //query.addCriteria(Criteria.where("objectiveAnswer").ne(null).ne(""));
//        //query.addCriteria(Criteria.where("paperId").ne(null).ne(""));
//        return mongoTemplate.find(query, ExamStudentAnswer.class);
        IPage<ExamStudentAnswer> examStudentAnswerIPage = examStudentAnswerDao.findByExamCodeByPage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(skip, limit),
                examCode);
        return examStudentAnswerIPage.getRecords();
    }

    @Override
    public List<ExamStudentAnswer> findObjectiveAnswerByExamCode(String examCode) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("objectiveAnswer").exists(true).ne("").ne(null));
//        query.addCriteria(Criteria.where("paperId").exists(true).ne("").ne(null));
//        query.addCriteria(Criteria.where("isAbsent").ne(true));
//        //query.addCriteria(Criteria.where("objectiveAnswer").ne(null).ne(""));
//        //query.addCriteria(Criteria.where("paperId").ne(null).ne(""));
//        return mongoTemplate.find(query, ExamStudentAnswer.class);
        return examStudentAnswerDao.findByExamCodeByTicketNo(examCode);
    }

    @Override
    public List<ExamStudentAnswer> findRecordExistsAnswerByExamCode(String examCode, int skip, int limit) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("paperName").exists(true).ne("").ne(null));
//        query.addCriteria(Criteria.where("isAbsent").ne(true));
//        query.skip(skip);
//        query.limit(limit);
//        query.with(new Sort(Direction.ASC, "student.ticketNo"));
//        return mongoTemplate.find(query, ExamStudentAnswer.class);
        IPage<ExamStudentAnswer> examStudentAnswerIPage = examStudentAnswerDao.findByExamCodeByPaperNamePage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(skip, limit),
                examCode);
        return examStudentAnswerIPage.getRecords();
    }

    @Override
    public List<ExamStudentAnswer> findByExamCodeAndCourseCode(String examCode, String courseCode) {
        if (StringUtils.isEmpty(examCode)) {
            throw new JkServerException("考试识别码不能够为空");
        }
        if (StringUtils.isEmpty(courseCode)) {
            throw new JkServerException("课程代码不能够为空");
        }
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("student.courseCode").is(courseCode));
//        query.with(new Sort(Direction.ASC, "student.courseCode"));
//        return mongoTemplate.find(query, ExamStudentAnswer.class);
        return examStudentAnswerDao.findByExamCodeByCourseCode(examCode, courseCode);
    }

    @Override
    public Collection<ExamStudentAnswer> save(Collection<ExamStudentAnswer> examStudentAnswers) {
//        return examStudentAnswerDao.save(examStudentAnswers);
        examStudentAnswerService.saveOrUpdateBatch(examStudentAnswers);
        return examStudentAnswers;
    }

    @Override
    public List<ExamStudentAnswer> findAll() {
        return examStudentAnswerService.list();
    }

    @Override
    public List<ExamStudentAnswer> findByExamCode(String examCode, String courseCode) {
        return examStudentAnswerDao.findByExamCode(examCode, courseCode);
    }

    @Override
    public void deleteAnswer(String examCode, String placeCode, String roomCode) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("student.placeCode").is(placeCode));
//        query.addCriteria(Criteria.where("student.roomCode").is(roomCode));
//        mongoTemplate.remove(query, ExamStudentAnswer.class);
        List<ExamStudentAnswer> list = examStudentAnswerDao.findByExamCodeByPlaceCodeAndRoomCode(examCode, placeCode, roomCode);
        examStudentAnswerService.removeByIds(list);
    }

    @Override
    public void deleteAnswer(String examCode, String ticketNo) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("student.ticketNo").is(ticketNo));
//        mongoTemplate.remove(query, ExamStudentAnswer.class);
        List<ExamStudentAnswer> list = examStudentAnswerDao.findByExamCodeByTicketNoDel(examCode, ticketNo);
        examStudentAnswerService.removeByIds(list);
    }

    @Override
    public void deleteAnswer(List<ExamStudentAnswer> answers) {
//        examStudentAnswerDao.delete(answers);
        examStudentAnswerService.removeByIds(answers);
    }

    @Override
    public Long findAnswerIdByStudentId(Long studentId) {
//        DBObject dbObject = new BasicDBObject();
//        dbObject.put("student._id", new ObjectId(studentId));
//        DBObject projection = new BasicDBObject();
//        projection.put("_id", 1);
//        DBCursor dbCursor = mongoTemplate.getCollection("jk_exam_student_answer").find(dbObject, projection);
//        List<DBObject> list = new ArrayList<DBObject>();
//        while (dbCursor.hasNext()) {
//            DBObject document = dbCursor.next();
//            list.add(document);
//        }
//        dbCursor.close();
        QueryWrapper<ExamStudentAnswer> examStudentAnswerQueryWrapper = new QueryWrapper<ExamStudentAnswer>();
        examStudentAnswerQueryWrapper.lambda().eq(ExamStudentAnswer::getStudentId, studentId);
        List<ExamStudentAnswer> list = examStudentAnswerService.list(examStudentAnswerQueryWrapper);
        if (list.size() == 0) {
            return null;
        } else {
            if (list.size() == 1) {
//                return (ObjectId) list.get(0).get("_id");
                return list.get(0).getId();
            } else {
                throw new JkServerException("一个考生考一个科目出现了多份答案，只能够有一份答案");
            }
        }
    }

    @Override
    public Map<String, Integer> computeCourseObjectiveQuesNumber(String examCode) {
//        DBObject queryObject = new BasicDBObject();
//        queryObject.put("exam_code", examCode);
//        queryObject.put("is_absent", false);
//        queryObject.put("objective_answer", new BasicDBObject("$exists", true));
//        DBObject projection = new BasicDBObject();
//        projection.put("objective_answer", 1);
//        projection.put("student.course_code", 1);
//        DBCursor dbCursor = mongoTemplate.getCollection("jk_exam_student_answer").find(queryObject, projection);
        QueryWrapper<ExamStudentAnswer> examStudentAnswerQueryWrapper = new QueryWrapper<>();
        examStudentAnswerQueryWrapper.lambda().eq(ExamStudentAnswer::getExamCode, examCode)
                .eq(ExamStudentAnswer::getIsAbsent, false)
                .isNotNull(ExamStudentAnswer::getObjectiveAnswer);
        List<ExamStudentAnswer> list = examStudentAnswerService.list(examStudentAnswerQueryWrapper);
        Map<String, Integer> map = new LinkedHashMap<String, Integer>();
//        while (dbCursor.hasNext()) {
//            DBObject dbObject = dbCursor.next();
        for (ExamStudentAnswer examStudentAnswer : list) {
//            if (dbObject.get("objective_answer") == null) {
            if (examStudentAnswer.getObjectiveAnswer() == null) {
                continue;
            }
//            String objAns = dbObject.get("objective_answer").toString();
            String objAns = examStudentAnswer.getObjectiveAnswer();
            String[] answers = StringUtils.splitByWholeSeparatorPreserveAllTokens(objAns, ";");
//            DBObject studentobj = (DBObject) dbObject.get("student");
            ExamStudent examStudent = examStudentService.getById(examStudentAnswer.getStudentId());
            if (examStudent != null) {
//                String courseCode = studentobj.get("course_code").toString();
                String courseCode = examStudent.getCourseCode();
                String key = examCode + courseCode;
                Integer old = map.get(key) == null ? 0 : map.get(key);
                map.put(key, Math.max(old, answers.length));
            }
        }
        return map;
    }

    @Override
    public ExamStudentAnswer find(String examCode, String ticketNo, String courseCode) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("examCode").is(examCode));
//        query.addCriteria(Criteria.where("student.ticketNo").is(ticketNo));
//        query.addCriteria(Criteria.where("student.courseCode").is(courseCode));
//        List<ExamStudentAnswer> examStudentAnswers = mongoTemplate.find(query, ExamStudentAnswer.class);
        List<ExamStudentAnswer> examStudentAnswers = examStudentAnswerDao.findByExamCodeByTicketNoAndCourseCode(examCode, ticketNo, courseCode);
        return examStudentAnswers.size() > 0 ? examStudentAnswers.get(0) : null;
    }

    @Override
    public ExamSolfegeRecord findRecordByStudentId(Long studentId) {
//        Query query = new Query();
//        query.addCriteria(Criteria.where("student.id").is(new ObjectId(studentId)));
//        List<ExamSolfegeRecord> list = mongoTemplate.find(query, ExamSolfegeRecord.class);
        List<ExamSolfegeRecord> list = jkExamSolfegeRecordDao.findByStudentId(studentId);
        return list.size() > 0 ? list.get(0) : null;
    }

    @Override
    public Long findRecordIdByStudentId(Long studentId) {
//        DBObject dbObject = new BasicDBObject();
//        dbObject.put("student._id", new ObjectId(studentId));
//        DBObject projection = new BasicDBObject();
//        projection.put("_id", 1);
//        DBCursor dbCursor = mongoTemplate.getCollection("jk_exam_solfege_record").find(dbObject, projection);
//        List<DBObject> list = new ArrayList<DBObject>();
//        while (dbCursor.hasNext()) {
//            DBObject document = dbCursor.next();
//            list.add(document);
//        }
//        dbCursor.close();
        QueryWrapper<ExamSolfegeRecord> examSolfegeRecordQueryWrapper = new QueryWrapper<ExamSolfegeRecord>();
        examSolfegeRecordQueryWrapper.lambda().eq(ExamSolfegeRecord::getStudentId, studentId);
        List<ExamSolfegeRecord> list = jkExamSolfegeRecordService.list(examSolfegeRecordQueryWrapper);
        if (list.size() == 0) {
            return null;
        } else {
            if (list.size() == 1) {
//                return (ObjectId) list.get(0).get("_id");
                return list.get(0).getId();
            } else {
                throw new JkServerException("一个考生考一个科目出现了多份答案，只能够有一份答案");
            }
        }
    }

}
