package com.qmth.qrzk.repository.user.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.qmth.qrzk.batch.model.BatchGJCourse;
import com.qmth.qrzk.dao.repositories.BatchGJCourseRepo;
import com.qmth.qrzk.paper.vo.UseBatchStock;
import com.qmth.qrzk.repository.common.base.BaseDao;
import com.qmth.qrzk.repository.service.query.DbfPaperInfoQueryParams;
import com.qmth.qrzk.repository.service.query.PaperParams;
import com.qmth.qrzk.repository.service.query.QueryParams;
import com.qmth.qrzk.repository.user.model.DbfPaperInfo;
import com.qmth.qrzk.repository.user.model.Paper;
import com.qmth.qrzk.repository.user.model.PaperBatch;

@Service
public class DbfPaperInfoServiceImpl {
	
	@Autowired
	private BaseDao dao;
	
	@Autowired private BatchGJCourseRepo gjRepo;
	
	public void addDbfPaperInfo(DbfPaperInfo dbfPaperInfo){
		dao.update("insertDbfPaperInfo", dbfPaperInfo);
	}
	
	public void addDbfPaperInfos(List<DbfPaperInfo> dbfPaperInfos, int batchId){
		Set<String> batchCourseCodes = new HashSet<String>();
		//查询出批次下已经存在的课程信息
		if(dbfPaperInfos.size() > 0){
			DbfPaperInfoQueryParams params = new DbfPaperInfoQueryParams();
			params.setPaperBatchId(batchId);
			List<DbfPaperInfo> batchCourses = dao.getList("queryDbfPaperInfo", params);
			for(DbfPaperInfo dbfPaperInfo : batchCourses){
				batchCourseCodes.add(dbfPaperInfo.getCourseCode());
			}
		}
		
		for(DbfPaperInfo dbfPaperInfo : dbfPaperInfos){
			if(!batchCourseCodes.contains(dbfPaperInfo.getCourseCode())){
				dbfPaperInfo.setPaperBatchId(batchId);
				dao.update("insertDbfPaperInfo", dbfPaperInfo);
			}
		}
	}
	
	
	public void updateDbfPaperInfo(DbfPaperInfo dbfPaperInfo){
		dao.update("updateDbfPaperInfoRelatedPapers", dbfPaperInfo);
	}
	
	public List<DbfPaperInfo> queryDbfPaperInfo(DbfPaperInfoQueryParams params){
		return dao.getPagerList("queryDbfPaperInfo", params);
	}
	
	private Map<String, Object> validateGJCourseRelDifferentPapers(int batchId){
		List<String> messages = new ArrayList<String>();
		boolean success = true;
		List<BatchGJCourse> gjCourseRelPapers = dao.getList("getGJCourseRelPapers", batchId);
		for(BatchGJCourse gjCoursePaper : gjCourseRelPapers){
			if(gjCoursePaper.getRelPaperCount() == 1){
				messages.add("共卷课程（" + gjCoursePaper.getCourseCode() + " - " + gjCoursePaper.getbCourseCode() 
						+ ") 其中一个课程已关联试卷：" + gjCoursePaper.getRelPaperCodes() + "请先移出试卷。 ");
				
				success = false;
			}else{
				String[] paperIds = gjCoursePaper.getRelPaperIds().split(",");
				if(!paperIds[0].equals(paperIds[1].trim())){
					messages.add("共卷课程（" + gjCoursePaper.getCourseCode() + " - " + gjCoursePaper.getbCourseCode() 
							+ ") 已关联不同的试卷：" + gjCoursePaper.getRelPaperCodes() + "请先移出试卷。 ");
					
					success = false;
				}
			}
		}
		
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("success", success);
		result.put("messages", messages);
		return result;
	}
	
	static class GJCourseCount implements Comparable{
		private String course;
		private Integer refCount;
		private Integer paperCount;
		
		public GJCourseCount(String course, int refCount, int paperCount){
			this.course = course;
			this.refCount = refCount;
			this.paperCount = paperCount;
		}
		
		@Override
		public int compareTo(Object o) {
			GJCourseCount c = (GJCourseCount) o;
			int result = c.refCount.compareTo(this.refCount);
			return result == 0 ? c.paperCount.compareTo(this.paperCount) : result;
		}
		
		public String getCourse(){
			return course;
		}
	}
	
	static class GJCourseGroup{
		private Map<String, Integer> courses;
		
		public GJCourseGroup(String course1, String course2){
			courses = new HashMap<String, Integer>();
			courses.put(course1, 1);
			courses.put(course2, 1);
		}
		
		public void addCourse(String course){
			Integer count = courses.get(course);
			if(count != null){
				count++;
			}else{
				count = 1;
			}
			courses.put(course, count);
		}
		
		public boolean hasCourse(String course){
			return courses.get(course) != null;
		}	
		
		public Map<String, Integer> getCourses(){
			return courses;
		}
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Map<String, Object> autoMatchPapers(PaperBatch paperBatch){
		Map<String, Object> result = new HashMap<String, Object>();
		List<Map> ls = new ArrayList<Map>();
		//启用批次随机抽取一套试卷
		if(PaperBatch.QIYONG.equalsIgnoreCase(paperBatch.getType())){
			//1.校验共卷课程与被共卷课程是否已关联了不同的试卷或部分关联试卷
			result = validateGJCourseRelDifferentPapers(paperBatch.getId());
			
			if((Boolean)result.get("success") == true){
				//2.查询出所有满足条件的清样试卷
				List<DbfPaperInfo> dbfPaperInfos = dao.getList("queryMatchedFormalPaperIds", paperBatch.getId());
				Map<String, DbfPaperInfo> matchedCoursePaperIdsMap = new HashMap<String, DbfPaperInfo>();
				for(DbfPaperInfo item : dbfPaperInfos){
					matchedCoursePaperIdsMap.put(item.getCourseCode(), item);
				}
				
				//3. 将所有的共卷课程分组
				List<BatchGJCourse> gjCourses = gjRepo.findByBatchId(paperBatch.getId(), null);
				List<GJCourseGroup> gjCourseGroups = new ArrayList<GJCourseGroup>();
				for(BatchGJCourse gjCourse : gjCourses){
					boolean foundGroup = false;
					for(GJCourseGroup group : gjCourseGroups){
						if(group.hasCourse(gjCourse.getCourseCode()) || group.hasCourse(gjCourse.getbCourseCode())){
							foundGroup = true;
							group.addCourse(gjCourse.getCourseCode());
							group.addCourse(gjCourse.getbCourseCode());
							break;
						}
					}
					if(!foundGroup){
						GJCourseGroup group = new GJCourseGroup(gjCourse.getCourseCode(), gjCourse.getbCourseCode());
						gjCourseGroups.add(group);
					}
				}
				
				//4. 按照共卷课程出现顺序进行排序后，依次获取对应的试卷信息，并将查找到的试卷共享给同组的其他课程
				for(GJCourseGroup group : gjCourseGroups){
					Map<String, Integer> groupCourses = group.getCourses();
					List<GJCourseCount> courseCounts = new ArrayList<GJCourseCount>();
					
					Set<String> mapKeys = groupCourses.keySet();
					boolean hasMatchedPaper = false;
					for(String courseCode : mapKeys){
						int refCount = groupCourses.get(courseCode);
						int paperCount = 0;
						if(matchedCoursePaperIdsMap.get(courseCode) != null){
							paperCount = matchedCoursePaperIdsMap.get(courseCode).getRelatedPaperNum();
							hasMatchedPaper = true;
						}
						courseCounts.add(new GJCourseCount(courseCode, refCount, paperCount));
					}
					if(hasMatchedPaper){
						Collections.sort(courseCounts);
						DbfPaperInfo selectedPapers = null;
						for(GJCourseCount item : courseCounts){
							if(item.paperCount > 0){
								selectedPapers = matchedCoursePaperIdsMap.get(item.getCourse());
								break;
							}
						}
						
						String[] paperCodes = selectedPapers.getRelatedPaperCode().split(",");
						String[] paperIds = selectedPapers.getRelatedPaperId().split(",");
						
						int oldestPaperIndex = 0;
						String oldestPaperCode = paperCodes[0];
						for(int i=0; i< paperCodes.length; i++){
							if(oldestPaperCode.compareTo(paperCodes[i]) > 0){
								oldestPaperCode = paperCodes[i];
								oldestPaperIndex = i;
							}
						}
						int selectedPaperId = Integer.parseInt(paperIds[oldestPaperIndex]);
						
						for(GJCourseCount item : courseCounts){
							DbfPaperInfo dbfPaperInfo = matchedCoursePaperIdsMap.get(item.getCourse());
							if(dbfPaperInfo == null){
								DbfPaperInfoQueryParams params = new DbfPaperInfoQueryParams();
								params.setCourseCode(item.getCourse());
								params.setPaperBatchId(paperBatch.getId());
								dbfPaperInfo = dao.get("queryDbfPaperInfoByCourseAndBatchId", params);
							}else{
								//从试卷匹配列表删除共卷课程
								matchedCoursePaperIdsMap.remove(item.getCourse());
							}
							Map<String, Integer> map = new HashMap<String, Integer>();
							map.put("dbfPaperInfoId", dbfPaperInfo.getId());
							map.put("paperId", selectedPaperId);
							ls.add(map);
						}
					}
				}
				
				//5. 继续处理非共卷课程的抽取信息
				Set<String> keySet = matchedCoursePaperIdsMap.keySet();
				for(String course : keySet){
					DbfPaperInfo dbfPaperInfo = matchedCoursePaperIdsMap.get(course);
					
					String[] paperCodes = dbfPaperInfo.getRelatedPaperCode().split(",");
					String[] paperIds = dbfPaperInfo.getRelatedPaperId().split(",");
					
					int oldestPaperIndex = 0;
					String oldestPaperCode = paperCodes[0];
					for(int i=0; i< paperCodes.length; i++){
						if(oldestPaperCode.compareTo(paperCodes[i]) > 0){
							oldestPaperCode = paperCodes[i];
							oldestPaperIndex = i;
						}
					}
					int selectedPaperId = Integer.parseInt(paperIds[oldestPaperIndex]);
					Map<String, Integer> map = new HashMap<String, Integer>();
					map.put("dbfPaperInfoId", dbfPaperInfo.getId());
					map.put("paperId", selectedPaperId);
					ls.add(map);
				}
			}
		}else{
			ls = dao.getList("queryMatchedDraftPaperIds", paperBatch.getId());
		}
		
		if(ls.size() > 0){
			dao.update("insertPaperRelDbfPaperInfo", ls);
			Set<Integer> batchPaperIds = new HashSet<Integer>();
			for(Map item : ls){
				batchPaperIds.add((Integer)item.get("paperId"));
			}
			Map<String, Object> batchIdAndPaperIds = new HashMap<String, Object>();
			batchIdAndPaperIds.put("paperBatchId", paperBatch.getId());
			batchIdAndPaperIds.put("paperIds", batchPaperIds.toArray());
			List<Integer> existPaperIds = dao.getList("queryExistPaperIdsInBatch", batchIdAndPaperIds);
			for(Integer paperId : existPaperIds){
				batchPaperIds.remove(paperId);
			}
			if(batchPaperIds.size() > 0){
				Map<String, Object> batchIdAndPaperIdsMap = new HashMap<String, Object>();
				batchIdAndPaperIdsMap.put("paperBatchId", paperBatch.getId());
				batchIdAndPaperIdsMap.put("paperIds", batchPaperIds.toArray());
				
				dao.update("insertMatchedPaperAndBatch", batchIdAndPaperIdsMap);
			}
		}
		return result;
	}
	
	public List<Paper> queryRelatedPapers(int dbfPaperInfoId){
		return dao.getList("queryRelatedPapers", dbfPaperInfoId);
	}
	
	public List<Paper> getPaperInfo(DbfPaperInfoQueryParams params){
		return dao.getList("getPaperInfo", params);
	}
	
	public int getPaperInfoCount(DbfPaperInfoQueryParams params){
		List<Paper> list=dao.getList("getPaperInfoCount", params);;
		return list.size();
	}
	
	public int isGet(DbfPaperInfoQueryParams params){
		return dao.getCount("isGet", params);
	}
	
	public List<Paper> searchRelatedPapers(DbfPaperInfoQueryParams params){
		return dao.getList("searchRelatedPapers", params);
	}
	
	/**
	 * 手动关联试卷
	 * 2014年9月19日
	 * @author wubaizhi
	 * @description 
	 * @param dbfPaperInfoId
	 * @param relatedPaperIds
	 */
	public void manualAddMatchedPapers(int dbfPaperInfoId, Integer[] relatedPaperIds){
		DbfPaperInfo dbfPaperInfoDB = dao.get("getById", dbfPaperInfoId);
		
		Map<String, Object> batchIdAndPaperIds = new HashMap<String, Object>();
		batchIdAndPaperIds.put("paperBatchId", dbfPaperInfoDB.getPaperBatchId());
		batchIdAndPaperIds.put("paperIds", relatedPaperIds);
		
		dao.update("insertMatchedPaperAndBatch", batchIdAndPaperIds);
		
		Map<String, Object> dbfPaperInfoIdAndPaperIds = new HashMap<String, Object>();
		dbfPaperInfoIdAndPaperIds.put("dbfPaperInfoId", dbfPaperInfoDB.getId());
		dbfPaperInfoIdAndPaperIds.put("paperIds", relatedPaperIds);
		
		dao.update("insertPaperRelDbfPaperInfoMap", dbfPaperInfoIdAndPaperIds);
	}
	
	/**
	 * 删除启用批次中的试卷
	 * 2014年9月19日
	 * @author wubaizhi
	 * @description 
	 * @param dbfPaperInfoId
	 * @param relatedPaperIds
	 */
	public void removePaperFromUsedBatch(int dbfPaperInfoId, Integer[] relatedPaperIds){
		DbfPaperInfo dbfPaperInfoDB = dao.get("getById", dbfPaperInfoId);
		
		Map<String, Object> batchIdAndPaperIds = new HashMap<String, Object>();
		batchIdAndPaperIds.put("batchId", dbfPaperInfoDB.getPaperBatchId());
		batchIdAndPaperIds.put("paperIds", relatedPaperIds);
		
		dao.update("deletePaperAndBatchRel", batchIdAndPaperIds);
		
		Map<String, Object> dbfPaperInfoIdAndPaperIds = new HashMap<String, Object>();
		dbfPaperInfoIdAndPaperIds.put("dbfPaperInfoId", dbfPaperInfoDB.getId());
		dbfPaperInfoIdAndPaperIds.put("paperIds", relatedPaperIds);
		
		dao.update("deletePaperRelDbfPaperInfoMap", dbfPaperInfoIdAndPaperIds);
	}
	
	/**
	 * 删除批次中的课程与教材信息
	 * 2014年9月19日
	 * @author wubaizhi
	 * @description 
	 * @param dbfPaperInfoId
	 * @param relatedPaperIds
	 */
	public void removeDbfPaperInfoFromBatch(Integer[] dbfPaperInfoIds, boolean isRemoveRelatedPapers){
		DbfPaperInfo dbfPaperInfoDB = dao.get("getById", dbfPaperInfoIds[0]);
		
		if(isRemoveRelatedPapers){
			List<Integer> param = new ArrayList<Integer>();
			Collections.addAll(param, dbfPaperInfoIds);
			List<Integer> relatedPaperIds = dao.getList("getPaperIdsByDbfPaperInfoIds", param);
			
			Map<String, Object> batchIdAndPaperIds = new HashMap<String, Object>();
			batchIdAndPaperIds.put("batchId", dbfPaperInfoDB.getPaperBatchId());
			batchIdAndPaperIds.put("paperIds", relatedPaperIds);
			
			dao.delete("deletePaperAndBatchRel", batchIdAndPaperIds);
		}
		
		dao.delete("deletePaperRelDbfPaperInfoByDbfPaperInfoIds", dbfPaperInfoIds);
		dao.delete("deleteDbfPaperInfoByDbfPaperInfoIds", dbfPaperInfoIds);
	}
	
	public List<Integer> queryRelatedPaperNumsByBatchId(int paperBatchId){
		return dao.getList("queryRelatedPaperNumsByBatchId", paperBatchId);
	}
	
	/**
	 * 2015-11-5  启用批次库存统计
	 * @param queryParams
	 * @return
	 */
	public List<UseBatchStock> queryUseBatchStock(PaperParams queryParams){
		return dao.getList("queryUseBatchStock", queryParams);
	}
	
	public int queryUseBatchStockCount(QueryParams pp) {
		return dao.get("queryUseBatchStockCount", pp);
	}
	
	public List<UseBatchStock> queryAllUseBatchStock(PaperParams queryParams){
		queryParams.setRows(Integer.MAX_VALUE);
		return dao.getList("queryUseBatchStock", queryParams);
	}
}
