package com.keao.edu.user.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.keao.edu.common.dal.BaseDAO;
import com.keao.edu.common.enums.YesOrNoEnum;
import com.keao.edu.common.exception.BizException;
import com.keao.edu.common.page.PageInfo;
import com.keao.edu.common.service.impl.BaseServiceImpl;
import com.keao.edu.common.tenant.TenantContextHolder;
import com.keao.edu.user.api.entity.ExamRoom;
import com.keao.edu.user.dao.ExamRegistrationDao;
import com.keao.edu.user.dao.ExamRoomDao;
import com.keao.edu.user.dao.ExamRoomStudentRelationDao;
import com.keao.edu.user.dao.ExaminationBasicDao;
import com.keao.edu.user.dto.ExamRoomDto;
import com.keao.edu.user.dto.ExamRoomStatisticsDto;
import com.keao.edu.user.api.enums.ExamModeEnum;
import com.keao.edu.user.entity.ExaminationBasic;
import com.keao.edu.user.page.ExamRoomQueryInfo;
import com.keao.edu.user.service.ExamRoomService;
import com.keao.edu.user.service.OrganizationService;
import com.keao.edu.util.collection.MapUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ExamRoomServiceImpl extends BaseServiceImpl<Long, ExamRoom> implements ExamRoomService {

	@Autowired
	private ExamRoomDao examRoomDao;
	@Autowired
	private ExamRoomStudentRelationDao examRoomStudentRelationDao;
	@Autowired
	private OrganizationService organizationService;
	@Autowired
	private ExamRegistrationDao examRegistrationDao;
	@Autowired
	private ExaminationBasicDao examinationBasicDao;

	@Override
	public BaseDAO<Long, ExamRoom> getDAO() {
		return examRoomDao;
	}

	@Override
	public PageInfo<ExamRoomDto> queryExamRoomPage(ExamRoomQueryInfo queryInfo) {
		PageInfo<ExamRoomDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
		Map<String, Object> params = new HashMap<>();
		MapUtil.populateMap(params, queryInfo);

		List<Integer> childOrganIds = organizationService.getChildOrganIds(queryInfo.getOrganId(), true);
		params.put("organIds", childOrganIds);

		List<ExamRoomDto> dataList = null;
		int count = examRoomDao.countExamRoomPage(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = examRoomDao.queryExamRoomPage(params);
		}
		if (count == 0) {
			dataList = new ArrayList<>();
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	@Override
	public void createExamRoom(ExamRoom examRoom) {
		if(Objects.isNull(examRoom.getExaminationBasicId())){
			throw new BizException("请指定考级项目");
		}
		ExaminationBasic examinationBasic = examinationBasicDao.get(examRoom.getExaminationBasicId().longValue());
		if(Objects.isNull(examinationBasic)){
			throw new BizException("考级项目不存在");
		}
		if(Objects.isNull(examRoom.getExamMode())){
			throw new BizException("请指定考试类型");
		}
		if(ExamModeEnum.OFFLINE.equals(examRoom.getExamMode())&&Objects.isNull(examRoom.getExamLocationId())){
			throw new BizException("线下考试请指定考试地址");
		}
		if(StringUtils.isBlank(examRoom.getSubjectIdList())){
			throw new BizException("请指定考试专业");
		}
		if(Objects.isNull(examRoom.getMainTeacherUserId())){
			throw new BizException("请指定主考老师");
		}
		if(StringUtils.isBlank(examRoom.getExamTimeJson())){
			throw new BizException("请指定考试时间");
		}
		examRoom.setTenantId(TenantContextHolder.getTenantId().toString());
		examRoom.setExamPlanPushFlag(YesOrNoEnum.NO);
		if(StringUtils.isBlank(examRoom.getExamTimeJson())){
			examRoomDao.insert(examRoom);
			return;
		}
		List<ExamRoom> examRooms=new ArrayList<>();
		List<JSONObject> examTimes = JSON.parseArray(examRoom.getExamTimeJson(), JSONObject.class);
		for (JSONObject examTime : examTimes) {
			ExamRoom er;
			try {
				er= (ExamRoom) BeanUtils.cloneBean(examRoom);
			} catch (Exception e) {
				throw new BizException("教室创建失败");
			}
			er.setExamStartTime(examTime.getDate("examStartTime"));
			er.setExamEndTime(examTime.getDate("examEndTime"));
			if(Objects.isNull(er.getExamStartTime())||Objects.isNull(er.getExamEndTime())){
				throw new BizException("请指定考试时间");
			}
			examRooms.add(er);
		}
		examRoomDao.batchInsert(examRooms);
	}

	@Override
	public ExamRoom updateExamRoom(ExamRoom examRoom) {
		if(Objects.isNull(examRoom.getId())){
			throw new BizException("请指定教室");
		}
		examRoomDao.update(examRoom);
		return examRoom;
	}

	@Override
	public void deleteExamRooms(String examRoomIdsStr) {
		if(StringUtils.isBlank(examRoomIdsStr)){
			return;
		}
		List<Long> examRoomIds = Arrays.asList(examRoomIdsStr.split(",")).stream().map(e -> Long.valueOf(e)).collect(Collectors.toList());
		examRoomDao.batchDeleteExamRooms(examRoomIds);
		examRoomStudentRelationDao.deleteWithExamRooms(examRoomIds);
	}

	@Override
	public void sendExamPlan(Integer organId, Integer examId) {
		List<Integer> nextLevelOrganIds = organizationService.getNextLevelOrganIds(organId, true);
		int withoutExamRoomStudentNum = examRegistrationDao.countWithoutExamRoomStudentNum(nextLevelOrganIds, examId);
		if(withoutExamRoomStudentNum>0){
			throw new BizException("存在未安排教室的学员");
		}
	}

	@Override
	public ExamRoomStatisticsDto getExamRoomStatisticsInfo(Integer organId, Integer examId) {
		ExamRoomStatisticsDto examRoomStatisticsInfo=new ExamRoomStatisticsDto();

        List<Integer> childOrganIds = organizationService.getChildOrganIds(organId, true);

		examRoomStatisticsInfo.setTotalRegistrationStudentNum(examRegistrationDao.countTotalRegistrationStudentNumWithExam(childOrganIds, examId));
		examRoomStatisticsInfo.setInRoomStudentNum(examRegistrationDao.countInExamRoomStudentNum(childOrganIds, examId));

		List<ExamRoom> examRooms = examRoomDao.getWithExam(childOrganIds, examId);
		if(!CollectionUtils.isEmpty(examRooms)){
			examRoomStatisticsInfo.setExamRoomNum(examRooms.size());
			examRoomStatisticsInfo.setFirstExamTime(examRooms.stream().min(Comparator.comparing(ExamRoom::getExamStartTime)).get().getExamStartTime());
			examRoomStatisticsInfo.setLastExamTime(examRooms.stream().max(Comparator.comparing(ExamRoom::getExamStartTime)).get().getExamStartTime());
			int teacherNum=0;
			for (ExamRoom examRoom : examRooms) {
				if(Objects.nonNull(examRoom.getMainTeacherUserId())){
					teacherNum+=1;
				}
				if(StringUtils.isNotBlank(examRoom.getAssistantTeacherUserIdList())){
					teacherNum = teacherNum + StringUtils.countMatches(examRoom.getAssistantTeacherUserIdList(), ",") + 1;
				}
			}
			examRoomStatisticsInfo.setExamRoomTeacherNum(teacherNum);
		}

        return examRoomStatisticsInfo;
	}
}
