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

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.ChargeTypeDao;
import com.ym.mec.biz.dal.dao.ClassGroupStudentMapperDao;
import com.ym.mec.biz.dal.dao.MusicGroupBuildLogDao;
import com.ym.mec.biz.dal.dao.MusicGroupDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentEntitiesDao;
import com.ym.mec.biz.dal.dao.MusicGroupQuitDao;
import com.ym.mec.biz.dal.dao.MusicGroupStudentFeeDao;
import com.ym.mec.biz.dal.dao.MusicGroupSubjectGoodsGroupDao;
import com.ym.mec.biz.dal.dao.MusicGroupSubjectPlanDao;
import com.ym.mec.biz.dal.dao.SchoolDao;
import com.ym.mec.biz.dal.dao.StudentPaymentOrderDao;
import com.ym.mec.biz.dal.dao.TeacherDao;
import com.ym.mec.biz.dal.dto.BasicUserDto;
import com.ym.mec.biz.dal.dto.MusicCardDto;
import com.ym.mec.biz.dal.dto.SubFeeSettingDto;
import com.ym.mec.biz.dal.entity.ApprovalStatus;
import com.ym.mec.biz.dal.entity.MusicGroup;
import com.ym.mec.biz.dal.entity.MusicGroupBuildLog;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentEntities;
import com.ym.mec.biz.dal.entity.MusicGroupQuit;
import com.ym.mec.biz.dal.entity.MusicGroupStudentFee;
import com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus;
import com.ym.mec.biz.dal.entity.MusicGroupSubjectGoodsGroup;
import com.ym.mec.biz.dal.entity.MusicGroupSubjectPlan;
import com.ym.mec.biz.dal.entity.StudentPaymentOrder;
import com.ym.mec.biz.dal.entity.StudentRegistration;
import com.ym.mec.biz.dal.enums.ClassGroupStudentStatusEnum;
import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
import com.ym.mec.biz.dal.enums.DealStatusEnum;
import com.ym.mec.biz.dal.enums.MusicGroupStatusEnum;
import com.ym.mec.biz.dal.enums.OrderTypeEnum;
import com.ym.mec.biz.dal.enums.PlatformCashAccountDetailTypeEnum;
import com.ym.mec.biz.dal.page.MusicGroupQueryInfo;
import com.ym.mec.biz.service.MusicGroupService;
import com.ym.mec.biz.service.PayService;
import com.ym.mec.biz.service.StudentRegistrationService;
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.entity.ImGroupMember;
import com.ym.mec.common.entity.ImGroupModel;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.im.ImFeignService;
import com.ym.mec.util.collection.MapUtil;

@Service
public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> implements MusicGroupService {

	@Autowired
	private MusicGroupDao musicGroupDao;
	@Autowired
	private ChargeTypeDao chargeTypeDao;
	@Autowired
	private TeacherDao teacherDao;
	@Autowired
	private IdGeneratorService idGeneratorService;
	@Autowired
	private SchoolDao schoolDao;
	@Autowired
	private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;
	@Autowired
	private MusicGroupPaymentEntitiesDao musicGroupPaymentEntitiesDao;
	@Autowired
	private MusicGroupSubjectGoodsGroupDao musicGroupSubjectGoodsGroupDao;
	@Autowired
	private MusicGroupSubjectPlanDao musicGroupSubjectPlanDao;
	@Autowired
	private ImFeignService imFeignService;
	@Autowired
	private MusicGroupBuildLogDao musicGroupBuildLogDao;

	@Autowired
	private MusicGroupStudentFeeDao musicGroupStudentFeeDao;

	@Autowired
	private ClassGroupStudentMapperDao classGroupStudentMapperDao;

	@Autowired
	private StudentPaymentOrderDao studentPaymentOrderDao;

	@Autowired
	private SysUserCashAccountService sysUserCashAccountService;

	@Autowired
	private SysUserCashAccountDetailService sysUserCashAccountDetailService;

	@Autowired
	private MusicGroupQuitDao musicGroupQuitDao;

	@Autowired
	private StudentRegistrationService studentRegistrationService;

	@Autowired
	private PayService payService;

	@Override
	public BaseDAO<String, MusicGroup> getDAO() {
		return musicGroupDao;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public String createGroup(SubFeeSettingDto subFeeSettingDto, Integer userId) {
		MusicGroup musicGroup = subFeeSettingDto.getMusicGroup();
		List<MusicGroupPaymentEntities> musicGroupPaymentEntities = subFeeSettingDto.getMusicGroupPaymentEntities();
		List<MusicGroupSubjectGoodsGroup> musicGroupSubjectGoodsGroups = subFeeSettingDto.getMusicGroupSubjectGoodsGroups();
		List<MusicGroupSubjectPlan> musicGroupSubjectPlans = subFeeSettingDto.getMusicGroupSubjectPlans();
		String musicGroupId = idGeneratorService.generatorId() + "";
		musicGroup.setId(musicGroupId);
		// 保存乐团基本信息
		musicGroupDao.insert(musicGroup);
		// 保存乐团付费主体列表
		musicGroupPaymentEntities.forEach(e -> {
			e.setMusicGroupId(musicGroupId);
			musicGroupPaymentEntitiesDao.insert(e);
		});
		// 保存学员付费周期
		List<Integer> months = subFeeSettingDto.getMonths();
		if (months != null && months.size() > 0) {
			MusicGroupPaymentCalender mg;
			for (Integer month : months) {
				mg = new MusicGroupPaymentCalender();
				mg.setMusicGroupId(musicGroupId);
				mg.setPaymentMonth(month);
				musicGroupPaymentCalenderDao.insert(mg);
			}
		}
		// 保存乐团声部规划
		if (musicGroupSubjectPlans == null) {
			musicGroupSubjectPlans = new ArrayList<>();
		}
		musicGroupSubjectPlans.forEach(e -> {
			e.setMusicGroupId(musicGroupId);
			musicGroupSubjectPlanDao.insert(e);
		});
		// 保存乐团声部商品规划
		if (musicGroupSubjectGoodsGroups == null) {
			musicGroupSubjectGoodsGroups = new ArrayList<>();
		}
		musicGroupSubjectGoodsGroups.forEach(e -> {
			e.setMusicGroupId(musicGroupId);
			musicGroupSubjectGoodsGroupDao.insert(e);
		});
		// 新增聊天群
		// ImGroupModel imGroupModel = new ImGroupModel(musicGroupId, musicGroup.getName());
		// 教务老师和运营主管加入群组
		ImGroupMember[] imGroupMembers = { new ImGroupMember(musicGroup.getTeamTeacherId().toString()),
				new ImGroupMember(musicGroup.getEducationalTeacherId().toString()) };
		// 创建群组
		imFeignService.groupCreate(new ImGroupModel(musicGroupId, imGroupMembers, musicGroup.getName()));
		// 记录创建日志
		musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "提交建团申请", userId, ""));
		return musicGroupId;
	}

	@Override
	public List<MusicCardDto> queryUserMusicGroups(Integer userId) {
		List<MusicCardDto> musicCardDtos = musicGroupDao.queryUserMusicGroups(userId);
		// 获取学员在该乐团续费状态
		musicCardDtos.forEach(e -> {
			MusicGroupStudentFee groupStudentFee = musicGroupStudentFeeDao.findByUser(userId, e.getMusicGroupId());
			if(groupStudentFee != null){
				e.setPaymentStatus(musicGroupStudentFeeDao.findByUser(userId, e.getMusicGroupId()).getPaymentStatus());
			}
		});
		return musicCardDtos;
	}

	@Override
	public MusicCardDto queryPersonalMusicGroups(Integer id) {
		MusicCardDto musicCardDto = musicGroupDao.queryPersonalMusicGroups(id);
		musicCardDto.setMusicGroupNum(musicGroupDao.countUserMusicGroups(id));
		musicCardDto.setVipClassNum(musicGroupDao.countCourseByType(id, ClassGroupTypeEnum.VIP));
		return musicGroupDao.queryPersonalMusicGroups(id);
	}

	@Override
	public List<BasicUserDto> findTeachersByStuId(Integer studentId) {
		return musicGroupDao.findTeachersByStuId(studentId);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean cancelMusicGroup(String musicGroupId) {
		MusicGroup musicGroup = musicGroupDao.getLocked(musicGroupId);
		if (musicGroup == null) {
			throw new BizException("乐团找不到");
		}

		if (musicGroup.getStatus() == MusicGroupStatusEnum.APPLY || musicGroup.getStatus() == MusicGroupStatusEnum.PAY) {
			musicGroup.setStatus(MusicGroupStatusEnum.CANCELED);
			musicGroup.setUpdateTime(new Date());
			musicGroupDao.update(musicGroup);
		} else {
			throw new BizException("乐团当前状态是{}，不能取消", musicGroup.getStatus().getMsg());
		}

		// 查询是否有中间状态的缴费信息
		List<StudentPaymentOrder> studentPaymentOrders = studentPaymentOrderDao.queryByDealStatus(musicGroupId, OrderTypeEnum.APPLY, DealStatusEnum.ING);

		if (studentPaymentOrders != null && studentPaymentOrders.size() > 0) {
			throw new BizException("缴费存在交易中的数据，不能取消乐团");
		}

		// 查询已缴费信息
		studentPaymentOrders = studentPaymentOrderDao.queryByDealStatus(musicGroupId, OrderTypeEnum.APPLY, DealStatusEnum.SUCCESS);

		// 退费
		for (StudentPaymentOrder order : studentPaymentOrders) {
			sysUserCashAccountService.updateBalance(order.getUserId(), order.getActualAmount());
			// 增加交易流水
			sysUserCashAccountDetailService.addCashAccountDetail(order.getUserId(), order.getActualAmount(), SysUserCashAccountDetailService.MUSIC_GROUP
					+ musicGroupId, "", PlatformCashAccountDetailTypeEnum.REFUNDS, null, DealStatusEnum.SUCCESS, "取消乐团");
		}

		return true;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean pauseMusicGroup(String musicGroupId) {
		MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
		if (musicGroup == null) {
			throw new BizException("乐团找不到");
		}

		if (musicGroup.getStatus() != MusicGroupStatusEnum.PROGRESS) {
			throw new BizException("乐团当前状态是{}，不能暂停", musicGroup.getStatus().getMsg());
		}

		musicGroup.setStatus(MusicGroupStatusEnum.PAUSE);
		musicGroup.setUpdateTime(new Date());
		musicGroupDao.update(musicGroup);

		// 清除下次缴费时间
		musicGroupStudentFeeDao.updateNextPaymentDate(musicGroupId, null);

		return true;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean resumeMusicGroup(String musicGroupId) {
		MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
		if (musicGroup == null) {
			throw new BizException("乐团找不到");
		}

		if (musicGroup.getStatus() != MusicGroupStatusEnum.PAUSE) {
			throw new BizException("乐团当前状态是{}，不能恢复", musicGroup.getStatus().getMsg());
		}

		musicGroup.setStatus(MusicGroupStatusEnum.PROGRESS);
		musicGroup.setUpdateTime(new Date());
		musicGroupDao.update(musicGroup);

		// 查询下次缴费时间
		List<MusicGroupPaymentCalender> musicGroupPaymentCalenderList = musicGroupPaymentCalenderDao.findByMusicGroupId(musicGroupId);
		if (musicGroupPaymentCalenderList != null && musicGroupPaymentCalenderList.size() > 0) {

			Collections.sort(musicGroupPaymentCalenderList);

			Calendar cale = Calendar.getInstance();
			int month = cale.get(Calendar.MONTH) + 1;

			MusicGroupPaymentCalender calender = null;

			for (MusicGroupPaymentCalender cal : musicGroupPaymentCalenderList) {
				if (cal.getPaymentMonth() >= month) {
					calender = cal;
					break;
				}
			}

			// 重新设置下次缴费时间
			musicGroupStudentFeeDao.updateNextPaymentDate(musicGroupId, calender.getStartPaymentDate());
		}

		return true;
	}

	@Override
	public boolean extensionPayment(String musicGroupId, Date expireDate) {
		MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
		if (musicGroup == null) {
			throw new BizException("乐团找不到");
		}

		if (musicGroup.getStatus() != MusicGroupStatusEnum.PAY) {
			throw new BizException("乐团当前状态是{}，延长缴费", musicGroup.getStatus().getMsg());
		}

		Date date = new Date();

		if (date.after(expireDate)) {
			throw new BizException("日期设置错误");
		}

		musicGroup.setPaymentExpireDate(expireDate);
		musicGroup.setUpdateTime(date);
		musicGroupDao.update(musicGroup);

		return true;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean applyQuitMusicGroup(String musicGroupId, SysUser sysUser) {
		MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
		if (musicGroup == null) {
			throw new BizException("乐团不存在");
		}

		MusicGroupQuit musicGroupQuit = new MusicGroupQuit();
		musicGroupQuit.setCreateTime(new Date());
		musicGroupQuit.setJoinDate(sysUser.getCreateTime());
		musicGroupQuit.setMusicGroupId(musicGroupId);
		musicGroupQuit.setUserId(sysUser.getId());
		musicGroupQuit.setStatus(ApprovalStatus.PROCESSING);

		musicGroupQuitDao.insert(musicGroupQuit);
		return true;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean approveQuitMusicGroup(Long id, ApprovalStatus status, String reason) {
		MusicGroupQuit musicGroupQuit = musicGroupQuitDao.get(id);
		if (musicGroupQuit != null) {

			Date date = new Date();

			String musicGroupId = musicGroupQuit.getMusicGroupId();
			Integer userId = musicGroupQuit.getUserId();

			musicGroupQuit.setStatus(status);
			musicGroupQuit.setReason(reason);
			musicGroupQuit.setQuitDate(date);
			musicGroupQuitDao.update(musicGroupQuit);

			if (status == ApprovalStatus.APPROVED) {
				classGroupStudentMapperDao.deleteStudentByMusicGroupId(musicGroupId, userId);

				// 判断乐器是否是租赁
				StudentRegistration studentRegistration = studentRegistrationService.queryByUserIdAndMusicGroupId(userId, musicGroupId);
				if (studentRegistration == null) {
					throw new BizException("用户注册信息不存在");
				}
				// 退团
				studentRegistration.setMusicGroupStatus(ClassGroupStudentStatusEnum.QUIT);
				studentRegistration.setUpdateTime(date);

				Integer subjectId = studentRegistration.getActualSubjectId();
				MusicGroupSubjectPlan musicGroupSubjectPlan = musicGroupSubjectPlanDao.getMusicOneSubjectClassPlan(musicGroupId, subjectId);
				if (musicGroupSubjectPlan == null) {
					throw new BizException("乐团声部费用设置不存在");
				}
				if (musicGroupSubjectPlan.getDepositFee().doubleValue() > 0) {
					// 增加交易流水
					sysUserCashAccountDetailService.addCashAccountDetail(userId, musicGroupSubjectPlan.getDepositFee(),
							SysUserCashAccountDetailService.MUSIC_GROUP + musicGroupId, "", PlatformCashAccountDetailTypeEnum.REFUNDS, null,
							DealStatusEnum.SUCCESS, "退出乐团");
				}
			}
		}
		return true;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public Map renew(String musicGroupId, Integer userId) {

		MusicGroup musicGroup = this.get(musicGroupId);
		if (musicGroup == null) {
			throw new BizException("乐团不存在");
		}

		MusicGroupStudentFee musicGroupStudentFee = musicGroupStudentFeeDao.findByUser(userId, musicGroupId);

		if (musicGroupStudentFee == null) {
			throw new BizException("个人信息不存在");
		}
		// 判断当前是否是续费状态
		if (musicGroupStudentFee.getPaymentStatus() != PaymentStatus.NON_PAYMENT) {
			throw new BizException("已缴费");
		}

		BigDecimal amount = musicGroupStudentFee.getTemporaryCourseFee();
		if (amount == null || amount.doubleValue() == 0) {
			amount = musicGroupStudentFee.getCourseFee();
		}

		try {
			return payService.getPayMap(amount, idGeneratorService.generatorId("payment") + "", "https://pay.dayaedu.com/api/yqpay/notify",
					"http://dev.dayaedu.com", "测试订单", "测试订单");
		} catch (Exception e) {
			throw new BizException("调用支付接口出错", e);
		}
	}

	@Override
	public PageInfo<MusicGroup> queryMusicGroupPage(MusicGroupQueryInfo queryInfo) {
		PageInfo<MusicGroup> musicGroupPageInfo = queryPage(queryInfo);
		List<MusicGroup> musicGroupList = musicGroupPageInfo.getRows();
		// 获取学校编号列表
		Set<Integer> schoolIds = musicGroupList.stream().map(e -> e.getSchoolId()).collect(Collectors.toSet());
		List<Map<Integer, String>> schoolNames = schoolDao.queryNameByIds(schoolIds);
		// 获取相关学校名称map
		Map<Integer, String> schoolNameMap = MapUtil.convertMybatisMap(schoolNames);

		// 获取教务老师编号列表
		Set<Integer> educationalTeacherIds = musicGroupList.stream().map(e -> e.getEducationalTeacherId()).collect(Collectors.toSet());
		// 获取相关老师的名字
		List<Map<Integer, String>> educationalTeacherNames = teacherDao.queryNameByIds(educationalTeacherIds);
		Map<Integer, String> educationalTeacherNameMap = MapUtil.convertMybatisMap(educationalTeacherNames);

		// 获取运营主管编号列表
		Set<Integer> teamTeacherIds = musicGroupList.stream().map(e -> e.getTeamTeacherId()).collect(Collectors.toSet());
		List<Map<Integer, String>> teamTeacherNames = teacherDao.queryNameByIds(teamTeacherIds);
		Map<Integer, String> teamTeacherNameMap = MapUtil.convertMybatisMap(teamTeacherNames);

		// 获取乐团编号列表
		Set<String> musicGroupIds = musicGroupList.stream().map(e -> e.getId()).collect(Collectors.toSet());
		// 统计乐团在读人数
		List<Map<String, Long>> payNums = musicGroupDao.countPayNum(musicGroupIds);
		Map<String, Long> payNumMap = MapUtil.convertMybatisMap(payNums);

		// 获取收费类型编号列表
		Set<Integer> chargeTypeIds = musicGroupList.stream().map(e -> e.getChargeTypeId()).collect(Collectors.toSet());
		List<Map<Integer, String>> chargeTypeNames = chargeTypeDao.queryNameByIds(chargeTypeIds);
		Map<Integer, String> chargeTypeNameMap = MapUtil.convertMybatisMap(chargeTypeNames);

		musicGroupList.forEach(e -> {
			e.setSchoolName(schoolNameMap.get(e.getSchoolId()));
			e.setEducationalTeacherName(educationalTeacherNameMap.get(e.getEducationalTeacherId()));
			e.setTeamTeacherName(teamTeacherNameMap.get(e.getTeamTeacherId()));
			e.setPayNum(payNumMap.get(e.getId()) == null ? 0 : payNumMap.get(e.getId()).intValue());
			e.setChargeTypeName(chargeTypeNameMap.get(e.getChargeTypeId()));
		});
		return musicGroupPageInfo;
	}
}