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

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.impl.BaseServiceImpl;
import com.keao.edu.common.tenant.TenantContextHolder;
import com.keao.edu.user.api.entity.ExamRoom;
import com.keao.edu.user.api.entity.ExamRoomStudentRelation;
import com.keao.edu.user.dao.*;
import com.keao.edu.user.dto.BaseUserInfoDto;
import com.keao.edu.user.dto.TeacherDto;
import com.keao.edu.user.entity.ExamTeacherSalary;
import com.keao.edu.user.entity.Teacher;
import com.keao.edu.user.enums.SettlementTypeEnum;
import com.keao.edu.user.enums.TeacherSettlementTypeEnum;
import com.keao.edu.user.page.ExamTeacherSalaryQueryInfo;
import com.keao.edu.user.service.ExamTeacherSalaryService;
import com.keao.edu.user.service.ExaminationBasicService;
import com.keao.edu.util.collection.MapUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class ExamTeacherSalaryServiceImpl extends BaseServiceImpl<Long, ExamTeacherSalary> implements ExamTeacherSalaryService {

	@Autowired
	private ExamRoomDao examRoomDao;
	@Autowired
	private ExamRoomStudentRelationDao examRoomStudentRelationDao;
	@Autowired
	private ExamTeacherSalaryDao examTeacherSalaryDao;
	@Autowired
	private TeacherDao teacherDao;

	@Override
	public BaseDAO<Long, ExamTeacherSalary> getDAO() {
		return examTeacherSalaryDao;
	}

	@Override
	public void teacherSalarySettlementWithExam(Integer examId) {
		List<ExamRoom> examRooms = examRoomDao.getWithExam(null, examId);
		if(CollectionUtils.isEmpty(examRooms)){
			return;
		}

		Map<Integer, List<ExamRoom>> teacherExamRoomMap=new HashMap<>();
		for (ExamRoom examRoom : examRooms) {
			if(!teacherExamRoomMap.containsKey(examRoom.getMainTeacherUserId())){
				teacherExamRoomMap.put(examRoom.getMainTeacherUserId(), new ArrayList<>());
			}
			teacherExamRoomMap.get(examRoom.getMainTeacherUserId()).add(examRoom);
			if(StringUtils.isBlank(examRoom.getAssistantTeacherUserIdList())){
				continue;
			}
			for (String assistantTeacherId : examRoom.getAssistantTeacherUserIdList().split(",")) {
				if(!teacherExamRoomMap.containsKey(Integer.valueOf(assistantTeacherId))){
					teacherExamRoomMap.put(Integer.valueOf(assistantTeacherId), new ArrayList<>());
				}
				teacherExamRoomMap.get(Integer.valueOf(assistantTeacherId)).add(examRoom);
			}
		}

		List<ExamRoomStudentRelation> examRoomStudentRelations = examRoomStudentRelationDao.getExamRoomStudentRelations(examId, null, null);

		List<ExamTeacherSalary> examTeacherSalaries = examTeacherSalaryDao.queryWithExam(examId);
		for (ExamTeacherSalary examTeacherSalary : examTeacherSalaries) {
			List<ExamRoom> teacherExamRooms = teacherExamRoomMap.get(examTeacherSalary.getTeacherId());
			if(CollectionUtils.isEmpty(teacherExamRooms)){
				examTeacherSalary.setTotalInvigilationNum(0);
				examTeacherSalary.setTotalInvigilationStudentNum(0);
				examTeacherSalary.setTotalSettlementCost(BigDecimal.ZERO);
				continue;
			}
			Set<Long> examRoomIds = teacherExamRooms.stream().map(ExamRoom::getId).collect(Collectors.toSet());
			long studentNum = examRoomStudentRelations.stream().filter(e -> examRoomIds.contains(e.getExamRoomId())).count();
			examTeacherSalary.setTotalInvigilationNum(examRoomIds.size());
			examTeacherSalary.setTotalInvigilationStudentNum((int) studentNum);
			examTeacherSalary.setTotalSettlementCost(examTeacherSalary.getShareProfitAmount().multiply(new BigDecimal(studentNum)));
		}
		examTeacherSalaryDao.batchUpdate(examTeacherSalaries);
	}

	@Override
	public void deleteExamTeacherSalary(Long examTeacherSalaryId) {
		ExamTeacherSalary examTeacherSalary = examTeacherSalaryDao.get(examTeacherSalaryId);
		if(Objects.isNull(examTeacherSalary)){
			throw new BizException("教室分润设置不能存在");
		}
		if(examTeacherSalary.getTotalInvigilationNum()>0){
			throw new BizException("该教室已被分配到考场");
		}
		examTeacherSalaryDao.delete(examTeacherSalaryId);
	}

	@Override
	public void addExamTeacherSalary(Integer examId, String teacherIdsStr) {
		if(Objects.isNull(examId)){
			throw new BizException("请指定考级项目");
		}
		if(StringUtils.isBlank(teacherIdsStr)){
			throw new BizException("请指定教师");
		}
		List<Integer> teacherIds = Arrays.stream(teacherIdsStr.split(",")).map(e -> Integer.valueOf(e)).collect(Collectors.toList());
		List<ExamTeacherSalary> withExamAndTeacher = examTeacherSalaryDao.getWithExamAndTeacher(examId, teacherIds);
		if(!CollectionUtils.isEmpty(withExamAndTeacher)){
			List<String> teacherNames = withExamAndTeacher.stream().map(e -> e.getTeacher().getRealName()).collect(Collectors.toList());
			throw new BizException("{}教师已存在", teacherNames);
		}
		List<Teacher> teachers = teacherDao.getWithTeachers(teacherIds);
		Map<Integer, Teacher> idTeacherMap = teachers.stream().collect(Collectors.toMap(Teacher::getUserId, t -> t));

		List<ExamTeacherSalary> examTeacherSalaries=new ArrayList<>();
		for (Integer teacherId : teacherIds) {
			Teacher teacher = idTeacherMap.get(teacherId);
			if(Objects.isNull(teacher)){
				throw new BizException("教师信息异常");
			}
			ExamTeacherSalary ets=new ExamTeacherSalary();
			ets.setExaminationBasicId(examId);
			ets.setTeacherId(teacherId);
			ets.setSettlementType(teacher.getSalarySettlementType());
			ets.setShareProfitAmount(teacher.getSalary());
			ets.setTotalSettlementCost(BigDecimal.ZERO);
			ets.setTotalInvigilationStudentNum(0);
			ets.setTotalInvigilationNum(0);
			ets.setTenantId(TenantContextHolder.getTenantId().toString());
			examTeacherSalaries.add(ets);
		}
		examTeacherSalaryDao.batchInsert(examTeacherSalaries);
	}

	@Override
	public List<BaseUserInfoDto> getExamTeachers(Integer examId) {
		if(Objects.isNull(examId)){
			throw new BizException("请指定考级项目");
		}
		return examTeacherSalaryDao.getTeachersWithExam(examId);
	}

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

		List<TeacherDto> dataList = new ArrayList<>();
		int count = examTeacherSalaryDao.countUnRelatedWithExamTeachers(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = examTeacherSalaryDao.queryUnRelatedWithExamTeachers(params);
			List<Integer> subjectIds=new ArrayList<>();
			for (TeacherDto teacher : dataList) {
				if(StringUtils.isBlank(teacher.getSubjectIdList())){
					continue;
				}
				for (String subjectId : teacher.getSubjectIdList().split(",")) {
					if(!subjectIds.contains(Integer.valueOf(subjectId))){
						subjectIds.add(Integer.valueOf(subjectId));
					}
				}
			}
			if(!CollectionUtils.isEmpty(subjectIds)){
				Map<Integer, String> subjectIdNameMap = this.getMap("subject", "id_", "name_", subjectIds, Integer.class, String.class);
				for (TeacherDto teacher : dataList) {
					if(StringUtils.isBlank(teacher.getSubjectIdList())){
						continue;
					}
					List<String> subjectNames=new ArrayList<>();
					for (String subjectId : teacher.getSubjectIdList().split(",")) {
						String subjectName = subjectIdNameMap.get(Integer.valueOf(subjectId));
						if(StringUtils.isNotBlank(subjectName)){
							subjectNames.add(subjectName);
						}
					}
					teacher.setSubjectNames(StringUtils.join(subjectNames, ","));
				}
			}
		}

		pageInfo.setRows(dataList);
		return pageInfo;
	}
}
