package com.ym.mec.biz.service.impl;

import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PayUserType.STUDENT;
import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentCalenderStatusEnum.*;
import static com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus.NON_PAYMENT;
import static com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus.PAID_COMPLETED;
import static com.ym.mec.biz.dal.enums.PaymentStatusEnum.YES;

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

import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.MusicArrearageStudentDto;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.CourseViewTypeEnum;
import com.ym.mec.biz.dal.enums.PeriodEnum;
import com.ym.mec.biz.dal.enums.StudentMusicGroupStatusEnum;
import com.ym.mec.biz.dal.page.ArrearageStudentsQueryInfo;
import com.ym.mec.biz.event.source.GroupEventSource;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.constant.CommonConstants;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.page.QueryInfo;
import com.ym.mec.biz.dal.enums.YesOrNoEnum;

import com.ym.mec.util.date.DateUtil;
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.transaction.annotation.Transactional;

import com.ym.mec.biz.dal.dto.FeeStudentDto;
import com.ym.mec.biz.dal.dto.SimpleUserDto;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentCalenderStatusEnum;
import com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus;
import com.ym.mec.biz.dal.enums.MessageTypeEnum;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.collection.MapUtil;

@Service
public class MusicGroupPaymentCalenderDetailServiceImpl extends BaseServiceImpl<Long, MusicGroupPaymentCalenderDetail>  implements MusicGroupPaymentCalenderDetailService {
	
	@Autowired
	private MusicGroupPaymentCalenderDetailDao musicGroupPaymentCalenderDetailDao;
	@Autowired
	private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;
	@Autowired
	private MusicGroupPaymentCalenderService musicGroupPaymentCalenderService;
	
	@Autowired
	private MusicGroupPaymentCalenderCourseSettingsDao musicGroupPaymentCalenderCourseSettingsDao;
	
	@Autowired
	private MusicGroupPaymentStudentCourseDetailDao musicGroupPaymentStudentCourseDetailDao;

	@Autowired
	private MusicGroupPaymentCalenderStudentDetailDao musicGroupPaymentCalenderStudentDetailDao;
	
	@Autowired
	private MusicGroupDao musicGroupDao;
	@Autowired
	private SysConfigDao sysConfigDao;
	@Autowired
	private MusicGroupStudentFeeDao musicGroupStudentFeeDao;
	@Autowired
	private StudentRegistrationDao studentRegistrationDao;
	@Autowired
	private SysMessageService sysMessageService;
	@Autowired
	private GroupEventSource groupEventSource;
	@Autowired
	private StudentService studentService;
	@Autowired
	private CloudTeacherOrderDao cloudTeacherOrderDao;

	@Override
	public BaseDAO<Long, MusicGroupPaymentCalenderDetail> getDAO() {
		return musicGroupPaymentCalenderDetailDao;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateExpectAmount(BigDecimal expectAmount,BigDecimal expectMemberAmount,String ids) {
		if((expectAmount == null && expectMemberAmount == null) || StringUtils.isEmpty(ids)){
			throw new BizException("参数校验失败");
		}
		if(expectAmount == null){
			expectAmount = BigDecimal.ZERO;
		}
		if(expectMemberAmount == null){
			expectMemberAmount = BigDecimal.ZERO;
		}
		//获取缴费列表
		List<MusicGroupPaymentCalenderDetail> calenderDetails = musicGroupPaymentCalenderDetailDao.queryListByIds(ids);
		if(calenderDetails.size() == 0){
			throw new BizException("缴费记录不存在");
		}
		Date date = new Date();
		MusicGroupPaymentCalender calender = musicGroupPaymentCalenderService.get(calenderDetails.get(0).getMusicGroupPaymentCalenderId());
		MusicGroup musicGroup = musicGroupDao.get(calender.getMusicGroupId());
		//缴费项目已结束，并且没有单独开启缴费的学员，不能修改缴费金额
//		if(calender.getStatus() == OVER){
//			List<MusicGroupPaymentCalenderDetail> paymentCalenderDetails = calenderDetails.stream().filter(e -> e.getOpenFlag() == YesOrNoEnum.NO).collect(Collectors.toList());
//			if(paymentCalenderDetails != null && paymentCalenderDetails.size() > 0){
//				throw new BizException("修改失败：存在未开启缴费的学员");
//			}
//		}
		if(calender.getPaymentAmount().doubleValue() > 0d){
			BigDecimal totalAmount = calender.getPaymentAmount();
			BigDecimal subExpectAmount = expectAmount;
			if(calender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.SPAN_GROUP_CLASS_ADJUST){
				List<MusicGroupPaymentCalenderStudentDetail> studentDetails = musicGroupPaymentCalenderStudentDetailDao.findByBatchNoAndUserId(calender.getBatchNo(), calenderDetails.get(0).getUserId());
				if(studentDetails.size() == 0){
					throw new BizException("修改失败：缴费项目数据异常");
				}
				List<Integer> studentIds = calenderDetails.stream().map(e -> e.getUserId()).collect(Collectors.toList());
				for (int i = 0; i < studentDetails.size(); i++) {
					MusicGroupPaymentCalenderStudentDetail studentDetail = studentDetails.get(i);
					if(i == studentDetails.size() - 1){
						musicGroupPaymentCalenderStudentDetailDao.updateByCourseType(studentDetail.getCourseType(),calender.getBatchNo(),studentIds,subExpectAmount);
					}else {
						BigDecimal divide = studentDetail.getCourseCurrentPrice().divide(totalAmount, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN);
						BigDecimal courseAmount = divide.multiply(expectAmount).setScale(0, BigDecimal.ROUND_DOWN);
						subExpectAmount = subExpectAmount.subtract(courseAmount);
						musicGroupPaymentCalenderStudentDetailDao.updateByCourseType(studentDetail.getCourseType(),calender.getBatchNo(),studentIds,courseAmount);
					}
				}
			}else {
				List<MusicGroupPaymentCalenderCourseSettings> courseSettingsList = musicGroupPaymentCalenderCourseSettingsDao.getWithPaymentCalender(calender.getId());
				if(courseSettingsList.size() == 0){
					throw new BizException("修改失败：缴费项目数据异常");
				}
				for (int i = 0; i < courseSettingsList.size(); i++) {
					MusicGroupPaymentCalenderCourseSettings courseSettings = courseSettingsList.get(i);
					if(i == courseSettingsList.size() - 1){
						musicGroupPaymentStudentCourseDetailDao.updateByCourseType(courseSettings.getCourseType().getCode(),ids,subExpectAmount);
					}else {
						BigDecimal divide = courseSettings.getCourseCurrentPrice().divide(totalAmount, CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN);
						BigDecimal courseAmount = divide.multiply(expectAmount).setScale(0, BigDecimal.ROUND_DOWN);
						subExpectAmount = subExpectAmount.subtract(courseAmount);
						musicGroupPaymentStudentCourseDetailDao.updateByCourseType(courseSettings.getCourseType().getCode(),ids,courseAmount);
					}
				}
			}
		}
		//为了解决学员欠费数量的问题，只要学员没有缴费就可以修改金额
		Set<Integer> studentIds = new HashSet<>();
		for (MusicGroupPaymentCalenderDetail e : calenderDetails) {
			if(e.getPaymentStatus() == null || e.getPaymentStatus() != NON_PAYMENT){
				throw new BizException("修改失败：缴费状态不匹配");
			}
			e.setUpdateTime(date);
			e.setExpectAmount(expectAmount);
			e.setExpectMemberAmount(expectMemberAmount);

			if(expectAmount.doubleValue() > 0 || expectMemberAmount.doubleValue() > 0){
				if((e.getOpen() != null && e.getOpen() == 1) || calender.getStatus() == PaymentCalenderStatusEnum.OPEN){
					studentIds.add(e.getUserId());
				}
			}else {
				// 添加会员有效时长
				if(calender.getMemberRankSettingId() != null){
					CloudTeacherOrder cloudTeacherOrder = new CloudTeacherOrder();
					cloudTeacherOrder.setOrganId(musicGroup.getOrganId());
					cloudTeacherOrder.setType(2);
					cloudTeacherOrder.setTime(calender.getMemberValidDate());
					//只用会员价格
					cloudTeacherOrder.setAmount(expectMemberAmount);
					cloudTeacherOrder.setStudentId(e.getUserId());
					cloudTeacherOrder.setLevel(calender.getMemberRankSettingId());
					cloudTeacherOrder.setStatus(2);
					cloudTeacherOrder.setStartTime(date);
					cloudTeacherOrder.setEndTime(DateUtil.addMonths(date,calender.getMemberValidDate()));
					cloudTeacherOrder.setRemark("进行中乐团加学生,缴费金额改为0元");
					cloudTeacherOrderDao.insert(cloudTeacherOrder);
					studentService.updateMemberRank(e.getUserId(),calender.getMemberRankSettingId(),PeriodEnum.MONTH,calender.getMemberValidDate());
				}
				calender.setActualNum((calender.getActualNum()==null?0:calender.getActualNum()) + 1);
				e.setPaymentStatus(PAID_COMPLETED);
				if(calender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.ADD_STUDENT){
					MusicGroupStudentFee musicGroupStudentFee = musicGroupStudentFeeDao.findByUser(e.getUserId(), calender.getMusicGroupId());
					if (musicGroupStudentFee != null) {
						musicGroupStudentFee.setUpdateTime(date);
						musicGroupStudentFee.setLatestPaidTime(date);
						musicGroupStudentFee.setPaymentStatus(PaymentStatus.PAID_COMPLETED);
						musicGroupStudentFee.setTemporaryCourseFee(new BigDecimal(0));
						musicGroupStudentFeeDao.update(musicGroupStudentFee);
					}
					//如果是进行中加学员
					StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(e.getUserId(), calender.getMusicGroupId());
					studentRegistration.setPaymentStatus(YES);
					studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
					studentRegistrationDao.update(studentRegistration);

					//统计变更学员数
					groupEventSource.musicGroupStudentChangeEvent(calender.getMusicGroupId(), StudentMusicGroupStatusEnum.NORMAL, new ArrayList<>(Arrays.asList(e.getUserId())));
				}
			}
		}
		musicGroupPaymentCalenderDao.update(calender);
		musicGroupPaymentCalenderDetailDao.batchUpdate(calenderDetails);
		//推送消息
		if (calender.getPayUserType() == STUDENT && studentIds.size() > 0) {
			Map<Integer, String> push = new HashMap<>();
			for (Integer userId : studentIds) {
				push.put(userId, userId + "");
			}
			String baseUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);
			String memo = "4?" + baseUrl + "/#/musicGroupRenew?calenderId="+calender.getId()+"&id=" + calender.getMusicGroupId();
			// 发送续费通知
			sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_WAIT_RENEW_MESSAGE, push,
					null, 0, memo,"STUDENT",musicGroup.getName());

			//获取未缴费且不是0元的学员列表
			Map<Integer,String> studentMaps = MapUtil.convertMybatisMap(musicGroupPaymentCalenderDetailDao.queryNoPaymentAndNotZeroStudent(calender.getId(),studentIds));
			if(studentMaps.size() > 0){
				sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.STUDENT_SMS_WAIT_RENEW_MESSAGE, studentMaps,
						null, 0, memo, null, musicGroup.getName());
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public String openPayment(String ids) {
		if(StringUtils.isEmpty(ids)){
			throw new BizException("参数校验失败");
		}
		//获取可开启缴费列表
		List<MusicGroupPaymentCalenderDetail> calenderDetails = musicGroupPaymentCalenderDetailDao.queryCanOpenList(ids);
		if(calenderDetails.size() == 0){
			return "操作失败：所选学员已开启缴费，或已完成缴费";
		}
		int length = ids.split(",").length;
		Date date = new Date();
		Long calenderId = calenderDetails.get(0).getMusicGroupPaymentCalenderId();
		MusicGroupPaymentCalender calender = musicGroupPaymentCalenderService.get(calenderId);
		calenderDetails.forEach(e->{
			e.setUpdateTime(date);
			e.setOpen(1);
			e.setStartPaymentDate(date);
			e.setDeadlinePaymentDate(date);
		});
		musicGroupPaymentCalenderDetailDao.batchUpdate(calenderDetails);
		Set<Integer> studentIds = calenderDetails.stream().map(e -> e.getUserId()).collect(Collectors.toSet());
		//推送消息
		if (calender.getPayUserType() == STUDENT && studentIds.size() > 0) {
			Map<Integer, String> push = new HashMap<>();
			for (Integer userId : studentIds) {
				push.put(userId, userId + "");
			}
			MusicGroup musicGroup = musicGroupDao.get(calender.getMusicGroupId());
			String baseUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);
			String memo = "4?" + baseUrl + "/#/musicGroupRenew?calenderId="+calender.getId()+"&id=" + calender.getMusicGroupId();
			// 发送续费通知
			sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_WAIT_RENEW_MESSAGE, push,
					null, 0, memo,"STUDENT",musicGroup.getName());
			//获取未缴费且不是0元的学员列表
			Map<Integer,String> studentMaps = MapUtil.convertMybatisMap(musicGroupPaymentCalenderDetailDao.queryNoPaymentAndNotZeroStudent(calender.getId(),studentIds));
			if(studentMaps.size() > 0){
				sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.STUDENT_SMS_WAIT_RENEW_MESSAGE, studentMaps,
						null, 0, memo, null, musicGroup.getName());
			}
		}
		StringBuffer append = new StringBuffer("操作成功: 成功开启缴费").append(studentIds.size()).append("条,失败").append(length - studentIds.size()).append("条");
		return append.toString();
	}

	@Override
	public List<SimpleUserDto> findMusicGroupStudentWithSubject(String musicGroupId, Integer subjectId) {
		if(Objects.isNull(musicGroupId)){
			throw new BizException("请指定乐团");
		}
		return musicGroupPaymentCalenderDetailDao.findMusicGroupStudentWithSubject(musicGroupId, subjectId);
	}

	@Override
	public void refreshUserMusicGroupPaymentStatusTask() {
		musicGroupPaymentCalenderDetailDao.refreshUserMusicGroupPaymentStatusTask();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void batchAdd(Long musicGroupPaymentCalenderId, Set<Integer> userIdList,MusicGroup musicGroup) {
		
		MusicGroupPaymentCalender musicGroupPaymentCalender = musicGroupPaymentCalenderService.get(musicGroupPaymentCalenderId);
		if(musicGroupPaymentCalender == null){
			throw new BizException("查询缴费信息失败");
		}
		if(musicGroupPaymentCalender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.MUSIC_APPLY){
			throw new BizException("操作失败：报名缴费项不允许添加学员");
		}
		if (musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.AUDITING
				|| musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.REJECT) {
			throw new BizException("当前缴费状态不能添加学生");
		}
		
		//判断学生是否已存在
		Set<Integer> userList = musicGroupPaymentCalenderDetailDao.queryStudentIds(musicGroupPaymentCalenderId);

		if(Collections.disjoint(userList, userIdList) == false){
			throw new BizException("操作失败：包含已存在的学员");
		}
		
		List<MusicGroupPaymentCalenderCourseSettings> courseSettingsList = musicGroupPaymentCalenderCourseSettingsDao.getWithPaymentCalender(musicGroupPaymentCalenderId);

		//总金额 = 会员费用 + 课程费用
		BigDecimal expectAmount = BigDecimal.ZERO;
		BigDecimal expectMemberAmount = musicGroupPaymentCalender.getMemberPaymentAmount();
		if (musicGroupPaymentCalender.getPayUserType() == STUDENT) {
			if (musicGroupPaymentCalender.getPayUserType() == STUDENT) {
				for (MusicGroupPaymentCalenderCourseSettings courseSettings : courseSettingsList) {
					// 剔除可选课程
					if (courseSettings.getIsStudentOptional() == false) {
						expectAmount = expectAmount.add(courseSettings.getCourseCurrentPrice());
					}
				}
			}
		}

		Date date = new Date();
		MusicGroupPaymentCalenderDetail musicGroupPaymentCalenderDetail = null;
		Map<Integer,MusicGroupPaymentCalenderDetail> userMap = new HashMap<Integer, MusicGroupPaymentCalenderDetail>();
		List<MusicGroupPaymentCalenderDetail> musicGroupPaymentCalenderDetailList = new ArrayList<MusicGroupPaymentCalenderDetail>();
		//创建缴费明细
		for(Integer studentId : userIdList){
			musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
			musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalenderId);
			musicGroupPaymentCalenderDetail.setCreateTime(date);
			musicGroupPaymentCalenderDetail.setExpectAmount(expectAmount);
			musicGroupPaymentCalenderDetail.setExpectMemberAmount(expectMemberAmount);
			if (expectAmount.doubleValue() == 0d && expectMemberAmount.doubleValue() == 0d) {
				musicGroupPaymentCalenderDetail.setActualAmount(BigDecimal.ZERO);
				musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.PAID_COMPLETED);
			} else {
				musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.NON_PAYMENT);
			}
			musicGroupPaymentCalenderDetail.setUpdateTime(date);
			musicGroupPaymentCalenderDetail.setUserId(studentId);
			musicGroupPaymentCalenderDetail.setStartPaymentDate(musicGroupPaymentCalender.getStartPaymentDate());
			musicGroupPaymentCalenderDetail.setDeadlinePaymentDate(musicGroupPaymentCalender.getDeadlinePaymentDate());
			musicGroupPaymentCalenderDetail.setResponsibleUserId(musicGroupPaymentCalender.getOperator());

			musicGroupPaymentCalenderDetailList.add(musicGroupPaymentCalenderDetail);
		}

		if (musicGroupPaymentCalenderDetailList.size() > 0) {
			musicGroupPaymentCalenderDetailDao.batchInsert(musicGroupPaymentCalenderDetailList);
			for(MusicGroupPaymentCalenderDetail cd : musicGroupPaymentCalenderDetailList){
				userMap.put(cd.getUserId(), cd);
			}
		}
		//更新预计缴费人数
		musicGroupPaymentCalender.setExpectNum(musicGroupPaymentCalender.getExpectNum() + userIdList.size());
		if (expectAmount.doubleValue() == 0d && expectMemberAmount.doubleValue() == 0d) {
			musicGroupPaymentCalender.setActualNum(musicGroupPaymentCalender.getActualNum() + userIdList.size());
		}
		musicGroupPaymentCalender.setUpdateTime(date);
		musicGroupPaymentCalenderService.update(musicGroupPaymentCalender);

		List<MusicGroupPaymentStudentCourseDetail> musicGroupPaymentStudentCourseDetailList = new ArrayList<MusicGroupPaymentStudentCourseDetail>();
		MusicGroupPaymentStudentCourseDetail musicGroupPaymentStudentCourseDetail = null;
		if(courseSettingsList.size() > 0){
			//创建学生课排课分钟数
			for(Integer studentId : userIdList){
				for(MusicGroupPaymentCalenderCourseSettings courseSettings : courseSettingsList){
					if (courseSettings.getIsStudentOptional() == true || courseSettings.getCourseTotalMinuties() == null || courseSettings.getCourseTotalMinuties() == 0) {
						continue;
					}
					musicGroupPaymentStudentCourseDetail = new MusicGroupPaymentStudentCourseDetail();
					musicGroupPaymentStudentCourseDetail.setCourseType(courseSettings.getCourseType());
					musicGroupPaymentStudentCourseDetail.setCreateTime(date);
					musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalenderId);
					musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderDetailId(userMap.get(studentId).getId());
					musicGroupPaymentStudentCourseDetail.setTotalCourseMinutes(courseSettings.getCourseTotalMinuties());
					musicGroupPaymentStudentCourseDetail.setCourseOriginalPrice(courseSettings.getCourseOriginalPrice());
					musicGroupPaymentStudentCourseDetail.setCourseCurrentPrice(courseSettings.getCourseCurrentPrice());
					musicGroupPaymentStudentCourseDetail.setUpdateTime(date);
					musicGroupPaymentStudentCourseDetail.setUsedCourseMinutes(0);
					musicGroupPaymentStudentCourseDetail.setUserId(studentId);
					musicGroupPaymentStudentCourseDetailList.add(musicGroupPaymentStudentCourseDetail);
				}
			}
		}

		if(musicGroupPaymentStudentCourseDetailList.size() > 0){
			musicGroupPaymentStudentCourseDetailDao.batchInsert(musicGroupPaymentStudentCourseDetailList);
		}
		//给学员推送缴费通知
		if(musicGroupPaymentCalender.getPayUserType() == STUDENT && musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.OPEN){
			musicGroupPaymentCalenderService.pushWaitRenewMessage(musicGroupPaymentCalenderId,musicGroupDao.get(musicGroupPaymentCalender.getMusicGroupId()),userIdList);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void batchAdd(MusicGroupPaymentCalender musicGroupPaymentCalender,List<MusicGroupPaymentCalenderStudentDetail> musicGroupPaymentCalenderStudentDetails) {
		Map<Integer, List<MusicGroupPaymentCalenderStudentDetail>> collect = musicGroupPaymentCalenderStudentDetails.stream().collect(Collectors.groupingBy(e -> e.getUserId()));
		MusicGroupPaymentCalenderDetail musicGroupPaymentCalenderDetail = null;
		Long musicGroupPaymentCalenderId = musicGroupPaymentCalender.getId();
		for (Integer studentId : collect.keySet()) {
			musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
			musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalenderId);
			musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.NON_PAYMENT);
			List<MusicGroupPaymentCalenderStudentDetail> calenderStudentDetails = collect.get(studentId);
			BigDecimal totalPrice = calenderStudentDetails.stream().map(e->e.getCourseCurrentPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
			musicGroupPaymentCalenderDetail.setExpectAmount(totalPrice);
			if(musicGroupPaymentCalender.getStatus() != AUDITING){
				if (totalPrice.doubleValue() == 0d) {
					musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.PAID_COMPLETED);
					musicGroupPaymentCalenderDetail.setActualAmount(totalPrice);
				}
			}
			musicGroupPaymentCalenderDetail.setMusicGroupId(musicGroupPaymentCalender.getMusicGroupId());
			musicGroupPaymentCalenderDetail.setUserId(studentId);
			musicGroupPaymentCalenderDetail.setStartPaymentDate(musicGroupPaymentCalender.getStartPaymentDate());
			musicGroupPaymentCalenderDetail.setDeadlinePaymentDate(musicGroupPaymentCalender.getDeadlinePaymentDate());
			musicGroupPaymentCalenderDetail.setResponsibleUserId(musicGroupPaymentCalender.getOperator());
			musicGroupPaymentCalenderDetailDao.insert(musicGroupPaymentCalenderDetail);
		}
		musicGroupPaymentCalender.setExpectNum(collect.keySet().size());
		musicGroupPaymentCalenderService.update(musicGroupPaymentCalender);
		//给学员推送缴费通知
		if(musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.OPEN){
			musicGroupPaymentCalenderService.pushWaitRenewMessage(musicGroupPaymentCalenderId,musicGroupDao.get(musicGroupPaymentCalender.getMusicGroupId()),collect.keySet());
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void batchAdd(String batchNo, Set<Integer> userIdList) {
		
		List<MusicGroupPaymentCalender> musicGroupPaymentCalenderList = musicGroupPaymentCalenderDao.findByBatchNo(batchNo);
		if(musicGroupPaymentCalenderList == null || musicGroupPaymentCalenderList.size() == 0){
			throw new BizException("操作失败：缴费项目不存在");
		}
		String musicGroupId = musicGroupPaymentCalenderList.get(0).getMusicGroupId();
		// 所有缴费项目已完成排课才能创建下一个缴费项目
		List<String> batchNoList = new ArrayList<>();
		batchNoList.add(batchNo);
		String orignBatchNo = musicGroupPaymentStudentCourseDetailDao.getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(musicGroupId, null, null,batchNoList);
		if (StringUtils.isNoneBlank(orignBatchNo)) {
			throw new BizException("当前乐团存在未排课的缴费项目，请先完成排课再操作");
		}
		//获取欠费学员列表
		List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(musicGroupId, new ArrayList<>(userIdList));
		if(noPaymentUserIds.size() > 0){
			throw new BizException("操作失败：有欠费的学员不允许创建缴费");
		}
		//获取缴费状态在审核中或者已拒绝的缴费项目的学员
		String studentIds = musicGroupPaymentCalenderDao.queryCalenderStudentIds(musicGroupId,batchNo);
		if(StringUtils.isNotEmpty(studentIds)){
			for (Integer integer : userIdList) {
				if(studentIds.contains(integer.toString())){
					throw new BizException("操作失败：所选学员有待审核或已拒绝的缴费项目");
				}
			}
		}
		List<MusicGroupPaymentStudentCourseDetail> musicGroupPaymentStudentCourseDetailList = new ArrayList<MusicGroupPaymentStudentCourseDetail>();
		
		Long musicGroupPaymentCalenderId = null;
		for(MusicGroupPaymentCalender musicGroupPaymentCalender : musicGroupPaymentCalenderList){
			musicGroupPaymentCalenderId = musicGroupPaymentCalender.getId();
			
			if(musicGroupPaymentCalender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.MUSIC_APPLY){
				throw new BizException("操作失败：报名缴费项不允许添加学员");
			}
			if (musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.AUDITING
					|| musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.REJECT) {
				throw new BizException("当前缴费状态不能添加学生");
			}
			
			//判断学生是否已存在
			Set<Integer> userList = musicGroupPaymentCalenderDetailDao.queryStudentIds(musicGroupPaymentCalenderId);

			if(Collections.disjoint(userList, userIdList) == false){
				throw new BizException("操作失败：包含已存在的学员");
			}
			
			List<MusicGroupPaymentCalenderCourseSettings> courseSettingsList = musicGroupPaymentCalenderCourseSettingsDao.getWithPaymentCalender(musicGroupPaymentCalenderId);
			
			BigDecimal expectAmount = BigDecimal.ZERO;
			BigDecimal expectMemberAmount = musicGroupPaymentCalender.getMemberPaymentAmount();

			if (musicGroupPaymentCalender.getPayUserType() == STUDENT) {
				for (MusicGroupPaymentCalenderCourseSettings courseSettings : courseSettingsList) {
					// 剔除可选课程
					if (courseSettings.getIsStudentOptional() == false) {
						expectAmount = expectAmount.add(courseSettings.getCourseCurrentPrice());
					}
				}
			}
			
			Date date = new Date();
			MusicGroupPaymentCalenderDetail musicGroupPaymentCalenderDetail = null;
			Map<Integer,MusicGroupPaymentCalenderDetail> userMap = new HashMap<Integer, MusicGroupPaymentCalenderDetail>();
			List<MusicGroupPaymentCalenderDetail> musicGroupPaymentCalenderDetailList = new ArrayList<MusicGroupPaymentCalenderDetail>();
			//创建缴费明细
			for(Integer studentId : userIdList){
				musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
				musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalenderId);
				musicGroupPaymentCalenderDetail.setCreateTime(date);
				musicGroupPaymentCalenderDetail.setExpectAmount(expectAmount);
				musicGroupPaymentCalenderDetail.setExpectMemberAmount(expectMemberAmount);
				if (expectAmount.doubleValue() == 0d && expectMemberAmount.doubleValue() == 0d) {
					musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.PAID_COMPLETED);
				} else {
					musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.NON_PAYMENT);
				}
				musicGroupPaymentCalenderDetail.setUpdateTime(date);
				musicGroupPaymentCalenderDetail.setUserId(studentId);
				musicGroupPaymentCalenderDetail.setStartPaymentDate(musicGroupPaymentCalender.getStartPaymentDate());
				musicGroupPaymentCalenderDetail.setDeadlinePaymentDate(musicGroupPaymentCalender.getDeadlinePaymentDate());
				musicGroupPaymentCalenderDetail.setResponsibleUserId(musicGroupPaymentCalender.getOperator());
				
				musicGroupPaymentCalenderDetailList.add(musicGroupPaymentCalenderDetail);
			}

			if (musicGroupPaymentCalenderDetailList.size() > 0) {
				musicGroupPaymentCalenderDetailDao.batchInsert(musicGroupPaymentCalenderDetailList);
				for(MusicGroupPaymentCalenderDetail cd : musicGroupPaymentCalenderDetailList){
					userMap.put(cd.getUserId(), cd);
				}
			}
			//更新预计缴费人数
			musicGroupPaymentCalender.setExpectNum(musicGroupPaymentCalender.getExpectNum() + userIdList.size());
			musicGroupPaymentCalender.setUpdateTime(date);
			if (expectAmount.doubleValue() == 0d && expectMemberAmount.doubleValue() == 0d) {
				musicGroupPaymentCalender.setActualNum(musicGroupPaymentCalender.getActualNum() + userIdList.size());
			}
			musicGroupPaymentCalenderService.update(musicGroupPaymentCalender);
			
			MusicGroupPaymentStudentCourseDetail musicGroupPaymentStudentCourseDetail = null;
			//创建学生课排课分钟数
			for(Integer studentId : userIdList){
				for(MusicGroupPaymentCalenderCourseSettings courseSettings : courseSettingsList){
					if (courseSettings.getIsStudentOptional() == true || courseSettings.getCourseTotalMinuties() == null || courseSettings.getCourseTotalMinuties() == 0) {
						continue;
					}
					musicGroupPaymentStudentCourseDetail = new MusicGroupPaymentStudentCourseDetail();
					musicGroupPaymentStudentCourseDetail.setCourseType(courseSettings.getCourseType());
					musicGroupPaymentStudentCourseDetail.setCreateTime(date);
					musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalenderId);
					musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderDetailId(userMap.get(studentId).getId());
					musicGroupPaymentStudentCourseDetail.setTotalCourseMinutes(courseSettings.getCourseTotalMinuties());
					musicGroupPaymentStudentCourseDetail.setCourseOriginalPrice(courseSettings.getCourseOriginalPrice());
					musicGroupPaymentStudentCourseDetail.setCourseCurrentPrice(courseSettings.getCourseCurrentPrice());
					musicGroupPaymentStudentCourseDetail.setUpdateTime(date);
					musicGroupPaymentStudentCourseDetail.setUsedCourseMinutes(0);
					musicGroupPaymentStudentCourseDetail.setUserId(studentId);
					
					musicGroupPaymentStudentCourseDetailList.add(musicGroupPaymentStudentCourseDetail);
				}
			}
		}
		
		if(musicGroupPaymentStudentCourseDetailList.size() > 0){
			musicGroupPaymentStudentCourseDetailDao.batchInsert(musicGroupPaymentStudentCourseDetailList);
		}
		//给学员推送缴费通知
		for (MusicGroupPaymentCalender musicGroupPaymentCalender : musicGroupPaymentCalenderList) {
			if (musicGroupPaymentCalender.getPayUserType() == STUDENT && musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.OPEN) {
				musicGroupPaymentCalenderService.pushWaitRenewMessage(musicGroupPaymentCalender.getId(),
						musicGroupDao.get(musicGroupPaymentCalender.getMusicGroupId()),userIdList);
			}
		}
	}

	@Override
	public List<FeeStudentDto> queryFeeStudents(String musicGroupId,String search,Integer subjectId) {
		return musicGroupStudentFeeDao.queryFeeStudents(musicGroupId,search,subjectId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void batchDel(String musicGroupPaymentCalenderDetailIds) {
		List<MusicGroupPaymentCalenderDetail> details = musicGroupPaymentCalenderDetailDao.queryListByIds(musicGroupPaymentCalenderDetailIds);
		if(details == null || details.size() == 0){
			throw new BizException("删除失败: 数据不可为空");
		}
		Long musicGroupPaymentCalenderId = details.get(0).getMusicGroupPaymentCalenderId();
		MusicGroupPaymentCalender musicGroupPaymentCalender = musicGroupPaymentCalenderDao.get(musicGroupPaymentCalenderId);
		
		if(musicGroupPaymentCalender == null){
			throw new BizException("查询缴费项目失败[{}]", musicGroupPaymentCalender);
		}
		
		long count = 0;
		if (musicGroupPaymentCalender.getPayUserType() == STUDENT) {
			// 是否已缴费
			count = details.stream().filter(e -> e.getPaymentStatus() != NON_PAYMENT).count();
			if (count > 0) {
				throw new BizException("删除失败: 存在已缴费的学员");
			}
		}
		List<Long> musicGroupPaymentCalenderDetailIdList = new ArrayList<Long>();
		for(String s : musicGroupPaymentCalenderDetailIds.split(",")){
			musicGroupPaymentCalenderDetailIdList.add(Long.parseLong(s));
		}
		//是否已排课
		List<MusicGroupPaymentStudentCourseDetail> musicGroupPaymentStudentCourseDetailList = musicGroupPaymentStudentCourseDetailDao.queryByMusicGroupPaymentStudentCourseDetailId(musicGroupPaymentCalenderDetailIdList);
		count = musicGroupPaymentStudentCourseDetailList.stream().filter(e -> e.getUsedCourseMinutes() > 0).count();
		if(count > 0){
			throw new BizException("删除失败：存在已排课的学员");
		}
		
		int currentNum = musicGroupPaymentCalender.getExpectNum() - details.size();
		musicGroupPaymentCalender.setExpectNum(currentNum < 0 ? 0 : currentNum);
		musicGroupPaymentCalender.setUpdateTime(new Date());
		musicGroupPaymentCalenderDao.update(musicGroupPaymentCalender);
		
		musicGroupPaymentCalenderDetailDao.batchDel(musicGroupPaymentCalenderDetailIds);
		musicGroupPaymentStudentCourseDetailDao.deleteByMusicGroupPaymentCalenderDetailId(musicGroupPaymentCalenderDetailIdList);
	}

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

		Set<Integer> organIds = null;
		if(StringUtils.isNotBlank(queryInfo.getOrganIds())){
			organIds = Arrays.stream(queryInfo.getOrganIds().split(",")).map(Integer::new).collect(Collectors.toSet());
		}
		params.put("organIds", organIds);

		List<MusicArrearageStudentDto> dataList = null;
		int count = musicGroupPaymentCalenderDetailDao.countArrearageStudents(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = musicGroupPaymentCalenderDetailDao.queryArrearageStudents(params);
		}
		if (count == 0) {
			dataList = new ArrayList<>();
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	@Override
	public List<MusicGroup> getNoPaymentStudentMusicGroups(String organIdsStr) {
		Set<Integer> organIds = null;
		if(StringUtils.isNotBlank(organIdsStr)){
			organIds = Arrays.stream(organIdsStr.split(",")).map(Integer::new).collect(Collectors.toSet());
		}
		return musicGroupPaymentCalenderDetailDao.getNoPaymentStudentMusicGroups(organIds);
	}

	@Override
	public void pushWaitRenewMessage(Long calenderId, String studentIds) {
		List<MusicGroupPaymentCalenderDetail> calenderDetails = musicGroupPaymentCalenderDetailDao.queryNoPaymentCanPushByCalenderId(calenderId,studentIds);
		if(calenderDetails == null || calenderDetails.size() == 0){
			throw new BizException("发送失败：没有可以发送缴费提醒的学员");
		}
		Set<Integer> studentIdList = calenderDetails.stream().map(e -> e.getUserId()).collect(Collectors.toSet());
		MusicGroupPaymentCalender paymentCalender = musicGroupPaymentCalenderDao.get(calenderId);
		//未缴费
		Map<Integer,String> studentMaps = MapUtil.convertMybatisMap(musicGroupPaymentCalenderDetailDao.queryNoPaymentAndNotZeroStudent(calenderId,studentIdList));
		MusicGroup musicGroup = musicGroupDao.get(paymentCalender.getMusicGroupId());
		String baseUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);
		String memo = "4?" + baseUrl + "/#/musicGroupRenew?calenderId="+calenderId+"&id=" + musicGroup.getId();
		Map<Integer, String> push = new HashMap<>();
		for (Integer userId : studentIdList) {
			push.put(userId, userId.toString());
		}
		// 发送续费通知
		sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_WAIT_RENEW_MESSAGE, push,
				null, 0, memo, "STUDENT", musicGroup.getName());
		sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.STUDENT_SMS_WAIT_RENEW_MESSAGE, studentMaps,
				null, 0, memo, null, musicGroup.getName());
	}
}
