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

import com.keao.edu.auth.api.entity.SysUser;
import com.keao.edu.common.dal.BaseDAO;
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.impl.BaseServiceImpl;
import com.keao.edu.common.tenant.TenantContextHolder;
import com.keao.edu.user.api.entity.ExamRoom;
import com.keao.edu.user.dao.*;
import com.keao.edu.user.dto.ExamRoomStudentRelationDto;
import com.keao.edu.user.api.entity.ExamRoomStudentRelation;
import com.keao.edu.user.entity.*;
import com.keao.edu.user.page.ExamRoomStudentRelationQueryInfo;
import com.keao.edu.user.service.ExamCertificationService;
import com.keao.edu.user.service.ExamRoomStudentRelationService;
import com.keao.edu.user.service.ExamTeacherSalaryService;
import com.keao.edu.user.service.OrganizationService;
import com.keao.edu.util.collection.MapUtil;
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 ExamCertificationDao examCertificationDao;
	@Autowired
	private ExamLocationDao examLocationDao;
	@Autowired
	private IdGeneratorService idGeneratorService;
	@Autowired
	private ExamRegistrationDao examRegistrationDao;
	@Autowired
	private ExamTeacherSalaryService examTeacherSalaryService;

	@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 studentIdsStr) {
		if(Objects.isNull(examRoomId)){
			throw new BizException("请指定教室");
		}
		if(StringUtils.isBlank(studentIdsStr)){
			throw new BizException("请指定学员");
		}
		ExamRoom examRoom = examRoomDao.lockRoom(examRoomId);
		if(Objects.isNull(examRoom)){
			throw new BizException("教室不存在");
		}
		ExamLocation examLocation = examLocationDao.get(examRoom.getExamLocationId());

		List<ExamRoomStudentRelation> studentsWithExamRoom = examRoomStudentRelationDao.findStudentsWithExamRoom(examRoomId);
		Set<Integer> existStudentIds = studentsWithExamRoom.stream().map(ExamRoomStudentRelation::getStudentId).collect(Collectors.toSet());
		String[] studentIds = studentIdsStr.split(",");

		List<ExamRegistration> examRegistrations = examRegistrationDao.getWithExamAndStudents(examRoom.getExaminationBasicId(), Arrays.asList(studentIds).stream().map(e -> Integer.valueOf(e)).collect(Collectors.toList()));
		Map<Integer, ExamRegistration> studentRegistMap = examRegistrations.stream().collect(Collectors.toMap(ExamRegistration::getStudentId, e -> e));

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

			ExamRoomStudentRelation e=new ExamRoomStudentRelation();
			e.setExaminationBasicId(examRoom.getExaminationBasicId());
			e.setExamRoomId(examRoom.getId());
			e.setStudentId(Integer.valueOf(studentId));
			e.setTenantId(TenantContextHolder.getTenantId().toString());
			examRoomStudentRelations.add(e);

			StudentExamResult ser = new StudentExamResult();
			ser.setExaminationBasicId(examRoom.getExaminationBasicId());
			ser.setStudentId(Integer.valueOf(studentId));
			ser.setIsFinishedExam(false);
			ser.setConfirmStatus(false);
			ser.setTenantId(TenantContextHolder.getTenantId().toString());
			studentExamResults.add(ser);

			ExamCertification ec=new ExamCertification();
			ec.setExaminationBasicId(examRoom.getExaminationBasicId());
			ec.setStudentId(Integer.valueOf(studentId));
			ec.setCardNo(String.valueOf(idGeneratorService.generatorId()));
			ec.setSubjectId(examRegistration.getSubjectId());
			ec.setLevel(examRegistration.getLevel());
			ec.setExamStartTime(examRoom.getExamStartTime());
			ec.setExamEndTime(examRoom.getExamEndTime());
			ec.setExamAddress(examLocation.getAddress());
			ec.setTenantId(TenantContextHolder.getTenantId().toString());
			examCertifications.add(ec);
		}
		if(!CollectionUtils.isEmpty(examRoomStudentRelations)){
			examRoomStudentRelationDao.batchInsert(examRoomStudentRelations);
			examTeacherSalaryService.teacherSalarySettlementWithExam(examRoom.getExaminationBasicId());
		}
		if(!CollectionUtils.isEmpty(studentExamResults)){
			studentExamResultDao.batchInsert(studentExamResults);
		}
		if(!CollectionUtils.isEmpty(examCertifications)){
			examCertificationDao.batchInsert(examCertifications);
		}
	}

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

		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(ExamRoomStudentRelationDto::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.getStudentId())));
				e.setSubject(new Subject(e.getExamRegistration().getSubjectId(), subjectIdNameMap.get(e.getExamRegistration().getSubjectId())));
			}
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	@Override
	public void deleteStudentFromRoom(Long examRoomId, String studentIdsStr) {
		if(Objects.isNull(examRoomId)){
			throw new BizException("请指定教室");
		}
		ExamRoom examRoom = examRoomDao.get(examRoomId);
		if(Objects.isNull(examRoom)){
			throw new BizException("教室不存在");
		}
		if(StringUtils.isBlank(studentIdsStr)){
			return;
		}
		List<Integer> studentIds = Arrays.asList(studentIdsStr.split(",")).stream().map(e -> Integer.valueOf(e)).collect(Collectors.toList());
		examRoomStudentRelationDao.deleteStudentsFromExamRoom(examRoomId, studentIds);
		examTeacherSalaryService.teacherSalarySettlementWithExam(examRoom.getExaminationBasicId());
	}

	@Override
	public ExamRoomStudentRelation getExamRoomStudentRelation(Integer basicId, String roomId, Integer studentId) {
		return examRoomStudentRelationDao.getExamRoomStudentRelation(basicId,roomId,studentId);
	}
}
