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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.dal.page.ActivityStudentQueryInfo;
import com.ym.mec.biz.dal.page.ActivityUserQueryInfo;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.controller.BaseController;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.entity.HttpResponseResult;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

import static com.ym.mec.biz.dal.enums.GroupType.ACTIVITY;
import static java.math.BigDecimal.ROUND_DOWN;
import static java.math.BigDecimal.ZERO;

@Service
public class ActivityUserMapperServiceImpl extends BaseServiceImpl<Integer, ActivityUserMapper>  implements ActivityUserMapperService {
	
	@Autowired
	private ActivityUserMapperDao activityUserMapperDao;
	@Autowired
	private ActivityUserMapperAdjustLogDao activityUserMapperAdjustLogDao;
	@Autowired
	private VipGroupActivityDao vipGroupActivityDao;
	@Autowired
	private StudentDao studentDao;
	@Autowired
	private TeacherDao teacherDao;
	@Autowired
	private SysUserCashAccountLogService sysUserCashAccountLogService;
	@Autowired
	private SysUserFeignService sysUserFeignService;
	@Autowired
	private SysConfigDao sysConfigDao;
	@Autowired
	private SubjectDao subjectDao;
	@Autowired
	private CourseScheduleService courseScheduleService;
	@Autowired
	private VipGroupCategoryService vipGroupCategoryService;
	@Autowired
	private VipGroupDao vipGroupDao;
	@Autowired
	private VipGroupService vipGroupService;
	@Autowired
	private VipGroupStudentCoursePriceDao vipGroupStudentCoursePriceDao;
	@Autowired
	private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
	@Autowired
	private CourseScheduleTeacherSalaryService courseScheduleTeacherSalaryService;
	@Autowired
	private VipGroupDefaultClassesUnitPriceDao vipGroupDefaultClassesUnitPriceDao;
	@Autowired
	private ClassGroupTeacherMapperDao classGroupTeacherMapperDao;
	@Autowired
	private ClassGroupTeacherSalaryDao classGroupTeacherSalaryDao;
	@Autowired
	private ClassGroupStudentMapperDao classGroupStudentMapperDao;
	@Autowired
	private ClassGroupDao classGroupDao;
	@Autowired
	private PracticeGroupDao practiceGroupDao;
	@Autowired
	private PracticeGroupService practiceGroupService;
	@Autowired
	private SysUserService sysUserService;
	@Autowired
	private TeacherService teacherService;
	@Autowired
	private PracticeGroupSellPriceDao practiceGroupSellPriceDao;
	@Autowired
	private ImGroupService imGroupService;
	@Autowired
	private ImGroupMemberService imGroupMemberService;
	@Autowired
	private ImUserFriendService imUserFriendService;

	@Override
	public BaseDAO<Integer, ActivityUserMapper> getDAO() {
		return activityUserMapperDao;
	}

    @Override
    public List<ActivityUserMapper> findByStudentIdList(Integer activityId, String studentIds, String type) {
        return activityUserMapperDao.findByStudentIdList(activityId,studentIds,type);
    }

	@Override
	public int use(String activityUserMapperIds, String studentIds, String type,Long groupId) {
		return activityUserMapperDao.use(activityUserMapperIds,studentIds,type,groupId);
	}

	@Override
	public int countActivityBuyNum(Integer activityId, Integer userId) {
		return activityUserMapperDao.countActivityBuyNum(activityId,userId);
	}

    @Override
    public void batchInsert(List<ActivityUserMapper> activityUserMappers) {
		activityUserMapperDao.batchInsert(activityUserMappers);
    }

	@Override
	public ActivityUserMapper findVipUserMapper(Long groupId, String groupType,Integer studentId) {
		return activityUserMapperDao.findVipUserMapper(groupId,groupType,studentId);
	}

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

		List<ActivityStudentDto> dataList = null;
		int count = activityUserMapperDao.countActivityUserMapper(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = activityUserMapperDao.queryActivityUserMapper(params);
		}
		if (count == 0) {
			dataList = new ArrayList<>();
		}
		pageInfo.setRows(dataList);
		return pageInfo;
    }

    @Override
	@Transactional(rollbackFor = Exception.class)
    public void add(ActivityUserMapperAddDto activityUserMapperAddDto) {
		List<ActivityStudentAdjustDto> activityStudentAdjustDtos = activityUserMapperAddDto.getActivityStudentAdjustDtos();
		if(activityStudentAdjustDtos == null || activityStudentAdjustDtos.size() == 0){
        	throw new BizException("请选择学员");
		}
		Integer activityId = activityUserMapperAddDto.getActivityId();
		String memo = activityUserMapperAddDto.getMemo();
		VipGroupActivity activity = vipGroupActivityDao.get(activityId);
		if(activity == null){
			throw new BizException("活动信息不存在");
		}
		if(activity.getActivityType() != 0){
			throw new BizException("操作失败:只有课程活动支持此操作");
		}
		SysUser sysUser = sysUserFeignService.queryUserInfo();
		Integer operatorId = sysUser.getId();
		String operatorName = sysUser.getRealName();
		Integer minCourseNum = activity.getMinCourseNum();

		List<Integer> studentIds = activityStudentAdjustDtos.stream().map(e -> e.getUserId()).collect(Collectors.toList());
		List<Student> studentTeacher = studentDao.findByStudentIds(studentIds);
		Map<Integer, List<Student>> collect = studentTeacher.stream().collect(Collectors.groupingBy(Student::getUserId));
		String courseType = activity.getCourseType();
		Integer giveCourseNum = activity.getGiveCourseNum();
		String giveCourseType = activity.getGiveCourseType();
		List<ActivityUserMapper> activityUserMappers = new ArrayList<>();
		List<ActivityUserMapperAdjustLog> activityUserMapperAdjustLogs = new ArrayList<>();
		for (ActivityStudentAdjustDto adjustDto : activityStudentAdjustDtos) {
			//添加操作记录
			ActivityUserMapperAdjustLog activityUserMapperAdjustLog = new ActivityUserMapperAdjustLog();
			activityUserMapperAdjustLog.setActivityId(activityId);
			activityUserMapperAdjustLog.setOperatorId(operatorId);
			activityUserMapperAdjustLog.setOperatorName(operatorName);
			activityUserMapperAdjustLog.setCourseNum(adjustDto.getCourseNum());
			activityUserMapperAdjustLog.setGiveCourseNum(adjustDto.getGiveCourseNum());
			activityUserMapperAdjustLog.setMemo(memo);
			activityUserMapperAdjustLog.setUserId(adjustDto.getUserId());
			activityUserMapperAdjustLog.setType(1);
			activityUserMapperAdjustLogs.add(activityUserMapperAdjustLog);

			int activityUserMapperNum = adjustDto.getCourseNum();
			if(giveCourseNum != null && giveCourseNum > 0){
				if(adjustDto.getGiveCourseNum() > activityUserMapperNum){
					activityUserMapperNum = adjustDto.getGiveCourseNum();
				}
			}
			if(activityUserMapperNum <= 0){
				throw new BizException("操作失败:加课次数不可为空");
			}
			List<Student> students = collect.get(adjustDto.getUserId());
			Integer teacherId = null;
			if(students != null && students.size() > 0){
				teacherId = students.get(0).getTeacherId();
			}
			for (int i = 0; i < activityUserMapperNum; i++) {
				ActivityUserMapper activityUserMapper = new ActivityUserMapper();
				activityUserMapper.setActivityId(activityId);
				activityUserMapper.setUserId(adjustDto.getUserId());
				activityUserMapper.setActualPrice(BigDecimal.ZERO);
				activityUserMapper.setSubNoCoursePrice(BigDecimal.ZERO);
				activityUserMapper.setReturnFee(false);
				activityUserMapper.setTeacherId(teacherId);
				activityUserMapper.setAddMemo(memo);
				boolean buyFlag = adjustDto.getCourseNum() > i;
				if(buyFlag){
					if("VIP".equals(courseType)){
						activityUserMapper.setVipFlag(1);
					}else {
						activityUserMapper.setPracticeFlag(1);
					}
				}
				boolean giveFlag = adjustDto.getGiveCourseNum() > i && giveCourseNum != null && giveCourseNum > 0;
				if(giveFlag){
					if("VIP".equals(giveCourseType)){
						activityUserMapper.setGiveVipFlag(1);
					}else {
						activityUserMapper.setGivePracticeFlag(1);
					}
				}
				this.copyProperty(activityUserMapper,activity,giveFlag,buyFlag);
				activityUserMappers.add(activityUserMapper);
			}
		}
		activityUserMapperAdjustLogDao.batchInsert(activityUserMapperAdjustLogs);
		activityUserMapperDao.batchInsert(activityUserMappers);
	}

	//拷贝部分属性
	public void copyProperty(ActivityUserMapper activityUserMapper,VipGroupActivity activity,boolean giveFlag,boolean buyFlag){
		if(buyFlag){
			activityUserMapper.setTotalCourseNum(activity.getMinCourseNum());
			activityUserMapper.setSubCourseNum(activity.getMinCourseNum());
			activityUserMapper.setSingleCourseTime(activity.getSingleCourseTime());
			if(StringUtils.isNotEmpty(activity.getVipGroupCategoryIdList())){
				activityUserMapper.setCategoryId(Integer.parseInt(activity.getVipGroupCategoryIdList()));
			}
		}
		if(giveFlag){
			activityUserMapper.setGiveSingleCourseTime(activity.getGiveSingleCourseTime());
			activityUserMapper.setTotalGiveCourseNum(activity.getGiveCourseNum());
			activityUserMapper.setSubGiveCourseNum(activity.getGiveCourseNum());
			if(StringUtils.isNotEmpty(activity.getGiveCategoryId())){
				activityUserMapper.setGiveCategoryId(Integer.parseInt(activity.getGiveCategoryId()));
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void cut(Integer activityUserMapperId, String memo, BigDecimal amount) {
		ActivityUserMapper activityUserMapper = activityUserMapperDao.get(activityUserMapperId);
		if(activityUserMapper.getVipFlag() == 2 ||
				activityUserMapper.getGiveVipFlag() == 2 ||
				activityUserMapper.getPracticeFlag() == 2 ||
				activityUserMapper.getGivePracticeFlag() == 2 || activityUserMapper.getReturnFee()){
			throw new BizException("操作失败：活动已消耗");
		}
		activityUserMapper.setCutMemo(memo);
		activityUserMapper.setReturnFee(true);
		activityUserMapperDao.update(activityUserMapper);

		SysUser sysUser = sysUserFeignService.queryUserInfo();
		Integer operatorId = sysUser.getId();
		String operatorName = sysUser.getRealName();
		//添加操作记录
		ActivityUserMapperAdjustLog activityUserMapperAdjustLog = new ActivityUserMapperAdjustLog();
		activityUserMapperAdjustLog.setActivityId(activityUserMapper.getActivityId());
		activityUserMapperAdjustLog.setOperatorId(operatorId);
		activityUserMapperAdjustLog.setOperatorName(operatorName);
		if(activityUserMapper.getVipFlag() == 1 || activityUserMapper.getPracticeFlag() == 1){
			activityUserMapperAdjustLog.setCourseNum(-1);
		}
		if(activityUserMapper.getGiveVipFlag() == 1 || activityUserMapper.getGivePracticeFlag() == 1){
			activityUserMapperAdjustLog.setGiveCourseNum(-1);
		}
		activityUserMapperAdjustLog.setMemo(memo);
		activityUserMapperAdjustLog.setUserId(activityUserMapper.getUserId());
		activityUserMapperAdjustLog.setType(0);
		activityUserMapperAdjustLog.setActivityUserMapperId(activityUserMapperId);
		activityUserMapperAdjustLogDao.insert(activityUserMapperAdjustLog);
		if(amount == null || amount.compareTo(BigDecimal.ZERO) <= 0){
			return;
		}

		BigDecimal actualPrice = sysUserCashAccountLogService.musicReturnFeeCharges(activityUserMapper.getActualPrice(),0);
		if(amount.compareTo(actualPrice) > 0){
			throw new BizException("操作失败：退费金额不得超过购买金额{}",actualPrice);
		}
		SysUser user = teacherDao.getUser(activityUserMapper.getUserId());
		SysUserCashAccountLog sysUserCashAccountLog = new SysUserCashAccountLog();
		sysUserCashAccountLog.setUserId(activityUserMapper.getUserId());
		sysUserCashAccountLog.setGroupType(ACTIVITY);
		sysUserCashAccountLog.setOrganId(user.getOrganId());
		sysUserCashAccountLog.setGroupId(activityUserMapperId.toString());
		sysUserCashAccountLog.setAmount(amount);
		sysUserCashAccountLog.setReturnFeeType(ReturnFeeEnum.CANCEL_ACTIVITY_COURSE);
		sysUserCashAccountLog.setComment("取消活动排课");
		sysUserCashAccountLogService.insert(sysUserCashAccountLog);
	}

    @Override
    public void addOrderDetail2Activity(StudentPaymentOrder studentPaymentOrder, List<StudentPaymentOrderDetail> activity) {
		List<VipGroupActivity> vipGroupActivities = vipGroupActivityDao.queryByIds(activity.stream().
				map(e -> e.getStudentInstrumentId().toString()).distinct().collect(Collectors.joining(",")));
		Map<Integer, VipGroupActivity> collect = vipGroupActivities.stream().collect(Collectors.groupingBy(e -> e.getId(),
				Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
		List<ActivityUserMapper> activityUserMapperList = new ArrayList<>();
		for (StudentPaymentOrderDetail orderDetail : activity) {
			ActivityUserMapper activityUserMapper = new ActivityUserMapper();
			activityUserMapper.setTenantId(studentPaymentOrder.getTenantId());
			activityUserMapper.setActualPrice(orderDetail.getPrice());
			activityUserMapper.setSubNoCoursePrice(orderDetail.getPrice());
			//这里的studentInstrumentId存的是活动编号
			activityUserMapper.setActivityId(orderDetail.getStudentInstrumentId().intValue());
			VipGroupActivity vipGroupActivity = collect.get(activityUserMapper.getActivityId());
			Student student = studentDao.get(studentPaymentOrder.getUserId());
			activityUserMapper.setUserId(studentPaymentOrder.getUserId());
			activityUserMapper.setTeacherId(student.getTeacherId());
			activityUserMapper.setPaymentOrderId(studentPaymentOrder.getId());
			if(orderDetail.getType() == OrderDetailTypeEnum.VIP){
				activityUserMapper.setVipFlag(1);
			}else {
				activityUserMapper.setPracticeFlag(1);
			}
			this.copyProperty(activityUserMapper,vipGroupActivity,false,true);
			activityUserMapperList.add(activityUserMapper);
		}
		activityUserMapperDao.batchInsert(activityUserMapperList);
    }

    @Override
    public Map<String,Object> getStudentNoMapperInfo() {
		HashMap<String, Object> map = new HashMap<>();
		SysUser sysUser = sysUserFeignService.queryUserInfo();
		map.put("userId",sysUser.getId());
		map.put("username",sysUser.getUsername());
		map.put("avatar",sysUser.getAvatar());
		Student student = studentDao.get(sysUser.getId());
		if(StringUtils.isNotEmpty(student.getSubjectIdList())){
			Subject subject = subjectDao.get(Integer.parseInt(student.getSubjectIdList()));
			if (subject != null) {
				map.put("subjectName",subject.getName());
			}
		}
		String activeConfig = sysConfigDao.findConfigValue("cloud_teacher_active_config");
		List<Cloud2022ActivityDto> cloud2022ActivityDtos = JSONArray.parseArray(activeConfig, Cloud2022ActivityDto.class);
		List<Cloud2022ActivityDto> activityDtos = cloud2022ActivityDtos.stream().filter(e -> e.getOrganId().contains(sysUser.getOrganId().toString())).collect(Collectors.toList());
		if(CollectionUtils.isEmpty(activityDtos)){
			map.put("courseNum",0);
			return map;
		}
		//是否还有购买资格
		Integer activityId = Integer.parseInt(activityDtos.get(0).getActivityId());
		Integer noCourseNum = activityUserMapperDao.getStudentNoMapperInfo(sysUser.getId(), activityId);
		map.put("courseNum",noCourseNum == null?0:noCourseNum);
		return map;
    }

	@Override
	public Integer getStudentNoCourseNum(Integer userId, Integer activityId) {
		return activityUserMapperDao.getStudentNoMapperInfo(userId, activityId);
	}

	@Override
	public List<ExportStudentSubCourse> exportStudentSubCourse(String organId, Integer tenantId) {
		return activityUserMapperDao.exportStudentSubCourse(organId,tenantId);
	}

    @Override
    public List<CourseFormDto> queryWaitCourseCategory(Integer userId,String organIds) {
        return activityUserMapperDao.queryWaitCourseCategory(userId,organIds);
    }

	@Override
	public List<ActivityUserDto> queryActivityStudentList(ActivityUserQueryInfo activityUserQueryInfo) {
		return activityUserMapperDao.queryActivityStudentList(activityUserQueryInfo);
	}

	@Override
	public List<Integer> queryActivityCourseTimeList(ActivityUserQueryInfo activityUserQueryInfo) {
		return activityUserMapperDao.queryActivityCourseTimeList(activityUserQueryInfo);
	}

	private void checkCreateActivityVipGroup(VipGroupApplyDto vipGroup,VipGroupApplyBaseInfoDto applyBaseInfo){
		Map<TeachModeEnum, List<CourseSchedule>> courseScheduleGroup;
		try {
			courseScheduleGroup = vipGroup.getCourseSchedules().stream().collect(Collectors.groupingBy(CourseSchedule::getTeachMode));
		} catch (Exception e) {
			throw new BizException("教学模式错误");
		}
		if(Objects.isNull(applyBaseInfo.getVipGroupCategoryId())){
			throw new BizException("请选择课程类型");
		}
		if ((Objects.isNull(courseScheduleGroup.get(TeachModeEnum.OFFLINE)) && applyBaseInfo.getOfflineClassesNum() != 0)
				|| (!Objects.isNull(courseScheduleGroup.get(TeachModeEnum.OFFLINE)) && (courseScheduleGroup.get(TeachModeEnum.OFFLINE).size() < applyBaseInfo.getOfflineClassesNum()))) {
			throw new BizException("线下课课时数量安排有误");
		}
		if ((Objects.isNull(courseScheduleGroup.get(TeachModeEnum.ONLINE)) && applyBaseInfo.getOnlineClassesNum() != 0)
				|| (!Objects.isNull(courseScheduleGroup.get(TeachModeEnum.ONLINE)) && (courseScheduleGroup.get(TeachModeEnum.ONLINE).size() < applyBaseInfo.getOnlineClassesNum()))) {
			throw new BizException("线上课课时数量安排有误");
		}
		//校验线上课学员上限
		if (applyBaseInfo.getOnlineClassesNum() > 0) {
			courseScheduleService.checkOnlineCategory(applyBaseInfo.getStudentNum());
		}
		if (applyBaseInfo.getOfflineClassesNum() > 0 && Objects.isNull(applyBaseInfo.getTeacherSchoolId())) {
			throw new BizException("请设置教学点");
		}
		if (Objects.isNull(applyBaseInfo.getOfflineClassesUnitPrice()) && Objects.isNull(applyBaseInfo.getOnlineClassesUnitPrice())) {
			throw new BizException("请设置课程单价");
		}
	}

    @Override
	@Transactional(rollbackFor = Exception.class)
    public HttpResponseResult createActivityVipGroup(VipGroupApplyDto vipGroup) {
		VipGroupApplyBaseInfoDto applyBaseInfo = vipGroup.getVipGroupApplyBaseInfo();
		this.checkCreateActivityVipGroup(vipGroup,applyBaseInfo);
		String studentIds = applyBaseInfo.getStudentIdList();
		if (StringUtils.isBlank(studentIds)) {
			throw new BizException("请选择学员");
		}
		int courseNum = vipGroup.getCourseSchedules().size();
		if (courseNum != (applyBaseInfo.getOfflineClassesNum() + applyBaseInfo.getOnlineClassesNum())) {
			throw new BizException("建课失败，课程数量异常");
		}
		Date now = new Date();
		Integer totalClassTimes = applyBaseInfo.getOnlineClassesNum() + applyBaseInfo.getOfflineClassesNum();
		//获取第一节课
		CourseSchedule firstCourseSchedule = vipGroup.getCourseSchedules().stream().min(Comparator.comparing(CourseSchedule::getStartClassTime)).get();
		//获取最后一节课
		CourseSchedule latestCourseSchedule = vipGroup.getCourseSchedules().stream().max(Comparator.comparing(CourseSchedule::getEndClassTime)).get();

		if (firstCourseSchedule.getStartClassTime().before(now)) {
			throw new BizException("开课时间不能小于当前时间");
		}
		applyBaseInfo.setRegistrationStartTime(now);
		applyBaseInfo.setPaymentExpireDate(now);
		if (applyBaseInfo.getRegistrationStartTime().after(applyBaseInfo.getPaymentExpireDate())) {
			throw new BizException("报名开始时间必须在报名截至时间之前");
		}
		VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(applyBaseInfo.getVipGroupCategoryId());
		if (Objects.isNull(vipGroupCategory)) {
			throw new BizException("课程形式不存在");
		}
		//如果是乐理课，那么声部固定给31
		if(vipGroupCategory.getMusicTheory()){
			applyBaseInfo.setSubjectIdList("31");
		}
		if (StringUtils.isBlank(applyBaseInfo.getSubjectIdList())) {
			throw new BizException("请选择声部");
		}
		List<Integer> studentIdList = Arrays.stream(studentIds.split(",")).map(id -> Integer.valueOf(id)).collect(Collectors.toList());
		if (!vipGroupCategory.getMusicTheory()) {
			if (studentIdList.size() != vipGroupCategory.getStudentNum()) {
				throw new BizException("学员数量异常");
			}
		} else if (studentIdList.size() > vipGroupCategory.getStudentNum()){
			throw new BizException("{}课程最多支持{}人", vipGroupCategory.getName(), vipGroupCategory.getStudentNum());
		}

		List<Integer> canBuyStudentIds = Arrays.stream(applyBaseInfo.getStudentIdList().split(",")).map(e -> Integer.valueOf(e)).collect(Collectors.toList());

		int repeatVipGroups = vipGroupDao.countUserRepeatVipGroupInCourseStartEndTime(applyBaseInfo.getUserId(), firstCourseSchedule.getStartClassTime(), latestCourseSchedule.getEndClassTime());
		if (repeatVipGroups > 0) {
			SysUser sysUser = sysUserFeignService.queryUserById(applyBaseInfo.getUserId());
			throw new BizException("{}课程时间冲突({}-{})", sysUser.getRealName(), DateUtil.dateToString(firstCourseSchedule.getStartClassTime(), "yyyy-MM-dd HH:mm:ss"), DateUtil.dateToString(latestCourseSchedule.getEndClassTime(), "HH:mm:ss"));
		}

		List<String> studentNames = studentDao.getStudentNames(canBuyStudentIds);

		//生成vip课信息
		List<String> bySubIds = subjectDao.findBySubIds(applyBaseInfo.getSubjectIdList());
		StringBuffer className = new StringBuffer();
		if (Objects.isNull(vipGroupCategory.getMusicTheory()) || !vipGroupCategory.getMusicTheory()) {
			className.append(StringUtils.join(bySubIds, ","));
			className.append(vipGroupCategory.getName());
		} else {
			className.append("乐理课•");
		}
		className.append(StringUtils.join(studentNames, ","));
		applyBaseInfo.setName(className.toString());

		applyBaseInfo.setAuditStatus(AuditStatusEnum.PASS);
		applyBaseInfo.setStatus(VipGroupStatusEnum.PROGRESS);

		//开课时间为排课的第一节课的开始时间
		applyBaseInfo.setCourseStartDate(firstCourseSchedule.getStartClassTime());
		//课程结束时间为排课的最后一节课的结束时间
		applyBaseInfo.setCoursesExpireDate(latestCourseSchedule.getEndClassTime());
		applyBaseInfo.setStudentNum(studentIdList.size());
		applyBaseInfo.setPaymentExpireDate(DateUtil.getLastSecondWithDay(applyBaseInfo.getPaymentExpireDate()));

		vipGroupDao.insert(applyBaseInfo);

		//校验排课资格，消耗排课资格(获取被使用的排课资格)
		List<CourseScheduleStudentPayment> courseScheduleStudentPayments =
				this.checkScheduleQualification(studentIdList, vipGroupCategory.getId(), applyBaseInfo.getSingleClassMinutes(), courseNum, applyBaseInfo.getId());

		List<VipGroupStudentCoursePrice> vscps = vipGroup.getVipGroupApplyBaseInfo().getVipGroupStudentCoursePrices();
		if (org.springframework.util.CollectionUtils.isEmpty(vscps)) {
			vscps = new ArrayList<>();
			for (Integer canBuyStudentId : canBuyStudentIds) {
				vscps.add(new VipGroupStudentCoursePrice(canBuyStudentId, applyBaseInfo.getOnlineClassesUnitPrice(), applyBaseInfo.getOfflineClassesUnitPrice(), applyBaseInfo.getTotalPrice()));
			}
		}
		vscps.forEach(e -> e.setVipGroupId(applyBaseInfo.getId()));
		vipGroupStudentCoursePriceDao.batchInsert(vscps);

		vipGroup.getVipGroupApplyBaseInfo().setId(applyBaseInfo.getId());

		//创建班级信息
		ClassGroup classGroup = new ClassGroup();
		classGroup.setSubjectIdList(applyBaseInfo.getSubjectIdList());
		classGroup.setExpectStudentNum(vipGroupCategory.getStudentNum());
		classGroup.setStudentNum(studentIdList.size());
		classGroup.setName(applyBaseInfo.getName());
		classGroup.setTotalClassTimes(totalClassTimes);
		classGroup.setType(ClassGroupTypeEnum.VIP);
		classGroup.setDelFlag(0);
		classGroup.setGroupType(GroupType.VIP);
		classGroup.setMusicGroupId(applyBaseInfo.getId().toString());
		classGroup.setCreateTime(now);
		classGroup.setUpdateTime(now);
		classGroupDao.insert(classGroup);

		//班级学员关联记录
		List<ClassGroupStudentMapper> classGroupStudentMapperList = new ArrayList<>();
		for (Integer studentId : studentIdList) {
			ClassGroupStudentMapper classGroupStudentMapper = new ClassGroupStudentMapper();
			classGroupStudentMapper.setMusicGroupId(applyBaseInfo.getId().toString());
			classGroupStudentMapper.setClassGroupId(classGroup.getId());
			classGroupStudentMapper.setUserId(studentId);
			classGroupStudentMapper.setCreateTime(now);
			classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
			classGroupStudentMapper.setGroupType(GroupType.VIP);
			classGroupStudentMapperList.add(classGroupStudentMapper);
		}
		classGroupStudentMapperDao.classGroupStudentsInsert(classGroupStudentMapperList);

		//计算课程相关费用信息
		Map<String, BigDecimal> costInfo = vipGroupService.countVipGroupPredictFee1(applyBaseInfo, applyBaseInfo.getUserId(), null);
		applyBaseInfo.setOfflineTeacherSalary(costInfo.get("offlineTeacherSalary"));
		applyBaseInfo.setTotalPrice(costInfo.get("totalPrice"));

		//创建班级老师关联记录
		ClassGroupTeacherMapper classGroupTeacherMapper = new ClassGroupTeacherMapper();
		classGroupTeacherMapper.setMusicGroupId(applyBaseInfo.getId().toString());
		classGroupTeacherMapper.setClassGroupId(classGroup.getId());
		classGroupTeacherMapper.setTeacherRole(TeachTypeEnum.BISHOP);
		classGroupTeacherMapper.setUserId(applyBaseInfo.getUserId());
		classGroupTeacherMapper.setGroupType(GroupType.VIP);
		classGroupTeacherMapper.setCreateTime(now);
		classGroupTeacherMapper.setUpdateTime(now);
		classGroupTeacherMapperDao.insert(classGroupTeacherMapper);

		//创建班级与老师课酬记录
		ClassGroupTeacherSalary classGroupTeacherSalary = new ClassGroupTeacherSalary();
		classGroupTeacherSalary.setMusicGroupId(applyBaseInfo.getId().toString());
		classGroupTeacherSalary.setClassGroupId(classGroup.getId());
		classGroupTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
		classGroupTeacherSalary.setUserId(applyBaseInfo.getUserId());
		classGroupTeacherSalary.setSalary(applyBaseInfo.getOfflineTeacherSalary());
		classGroupTeacherSalary.setOnlineClassesSalary(applyBaseInfo.getOfflineTeacherSalary());
		classGroupTeacherSalary.setGroupType(GroupType.VIP);
		classGroupTeacherSalary.setCreateTime(now);
		classGroupTeacherSalary.setUpdateTime(now);
		classGroupTeacherSalaryDao.insert(classGroupTeacherSalary);

		//创建课程
		List<CourseSchedule> courseSchedules = vipGroup.getCourseSchedules();
		for (CourseSchedule courseSchedule : courseSchedules) {
			courseSchedule.setGroupType(GroupType.VIP);
			courseSchedule.setMusicGroupId(applyBaseInfo.getId().toString());
			if (courseSchedule.getTeachMode().equals(TeachModeEnum.OFFLINE)) {
				courseSchedule.setSchoolId(vipGroup.getVipGroupApplyBaseInfo().getTeacherSchoolId());
			}
			courseSchedule.setTeacherId(applyBaseInfo.getUserId());
			courseSchedule.setActualTeacherId(applyBaseInfo.getUserId());
			courseSchedule.setStatus(CourseStatusEnum.NOT_START);
			courseSchedule.setType(CourseSchedule.CourseScheduleType.VIP);
			courseSchedule.setClassGroupId(classGroup.getId());
			courseSchedule.setName(applyBaseInfo.getName());
			courseSchedule.setOrganId(applyBaseInfo.getOrganId());
		}
		courseScheduleService.batchAddCourseSchedule(courseSchedules);

		//创建老师单节课课酬信息
		List<CourseScheduleTeacherSalary> courseScheduleTeacherSalaries = new ArrayList<>();
		//课程信息调整
		for (CourseSchedule courseSchedule : courseSchedules) {
			courseSchedule.setGroupType(GroupType.VIP);
			courseSchedule.setMusicGroupId(applyBaseInfo.getId().toString());
			if (courseSchedule.getTeachMode().equals(TeachModeEnum.OFFLINE)) {
				courseSchedule.setSchoolId(vipGroup.getVipGroupApplyBaseInfo().getTeacherSchoolId());
			}
			courseSchedule.setTeacherId(applyBaseInfo.getUserId());
			courseSchedule.setActualTeacherId(applyBaseInfo.getUserId());
			courseSchedule.setStatus(CourseStatusEnum.NOT_START);
			courseSchedule.setType(CourseSchedule.CourseScheduleType.VIP);
			courseSchedule.setClassGroupId(classGroup.getId());
			courseSchedule.setName(applyBaseInfo.getName());
			courseSchedule.setOrganId(applyBaseInfo.getOrganId());

			//创建教师课程薪水记录
			CourseScheduleTeacherSalary courseScheduleTeacherSalary = new CourseScheduleTeacherSalary();
			courseScheduleTeacherSalary.setCourseScheduleId(courseSchedule.getId());
			courseScheduleTeacherSalary.setGroupType(courseSchedule.getGroupType());
			courseScheduleTeacherSalary.setMusicGroupId(courseSchedule.getMusicGroupId());
			courseScheduleTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
			courseScheduleTeacherSalary.setUserId(courseSchedule.getActualTeacherId().intValue());
			courseScheduleTeacherSalary.setClassGroupId(courseSchedule.getClassGroupId());
			courseScheduleTeacherSalary.setExpectSalary(classGroupTeacherSalary.getSalary());
			courseScheduleTeacherSalary.setActualSalary(null);
			courseScheduleTeacherSalaries.add(courseScheduleTeacherSalary);
		}
		if (courseScheduleTeacherSalaries.size() > 0) {
			courseScheduleTeacherSalaryService.batchInsert(courseScheduleTeacherSalaries);
		}

		applyBaseInfo.setCourseSchedulesJson(JSON.toJSONString(vipGroup.getCourseSchedules()));
		vipGroupDao.update(applyBaseInfo);

		Map<Integer, String> userRoleMap = new HashMap<>();
		if (Objects.nonNull(applyBaseInfo.getEducationalTeacherId())) {
			userRoleMap.put(applyBaseInfo.getEducationalTeacherId(), "乐团主管");
		}
		userRoleMap.put(applyBaseInfo.getUserId(), "指导老师");
		VipGroupDefaultClassesUnitPrice vipGroupDefaultClassesUnitPrice = vipGroupDefaultClassesUnitPriceDao.getByVipGroup(applyBaseInfo.getId());
		if (Objects.isNull(vipGroupDefaultClassesUnitPrice)) {
			throw new BizException("课程单价设置错误");
		}
		//生成学生单课缴费信息
		Map<Integer, List<CourseScheduleStudentPayment>> collect = courseScheduleStudentPayments.stream().collect(Collectors.groupingBy(CourseScheduleStudentPayment::getUserId));
		for (Integer integer : collect.keySet()) {
			List<CourseScheduleStudentPayment> studentPayments = collect.get(integer);
			for (int i = 0; i < studentPayments.size(); i++) {
				CourseScheduleStudentPayment courseScheduleStudentPayment = studentPayments.get(i);
				CourseSchedule courseSchedule = courseSchedules.get(i);
				courseScheduleStudentPayment.setGroupType(courseSchedule.getGroupType());
				courseScheduleStudentPayment.setMusicGroupId(courseSchedule.getMusicGroupId());
				courseScheduleStudentPayment.setCourseScheduleId(courseSchedule.getId());
				courseScheduleStudentPayment.setClassGroupId(courseSchedule.getClassGroupId());
				courseScheduleStudentPayment.setOriginalPrice(TeachModeEnum.ONLINE.equals(courseSchedule.getTeachMode()) ? vipGroupDefaultClassesUnitPrice.getOnlineClassesUnitPrice() : vipGroupDefaultClassesUnitPrice.getOfflineClassesUnitPrice());
				userRoleMap.put(courseScheduleStudentPayment.getUserId(), null);
			}
		}

		if (courseScheduleStudentPayments.size() > 0) {
			courseScheduleStudentPaymentDao.batchInsert(courseScheduleStudentPayments);
			studentDao.updateStudentServiceTag(null, studentIdList, YesOrNoEnum.YES.getCode());
		}
		try {
			imGroupService.create(classGroup.getId().toString(), null, classGroup.getName(), classGroup.getName(),
					applyBaseInfo.getName(), null, null, GroupType.VIP.getCode(), ImGroup.GroupTypeEnum.VIP);
			imGroupMemberService.join(classGroup.getId().toString(), userRoleMap);
			imUserFriendService.refreshGroupImUserFriend(classGroup.getMusicGroupId(), classGroup.getGroupType());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return BaseController.succeed(applyBaseInfo.getAuditStatus().getCode());
    }

	//校验排课资格并消耗
	private List<CourseScheduleStudentPayment> checkScheduleQualification(List<Integer> studentIdList,Integer categoryId,Integer classMinutes,Integer courseNum,Long groupId) {
		//获取学员排课资格
		List<ActivityUserMapper> totalActivityUserMappers = activityUserMapperDao.findTotalByStudents(studentIdList,categoryId,classMinutes);
		if (CollectionUtils.isEmpty(totalActivityUserMappers)) {
			throw new BizException("所选学员暂无排课资格");
		}
		totalActivityUserMappers.stream().collect(Collectors.groupingBy(ActivityUserMapper::getUserId,Collectors.collectingAndThen(Collectors.toList(), list -> {
			Integer sum = list.stream().mapToInt(ActivityUserMapper::getSubCourseNum).sum();
			if (sum < courseNum) {
				throw new BizException("所选学员排课资格不足");
			}
			return sum;
		})));
		//消耗排课资格(获取被使用的排课资格)
		return this.use(categoryId,classMinutes, courseNum,groupId,studentIdList);
	}

	private void getStudentPayment(Integer userId,
								   BigDecimal totalAmount,
								   Integer courseNum,
								   List<CourseScheduleStudentPayment> courseScheduleStudentPayments,
								   Integer activityUserMapperId){
		//实际支付金额，去除优惠券
		BigDecimal singleAmount = totalAmount.divide(new BigDecimal(courseNum), ROUND_DOWN);
		BigDecimal firstSingleAmount = totalAmount.subtract(singleAmount.multiply(new BigDecimal(courseNum))).add(singleAmount);
		for (Integer i = 0; i < courseNum; i++) {
			CourseScheduleStudentPayment courseScheduleStudentPayment = new CourseScheduleStudentPayment();
			courseScheduleStudentPayment.setUserId(userId);
			if (i == 0) {
				courseScheduleStudentPayment.setExpectPrice(firstSingleAmount);
			} else {
				courseScheduleStudentPayment.setExpectPrice(singleAmount);
			}
			courseScheduleStudentPayment.setActivityUserMapperId(activityUserMapperId);
			courseScheduleStudentPayment.setActualPrice(courseScheduleStudentPayment.getExpectPrice());
			courseScheduleStudentPayments.add(courseScheduleStudentPayment);
		}
	}
	private void getStudentPayment(Integer userId,
								   Integer courseNum,
								   BigDecimal singlePrice,
								   List<CourseScheduleStudentPayment> courseScheduleStudentPayments,
								   Integer activityUserMapperId){
		for (Integer i = 0; i < courseNum; i++) {
			CourseScheduleStudentPayment courseScheduleStudentPayment = new CourseScheduleStudentPayment();
			courseScheduleStudentPayment.setUserId(userId);
			courseScheduleStudentPayment.setExpectPrice(singlePrice);
			courseScheduleStudentPayment.setActualPrice(courseScheduleStudentPayment.getExpectPrice());
			courseScheduleStudentPayment.setActivityUserMapperId(activityUserMapperId);
			courseScheduleStudentPayments.add(courseScheduleStudentPayment);
		}
	}

	@Override
	public List<CourseScheduleStudentPayment> use(Integer categoryId,Integer classMinutes,
												  int courseNum,
												  Long groupId,List<Integer> studentIdList) {
		Map<Integer,Integer> subCourseMap = new HashMap<>();
		studentIdList.stream().forEach(e-> subCourseMap.put(e,courseNum));
		List<CourseScheduleStudentPayment> courseScheduleStudentPayments = new ArrayList<>();
		//获取学员付费排课资格
		List<ActivityUserMapper> activityUserMappers = activityUserMapperDao.findByStudents(studentIdList,categoryId,classMinutes);
		if(CollectionUtils.isNotEmpty(activityUserMappers)){
			Map<Integer, List<ActivityUserMapper>> collect = activityUserMappers.stream().collect(Collectors.groupingBy(ActivityUserMapper::getUserId));
			one:for (Integer integer : collect.keySet()) {
				Integer subCourseNum = courseNum;
				List<ActivityUserMapper> activityUserMapperList = collect.get(integer);
				for (ActivityUserMapper activityUserMapper : activityUserMapperList) {
					if(subCourseNum == 0){
						continue one;
					}
					//区分vip还是网管
					this.modifyGroupId(activityUserMapper,groupId);
					int num = activityUserMapper.getSubCourseNum();
					//剩余课次不足
					if(num <= subCourseNum){
						subCourseNum = subCourseNum - num;
						subCourseMap.put(integer, subCourseNum);
						activityUserMapper.setSubCourseNum(0);
						//生成学员课程支付记录
						this.getStudentPayment(integer,activityUserMapper.getSubNoCoursePrice(),num,courseScheduleStudentPayments,activityUserMapper.getId());
						activityUserMapper.setCurrentCoursePrice(activityUserMapper.getSubNoCoursePrice());
						activityUserMapper.setSubNoCoursePrice(BigDecimal.ZERO);
					}else {
						subCourseMap.put(integer, 0);
						activityUserMapper.setSubCourseNum(num - subCourseNum);
						//单课价值
						BigDecimal singlePrice = activityUserMapper.getActualPrice().divide(new BigDecimal(activityUserMapper.getTotalCourseNum()), RoundingMode.DOWN);
						//消耗的课程总价值
						BigDecimal divide = singlePrice.multiply(new BigDecimal(subCourseNum));
						activityUserMapper.setSubNoCoursePrice(activityUserMapper.getSubNoCoursePrice().subtract(divide));
						activityUserMapper.setCurrentCoursePrice(divide);
						this.getStudentPayment(integer,subCourseNum,singlePrice,courseScheduleStudentPayments,activityUserMapper.getId());
						//剩余课次充足
						continue one;
					}
				}
			}
			activityUserMapperDao.batchUpdate(activityUserMappers);
		}
		//获取学员赠送排课资格
		List<ActivityUserMapper> freeActivityUserMappers = activityUserMapperDao.findByStudents1(studentIdList,categoryId,classMinutes);
		if(CollectionUtils.isNotEmpty(freeActivityUserMappers)){
			Map<Integer, List<ActivityUserMapper>> collect1 = freeActivityUserMappers.stream().collect(Collectors.groupingBy(ActivityUserMapper::getUserId));
			one:for (Integer integer : subCourseMap.keySet()) {
				Integer subCourseNum = subCourseMap.get(integer);
				if(subCourseNum == 0){
					continue;
				}
				List<ActivityUserMapper> activityUserMapperList = collect1.get(integer);
				for (ActivityUserMapper activityUserMapper : activityUserMapperList) {
					if(subCourseNum == 0){
						continue one;
					}
					//区分vip还是网管
					this.modifyGiveGroupId(activityUserMapper,groupId);
					int num = activityUserMapper.getSubGiveCourseNum();
					//剩余课次不足
					if(num <= subCourseNum){
						activityUserMapper.setSubGiveCourseNum(0);
						subCourseNum = subCourseNum - num;
						this.getStudentPayment(integer,num,BigDecimal.ZERO,courseScheduleStudentPayments,activityUserMapper.getId());
					}else {
						activityUserMapper.setSubGiveCourseNum(num - subCourseNum);
						this.getStudentPayment(integer,subCourseNum,BigDecimal.ZERO,courseScheduleStudentPayments,activityUserMapper.getId());
						continue one;
					}
				}
				if (subCourseNum > 0){
					throw new BizException("所选部分学员排课资格不足，请重新选择");
				}
			}
			activityUserMapperDao.batchUpdate(freeActivityUserMappers);
		}
		return courseScheduleStudentPayments;
	}

	private void modifyGroupId(ActivityUserMapper activityUserMapper,Long groupId){
		if(activityUserMapper.getCategoryId() == null){
			if(StringUtils.isEmpty(activityUserMapper.getPracticeGroupId())){
				activityUserMapper.setPracticeGroupId(groupId.toString());
			}else {
				String[] split = activityUserMapper.getPracticeGroupId().split(",");
				List<String> idList = Arrays.stream(split).collect(Collectors.toList());
				if(!idList.contains(groupId.toString())){
					activityUserMapper.setPracticeGroupId(activityUserMapper.getPracticeGroupId()+","+groupId);
				}
			}
			//虽然还有剩余价值，但是这里处理为已排课，不再考虑退费问题
			activityUserMapper.setPracticeFlag(2);
		}else {
			if(StringUtils.isEmpty(activityUserMapper.getVipGroupId())){
				activityUserMapper.setVipGroupId(groupId.toString());
			}else {
				String[] split = activityUserMapper.getVipGroupId().split(",");
				List<String> idList = Arrays.stream(split).collect(Collectors.toList());
				if(!idList.contains(groupId.toString())){
					activityUserMapper.setVipGroupId(activityUserMapper.getVipGroupId()+","+groupId);
				}
			}
			activityUserMapper.setVipFlag(2);
		}
	}
	private void modifyGiveGroupId(ActivityUserMapper activityUserMapper,Long groupId){
		if(activityUserMapper.getGiveCategoryId() == null){
			if(StringUtils.isEmpty(activityUserMapper.getGivePracticeGroupId())){
				activityUserMapper.setGivePracticeGroupId(groupId.toString());
			}else {
				String[] split = activityUserMapper.getGivePracticeGroupId().split(",");
				List<String> idList = Arrays.stream(split).collect(Collectors.toList());
				if(!idList.contains(groupId.toString())){
					activityUserMapper.setGivePracticeGroupId(activityUserMapper.getGivePracticeGroupId()+","+groupId);
				}
			}
			//虽然还有剩余价值，但是这里处理为已排课，不再考虑退费问题
			activityUserMapper.setGivePracticeFlag(2);
		}else {
			if(StringUtils.isEmpty(activityUserMapper.getGiveVipGroupId())){
				activityUserMapper.setGiveVipGroupId(groupId.toString());
			}else {
				String[] split = activityUserMapper.getGiveVipGroupId().split(",");
				List<String> idList = Arrays.stream(split).collect(Collectors.toList());
				if(!idList.contains(groupId.toString())){
					activityUserMapper.setGiveVipGroupId(activityUserMapper.getGiveVipGroupId()+","+groupId);
				}
			}
			activityUserMapper.setGiveVipFlag(2);
		}
	}

    @Override
	@Transactional(rollbackFor = Exception.class)
    public HttpResponseResult createActivityPracticeGroup(PracticeGroupApplyDto practice) {
		PracticeGroupApplyBaseInfoDto applyBaseInfo = practice.getPracticeGroupApplyBaseInfoDto();
		List<CourseSchedule> courseSchedules = practice.getCourseSchedules();
		Integer allCourseNum = applyBaseInfo.getAllCourseNum();
		if (courseSchedules.size() != allCourseNum) {
			throw new BizException("建课失败，课程数量异常");
		}
		if (applyBaseInfo.getSubjectId() == null) {
			throw new BizException("请选择声部");
		}
		Integer studentId = applyBaseInfo.getStudentId();
		Date now = new Date();

		//获取第一节课
		CourseSchedule firstCourseSchedule = courseSchedules.stream().min(Comparator.comparing(CourseSchedule::getStartClassTime)).get();
		//获取最后一节课
		CourseSchedule latestCourseSchedule = courseSchedules.stream().max(Comparator.comparing(CourseSchedule::getEndClassTime)).get();

		if (firstCourseSchedule.getStartClassTime().before(now)) {
			throw new BizException("开课时间不能小于当前时间");
		}

		applyBaseInfo.setRegistrationStartTime(now);
		applyBaseInfo.setPaymentExpireDate(now);

		if (applyBaseInfo.getRegistrationStartTime().after(applyBaseInfo.getPaymentExpireDate())) {
			throw new BizException("报名开始时间必须在报名截至时间之前");
		}

		int repeatVipGroups = practiceGroupDao.countUserRepeatPracticeGroupInCourseStartEndTime(applyBaseInfo.getUserId(), firstCourseSchedule.getStartClassTime(), latestCourseSchedule.getEndClassTime());
		if (repeatVipGroups > 0) {
			SysUser sysUser = sysUserService.queryUserById(applyBaseInfo.getUserId());
			throw new BizException("{}课程时间冲突({}-{})", sysUser.getRealName(), DateUtil.dateToString(firstCourseSchedule.getStartClassTime(), "yyyy-MM-dd HH:mm:ss"), DateUtil.dateToString(latestCourseSchedule.getEndClassTime(), "HH:mm:ss"));
		}

		//生成网管课信息
		Subject subject = subjectDao.get(applyBaseInfo.getSubjectId());
		SysUser user = teacherDao.getUser(studentId);
		StringBuffer className = new StringBuffer(subject.getName()).append("•").append(user.getUsername());
		applyBaseInfo.setName(className.toString());
		applyBaseInfo.setAuditStatus(AuditStatusEnum.PASS);
		applyBaseInfo.setGroupStatus(GroupStatusEnum.NORMAL);

		Teacher teacher = teacherService.get(applyBaseInfo.getUserId());
		if (Objects.isNull(teacher)) {
			throw new BizException("教师不存在");
		}

		//开课时间为排课的第一节课的开始时间
		applyBaseInfo.setCoursesStartDate(firstCourseSchedule.getStartClassTime());
		//课程结束时间为排课的最后一节课的结束时间
		applyBaseInfo.setCoursesExpireDate(latestCourseSchedule.getEndClassTime());

		applyBaseInfo.setPaymentExpireDate(DateUtil.getLastSecondWithDay(applyBaseInfo.getPaymentExpireDate()));
		applyBaseInfo.setType(PracticeGroupType.CHARGE);
		practiceGroupDao.insert(applyBaseInfo);

		//消耗排课资格
		List<Integer> studentIdList = new ArrayList<>();
		studentIdList.add(studentId);
		List<CourseScheduleStudentPayment> courseScheduleStudentPayments =
				this.checkScheduleQualification(studentIdList,null, applyBaseInfo.getSingleClassMinutes(), applyBaseInfo.getAllCourseNum(), applyBaseInfo.getId());

		//创建班级信息
		ClassGroup classGroup = new ClassGroup();
		classGroup.setSubjectIdList(applyBaseInfo.getSubjectId().toString());
		classGroup.setExpectStudentNum(1);
		classGroup.setStudentNum(1);
		classGroup.setName(applyBaseInfo.getName());
		classGroup.setTotalClassTimes(allCourseNum);
		classGroup.setType(ClassGroupTypeEnum.PRACTICE);
		classGroup.setDelFlag(0);
		classGroup.setGroupType(GroupType.PRACTICE);
		classGroup.setMusicGroupId(applyBaseInfo.getId().toString());
		classGroup.setCreateTime(now);
		classGroup.setUpdateTime(now);
		classGroupDao.insert(classGroup);

		//班级学员关联记录
		List<ClassGroupStudentMapper> classGroupStudentMapperList = new ArrayList<>();
		ClassGroupStudentMapper classGroupStudentMapper = new ClassGroupStudentMapper();
		classGroupStudentMapper.setMusicGroupId(applyBaseInfo.getId().toString());
		classGroupStudentMapper.setClassGroupId(classGroup.getId());
		classGroupStudentMapper.setUserId(studentId);
		classGroupStudentMapper.setCreateTime(now);
		classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
		classGroupStudentMapper.setGroupType(GroupType.PRACTICE);
		classGroupStudentMapperList.add(classGroupStudentMapper);
		classGroupStudentMapperDao.classGroupStudentsInsert(classGroupStudentMapperList);

		//计算课程相关费用信息
		Map<String, BigDecimal> costInfo = practiceGroupService.countPracticeGroupPredictFee(applyBaseInfo, applyBaseInfo.getUserId());
		applyBaseInfo.setOnlineTeacherSalary(costInfo.get("onlineTeacherSalary"));

		//创建班级老师关联记录
		ClassGroupTeacherMapper classGroupTeacherMapper = new ClassGroupTeacherMapper();
		classGroupTeacherMapper.setMusicGroupId(applyBaseInfo.getId().toString());
		classGroupTeacherMapper.setClassGroupId(classGroup.getId());
		classGroupTeacherMapper.setTeacherRole(TeachTypeEnum.BISHOP);
		classGroupTeacherMapper.setUserId(applyBaseInfo.getUserId());
		classGroupTeacherMapper.setGroupType(GroupType.PRACTICE);
		classGroupTeacherMapper.setCreateTime(now);
		classGroupTeacherMapper.setUpdateTime(now);
		classGroupTeacherMapperDao.insert(classGroupTeacherMapper);

		//创建班级与老师课酬记录
		ClassGroupTeacherSalary classGroupTeacherSalary = new ClassGroupTeacherSalary();
		classGroupTeacherSalary.setMusicGroupId(applyBaseInfo.getId().toString());
		classGroupTeacherSalary.setClassGroupId(classGroup.getId());
		classGroupTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
		classGroupTeacherSalary.setUserId(applyBaseInfo.getUserId());
		classGroupTeacherSalary.setSalary(BigDecimal.ZERO);
		classGroupTeacherSalary.setOnlineClassesSalary(applyBaseInfo.getOnlineTeacherSalary());
		classGroupTeacherSalary.setGroupType(GroupType.PRACTICE);
		classGroupTeacherSalary.setCreateTime(now);
		classGroupTeacherSalary.setUpdateTime(now);
		classGroupTeacherSalaryDao.insert(classGroupTeacherSalary);

		//课程信息调整
		courseSchedules.forEach(courseSchedule -> {
			courseSchedule.setGroupType(GroupType.PRACTICE);
			courseSchedule.setMusicGroupId(applyBaseInfo.getId().toString());
			courseSchedule.setTeacherId(applyBaseInfo.getUserId());
			courseSchedule.setActualTeacherId(applyBaseInfo.getUserId());
			courseSchedule.setStatus(CourseStatusEnum.NOT_START);
			courseSchedule.setType(CourseSchedule.CourseScheduleType.PRACTICE);
			courseSchedule.setClassGroupId(classGroup.getId());
			courseSchedule.setName(applyBaseInfo.getName());
			courseSchedule.setOrganId(applyBaseInfo.getOrganId());
		});

		applyBaseInfo.setCourseScheduleJson(JSON.toJSONString(courseSchedules));
		practiceGroupDao.update(applyBaseInfo);

		//创建课程
		courseScheduleService.batchAddCourseSchedule(courseSchedules);

		//创建老师单节课课酬信息
		List<CourseScheduleTeacherSalary> courseScheduleTeacherSalaries = new ArrayList<>();
		for (CourseSchedule courseSchedule : courseSchedules) {
			//创建教师课程薪水记录
			CourseScheduleTeacherSalary courseScheduleTeacherSalary = new CourseScheduleTeacherSalary();
			courseScheduleTeacherSalary.setCourseScheduleId(courseSchedule.getId());
			courseScheduleTeacherSalary.setGroupType(courseSchedule.getGroupType());
			courseScheduleTeacherSalary.setMusicGroupId(courseSchedule.getMusicGroupId());
			courseScheduleTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
			courseScheduleTeacherSalary.setUserId(courseSchedule.getActualTeacherId().intValue());
			courseScheduleTeacherSalary.setClassGroupId(courseSchedule.getClassGroupId());
			courseScheduleTeacherSalary.setExpectSalary(classGroupTeacherSalary.getOnlineClassesSalary());
			courseScheduleTeacherSalary.setActualSalary(null);
			courseScheduleTeacherSalaries.add(courseScheduleTeacherSalary);
		}
		if (courseScheduleTeacherSalaries.size() > 0) {
			courseScheduleTeacherSalaryService.batchInsert(courseScheduleTeacherSalaries);
		}
		PracticeGroupSellPrice practiceGroupSellPrice = practiceGroupSellPriceDao.get(applyBaseInfo.getOrganId());
		BigDecimal singleClassMinutesPrice = practiceGroupSellPrice.getSingleClassMinutesPrice();
		Map<Integer, List<CourseScheduleStudentPayment>> collect = courseScheduleStudentPayments.stream().collect(Collectors.groupingBy(CourseScheduleStudentPayment::getUserId));
		for (Integer integer : collect.keySet()) {
			List<CourseScheduleStudentPayment> studentPayments = collect.get(integer);
			for (int i = 0; i < studentPayments.size(); i++) {
				CourseScheduleStudentPayment courseScheduleStudentPayment = studentPayments.get(i);
				CourseSchedule courseSchedule = courseSchedules.get(i);
				courseScheduleStudentPayment.setGroupType(courseSchedule.getGroupType());
				courseScheduleStudentPayment.setMusicGroupId(courseSchedule.getMusicGroupId());
				courseScheduleStudentPayment.setCourseScheduleId(courseSchedule.getId());
				courseScheduleStudentPayment.setClassGroupId(courseSchedule.getClassGroupId());
				courseScheduleStudentPayment.setOriginalPrice(singleClassMinutesPrice);
			}
		}

		if (courseScheduleStudentPayments.size() > 0) {
			courseScheduleStudentPaymentDao.batchInsert(courseScheduleStudentPayments);
			studentDao.updateStudentServiceTag(null, studentIdList, YesOrNoEnum.YES.getCode());
		}
		return BaseController.succeed(applyBaseInfo.getAuditStatus().getCode());
    }

    @Override
    public List<ActivityUserMapper> findByIds(String activityUserMapperIds) {
        return activityUserMapperDao.findByIds(activityUserMapperIds);
    }

	@Override
	public void subCourseConvert(List<CourseScheduleStudentPayment> studentPayments, Integer studentId, Integer singleClassMinutes,Integer categoryId) {
		studentPayments = studentPayments.stream().filter(e->e.getActualPrice().compareTo(ZERO) > 0).collect(Collectors.toList());
		if(CollectionUtils.isEmpty(studentPayments)){
			return;
		}
		ActivityUserMapper activityUserMapper = new ActivityUserMapper();
		activityUserMapper.setReturnFee(false);
		activityUserMapper.setSingleCourseTime(singleClassMinutes);
		activityUserMapper.setTotalCourseNum(studentPayments.size());
		activityUserMapper.setSubCourseNum(studentPayments.size());
		if(Objects.nonNull(categoryId)){
			activityUserMapper.setVipFlag(1);
			activityUserMapper.setCategoryId(categoryId);
			activityUserMapper.setAddMemo("学员休学转化排课资格:" + studentPayments.get(0).getMusicGroupId());
		}else {
			activityUserMapper.setPracticeFlag(1);
			activityUserMapper.setAddMemo("网管课关闭转化排课资格");
		}
		BigDecimal reduce = studentPayments.stream().map(e -> e.getActualPrice()).reduce(ZERO, BigDecimal::add);
		activityUserMapper.setActualPrice(reduce);
		activityUserMapper.setSubNoCoursePrice(reduce);
		Student student = studentDao.get(studentId);
		activityUserMapper.setTenantId(student.getTenantId());
		activityUserMapper.setTeacherId(student.getTeacherId());
		activityUserMapper.setUserId(studentId);
		activityUserMapperDao.insert(activityUserMapper);
	}

	@Override
	public ActivityUserMapperDao getDao() {
		return activityUserMapperDao;
	}


	@Override
	public void use(List<ActivityUserMapper> activityUserMappers, List<ActivityUserMapper> freeActivityUserMappers,
										   BaseMapDto<Integer,Integer> indexDto,Long groupId,CourseScheduleStudentPayment courseScheduleStudentPayment) {
		//扣除排课资格
		if(!org.springframework.util.CollectionUtils.isEmpty(activityUserMappers) && activityUserMappers.size() > indexDto.getValue()){
			ActivityUserMapper activityUserMapper = activityUserMappers.get(indexDto.getValue());
			BigDecimal consumerPrice = ZERO;
			Integer subCourseNum = activityUserMapper.getSubCourseNum();
			if(subCourseNum == 1){
				indexDto.setValue(indexDto.getValue() + 1);
				consumerPrice = activityUserMapper.getSubNoCoursePrice();
				activityUserMapper.setSubNoCoursePrice(ZERO);
			}else {
				if(activityUserMapper.getActualPrice().compareTo(ZERO) > 0) {
					//单课金额
					consumerPrice = activityUserMapper.getActualPrice().divide(new BigDecimal(activityUserMapper.getTotalCourseNum()), BigDecimal.ROUND_CEILING, RoundingMode.DOWN);
					activityUserMapper.setSubNoCoursePrice(activityUserMapper.getSubNoCoursePrice().subtract(consumerPrice));
				}
			}
			activityUserMapper.setSubCourseNum(subCourseNum - 1);
			this.modifyGroupId(activityUserMapper,groupId);
			courseScheduleStudentPayment.setActivityUserMapperId(activityUserMapper.getId());
			courseScheduleStudentPayment.setActualPrice(consumerPrice);
			courseScheduleStudentPayment.setExpectPrice(consumerPrice);
		}else if (!org.springframework.util.CollectionUtils.isEmpty(freeActivityUserMappers) && freeActivityUserMappers.size() > indexDto.getKey()) {
			ActivityUserMapper activityUserMapper = freeActivityUserMappers.get(indexDto.getKey());
			Integer subCourseNum = activityUserMapper.getSubGiveCourseNum();
			if(subCourseNum == 1){
				indexDto.setKey(indexDto.getKey() + 1);
			}
			activityUserMapper.setSubGiveCourseNum(subCourseNum - 1);
			this.modifyGiveGroupId(activityUserMapper,groupId);
			courseScheduleStudentPayment.setActivityUserMapperId(activityUserMapper.getId());
			courseScheduleStudentPayment.setActualPrice(ZERO);
			courseScheduleStudentPayment.setExpectPrice(ZERO);
		}else {
			throw new BizException("所选学员排课资格不足");
		}
	}

}