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

import com.alibaba.fastjson.JSON;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.VipGroupSalarySettlementDto;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.service.CourseScheduleTeacherSalaryService;
import com.ym.mec.biz.service.SysUserCashAccountDetailService;
import com.ym.mec.biz.service.SysUserCashAccountService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long, CourseScheduleTeacherSalary>  implements CourseScheduleTeacherSalaryService {
	
	@Autowired
	private CourseScheduleTeacherSalaryDao courseScheduleTeacherSalaryDao;
	@Autowired
	private TeacherDefaultVipGroupSalaryDao teacherDefaultVipGroupSalaryDao;
	@Autowired
	private VipGroupActivityDao vipGroupActivityDao;
	@Autowired
	private CourseScheduleComplaintsDao courseScheduleComplaintsDao;
	@Autowired
	private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
	@Autowired
	private SysUserCashAccountService sysUserCashAccountService;
	@Autowired
	private SysUserCashAccountDetailService sysUserCashAccountDetailService;
	@Autowired
	private StudentPaymentOrderDao studentPaymentOrderDao;

	private static final Logger LOGGER = LoggerFactory
			.getLogger(CourseScheduleTeacherSalaryServiceImpl.class);

	@Override
	public BaseDAO<Long, CourseScheduleTeacherSalary> getDAO() {
		return courseScheduleTeacherSalaryDao;
	}

	@Override
	public int createCourseScheduleTeacherVipSalary(VipGroup vipGroup,
													List<CourseSchedule> vipCourseSchedules,
													BigDecimal onlineTeacherSalary,
													BigDecimal offlineTeacherSalary) {
		TeacherDefaultVipGroupSalary teacherDefaultVipGroupSalary = teacherDefaultVipGroupSalaryDao.findByTeacherAndCategory(vipGroup.getUserId().longValue(),
				vipGroup.getVipGroupCategoryId());

		//获取活动信息
		VipGroupActivity vipGroupActivity = vipGroupActivityDao.get(vipGroup.getVipGroupActivityId().intValue());
		VipGroupSalarySettlementDto vipGroupSalarySettlementDto = JSON.parseObject(vipGroupActivity.getSalarySettlementJson(), VipGroupSalarySettlementDto.class);

		List<CourseScheduleTeacherSalary> courseScheduleTeacherSalaries=new ArrayList<>();
		Map<TeachModeEnum, List<CourseSchedule>> courseScheduleGroupByTeachMode = vipCourseSchedules.stream().collect(Collectors.groupingBy(CourseSchedule::getTeachMode));

		for(TeachModeEnum teachModeEnum:courseScheduleGroupByTeachMode.keySet()){
			List<CourseSchedule> courseSchedules = courseScheduleGroupByTeachMode.get(teachModeEnum)
					.stream()
					.sorted(Comparator.comparing(CourseSchedule::getStartClassTime)).collect(Collectors.toList());
			for(int i=0;i<courseSchedules.size();i++){
				//创建教师课程薪水记录
				CourseScheduleTeacherSalary courseScheduleTeacherSalary=new CourseScheduleTeacherSalary();
				courseScheduleTeacherSalary.setCourseScheduleId(courseSchedules.get(i).getId());
				courseScheduleTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
				courseScheduleTeacherSalary.setUserId(vipGroup.getUserId());

				if(teachModeEnum==TeachModeEnum.ONLINE){
					if(vipGroupActivity.getType()== VipGroupActivityTypeEnum.GIVE_CLASS
							&&vipGroup.getGiveTeachMode()==teachModeEnum
							&&i>=Integer.parseInt(vipGroupActivity.getAttribute1())
							&&"0".equals(vipGroupActivity.getGiveClassPaySalaryFlag())){
						courseScheduleTeacherSalary.setExpectSalary(new BigDecimal(0));
					}else {
						//教师课酬线上单课酬计算
						switch (vipGroupSalarySettlementDto.getOnlineSalarySettlement().getSalarySettlementType()){
							case TEACHER_DEFAULT:
								courseScheduleTeacherSalary.setExpectSalary(teacherDefaultVipGroupSalary.getOnlineClassesSalary());
								break;
							case RATIO_DISCOUNT:
								courseScheduleTeacherSalary.setExpectSalary(onlineTeacherSalary.multiply(vipGroupSalarySettlementDto.getOnlineSalarySettlement().getSettlementValue()));
								break;
							case FIXED_SALARY:
								courseScheduleTeacherSalary.setExpectSalary(vipGroupSalarySettlementDto.getOnlineSalarySettlement().getSettlementValue());
								break;
							default:
								throw new BizException("未指定课酬结算标准!");
						}
					}
				}else{
					//教师线下单课酬计算
					switch (vipGroupSalarySettlementDto.getOfflineSalarySettlement().getSalarySettlementType()){
						case TEACHER_DEFAULT:
							courseScheduleTeacherSalary.setExpectSalary(teacherDefaultVipGroupSalary.getOfflineClassesSalary());
							break;
						case RATIO_DISCOUNT:
							courseScheduleTeacherSalary.setExpectSalary(offlineTeacherSalary.multiply(vipGroupSalarySettlementDto.getOfflineSalarySettlement().getSettlementValue()));
							break;
						case FIXED_SALARY:
							courseScheduleTeacherSalary.setExpectSalary(vipGroupSalarySettlementDto.getOfflineSalarySettlement().getSettlementValue());
							break;
						default:
							throw new BizException("未指定课酬结算标准!");
					}
				}
				courseScheduleTeacherSalaries.add(courseScheduleTeacherSalary);
			}
		}
		return courseScheduleTeacherSalaryDao.batchInsert(courseScheduleTeacherSalaries);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void teacherSalarySettlement() {
		//获取教师未结算课程记录
		List<CourseScheduleTeacherSalary> someDayAgoTeacherCourseSalaryNoSettlement = courseScheduleTeacherSalaryDao.findSomeDayAgoTeacherCourseSalaryNoSettlement(7);
		if(CollectionUtils.isEmpty(someDayAgoTeacherCourseSalaryNoSettlement)){
			LOGGER.info("未获取到未结算课酬记录!");
		}
		Date now=new Date();
		//获取未结算课程编号列表
		List<Long> courseScheduleIds = someDayAgoTeacherCourseSalaryNoSettlement.stream().map(CourseScheduleTeacherSalary::getCourseScheduleId).collect(Collectors.toList());
		//获取未结算课程投诉记录
		List<CourseScheduleComplaints> courseScheduleComplaints = courseScheduleComplaintsDao.findByCourseScheduleIds(courseScheduleIds);
		//获取未结算课程学生缴费信息
		List<CourseScheduleStudentPayment> courseScheduleStudentPayments = courseScheduleStudentPaymentDao.findByCourseScheduleIds(courseScheduleIds);

		//根据课程将投诉信息分组
		Map<Long, List<CourseScheduleComplaints>> complaintsGroupByCourse = courseScheduleComplaints.stream().collect(Collectors.groupingBy(CourseScheduleComplaints::getCourseScheduleId));
		//根据课程将学生缴费信息分组
		Map<Long, List<CourseScheduleStudentPayment>> studentPaymentGroupByCourse = courseScheduleStudentPayments.stream().collect(Collectors.groupingBy(CourseScheduleStudentPayment::getCourseScheduleId));

		//需更新教师课程结算记录
		List<CourseScheduleTeacherSalary> updateTeacherSalarys=new ArrayList<>();
		//需更新学生课程缴费记录
		List<CourseScheduleStudentPayment> updateStudentPayments=new ArrayList<>();

		//用户账户自己变动信息列表
		List<SysUserCashAccountDetail> userCashAccountDetails=new ArrayList<>();

		//处理课酬信息
		someDayAgoTeacherCourseSalaryNoSettlement.forEach(courseScheduleTeacherSalary -> {
			//获取当前课程学生缴费记录
			List<CourseScheduleStudentPayment> studentPaymentsWithCourse = studentPaymentGroupByCourse.get(courseScheduleTeacherSalary.getCourseScheduleId());
			//当前课程缴费学生数量
			BigDecimal courseStudentNum=new BigDecimal(studentPaymentsWithCourse.size());
			//教师预计课酬
			BigDecimal expectSalary=courseScheduleTeacherSalary.getExpectSalary();
			//当前课程每个学生平均课酬
			BigDecimal avgSalary=expectSalary.divide(courseStudentNum);
			//教师当前课程责任总占比,当前课程应得课酬
			BigDecimal teacherLiabilityAllratio,teacherCourseSalary;

			//当前课程学生投诉记录
			List<CourseScheduleComplaints> courseStudentComplaints=complaintsGroupByCourse.get(courseScheduleTeacherSalary.getCourseScheduleId());

			//如果存在投诉记录,需要扣除相应费用
			if(Objects.nonNull(courseStudentComplaints)){
				//获取审批中的投诉
				List<CourseScheduleComplaints> auditIng = courseStudentComplaints.stream().filter(courseScheduleComplaint -> courseScheduleComplaint.getStatus() == AuditStatusEnum.ING).collect(Collectors.toList());
				if(!CollectionUtils.isEmpty(auditIng)){
					//如果当前课程存在未处理的投诉，则不做结算处理
					return;
				}
				//计算教师责任总占比
				double teacherLiabilityRatioSum = courseStudentComplaints.stream().mapToDouble(CourseScheduleComplaints::getTeacherLiabilityRatio).sum();
				teacherLiabilityAllratio=new BigDecimal(teacherLiabilityRatioSum);
			}else{
				//如果没有投诉，则教师和学生的责任占比为0
				teacherLiabilityAllratio=new BigDecimal(0);
			}

			//教师应扣除费用
			BigDecimal deductPrice=avgSalary.multiply(teacherLiabilityAllratio);
			//教师实际课酬
			BigDecimal actualSalary=expectSalary.subtract(deductPrice);

			//更新教师结算信息
			courseScheduleTeacherSalary.setActualSalary(actualSalary);
			courseScheduleTeacherSalary.setSettlementTime(now);
			courseScheduleTeacherSalaryDao.update(courseScheduleTeacherSalary);
			updateTeacherSalarys.add(courseScheduleTeacherSalary);

			//生成教师账户资金变动记录
			sysUserCashAccountService.updateBalance(courseScheduleTeacherSalary.getUserId(),actualSalary);
			SysUserCashAccount teacherCashAccount = sysUserCashAccountService.get(courseScheduleTeacherSalary.getUserId().intValue());
			SysUserCashAccountDetail teacherCashAccountDetail=new SysUserCashAccountDetail();
			teacherCashAccountDetail.setUserId(courseScheduleTeacherSalary.getUserId());
			teacherCashAccountDetail.setType(PlatformCashAccountDetailTypeEnum.REFUNDS);
			teacherCashAccountDetail.setStatus(DealStatusEnum.SUCCESS);
			teacherCashAccountDetail.setAmount(actualSalary);
			teacherCashAccountDetail.setBalance(teacherCashAccount.getBalance());
			teacherCashAccountDetail.setAttribute(courseScheduleTeacherSalary.getCourseScheduleId().toString());

			userCashAccountDetails.add(teacherCashAccountDetail);


			//根据学生进行投诉分组
			Map<Integer, List<CourseScheduleComplaints>> complainsGroupByStudent = courseStudentComplaints.stream().collect(Collectors.groupingBy(CourseScheduleComplaints::getUserId));

			//计算学生当前课程应缴费用
			studentPaymentsWithCourse.forEach(studentPayment -> {
				//当前课程学生应缴费用
				BigDecimal studentExpectPrice=studentPayment.getExpectPrice();
				//当前课程学生责任占比
				BigDecimal studentLiabilityRatio;
				List<CourseScheduleComplaints> currentCourseScheduleComplaints = complainsGroupByStudent.get(studentPayment.getUserId());
				if(CollectionUtils.isEmpty(currentCourseScheduleComplaints)){
					Double temp=currentCourseScheduleComplaints.get(0).getStudentLiabilityRatio();
					studentLiabilityRatio=new BigDecimal(temp);
				}else{
					studentLiabilityRatio=new BigDecimal(0);
				}

				//当前课程学生应退费用
				BigDecimal returnPrice=studentExpectPrice.multiply(studentLiabilityRatio);
				//当前课程学生实际缴费
				BigDecimal actualPrice=expectSalary.subtract(returnPrice);
				//更新学生结算信息
				studentPayment.setActualPrice(actualPrice);
				studentPayment.setSettlementTime(now);
				courseScheduleStudentPaymentDao.update(studentPayment);
				updateStudentPayments.add(studentPayment);

				//生成学生账户资金变动记录
				sysUserCashAccountService.updateBalance(studentPayment.getUserId(),returnPrice);
				SysUserCashAccount studentCashAccount = sysUserCashAccountService.get(studentPayment.getUserId().intValue());
				SysUserCashAccountDetail studentAccountDetail=new SysUserCashAccountDetail();
//				studentAccountDetail.setTransNo(studentPayment.getT());
				studentAccountDetail.setUserId(studentPayment.getUserId());
				studentAccountDetail.setType(PlatformCashAccountDetailTypeEnum.REFUNDS);
				studentAccountDetail.setStatus(DealStatusEnum.SUCCESS);
				studentAccountDetail.setAmount(returnPrice);
				studentAccountDetail.setBalance(studentCashAccount.getBalance());
				studentAccountDetail.setAttribute(courseScheduleTeacherSalary.getCourseScheduleId().toString());

				userCashAccountDetails.add(studentAccountDetail);

			});

		});

	}
}