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

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.DemoGroupApplyDto;
import com.ym.mec.biz.dal.dto.EducationDemoGroupListDto;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.ClassGroupStudentStatusEnum;
import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.enums.TeachTypeEnum;
import com.ym.mec.biz.dal.enums.YesOrNoEnum;
import com.ym.mec.biz.dal.page.StudentDemoGroupQueryInfo;
import com.ym.mec.biz.dal.page.TeacherManageDemoGroupQueryInfo;
import com.ym.mec.biz.service.CourseScheduleService;
import com.ym.mec.biz.service.DemoGroupService;
import com.ym.mec.biz.service.SysConfigService;
import com.ym.mec.biz.service.TeacherAttendanceService;
import com.ym.mec.common.dal.BaseDAO;
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.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

/**
 * @author Joburgess
 */
@Service
public class DemoGroupServiceImpl extends BaseServiceImpl<Long, DemoGroup>  implements DemoGroupService {
	
	@Autowired
	private DemoGroupDao demoGroupDao;
	@Autowired
	private ClassGroupDao classGroupDao;
	@Autowired
	private DemoGroupCoursesPlanDao demoGroupCoursesPlanDao;
	@Autowired
	private CourseScheduleDao courseScheduleDao;
	@Autowired
	private CourseScheduleService courseScheduleService;
	@Autowired
	private ClassGroupStudentMapperDao classGroupStudentMapperDao;

	@Autowired
	private SysUserFeignService sysUserFeignService;
	@Autowired
	private SubjectDao subjectDao;
	@Autowired
	private SysConfigDao sysConfigDao;
	@Autowired
	private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
	@Autowired
	private CourseScheduleTeacherSalaryDao courseScheduleTeacherSalaryDao;
	@Autowired
	private TeacherAttendanceService teacherAttendanceService;

	@Override
	public BaseDAO<Long, DemoGroup> getDAO() {
		return demoGroupDao;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void demoGroupApply(DemoGroupApplyDto demoGroupApplyDto) {

		Date now=new Date();
		Date dayEnd = DateUtil.dayEnd(now);
		//下周一日期
		Date nextMonday= DateUtil.getNextWeekMonday(now);
		//下周日日期
		Date nextSunday=DateUtil.getNextWeekSunday(now);

		//当前教师下周的试听课计划
		List<DemoGroupCoursesPlan> nextWeekDemoGroupCoursePlan = demoGroupCoursesPlanDao.findByDateZone(nextMonday, nextSunday, demoGroupApplyDto.getUserId());

		demoGroupApplyDto.setSingleClassMinutes(Integer.parseInt(sysConfigDao.findConfigValue(SysConfigService.DEMO_GROUP_SINGLE_CLASS_MINUTES_)));

		if(CollectionUtils.isEmpty(nextWeekDemoGroupCoursePlan)){
			demoGroupDao.insert(demoGroupApplyDto);
			demoGroupCoursesPlanDao.batchInsertByDates(demoGroupApplyDto.getCourseDates(),
					demoGroupApplyDto.getId(),
					demoGroupApplyDto.getSingleClassMinutes());
		}else{
			if(Objects.isNull(demoGroupApplyDto.getId())){
				throw new BizException("请指定试听课");
			}
			List<DateUtil.DateZone> dateZones=new ArrayList<>();
			List<Date> newDates=new ArrayList<>();
			Map<YesOrNoEnum, List<DemoGroupCoursesPlan>> demoGroupPlanByStatus = nextWeekDemoGroupCoursePlan.stream().collect(Collectors.groupingBy(DemoGroupCoursesPlan::getStatus));
			//已生成课程的试听课计划
			List<DemoGroupCoursesPlan> demoGroupCoursesPlansWithCreated = demoGroupPlanByStatus.get(YesOrNoEnum.YES);
			if(!CollectionUtils.isEmpty(demoGroupCoursesPlansWithCreated)){
				demoGroupCoursesPlansWithCreated.forEach(demoGroupCoursesPlan -> {
					dateZones.add(new DateUtil.DateZone(demoGroupCoursesPlan.getStartTime(),demoGroupCoursesPlan.getEndTime()));
				});
			}
			demoGroupApplyDto.getCourseDates().forEach(startTime->{
				if(dayEnd.before(startTime)){
					Date endTime = DateUtil.addMilliseconds(startTime, demoGroupApplyDto.getSingleClassMinutes());
					dateZones.add(new DateUtil.DateZone(startTime,endTime));
					newDates.add(startTime);
				}
			});
			boolean isHaveOverlap = DateUtil.checkDateZoneOverlap(dateZones);
			if(isHaveOverlap){
				throw new BizException("上课时间存在冲突");
			}
			demoGroupDao.update(demoGroupApplyDto);
			demoGroupCoursesPlanDao.deleteAfterDate(dayEnd,demoGroupApplyDto.getId().intValue());
			if(!CollectionUtils.isEmpty(newDates)){
				demoGroupCoursesPlanDao.batchInsertByDates(newDates,
						demoGroupApplyDto.getId(),
						demoGroupApplyDto.getSingleClassMinutes());
			}
		}
	}

	@Override
	public DemoGroup getDemoGroupByTeacherId() throws Exception {
		SysUser user = sysUserFeignService.queryUserInfo();
		if(user == null){
			throw new BizException("获取用户信息失败");
		}
		return demoGroupDao.findDemoGroupByTeacherId(user.getId());
	}

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

		List dataList = null;
		int count = demoGroupDao.countDemoGroupList(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			List<Integer> demoGoupIds = demoGroupDao.findDemoGoupIds(params);
			dataList = demoGroupDao.findDemoGroupList(params,demoGoupIds);
		}
		if (count == 0) {
			dataList = new ArrayList<>();
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void demoGroupSubscribe(Long demoGroupId,Long coursePlanId) {
		createCourseScheduleAndUpdateOrganId(demoGroupId,coursePlanId);
	}

	/**
	 * @Author: Joburgess
	 * @Date: 2019/9/25
	 * 创建上课计划及跟新所属分部列表
	 */
	public void createCourseScheduleAndUpdateOrganId(Long demoGroupId,Long coursePlanId){

		if(Objects.isNull(demoGroupId)){
			throw new BizException("请指定试听课");
		}

		DemoGroup demoGroup=demoGroupDao.get(demoGroupId);

		if(Objects.isNull(demoGroup)){
			throw new BizException("指定的试听课不存在");
		}

		DemoGroupCoursesPlan demoGroupCoursesPlan1 = demoGroupCoursesPlanDao.get(coursePlanId);
		if(demoGroupCoursesPlan1.getStatus()==YesOrNoEnum.YES){
			throw new BizException("该时段课程已被预约");
		}

		int i = courseScheduleDao.countExistRepeatInDateZone(demoGroup.getUserId(),
				demoGroupCoursesPlan1.getCourseDate(),
				demoGroupCoursesPlan1.getStartTime(),
				demoGroupCoursesPlan1.getEndTime());
		if(i>0){
			throw new BizException("此课程教师在该时段内的课程存在冲突");
		}

		Date now=new Date();

		SysUser user = sysUserFeignService.queryUserInfo();

		//创建班级
		ClassGroup classGroup=new ClassGroup();
		classGroup.setMusicGroupId(demoGroup.getId().toString());
		classGroup.setName(demoGroup.getName());
		classGroup.setType(ClassGroupTypeEnum.DEMO);
		classGroup.setDelFlag(0);
		classGroup.setTotalClassTimes(1);
		classGroup.setGroupType(GroupType.DEMO);
		classGroup.setCreateTime(now);
		classGroup.setUpdateTime(now);
		classGroup.setSubjectIdList(demoGroup.getSubjectId().toString());
		classGroupDao.insert(classGroup);

		//创建班级学生映射
		ClassGroupStudentMapper classGroupStudentMapper=new ClassGroupStudentMapper();
		classGroupStudentMapper.setClassGroupId(classGroup.getId());
		classGroupStudentMapper.setUserId(user.getId());
		classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
		classGroupStudentMapper.setMusicGroupId(demoGroup.getId().toString());
		classGroupStudentMapper.setGroupType(GroupType.DEMO);
		classGroupStudentMapperDao.insert(classGroupStudentMapper);

		//创建课程
		DemoGroupCoursesPlan demoGroupCoursesPlan=demoGroupCoursesPlanDao.get(coursePlanId);
		CourseSchedule courseScheduleByDemoGroup = demoGroupDao.createCourseScheduleByDemoGroupPlan(
				demoGroup,
				coursePlanId,
				classGroup.getId().longValue());
		StringBuilder className=new StringBuilder(subjectDao.get(demoGroup.getSubjectId().intValue()).getName());
		className.append("-");
		className.append(CourseSchedule.CourseScheduleType.DEMO.getMsg());
		courseScheduleByDemoGroup.setName(className.toString());
		courseScheduleByDemoGroup.setGroupType(GroupType.DEMO);
		courseScheduleByDemoGroup.setMusicGroupId(classGroup.getMusicGroupId());
		List<CourseSchedule> courseSchedules=new ArrayList<>();
		courseSchedules.add(courseScheduleByDemoGroup);
		courseScheduleService.checkNewCourseSchedules(courseSchedules,false,false);
		courseScheduleDao.insert(courseScheduleByDemoGroup);

		CourseScheduleStudentPayment courseScheduleStudentPayment = new CourseScheduleStudentPayment();
		courseScheduleStudentPayment.setUserId(user.getId());
        courseScheduleStudentPayment.setGroupType(GroupType.DEMO);
        courseScheduleStudentPayment.setMusicGroupId(demoGroup.getId().toString());
		courseScheduleStudentPayment.setCourseScheduleId(courseScheduleByDemoGroup.getId());
		courseScheduleStudentPayment.setClassGroupId(courseScheduleByDemoGroup.getClassGroupId());
		courseScheduleStudentPayment.setExpectPrice(demoGroup.getPrice());
		courseScheduleStudentPayment.setCreateTime(now);
		courseScheduleStudentPayment.setUpdateTime(now);
		courseScheduleStudentPaymentDao.insert(courseScheduleStudentPayment);

		CourseScheduleTeacherSalary courseScheduleTeacherSalary = new CourseScheduleTeacherSalary();
		courseScheduleTeacherSalary.setCourseScheduleId(courseScheduleByDemoGroup.getId());
        courseScheduleTeacherSalary.setGroupType(GroupType.DEMO);
        courseScheduleTeacherSalary.setMusicGroupId(demoGroup.getId().toString());
		courseScheduleTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
		courseScheduleTeacherSalary.setUserId(demoGroup.getUserId());
		courseScheduleTeacherSalary.setExpectSalary(demoGroup.getPrice());
		courseScheduleTeacherSalary.setClassGroupId(classGroup.getId());
		courseScheduleTeacherSalary.setCreateTime(now);
		courseScheduleTeacherSalary.setUpdateTime(now);
		courseScheduleTeacherSalaryDao.insert(courseScheduleTeacherSalary);

		//更新所属分部列表
		List<Integer> organIds = demoGroupDao.organIdListByDemoGroupId(demoGroup.getId());
		organIds.add(demoGroupDao.getOrganIdByUserId(demoGroup.getUserId().longValue()));
		HashSet<Integer> hashSet = new HashSet<>(organIds);
		String organIdsString = StringUtils.join(hashSet, ",");
		demoGroup.setOrganIdList(organIdsString);
		demoGroupDao.update(demoGroup);

		TeacherAttendance teacherAttendance=new TeacherAttendance(demoGroup.getUserId(),demoGroup.getId().toString(),classGroup.getId(),courseScheduleByDemoGroup.getId(),now);
		teacherAttendance.setGroupType(GroupType.DEMO);
		teacherAttendance.setMusicGroupId(demoGroup.getId().toString());
		teacherAttendanceService.insert(teacherAttendance);

		//修改课程预约状态
		demoGroupCoursesPlan.setStatus(YesOrNoEnum.YES);
		demoGroupCoursesPlanDao.update(demoGroupCoursesPlan);
	}

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

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

	@Override
	public List<EducationDemoGroupListDto> findDemoGroupStartClassTimesWithWeekByTeacherId(Long teacherID) {
		return demoGroupDao.findDemoGroupStartClassTimesWithWeekByTeacherId(teacherID);
	}

	@Override
	public Map<String,Object> findByTeacherId(Integer teacherId,Date startTime,Date endTime) {
		Date now=new Date();
		if(Objects.isNull(startTime)||Objects.isNull(endTime)){
			//下周一日期
			startTime= DateUtil.getNextWeekMonday(now);
			//下周日日期
			endTime=DateUtil.getNextWeekSunday(now);
		}

		Map<String,Object> result=new HashMap<>();

		//当前教师下周的试听课计划
		List<DemoGroupCoursesPlan> nextWeekDemoGroupCoursePlan = demoGroupCoursesPlanDao.findByDateZone(startTime, endTime, teacherId);
		if(CollectionUtils.isEmpty(nextWeekDemoGroupCoursePlan)){
			result.put("baseInfo",new Object());
			result.put("list",new ArrayList<>());
		}else{
			DemoGroup demoGroup = demoGroupDao.findById(nextWeekDemoGroupCoursePlan.get(0).getDemoGroupId());
			result.put("baseInfo",demoGroup);
			List<Map<String,Object>> courses=new ArrayList<>();
			Map<String, List<DemoGroupCoursesPlan>> collect = nextWeekDemoGroupCoursePlan.stream().collect(Collectors.groupingBy(DemoGroupCoursesPlan::getCourseDateStr));
			for(String key:collect.keySet()){
				Map<String,Object> r=new HashMap<>();
				r.put("day",key);
				r.put("list",collect.get(key));
				courses.add(r);
			}
			result.put("list",courses);
		}
		return result;

	}
}
