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

import com.ym.mec.biz.dal.dao.MusicGroupOrganizationCourseSettingsDetailDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentStudentCourseDetailDao;
import com.ym.mec.biz.dal.dao.OrganizationCourseUnitPriceSettingsDao;
import com.ym.mec.biz.dal.dto.MusicGroupPaymentBaseCalender;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.CalenderBaseServiceEnum;
import com.ym.mec.biz.service.MusicGroupOrganizationCourseSettingsService;
import com.ym.mec.biz.service.MusicGroupPaymentCalenderBaseService;
import com.ym.mec.common.controller.BaseController;
import com.ym.mec.common.exception.BizException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderCourseSettingsDao;
import com.ym.mec.biz.service.MusicGroupPaymentCalenderCourseSettingsService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PayUserType.SCHOOL;
import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentCalenderStatusEnum.AUDITING;
import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentType.MUSIC_APPLY;
import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentType.MUSIC_RENEW;

@Service
public class MusicGroupPaymentCalenderCourseSettingsServiceImpl extends BaseServiceImpl<Integer, MusicGroupPaymentCalenderCourseSettings>
		implements MusicGroupPaymentCalenderCourseSettingsService, MusicGroupPaymentCalenderBaseService<MusicGroupPaymentCalenderCourseSettings> {
	
	@Autowired
	private MusicGroupPaymentCalenderCourseSettingsDao musicGroupPaymentCalenderCourseSettingsDao;
	@Autowired
	private MusicGroupPaymentStudentCourseDetailDao musicGroupPaymentStudentCourseDetailDao;
	@Autowired
	private MusicGroupOrganizationCourseSettingsDetailDao musicGroupOrganizationCourseSettingsDetailDao;
	@Autowired
	private OrganizationCourseUnitPriceSettingsDao organizationCourseUnitPriceSettingsDao;
	@Autowired
	private MusicGroupOrganizationCourseSettingsService musicGroupOrganizationCourseSettingsService;

	public MusicGroupPaymentCalenderCourseSettingsServiceImpl() {
		MusicGroupPaymentCalenderBaseService.calenderBaseServiceMap.put(CalenderBaseServiceEnum.COURSE,this);
	}

	@Override
	public BaseDAO<Integer, MusicGroupPaymentCalenderCourseSettings> getDAO() {
		return musicGroupPaymentCalenderCourseSettingsDao;
	}

	@Override
	public Map<String, Integer> getMusicCourseSettingsWithStudents(String musicGroupId, List<Integer> studentIds) {
		List<MusicGroupPaymentStudentCourseDetail> mgpscds = musicGroupPaymentStudentCourseDetailDao.getUnUseWithStudents(musicGroupId, studentIds);
		if(CollectionUtils.isEmpty(mgpscds)){
			return Collections.emptyMap();
		}
		Map<String, Integer> result = new HashMap<>();
		Map<CourseSchedule.CourseScheduleType, List<MusicGroupPaymentStudentCourseDetail>> courseTypeDetailsMap = mgpscds.stream().collect(Collectors.groupingBy(MusicGroupPaymentStudentCourseDetail::getCourseType));
		for (Map.Entry<CourseSchedule.CourseScheduleType, List<MusicGroupPaymentStudentCourseDetail>> courseTypeDetailsEntry : courseTypeDetailsMap.entrySet()) {
			Map<Integer, List<MusicGroupPaymentStudentCourseDetail>> userDetailsMap = courseTypeDetailsEntry.getValue().stream().collect(Collectors.groupingBy(MusicGroupPaymentStudentCourseDetail::getUserId));
			if(CollectionUtils.isEmpty(userDetailsMap)||userDetailsMap.keySet().size()!=studentIds.size()){
				continue;
			}
			List<MusicGroupPaymentStudentCourseDetail> details = new ArrayList<>();
			for (Map.Entry<Integer, List<MusicGroupPaymentStudentCourseDetail>> userDetailsEntry : userDetailsMap.entrySet()) {
				details.add(userDetailsEntry.getValue().stream().min(Comparator.comparing(MusicGroupPaymentStudentCourseDetail::getId)).get());
			}
			result.put(courseTypeDetailsEntry.getKey().getCode(), details.stream().min(Comparator.comparing(MusicGroupPaymentStudentCourseDetail::getTotalCourseMinutes)).get().getTotalCourseMinutes());
		}
		//校验剩余时长是否一致
		List<CourseSchedule.CourseScheduleType> courseTypes = mgpscds.stream().map(e -> e.getCourseType()).distinct().collect(Collectors.toList());
		Integer checkCourseTimes = musicGroupPaymentStudentCourseDetailDao.checkCourseTimes(musicGroupId, courseTypes, studentIds);
		if(checkCourseTimes == null || checkCourseTimes == 0){
			result.put("checkCourseTimesFlag",1);
		}else {
			result.put("checkCourseTimesFlag",0);
		}
		return result;
	}

    @Override
    public void batchInsert(MusicGroupPaymentCalender musicGroupPaymentCalender) {
		List<MusicGroupPaymentCalenderCourseSettings> musicGroupPaymentCalenderCourseSettingss = musicGroupPaymentCalender.getMusicGroupPaymentCalenderCourseSettingsList();
		if (musicGroupPaymentCalenderCourseSettingss != null && musicGroupPaymentCalenderCourseSettingss.size() > 0) {
//			if (musicGroupPaymentCalender.getPayUserType() == SCHOOL) {
//				musicGroupPaymentCalenderCourseSettingss.forEach(e->e.setCourseCurrentPrice(BigDecimal.ZERO));
//			}
			MusicGroupOrganizationCourseSettings courseSettings = musicGroupOrganizationCourseSettingsService.get(musicGroupPaymentCalender
					.getMusicGroupOrganizationCourseSettingId());
			for (MusicGroupPaymentCalenderCourseSettings musicGroupPaymentCalenderCourseSettings : musicGroupPaymentCalenderCourseSettingss) {
				musicGroupPaymentCalenderCourseSettings.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
				if (courseSettings != null) {
					musicGroupPaymentCalenderCourseSettings.setName(courseSettings.getName());
				}
			}
			musicGroupPaymentCalenderCourseSettingsDao.batchInsert(musicGroupPaymentCalenderCourseSettingss);
		}
    }

	@Override
	public void deleteByMusicGroupPaymentCalenderId(List<Long> calenderIds) {
		musicGroupPaymentCalenderCourseSettingsDao.deleteByMusicGroupPaymentCalenderId(calenderIds);
	}

	@Override
	public List<MusicGroupPaymentCalenderCourseSettings> queryCalenderCourseSettings(Long calenderId) {
		return musicGroupPaymentCalenderCourseSettingsDao.queryCalenderCourseSettings(calenderId);
	}

	@Override
	public List<MusicGroupPaymentCalenderCourseSettings> queryCalenderCourseSettingsByBatchNo(String batchNo) {
		return musicGroupPaymentCalenderCourseSettingsDao.queryCalenderCourseSettingsByBatchNo(batchNo);
	}

	@Override
	public MusicGroupPaymentCalender.PaymentCalenderStatusEnum checkComponentAmount(MusicGroupPaymentBaseCalender baseCalender) {
		List<MusicGroupPaymentCalenderCourseSettings> musicGroupPaymentCalenderCourseSettingsList = baseCalender.getMusicGroupPaymentCalenderCourseSettingsList();
		if(musicGroupPaymentCalenderCourseSettingsList != null && musicGroupPaymentCalenderCourseSettingsList.size() > 0){
			if (baseCalender.getPaymentType() == MUSIC_APPLY || baseCalender.getPaymentType() == MUSIC_RENEW) {
				// 当前缴费的课程费用
				Map<CourseSchedule.CourseScheduleType, BigDecimal> currentCoursePrice = musicGroupPaymentCalenderCourseSettingsList.stream().collect(
						Collectors.toMap(MusicGroupPaymentCalenderCourseSettings::getCourseType, MusicGroupPaymentCalenderCourseSettings::getCourseCurrentPrice));

				// 查询默认课程费用
				Integer musicGroupOrganizationCourseSettingId = baseCalender.getMusicGroupOrganizationCourseSettingId();
				Map<CourseSchedule.CourseScheduleType, BigDecimal> defaultCoursePrice = musicGroupOrganizationCourseSettingsDetailDao
						.queryByMusicGroupOrganizationCourseSettingsId(musicGroupOrganizationCourseSettingId)
						.stream()
						.collect(Collectors.toMap(MusicGroupOrganizationCourseSettingsDetail::getCourseType,
										MusicGroupOrganizationCourseSettingsDetail::getCourseCurrentPrice));

				// 相同类型的课程如果修改了课程费用，需要走审批
				for (Map.Entry<CourseSchedule.CourseScheduleType, BigDecimal> entry : currentCoursePrice.entrySet()) {
					if (defaultCoursePrice.get(entry.getKey()).compareTo(entry.getValue()) != 0) {
						return AUDITING;
					}
				}
			} else if (baseCalender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.ADD_COURSE) {
				MusicGroup musicGroup = baseCalender.getMusicGroup();
				// 如果是课程收费，判断是否审核
				for (MusicGroupPaymentCalenderCourseSettings courseSettings : musicGroupPaymentCalenderCourseSettingsList) {
					OrganizationCourseUnitPriceSettings defaultUnitPrice = organizationCourseUnitPriceSettingsDao.queryByOrganIdAndCourseTypeAndChargeType(
							musicGroup.getOrganId(), courseSettings.getCourseType(), musicGroup.getChargeTypeId());
					if (defaultUnitPrice == null) {
						throw new BizException("请先设置分部课程类型单价");
					}
					if (courseSettings.getCourseTotalMinuties() != 0) {
						if (defaultUnitPrice.getUnitPrice().multiply(new BigDecimal(courseSettings.getCourseTotalMinuties())).setScale(0, BigDecimal.ROUND_HALF_UP)
								.compareTo(courseSettings.getCourseCurrentPrice()) != 0) {
							return AUDITING;
						}
					} else {
						return AUDITING;
					}
				}
			}else {
				throw new BizException("错误的缴费类型");
			}
		}
		return MusicGroupPaymentCalender.PaymentCalenderStatusEnum.NO;
	}

	@Override
	public BigDecimal getActualAmount(MusicGroupPaymentBaseCalender baseCalender) {
		List<MusicGroupPaymentCalenderCourseSettings> musicGroupPaymentCalenderCourseSettingsList = baseCalender.getMusicGroupPaymentCalenderCourseSettingsList();
		if(musicGroupPaymentCalenderCourseSettingsList != null && musicGroupPaymentCalenderCourseSettingsList.size() > 0){
			return musicGroupPaymentCalenderCourseSettingsList.stream().map(e -> e.getCourseCurrentPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
		}
		return BigDecimal.ZERO;
	}

    @Override
    public BigDecimal getOriginalAmount(MusicGroupPaymentBaseCalender baseCalender) {
		List<MusicGroupPaymentCalenderCourseSettings> musicGroupPaymentCalenderCourseSettingsList = baseCalender.getMusicGroupPaymentCalenderCourseSettingsList();
		if(musicGroupPaymentCalenderCourseSettingsList != null && musicGroupPaymentCalenderCourseSettingsList.size() > 0){
			return musicGroupPaymentCalenderCourseSettingsList.stream().map(e->e.getCourseOriginalPrice()).reduce(BigDecimal.ZERO,BigDecimal::add);
		}
        return BigDecimal.ZERO;
    }

	@Override
	public BigDecimal getCurrentAmount(MusicGroupPaymentBaseCalender baseCalender) {
		BigDecimal totalAmount = BigDecimal.ZERO;
		List<MusicGroupPaymentCalenderCourseSettings> musicGroupPaymentCalenderCourseSettingsList = baseCalender.getMusicGroupPaymentCalenderCourseSettingsList();
		if(musicGroupPaymentCalenderCourseSettingsList != null && musicGroupPaymentCalenderCourseSettingsList.size() > 0){
			if(baseCalender.getMusicGroupOrganizationCourseSettingId() != null){
				List<MusicGroupOrganizationCourseSettingsDetail> musicGroupOrganizationCourseSettingsDetails = musicGroupOrganizationCourseSettingsDetailDao
						.queryByMusicGroupOrganizationCourseSettingsId(baseCalender.getMusicGroupOrganizationCourseSettingId());
				return musicGroupOrganizationCourseSettingsDetails.stream().map(e -> e.getCourseCurrentPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
			}else {
				MusicGroup musicGroup = baseCalender.getMusicGroup();
				// 如果是课程收费，判断是否审核
				for (MusicGroupPaymentCalenderCourseSettings courseSettings : musicGroupPaymentCalenderCourseSettingsList) {
					OrganizationCourseUnitPriceSettings defaultUnitPrice = organizationCourseUnitPriceSettingsDao.queryByOrganIdAndCourseTypeAndChargeType(
							musicGroup.getOrganId(), courseSettings.getCourseType(), musicGroup.getChargeTypeId());
					if (defaultUnitPrice == null) {
						throw new BizException("请先设置分部课程类型单价");
					}
					totalAmount = totalAmount.add(defaultUnitPrice.getUnitPrice().multiply(new BigDecimal(courseSettings.getCourseTotalMinuties())));
				}
				return totalAmount;
			}
		}
		return totalAmount;
	}

	@Override
	public <T> T initBean(T bean) {
		return null;
	}
}
