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

import com.alibaba.fastjson.JSONObject;
import com.keao.edu.auth.api.client.SysUserFeignService;
import com.keao.edu.auth.api.entity.SysUser;
import com.keao.edu.common.dal.BaseDAO;
import com.keao.edu.common.entity.SysConfig;
import com.keao.edu.common.enums.MessageTypeEnum;
import com.keao.edu.common.exception.BizException;
import com.keao.edu.common.page.PageInfo;
import com.keao.edu.common.service.IdGeneratorService;
import com.keao.edu.common.service.SysMessageService;
import com.keao.edu.common.service.impl.BaseServiceImpl;
import com.keao.edu.common.tenant.TenantContextHolder;
import com.keao.edu.im.api.client.ImFeignService;
import com.keao.edu.im.api.entity.MemberChangedMessage;
import com.keao.edu.im.api.entity.PublishMessageDto;
import com.keao.edu.im.api.entity.ReqUserData;
import com.keao.edu.thirdparty.message.provider.JiguangPushPlugin;
import com.keao.edu.thirdparty.message.provider.YimeiSmsPlugin;
import com.keao.edu.user.api.entity.ExamRoom;
import com.keao.edu.user.api.entity.ExamRoomStudentRelation;
import com.keao.edu.user.api.enums.ExamModeEnum;
import com.keao.edu.user.dao.*;
import com.keao.edu.user.dto.ExamRoomStudentRelationDto;
import com.keao.edu.user.dto.NeedCheckingDetailDto;
import com.keao.edu.user.dto.RoomStudentListDto;
import com.keao.edu.user.dto.StuRecordDetailDto;
import com.keao.edu.user.entity.*;
import com.keao.edu.user.page.ExamRoomStudentRelationQueryInfo;
import com.keao.edu.user.service.*;
import com.keao.edu.util.collection.MapUtil;
import com.keao.edu.util.date.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ExamRoomStudentRelationServiceImpl extends BaseServiceImpl<Long, ExamRoomStudentRelation> implements ExamRoomStudentRelationService {
	
	@Autowired
	private ExamRoomStudentRelationDao examRoomStudentRelationDao;
	@Autowired
	private ExamRoomDao examRoomDao;
	@Autowired
	private OrganizationService organizationService;
	@Autowired
	private StudentExamResultDao studentExamResultDao;
	@Autowired
	private ExamCertificationService examCertificationService;
	@Autowired
	private ExamLocationDao examLocationDao;
	@Autowired
	private ExamRegistrationDao examRegistrationDao;
	@Autowired
	private ExamTeacherSalaryService examTeacherSalaryService;
	@Autowired
	private ImFeignService imFeignService;
	@Autowired
	private SysUserFeignService sysUserFeignService;
	@Autowired
	private SysConfigDao sysConfigDao;
	@Autowired
	private ExaminationBasicDao examinationBasicDao;
	@Autowired
	private ExamOrganizationRelationDao examOrganizationRelationDao;
	@Autowired
	private SysMessageService sysMessageService;
	@Autowired
	private IdGeneratorService idGeneratorService;
	@Autowired
	private SysConfigService sysConfigService;

	@Override
	public BaseDAO<Long, ExamRoomStudentRelation> getDAO() {
		return examRoomStudentRelationDao;
	}

	@Override
	public void switchClassRoom(Integer openFlag, Integer examinationBasicId, Integer studentId) {
		examRoomStudentRelationDao.switchClassRoom(openFlag,examinationBasicId,studentId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
	public void addStudentForRoom(Long examRoomId, String registIdsStr, Integer organId) {
		if(Objects.isNull(examRoomId)){
			throw new BizException("请指定教室");
		}
		if(StringUtils.isBlank(registIdsStr)){
			throw new BizException("请指定学员报名编号");
		}
		ExamRoom examRoom = examRoomDao.lockRoom(examRoomId);
		if(Objects.isNull(examRoom)){
			throw new BizException("教室不存在");
		}
		Date now=new Date();
		if(now.compareTo(examRoom.getExamStartTime())>0||DateUtil.isSameDay(now, examRoom.getExamStartTime())){
			throw new BizException("无法添加学员");
		}

		ExamOrganizationRelation examOrganizationRelation = examOrganizationRelationDao.getExamOrganizationRelation(examRoom.getExaminationBasicId(), organId);
		if(Objects.isNull(examOrganizationRelation)||examOrganizationRelation.getIsAllowArrangeExam()==0){
			throw new BizException("无权操作");
		}

		ExamLocation examLocation = null;
		if(ExamModeEnum.OFFLINE.equals(examRoom.getExamMode())){
			examLocation = examLocationDao.get(examRoom.getExamLocationId());
			if(Objects.isNull(examLocation)){
				throw new BizException("考点信息错误");
			}
		}

		List<ExamRoomStudentRelation> studentsWithExamRoom = examRoomStudentRelationDao.findStudentsWithExamRoom(examRoomId);
		Set<Long> existRegistIds = studentsWithExamRoom.stream().map(ExamRoomStudentRelation::getExamRegistrationId).collect(Collectors.toSet());
		Set<Integer> existStudentIds = studentsWithExamRoom.stream().map(ExamRoomStudentRelation::getStudentId).collect(Collectors.toSet());

		String[] registIds = registIdsStr.split(",");

		List<ExamRegistration> examRegistrations = examRegistrationDao.getRegists(Arrays.asList(registIds).stream().map(e -> Long.valueOf(e)).collect(Collectors.toList()));
		Map<Integer, ExamRegistration> studentRegistMap = examRegistrations.stream().collect(Collectors.toMap(ExamRegistration::getId, e -> e));

		Set<Integer> studentIds = examRegistrations.stream().map(ExamRegistration::getStudentId).collect(Collectors.toSet());
		if(studentIds.size()!=registIds.length){
			throw new BizException("学员重复");
		}

		List<ExamRoomStudentRelation> examRoomStudentRelations=new ArrayList<>();
		List<ExamCertification> examCertifications=new ArrayList<>();
		List<StudentExamResult> studentExamResults=new ArrayList<>();
		for (String registId : registIds) {
			if(existRegistIds.contains(Long.valueOf(registId))){
				continue;
			}
			ExamRegistration examRegistration = studentRegistMap.get(Integer.valueOf(registId));
			if(Objects.isNull(examRegistration)){
				throw new BizException("学员信息错误");
			}
			if(existStudentIds.contains(examRegistration.getStudentId())){
				throw new BizException("学员重复");
			}

			ExamRoomStudentRelation e=new ExamRoomStudentRelation();
			e.setExamRegistrationId(Long.valueOf(registId));
			e.setExaminationBasicId(examRoom.getExaminationBasicId());
			e.setExamRoomId(examRoom.getId());
			e.setStudentId(examRegistration.getStudentId());
			e.setTenantId(TenantContextHolder.getTenantId());
			examRoomStudentRelations.add(e);

			if(examRoom.getExamPlanPushFlag()==1){
				ExamCertification ec=new ExamCertification();
				ec.setExamRegistrationId(examRegistration.getId().longValue());
				ec.setExaminationBasicId(examRegistration.getExaminationBasicId());
				ec.setStudentId(examRegistration.getStudentId());
				ec.setCardNo(String.valueOf(idGeneratorService.generatorId()));
				ec.setSubjectId(examRegistration.getSubjectId());
				ec.setLevel(examRegistration.getLevel());
				ec.setExamStartTime(examRoom.getExamStartTime());
				ec.setExamEndTime(examRoom.getExamEndTime());
				if(ExamModeEnum.OFFLINE.equals(examRoom.getExamMode())){
					ec.setExamAddress(examLocation.getName());
				}
				ec.setTenantId(TenantContextHolder.getTenantId());
				examCertifications.add(ec);

				StudentExamResult ser = new StudentExamResult();
				ser.setExamRegistrationId(examRegistration.getId().longValue());
				ser.setExaminationBasicId(examRegistration.getExaminationBasicId());
				ser.setStudentId(examRegistration.getStudentId());
				ser.setIsFinishedExam(3);
				ser.setConfirmStatus(0);
				ser.setTenantId(TenantContextHolder.getTenantId());
				ser.setExamRoomId(examRoom.getId());
				studentExamResults.add(ser);
			}
		}
		if(!CollectionUtils.isEmpty(examRoomStudentRelations)){
			examRoomStudentRelationDao.batchInsert(examRoomStudentRelations);
			examTeacherSalaryService.teacherSalarySettlementWithExam(examRoom.getExaminationBasicId());
			examRoom.setExamRoomStudentNum(examRoomStudentRelationDao.countStudentsWithRoom(examRoom.getId()));
			examRoomDao.update(examRoom);
		}
		if(!CollectionUtils.isEmpty(examCertifications)){
			examCertificationService.batchInsert(examCertifications);
		}
		if(!CollectionUtils.isEmpty(studentExamResults)){
			studentExamResultDao.batchInsert(studentExamResults);
			ExaminationBasic exam = examinationBasicDao.get(examRoom.getExaminationBasicId());
			SysConfig baseH5UrlConfig = sysConfigService.findByParamName(SysConfigService.BASE_H5_URL);
			String baseH5Url = "";
			if(Objects.nonNull(baseH5UrlConfig)){
				baseH5Url = baseH5UrlConfig.getParanValue();
			}

			Map<Integer, String> idPhoneMap = this.getMap("sys_user", "id_", "phone_", new ArrayList(studentIds), Integer.class, String.class);

			String baseUrl = "2?examRegistrationId=";
			String downloadUrl = baseH5Url + "/#/downLoad?memo=2&examRegistrationId=";
			for (ExamRoomStudentRelation examRoomStudentRelation : examRoomStudentRelations) {
				MessageTypeEnum pushMessageType = MessageTypeEnum.EXAM_ROOM_CONFIRM_ONLINE_STUDENT_PUSH;
				MessageTypeEnum smsMessageType = MessageTypeEnum.EXAM_ROOM_CONFIRM_ONLINE_STUDENT_SMS;

				Map<Integer, String> receiverMap = new HashMap<>(1);
				receiverMap.put(examRoomStudentRelation.getStudentId(), examRoomStudentRelation.getStudentId().toString());

				Map<Integer, String> phoneMap = new HashMap<>(1);
				phoneMap.put(examRoomStudentRelation.getStudentId(), idPhoneMap.get(examRoomStudentRelation.getStudentId()));

				String examName = exam.getName();

				String examDayStr = DateUtil.dateToString(examRoom.getExamStartTime(), "MM月dd日");
				StringBuffer examTimeStr = new StringBuffer();
				examTimeStr.append(DateUtil.dateToString(examRoom.getExamStartTime(), "HH时mm分"));
				examTimeStr.append("-");
				examTimeStr.append(DateUtil.dateToString(examRoom.getExamEndTime(), "HH时mm分"));

				String locationName = "网络考场";
				if(ExamModeEnum.OFFLINE.equals(examRoom.getExamMode())){
					pushMessageType = MessageTypeEnum.EXAM_ROOM_CONFIRM_OFFLINE_STUDENT_PUSH;
					smsMessageType = MessageTypeEnum.EXAM_ROOM_CONFIRM_OFFLINE_STUDENT_SMS;
					locationName=examLocation.getName();
				}
				String url = baseUrl + examRoomStudentRelation.getExamRegistrationId();
				sysMessageService.batchSendMessage(pushMessageType,
						receiverMap, null, 0, url, JiguangPushPlugin.PLUGIN_NAME,
						examName, examDayStr, examTimeStr, locationName);
				sysMessageService.batchSendMessage(smsMessageType,
						phoneMap, null, 0, null, YimeiSmsPlugin.PLUGIN_NAME,
						examName, examDayStr, examTimeStr, locationName, downloadUrl + examRoomStudentRelation.getExamRegistrationId());
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void changeStudentExamRoom(Long registId, Long examRoomId, Integer organId) {
		if(Objects.isNull(registId)){
			throw new BizException("请指定报名信息");
		}
		if(Objects.isNull(examRoomId)){
			throw new BizException("请指定新考场");
		}
		ExamRegistration examRegistration = examRegistrationDao.get(registId);
		if(Objects.isNull(examRegistration)){
			throw new BizException("学员报名信息不存在");
		}
		ExamRoom examRoom = examRoomDao.get(examRoomId);
		if(Objects.isNull(examRoom)){
			throw new BizException("考场信息不存在");
		}

		List<ExamRoomStudentRelation> studentsWithExamRoom = examRoomStudentRelationDao.findStudentsWithExamRoom(examRoomId);
		Set<Long> existRegistIds = studentsWithExamRoom.stream().map(ExamRoomStudentRelation::getExamRegistrationId).collect(Collectors.toSet());
		Set<Integer> existStudentIds = studentsWithExamRoom.stream().map(ExamRoomStudentRelation::getStudentId).collect(Collectors.toSet());

		if(existRegistIds.contains(Long.valueOf(registId))){
			throw new BizException("学员重复");
		}
		if(existStudentIds.contains(examRegistration.getStudentId())){
			throw new BizException("学员重复");
		}

		ExamOrganizationRelation examOrganizationRelation = examOrganizationRelationDao.getExamOrganizationRelation(examRoom.getExaminationBasicId(), organId);
		if(Objects.isNull(examOrganizationRelation)||examOrganizationRelation.getIsAllowArrangeExam()==0){
			throw new BizException("无权操作");
		}

		ExamRoomStudentRelation studentExamRoom = examRoomStudentRelationDao.getStudentExamRoom(registId);
		if(Objects.isNull(studentExamRoom)){
			studentExamRoom=new ExamRoomStudentRelation();
			studentExamRoom.setExaminationBasicId(examRegistration.getExaminationBasicId());
			studentExamRoom.setExamRoomId(examRoomId);
			studentExamRoom.setExamRegistrationId(examRegistration.getId().longValue());
			studentExamRoom.setStudentId(examRegistration.getStudentId());
			studentExamRoom.setClassroomSwitch(0);
			examRoomStudentRelationDao.insert(studentExamRoom);
			return;
		}
		studentExamRoom.setExamRoomId(examRoomId);
		examRoomStudentRelationDao.update(studentExamRoom);

		examRoom.setExamRoomStudentNum(examRoomStudentRelationDao.countStudentsWithRoom(examRoom.getId()));
		examRoomDao.update(examRoom);
	}

	@Override
	public PageInfo<ExamRoomStudentRelationDto> findExamRoomStudents(ExamRoomStudentRelationQueryInfo queryInfo) {
		if(Objects.nonNull(queryInfo.getInRoom())&&Objects.isNull(queryInfo.getExamRoomId())){
			throw new BizException("请指定考场");
		}

		PageInfo<ExamRoomStudentRelationDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
		Map<String, Object> params = new HashMap<String, Object>();
		MapUtil.populateMap(params, queryInfo);

		if(Objects.nonNull(queryInfo.getExamRoomId())){
			ExamRoom examRoom = examRoomDao.get(queryInfo.getExamRoomId());
			if(Objects.isNull(examRoom)){
				throw new BizException("考场不存在");
			}
			if(!examRoom.getExaminationBasicId().equals(queryInfo.getExamId())){
				throw new BizException("考场信息异常");
			}
			params.put("subjectIds", examRoom.getSubjectIdList());
		}

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

		List<ExamRoomStudentRelationDto> dataList = new ArrayList<>();
		int count = examRoomStudentRelationDao.countExamRoomStudents(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = examRoomStudentRelationDao.findExamRoomStudents(params);
			List<Integer> studentIds = dataList.stream().map(e->e.getExamRegistration().getStudentId()).collect(Collectors.toList());
			List<Integer> subjectIds = dataList.stream().map(e->e.getExamRegistration().getSubjectId()).collect(Collectors.toList());
			Map<Integer, String> studentIdNameMap = this.getMap("sys_user", "id_", "real_name_", studentIds, Integer.class, String.class);
			Map<Integer, String> subjectIdNameMap = this.getMap("subject", "id_", "name_", subjectIds, Integer.class, String.class);
			for (ExamRoomStudentRelationDto e : dataList) {
				e.setStudentInfo(new SysUser(e.getStudentId(),studentIdNameMap.get(e.getExamRegistration().getStudentId())));
				e.setSubject(new Subject(e.getExamRegistration().getSubjectId(), subjectIdNameMap.get(e.getExamRegistration().getSubjectId())));
			}
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
	public void deleteStudentFromRoom(Long examRoomId, String registIdsStr, Integer organId) {
		if(Objects.isNull(examRoomId)){
			throw new BizException("请指定教室");
		}
		ExamRoom examRoom = examRoomDao.lockRoom(examRoomId);
		if(Objects.isNull(examRoom)){
			throw new BizException("教室不存在");
		}

		if(examRoom.getExamPlanPushFlag()==1){
			throw new BizException("无法删除学员");
		}

		ExamOrganizationRelation examOrganizationRelation = examOrganizationRelationDao.getExamOrganizationRelation(examRoom.getExaminationBasicId(), organId);
		if(Objects.isNull(examOrganizationRelation)||examOrganizationRelation.getIsAllowArrangeExam()==0){
			throw new BizException("无权操作");
		}

		if(StringUtils.isBlank(registIdsStr)){
			return;
		}
		List<Long> registIds = Arrays.asList(registIdsStr.split(",")).stream().map(e -> Long.valueOf(e)).collect(Collectors.toList());
		examRoomStudentRelationDao.deleteStudentsFromExamRoom(examRoomId, registIds);
		studentExamResultDao.deleteWithRegists(registIds);
		examRoom.setExamRoomStudentNum(examRoomStudentRelationDao.countStudentsWithRoom(examRoom.getId()));
		examRoomDao.update(examRoom);
		examTeacherSalaryService.teacherSalarySettlementWithExam(examRoom.getExaminationBasicId());
	}

	@Override
	public ExamRoomStudentRelation getExamRoomStudentRelation(Long registrationId) {
		return examRoomStudentRelationDao.getStudentExamRoom(registrationId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void recorded(Long roomId) {
		List<RoomStudentListDto> roomStudentListDtos = examRoomStudentRelationDao.queryStudentList(roomId);
		if(roomStudentListDtos != null && roomStudentListDtos.size() > 0){
			SysUser sysUser = sysUserFeignService.queryUserInfo();
			RoomStudentListDto roomStudentListDto = roomStudentListDtos.get(0);
			if(roomStudentListDto.getFinishedExam() != 0){
				throw new BizException("操作失败：当前学员状态不支持录播");
			}
			ExamRoomStudentRelation examRoomStudentRelation = examRoomStudentRelationDao.get(roomStudentListDto.getExamRoomStudentRelationId());

			//修改学员考试状态
			StudentExamResult studentExamResult = studentExamResultDao.findByRegistrationId(examRoomStudentRelation.getExamRegistrationId());
			studentExamResult.setRecordFlag(1);
			studentExamResult.setIsFinishedExam(4);
			studentExamResultDao.update(studentExamResult);
			//关闭学员房间入口
			examRoomStudentRelation.setClassroomSwitch(0);
			examRoomStudentRelationDao.update(examRoomStudentRelation);
			publishMessage(examRoomStudentRelation,MemberChangedMessage.Action_Recorded,true,sysUser.getId());
			if(roomStudentListDtos.size() > 1){
				RoomStudentListDto roomStudentListDto1 = roomStudentListDtos.get(1);
				if(roomStudentListDto1.getFinishedExam() == 2){
					nextStudent(roomStudentListDto1.getExamRoomStudentRelationId(),false,sysUser.getId());
				}
			}
			//当等待人数到指定数值时，推送准备考试消息
			int actionExamPush = Integer.parseInt(sysConfigDao.findConfigValue("action_exam_push"));
			if(actionExamPush != 0 && roomStudentListDtos.size() > actionExamPush){
				RoomStudentListDto studentListDto = roomStudentListDtos.get(actionExamPush - 1);
				if(studentListDto.getFinishedExam() == 3){
					HashMap<Integer, String> map = new HashMap<>();
					map.put(studentListDto.getStudentId(),studentListDto.getStudentId().toString());
					String url = "3?examRegistrationId=" + studentListDto.getExamRegistrationId();
					sysMessageService.batchSendMessage(MessageTypeEnum.EXAM_WILL_START_PUSH,map,null,null,url, JiguangPushPlugin.PLUGIN_NAME);
				}
			}
			//将当前学员退踢出教室
//			imFeignService.kickRoom(new ReqUserData(examRoomStudentRelation.getExamRegistrationId(),roomStudentListDto.getStudentId().toString()));
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public NeedCheckingDetailDto stuRecorded(Long examRegistrationId) {
		//修改考试状态为录播
		/*StudentExamResult studentExamResult = studentExamResultDao.findByRegistrationId(examRegistrationId);
		studentExamResult.setRecordFlag(1);
		studentExamResult.setRecordStartTime(new Date());
		studentExamResultDao.update(studentExamResult);*/
		//返回详情数据
		return examCertificationService.needCheckingDetail(examRegistrationId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public NeedCheckingDetailDto againQueue(Long examRegistrationId) {
		//清除排队状态
		examRoomStudentRelationDao.cleanSignInTime(examRegistrationId);
		//返回详情数据
		return examCertificationService.needCheckingDetail(examRegistrationId);
	}

	@Override
	public List<ExamRoomStudentRelation> findStudentsWithExamRooms(List<Long> examRoomIds) {
		return examRoomStudentRelationDao.findStudentsWithExamRooms(examRoomIds);
	}

	@Override
	public void deleteWithExamRooms(List<Long> examRoomIds) {
		examRoomStudentRelationDao.deleteWithExamRooms(examRoomIds);
	}

	@Override
	public String getStudentIds(Long examRoomId) {
		return examRoomStudentRelationDao.getStudentIds(examRoomId);
	}

	@Override
	public List<Map<Integer, String>> getStuRegistrationMap(Long examRoomId) {
		return examRoomStudentRelationDao.getStuRegistrationMap(examRoomId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public StuRecordDetailDto stuRecordDetail(Long examRegistrationId) {
		StudentExamResult studentExamResult = studentExamResultDao.findByRegistrationId(examRegistrationId);
		//当前学员是否完成考试
		if(studentExamResult.getIsFinishedExam() != 4){
			throw new BizException("操作失败：当前状态不允许录播");
		}
		//是否允许录播
		if(studentExamResult.getRecordStartTime() == null){
			if(studentExamResult.getRecordFlag() == 0){
				studentExamResult.setRecordFlag(1);
				studentExamResult.setRecordStartTime(new Date());
				studentExamResultDao.update(studentExamResult);
			}else {
				studentExamResult.setRecordStartTime(new Date());
				studentExamResultDao.update(studentExamResult);
			}
		}


		StuRecordDetailDto stuRecordDetailDto = examRegistrationDao.getStuRecordDetail(examRegistrationId);
		int recordMinutes = Integer.parseInt(sysConfigDao.findConfigValue("record_minutes"));
		Date date = DateUtil.addMinutes(stuRecordDetailDto.getRecordStartTime(),recordMinutes);
		stuRecordDetailDto.setExamEndTime(date);
		int secondsBetween = DateUtil.secondsBetween(new Date(),date);
		if(secondsBetween <= 0){
			throw new BizException("操作失败：录制超时");
		}
		stuRecordDetailDto.setSubTime(secondsBetween);
		stuRecordDetailDto.setRecordTime(recordMinutes);
		stuRecordDetailDto.setExamRegistrationId(examRegistrationId);
		stuRecordDetailDto.setSongJson(stuRecordDetailDto.getSongJson());
		stuRecordDetailDto.setSingleSongRecordMinutes(Integer.parseInt(sysConfigDao.findConfigValue("single_song_record_minutes")));
		return stuRecordDetailDto;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void stuEndRecord(Long examRegistrationId, String videoUrl) {
		StudentExamResult studentExamResult = studentExamResultDao.findByRegistrationId(examRegistrationId);
		//当前学员是否完成考试
		if(studentExamResult.getIsFinishedExam() != 4){
			throw new BizException("提交失败：当前考试状态不允许录播");
		}
		studentExamResult.setVideoUrl(videoUrl);
		studentExamResult.setIsFinishedExam(5);
		studentExamResult.setRecordEndTime(new Date());
		studentExamResultDao.update(studentExamResult);
		ExamRoomStudentRelation roomStudentRelation = examRoomStudentRelationDao.getStudentExamRoom(examRegistrationId);
		publishMessage(roomStudentRelation,MemberChangedMessage.Student_Queue,true,studentExamResult.getStudentId());
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void actionExam(Long roomId) {
		ExamRoom examRoom = examRoomDao.get(roomId);
		if(examRoom.getExamFlag() == 1){
			throw new BizException("考试已开启，请勿重复操作");
		}
		examRoom.setExamFlag(1);
		examRoomDao.update(examRoom);
		nextBit(null,roomId);
	}

	@Override
	public Integer countSignInNum(Long examRoomId) {
		return examRoomStudentRelationDao.countSignInNum(examRoomId);
	}

	@Override
	public ExamRoomStudentRelation getStudentExamRoom(Long examRegistrationId) {
		return examRoomStudentRelationDao.getStudentExamRoom(examRegistrationId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void nextBit(Integer examStatus,Long examRoomId) {
		List<RoomStudentListDto> roomStudentListDtos = examRoomStudentRelationDao.queryStudentList(examRoomId);
		if(roomStudentListDtos != null && roomStudentListDtos.size() > 0){
			RoomStudentListDto roomStudentListDto = roomStudentListDtos.get(0);
			SysUser sysUser = sysUserFeignService.queryUserInfo();
			if(roomStudentListDto.getFinishedExam() == 0 || roomStudentListDto.getFinishedExam() == 1){
				//考试中
				currentStudent(roomStudentListDto.getExamRoomStudentRelationId(),true,examStatus,sysUser.getId());
				if(roomStudentListDtos.size() > 1){
					RoomStudentListDto roomStudentListDto1 = roomStudentListDtos.get(1);
					if(roomStudentListDto1.getFinishedExam() == 2){
						nextStudent(roomStudentListDto1.getExamRoomStudentRelationId(),false,sysUser.getId());
					}
				}
			}else if(roomStudentListDto.getFinishedExam() == 2){
				//未开始
				nextStudent(roomStudentListDto.getExamRoomStudentRelationId(),true,sysUser.getId());
			}else {
				throw new BizException("操作失败：没有待考学员");
			}
			//当等待人数到指定数值时，推送准备考试消息
			int actionExamPush = Integer.parseInt(sysConfigDao.findConfigValue("action_exam_push"));
			if(actionExamPush != 0 && roomStudentListDtos.size() > actionExamPush){
				RoomStudentListDto studentListDto = roomStudentListDtos.get(actionExamPush - 1);
				if(studentListDto.getFinishedExam() == 3){
					HashMap<Integer, String> map = new HashMap<>();
					map.put(studentListDto.getStudentId(),studentListDto.getStudentId().toString());
					String url = "3?examRegistrationId=" + studentListDto.getExamRegistrationId();
					sysMessageService.batchSendMessage(MessageTypeEnum.EXAM_WILL_START_PUSH,map,null,null,url, JiguangPushPlugin.PLUGIN_NAME);
				}
			}
		}
	}

	private void currentStudent(Long examRoomStudentRelationId,Boolean isPush,Integer examStatus,Integer operator){
		ExamRoomStudentRelation examRoomStudentRelation = examRoomStudentRelationDao.get(examRoomStudentRelationId);
		//将当前学员退出教室并添加参考状态，如果考试未完成，清除签到时间，重新签到
//
		if(examStatus != null && examStatus == 0){
			//未完成
			examRoomStudentRelationDao.cleanSignInTime(examRoomStudentRelation.getExamRegistrationId());
			examRoomStudentRelation.setSignInTime(null);
			studentExamResultDao.updateFinishedExam(examRoomStudentRelation.getExamRegistrationId(),3);
			publishMessage(examRoomStudentRelation,MemberChangedMessage.Not_Finish,isPush,operator);
			HashMap<Integer, String> map = new HashMap<>(1);
			map.put(examRoomStudentRelation.getStudentId(),examRoomStudentRelation.getStudentId().toString());
			ExaminationBasic examinationBasic = examinationBasicDao.get(examRoomStudentRelation.getExaminationBasicId());
			sysMessageService.batchSendMessage(MessageTypeEnum.EXAM_ROOM_STUDENT_SIGN_IN_AGAIN_PUSH,map,null,null,null,JiguangPushPlugin.PLUGIN_NAME,examinationBasic.getName());
		}else {
            imFeignService.kickRoom(new ReqUserData(examRoomStudentRelation.getExamRegistrationId(),examRoomStudentRelation.getStudentId().toString()));
			//结束考试
			studentExamResultDao.updateFinishedExam(examRoomStudentRelation.getExamRegistrationId(),5);
		}
		//关闭学员房间入口
		examRoomStudentRelation.setClassroomSwitch(0);
		examRoomStudentRelationDao.update(examRoomStudentRelation);
		publishMessage(examRoomStudentRelation,MemberChangedMessage.Student_Queue,isPush,operator);
	}

	private void nextStudent(Long nextExamRoomStudentRelationId,Boolean isPush,Integer operator){
		ExamRoomStudentRelation examRoomStudentRelation = examRoomStudentRelationDao.get(nextExamRoomStudentRelationId);
		//开启学员房间入口
		examRoomStudentRelation.setClassroomSwitch(1);
		examRoomStudentRelationDao.update(examRoomStudentRelation);
		HashMap<Integer, String> map = new HashMap<>(1);
		map.put(examRoomStudentRelation.getStudentId(),examRoomStudentRelation.getStudentId().toString());
		String url = "3?examRegistrationId=" + nextExamRoomStudentRelationId;
		sysMessageService.batchSendMessage(MessageTypeEnum.EXAM_STARTED_PUSH,map,null,null,url,JiguangPushPlugin.PLUGIN_NAME);

		//状态变更为呼叫中
		studentExamResultDao.updateFinishedExam(examRoomStudentRelation.getExamRegistrationId(),1);
		publishMessage(examRoomStudentRelation,MemberChangedMessage.Student_Queue,isPush,operator);
	}

	@Override
	public void publishMessage(ExamRoomStudentRelation examRoomStudentRelation,Integer action,Boolean isPush,Integer operator){
		if (!isPush){
			return;
		}
		PublishMessageDto publishMessageDto = new PublishMessageDto();
		publishMessageDto.setUserId(operator.toString());
		publishMessageDto.setRoomId(examRoomStudentRelation.getExamRoomId().toString());
		MemberChangedMessage msg = new MemberChangedMessage(action, examRoomStudentRelation.getStudentId().toString(),3);
		/*if(action == 3 || action == 4){
			msg = new MemberChangedMessage(action, examRoomStudentRelation.getStudentId().toString(),3);
		}else {
			msg = new MemberChangedMessage(action, examRoomStudentRelation.getStudentId(),3);
		}*/
//		String jsonString = JSONObject.toJSONString(examCertificationService.needCheckingDetail(examRoomStudentRelation.getExamRegistrationId()));
		NeedCheckingDetailDto needCheckingDetailDto = examCertificationService.needCheckingDetail(examRoomStudentRelation.getExamRegistrationId());
		msg.setWaitNum(needCheckingDetailDto.getWaitNum());
		msg.setClassroomSwitch(needCheckingDetailDto.getClassroomSwitch());
		msg.setOpenFlag(needCheckingDetailDto.getOpenFlag());
//		msg.setAppParamJson(jsonString);
		Map<String,Object> paramMap = new HashMap<>(2);

		paramMap.put("studentQueue",this.queryNeedCheckingList(examRoomStudentRelation.getExamRoomId()));
		paramMap.put("examCertification",examCertificationService.findDetailByStudentId(examRoomStudentRelation.getExamRegistrationId()));
		msg.setWebParamJson(JSONObject.toJSONString(paramMap));
		publishMessageDto.setMemberChangedMessage(msg);
		imFeignService.publishMessage(publishMessageDto);
	}

	public PublishMessageDto getPublishMessage(Long examRegistrationId){
		SysUser sysUser = sysUserFeignService.queryUserInfo();
		ExamRoomStudentRelation examRoomStudentRelation = examRoomStudentRelationDao.getStudentExamRoom(examRegistrationId);
		PublishMessageDto publishMessageDto = new PublishMessageDto();
		String userId = sysUser.getId().toString();
		publishMessageDto.setUserId(userId);
		publishMessageDto.setRoomId(examRoomStudentRelation.getExamRoomId().toString());
		MemberChangedMessage msg = new MemberChangedMessage(MemberChangedMessage.Student_Queue, examRoomStudentRelation.getStudentId().toString(),3);
//		String jsonString = JSONObject.toJSONString(examCertificationService.needCheckingDetail(examRoomStudentRelation.getExamRegistrationId()));
//		msg.setAppParamJson(jsonString);
		NeedCheckingDetailDto needCheckingDetailDto = examCertificationService.needCheckingDetail(examRoomStudentRelation.getExamRegistrationId());
		msg.setWaitNum(needCheckingDetailDto.getWaitNum());
		msg.setClassroomSwitch(needCheckingDetailDto.getClassroomSwitch());
		msg.setOpenFlag(needCheckingDetailDto.getOpenFlag());
		Map<String,Object> paramMap = new HashMap<>(2);
		this.queryNeedCheckingList(examRoomStudentRelation.getExamRoomId());
		paramMap.put("studentQueue",this.queryNeedCheckingList(examRoomStudentRelation.getExamRoomId()));
		paramMap.put("examCertification",examCertificationService.findDetailByStudentId(examRoomStudentRelation.getExamRegistrationId()));
		msg.setWebParamJson(JSONObject.toJSONString(paramMap));
		publishMessageDto.setMemberChangedMessage(msg);
		return publishMessageDto;
	}

	@Override
	public Map<String, Object> queryNeedCheckingList(Long roomId) {
		List<RoomStudentListDto> roomStudentListDtos = examRoomStudentRelationDao.queryStudentList(roomId);
		Map<String,Object> resultMap = new HashMap<>(3);
		resultMap.put("studentList",roomStudentListDtos);
		resultMap.put("totalNum",examRoomStudentRelationDao.queryTotalNum(roomId));
		resultMap.put("endNum",examRoomStudentRelationDao.queryEndNum(roomId));
//		resultMap.put("surplusNum",examRoomStudentRelationDao.querySurplusNum(roomId));
		return resultMap;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public synchronized void signIn(Long examRegistrationId) {
		ExamRoomStudentRelation studentExamRoom = examRoomStudentRelationDao.getStudentExamRoom(examRegistrationId);
		if(studentExamRoom.getSignInTime() != null){
			throw new BizException("您已签到,请勿重复操作!");
		}
		studentExamRoom.setSignInTime(new Date());
		examRoomStudentRelationDao.update(studentExamRoom);
		SysUser sysUser = sysUserFeignService.queryUserInfo();
		PublishMessageDto publishMessageDto = new PublishMessageDto();
		String userId = sysUser.getId().toString();
		publishMessageDto.setUserId(userId);
		publishMessageDto.setRoomId(studentExamRoom.getExamRoomId().toString());
		MemberChangedMessage msg = new MemberChangedMessage(MemberChangedMessage.Student_Queue, userId,3);
//		String jsonString = JSONObject.toJSONString(examCertificationService.needCheckingDetail(examRegistrationId));
		NeedCheckingDetailDto needCheckingDetailDto = examCertificationService.needCheckingDetail(examRegistrationId);
//		msg.setAppParamJson(needCheckingDetailDto.getWaitNum());
		msg.setWaitNum(needCheckingDetailDto.getWaitNum());
		msg.setClassroomSwitch(0);
		msg.setOpenFlag(needCheckingDetailDto.getOpenFlag());
		publishMessageDto.setMemberChangedMessage(msg);
		//修改签到状态
		studentExamResultDao.updateFinishedExam(examRegistrationId,2);
		imFeignService.publishMessage(publishMessageDto);
	}
}
