package cn.com.qmth.examcloud.core.questions.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import cn.com.qmth.examcloud.api.commons.enums.AdminOperateType;
import cn.com.qmth.examcloud.api.commons.security.bean.User;
import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.core.questions.base.Model;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperType;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.Paper;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetail;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetailUnit;
import cn.com.qmth.examcloud.core.questions.service.PaperDetailService;
import cn.com.qmth.examcloud.core.questions.service.PaperDetailUnitService;
import cn.com.qmth.examcloud.core.questions.service.QuesTypeNameService;
import cn.com.qmth.examcloud.reports.commons.bean.AdminOperateReport;
import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;

/**
 * @author chenken
 * @date 2017年9月13日 上午11:32:33
 * @company QMTH
 * @description PaperDetailServiceImpl.java
 */
@Service("paperDetailService")
public class PaperDetailServiceImpl implements PaperDetailService {

	@Autowired
	PaperDetailRepo paperDetailRepo;

	@Autowired
	PaperDetailUnitService unitService;

	@Autowired
	PaperRepo paperRepo;

	@Autowired
	QuesTypeNameService quesTypeNameService;

	@Autowired
	PaperDetailUnitRepo paperDetailUnitRepo;

	@Autowired
	MongoTemplate mongoTemplate;

	/**
	 * 根据Id获得对应所有小题
	 *
	 * @param id
	 * @return
	 */
	public List<PaperDetailUnit> getUnitsByPaperDetailId(String id) {
		return unitService.getUnitsByPaperDetail(Model.of(paperDetailRepo.findById(id)));
	}

	/**
	 * 按ID查询大题
	 *
	 * @param id
	 * @return
	 */
	public PaperDetail findById(String id) {
		return Model.of(paperDetailRepo.findById(id));
	}

	/**
	 * 保存大题
	 *
	 * @param pd
	 * @return
	 */
	public PaperDetail savePaperDetail(PaperDetail pd, String paperId, User user) {
		Paper paper = Model.of(paperRepo.findById(paperId));
		paper.setLastModifyName(user.getDisplayName());
		if (PaperType.GENERATE.equals(paper.getPaperType())) {
			paper.setAuditStatus(false);
		}
		paper = paperRepo.save(paper);
		pd.setPaper(paper);
		PaperDetail oldpaperDetail = Model.of(paperDetailRepo.findById(pd.getId()));
		PaperDetail paperDetail = paperDetailRepo.save(pd);
		List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetailOrderByNumber(paperDetail);
		quesTypeNameService.saveQuesTypeName(paperDetailUnits);

		if (!oldpaperDetail.getName().equals(paperDetail.getName())) {
			StringBuilder paperInfo = new StringBuilder();
			paperInfo.append("课程:" + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ") 试卷名称:"
					+ paper.getName());
			paperInfo.append("第" + paperDetail.getNumber() + "大题名称由改 " + oldpaperDetail.getName() + " 为 "
					+ paperDetail.getName());
			if (PaperType.IMPORT.equals(paper.getPaperType())) {
				ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
						AdminOperateType.TYPE38.getDesc(), paperInfo.toString()));
			} else {
				ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
						AdminOperateType.TYPE39.getDesc(), paperInfo.toString()));

			}
		}
		return paperDetail;
	}

	/**
	 * 删除大题
	 *
	 * @param id
	 * @return
	 */
	public void deletePaperDetail(String paperId, String id, User user) {
		Paper paper = Model.of(paperRepo.findById(paperId));
		if (paper.getInUse() != null && paper.getInUse() == 1) {
			throw new StatusException("500", "试卷已调用");
		}
		PaperDetail oldpaperDetail = Model.of(paperDetailRepo.findById(id));
		paperDetailRepo.deleteById(id);
		if (PaperType.GENERATE.equals(paper.getPaperType())) {
			paper.setAuditStatus(false);
			paperRepo.save(paper);
		}
		StringBuilder paperInfo = new StringBuilder();
		paperInfo.append(
				"课程:" + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ") 试卷名称:" + paper.getName());
		paperInfo.append("删除第" + oldpaperDetail.getNumber() + "大题");
		Integer dc = paper.getPaperDetailCount();
		paperInfo.append(" 试卷大题数量变动(" + dc + "变为" + (dc - 1) + ")");
		if (PaperType.IMPORT.equals(paper.getPaperType())) {
			ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
					AdminOperateType.TYPE40.getDesc(), paperInfo.toString()));
		} else {
			ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
					AdminOperateType.TYPE41.getDesc(), paperInfo.toString()));
		}
	}

	/**
	 * 查询同一个试卷对象对应大题
	 *
	 * @param paper
	 * @return
	 */
	public List<PaperDetail> getPaperDetailsByPaper(Paper paper) {
		return paperDetailRepo.findByPaperOrderByNumber(paper);
	}

	/**
	 * 删除试卷大题
	 *
	 * @param paper
	 */
	public void deletePaperDetailsByPaper(Paper paper) {
		List<PaperDetail> details = getPaperDetailsByPaper(paper);
		unitService.deleteUnitsByPaperDetails(details);
		paperDetailRepo.deleteAll(details);
	}

	/**
	 * 批量删除试卷大题
	 *
	 * @param papers
	 */
	public void deletePaperDetailsByPapers(List<Paper> papers) {
		for (Paper paper : papers) {
			List<PaperDetail> details = getPaperDetailsByPaper(paper);
			unitService.deleteUnitsByPaperDetails(details);
			paperDetailRepo.deleteAll(details);
		}
	}

	@Override
	public void movePaperDetail(String paperId, String detailId, String vc, User user) {
		Paper paper = Model.of(paperRepo.findById(paperId));
		if (paper.getInUse() != null && paper.getInUse() == 1) {
			throw new StatusException("500", "试卷已调用");
		}
		List<PaperDetail> pds = getPaperDetailsByPaper(paper);
		if (pds == null || pds.size() <= 1) {
			throw new StatusException("500", "大题数量未达到两题，无法移动");
		}
		if (detailId.equals(pds.get(0).getId()) && "up".equals(vc)) {
			throw new StatusException("500", "第一题无法上移");
		}
		if (detailId.equals(pds.get(pds.size() - 1).getId()) && "down".equals(vc)) {
			throw new StatusException("500", "最后一题无法下移");
		}
		int number = movePaperDetail(pds, detailId, vc);
		List<PaperDetailUnit> pdus = paperDetailUnitRepo.findByPaperIdOrderByNumber(paperId);
		if (pdus != null && pdus.size() > 0) {
			int subIndex = 0;
			Map<String, List<PaperDetailUnit>> map = getPaperDetailUnitMap(pdus);
			for (PaperDetail pd : pds) {
				if (CollectionUtils.isNotEmpty(map.get(pd.getId()))) {
					for (PaperDetailUnit pdu : map.get(pd.getId())) {
						subIndex++;
						pdu.setNumber(subIndex);
					}
				}
			}
			savePaperDetailUnitNumber(pds, map);
		}
		savePaperDetailNumber(pds);
		if (PaperType.GENERATE.equals(paper.getPaperType())) {
			paper.setAuditStatus(false);
			paperRepo.save(paper);
		}
		StringBuilder paperInfo = new StringBuilder();
		paperInfo.append(
				"课程:" + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ") 试卷名称:" + paper.getName());
		if ("up".equals(vc)) {
			paperInfo.append(" 上移");
		} else {
			paperInfo.append(" 下移");
		}
		paperInfo.append("第" + number + "大题");
		ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
				AdminOperateType.TYPE42.getDesc(), paperInfo.toString()));
	}

	private void savePaperDetailNumber(List<PaperDetail> pds) {
		Query query;
		int index = 0;
		for (PaperDetail pd : pds) {
			index++;
			if (pd.getId().length() == 24) {
				query = Query.query(Criteria.where("_id").is(new ObjectId(pd.getId())));
			} else {
				query = Query.query(Criteria.where("_id").is(pd.getId()));
			}
			Update update = new Update();
			update.set("number", index);
			mongoTemplate.updateFirst(query, update, "paperDetail");
		}
	}

	private void savePaperDetailUnitNumber(List<PaperDetail> pds, Map<String, List<PaperDetailUnit>> map) {
		Query query;
		for (PaperDetail pd : pds) {
			if (CollectionUtils.isNotEmpty(map.get(pd.getId()))) {
				for (PaperDetailUnit pdu : map.get(pd.getId())) {
					if (pdu.getId().length() == 24) {
						query = Query.query(Criteria.where("_id").is(new ObjectId(pdu.getId())));
					} else {
						query = Query.query(Criteria.where("_id").is(pdu.getId()));
					}
					Update update = new Update();
					update.set("number", pdu.getNumber());
					mongoTemplate.updateFirst(query, update, "paperDetailUnit");
				}
			}
		}
	}

	private int movePaperDetail(List<PaperDetail> pds, String detailId, String vc) {
		for (int i = 0; i < pds.size(); i++) {
			if (pds.get(i).getId().equals(detailId)) {
				if ("up".equals(vc)) {
					PaperDetail tem = pds.get(i);
					pds.set(i, pds.get(i - 1));
					pds.set(i - 1, tem);
				} else {
					PaperDetail tem = pds.get(i);
					pds.set(i, pds.get(i + 1));
					pds.set(i + 1, tem);
				}
				return i + 1;
			}
		}
		return -1;
	}

	private Map<String, List<PaperDetailUnit>> getPaperDetailUnitMap(List<PaperDetailUnit> pdus) {
		Map<String, List<PaperDetailUnit>> map = new HashMap<>();

		for (PaperDetailUnit pdu : pdus) {
			List<PaperDetailUnit> pl = map.get(pdu.getPaperDetail().getId());
			if (pl == null) {
				pl = new ArrayList<>();
				map.put(pdu.getPaperDetail().getId(), pl);
			}
			pl.add(pdu);
		}

		return map;
	}

}