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

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.MemberRankPrivilegesDao;
import com.ym.mec.biz.dal.dao.MemberRankSettingDao;
import com.ym.mec.biz.dal.entity.CloudTeacherOrder;
import com.ym.mec.biz.dal.entity.MemberFeeSetting;
import com.ym.mec.biz.dal.entity.MemberRankPrivileges;
import com.ym.mec.biz.dal.entity.MemberRankSetting;
import com.ym.mec.biz.dal.entity.Student;
import com.ym.mec.biz.dal.entity.StudentPaymentOrder;
import com.ym.mec.biz.dal.entity.SysUserCashAccount;
import com.ym.mec.biz.dal.entity.SysUserCashAccountDetail;
import com.ym.mec.biz.dal.enums.DealStatusEnum;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.enums.OrderTypeEnum;
import com.ym.mec.biz.dal.enums.PeriodEnum;
import com.ym.mec.biz.dal.enums.PlatformCashAccountDetailTypeEnum;
import com.ym.mec.biz.service.CloudTeacherOrderService;
import com.ym.mec.biz.service.ContractService;
import com.ym.mec.biz.service.MemberFeeSettingService;
import com.ym.mec.biz.service.MemberRankSettingService;
import com.ym.mec.biz.service.StudentPaymentOrderService;
import com.ym.mec.biz.service.StudentService;
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.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.util.date.DateUtil;

@Service
public class MemberRankSettingServiceImpl extends BaseServiceImpl<Integer, MemberRankSetting> implements MemberRankSettingService {

	@Autowired
	private MemberRankSettingDao memberRankSettingDao;
	@Autowired
	private MemberRankPrivilegesDao memberRankPrivilegesDao;

	@Autowired
	private MemberFeeSettingService memberFeeSettingService;

	@Autowired
	private StudentService studentService;

	@Autowired
	private StudentPaymentOrderService studentPaymentOrderService;

	@Autowired
	private SysUserCashAccountService sysUserCashAccountService;

	@Autowired
	private SysUserCashAccountDetailService sysUserCashAccountDetailService;

	@Autowired
	private ContractService contractService;

	@Autowired
	private SysUserFeignService sysUserFeignService;

	@Autowired
	private CloudTeacherOrderService cloudTeacherOrderService;

	@Autowired
	private IdGeneratorService idGeneratorService;

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Override
	public BaseDAO<Integer, MemberRankSetting> getDAO() {
		return memberRankSettingDao;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void add(MemberRankSetting memberRankSetting) {
		memberRankSettingDao.insert(memberRankSetting);
		List<Integer> memberPrivilegesItemIdList = memberRankSetting.getMemberPrivilegesItemIdList();
		if (memberPrivilegesItemIdList == null || memberPrivilegesItemIdList.size() == 0) {
			throw new BizException("操作失败：请配置会员权益");
		}
		memberRankPrivilegesDao.batchInsert(memberRankSetting.getId(), memberPrivilegesItemIdList);
	}

	@Override
	public MemberRankSetting getDetail(Integer memberRankSettingId) {
		MemberRankSetting memberRankSetting = memberRankSettingDao.get(memberRankSettingId);
		List<MemberRankPrivileges> byRankSettingId = memberRankPrivilegesDao.findByRankSettingId(memberRankSettingId);
		if (byRankSettingId != null && byRankSettingId.size() > 0) {
			memberRankSetting.setMemberRankPrivileges(byRankSettingId);
			memberRankSetting.setMemberPrivilegesItemIdList(byRankSettingId.stream().map(e -> e.getMemberPrivilegesId()).collect(Collectors.toList()));
		}
		return memberRankSetting;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateSetting(MemberRankSetting memberRankSetting) {
		memberRankSettingDao.update(memberRankSetting);
		memberRankPrivilegesDao.deleteByRankSettingId(memberRankSetting.getId());
		List<Integer> memberPrivilegesItemIdList = memberRankSetting.getMemberPrivilegesItemIdList();
		if (memberPrivilegesItemIdList != null && memberPrivilegesItemIdList.size() > 0) {
			memberRankPrivilegesDao.batchInsert(memberRankSetting.getId(), memberPrivilegesItemIdList);
		}
	}

	@Override
	public List<MemberRankSetting> queryListByIsDefault(Boolean isDefault) {
		return memberRankSettingDao.queryListByIsDefault(isDefault);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public Map buy(Integer userId, Integer memberRankId, PeriodEnum periodEnum, BigDecimal amount, boolean isUseBalance) throws Exception {
		Student student = studentService.get(userId);
		if (student == null) {
			throw new BizException("非法访问");
		}

		SysUser user = sysUserFeignService.queryUserById(userId);

		Integer organId = user.getOrganId();
		if (organId == null) {
			throw new BizException("学生没有分部编号");
		}

		MemberRankSetting memberRankSetting = memberRankSettingDao.get(memberRankId);
		if (memberRankSetting == null) {
			throw new BizException("会员等级错误");
		}

		MemberFeeSetting memberFeeSetting = memberFeeSettingService.findByRankIdAndOrganId(organId, memberRankId);

		if (memberFeeSetting == null) {
			throw new BizException("分部会员价格出现异常");
		}

		CloudTeacherOrder cloudTeacherOrder = new CloudTeacherOrder();

		BigDecimal actualAmount = BigDecimal.ZERO;

		switch (periodEnum) {
		case DAY:
			actualAmount = memberFeeSetting.getCurrentDayFee();
			cloudTeacherOrder.setType(1);
			cloudTeacherOrder.setTime(1);
			break;
		case MONTH:
			actualAmount = memberFeeSetting.getCurrentMonthFee();
			cloudTeacherOrder.setType(2);
			cloudTeacherOrder.setTime(1);
			break;
		case YEAR_HALF:
			actualAmount = memberFeeSetting.getCurrentHalfYearFee();
			cloudTeacherOrder.setType(2);
			cloudTeacherOrder.setTime(6);
			break;
		case YEAR:
			actualAmount = memberFeeSetting.getCurrentYearFee();
			cloudTeacherOrder.setType(3);
			cloudTeacherOrder.setTime(1);
			break;

		default:
			break;
		}

		// 判断金额是否正确
		if (actualAmount.compareTo(amount) != 0) {
			throw new BizException("非法请求");
		}

		Date date = new Date();

		StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
		studentPaymentOrder.setUserId(userId);
		studentPaymentOrder.setOrganId(organId);
		studentPaymentOrder.setRoutingOrganId(organId);
		studentPaymentOrder.setCreateTime(date);
		studentPaymentOrder.setUpdateTime(date);
		studentPaymentOrder.setExpectAmount(amount);
		studentPaymentOrder.setActualAmount(amount);
		studentPaymentOrder.setBalancePaymentAmount(BigDecimal.ZERO);
		studentPaymentOrder.setStatus(DealStatusEnum.ING);
		studentPaymentOrder.setVersion(0);
		studentPaymentOrder.setType(OrderTypeEnum.MEMBER);
		studentPaymentOrder.setGroupType(GroupType.MEMBER);
		studentPaymentOrder.setRemitFee(BigDecimal.ZERO);
		studentPaymentOrder.setCourseRemitFee(BigDecimal.ZERO);
		studentPaymentOrder.setMemo(memberRankSetting.getName());
		studentPaymentOrder.setPaymentChannel("BALANCE");
		studentPaymentOrder.setMusicGroupId(memberRankId + "");

		if (isUseBalance) {
			SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(userId);
			if (userCashAccount == null) {
				throw new BizException("用户账户找不到");
			}
			studentPaymentOrder.setPaymentChannel("BALANCE");
			if (userCashAccount.getBalance().subtract(amount).doubleValue() >= 0) {
				studentPaymentOrder.setActualAmount(BigDecimal.ZERO);
				studentPaymentOrder.setBalancePaymentAmount(amount);
				sysUserCashAccountService.updateBalance(userId, amount.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "购买会员");

			} else {
				if (userCashAccount.getBalance().doubleValue() > 0) {
					sysUserCashAccountService.updateBalance(userId, userCashAccount.getBalance().negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "购买会员");
					studentPaymentOrder.setBalancePaymentAmount(userCashAccount.getBalance());
					studentPaymentOrder.setActualAmount(studentPaymentOrder.getExpectAmount().subtract(userCashAccount.getBalance()));
				}
			}
		}
		String orderNo = idGeneratorService.generatorId("payment") + "";
		studentPaymentOrder.setOrderNo(orderNo);
		studentPaymentOrder.setCreateTime(date);
		studentPaymentOrder.setUpdateTime(date);
		studentPaymentOrder.setVersion(0);
		studentPaymentOrderService.insert(studentPaymentOrder);

		// 订单明细
		cloudTeacherOrder.setOrganId(studentPaymentOrder.getOrganId());
		cloudTeacherOrder.setStudentId(studentPaymentOrder.getUserId());
		cloudTeacherOrder.setLevel(memberRankId);
		cloudTeacherOrder.setAmount(studentPaymentOrder.getExpectAmount());
		cloudTeacherOrder.setStatus(0);
		cloudTeacherOrder.setOrderId(studentPaymentOrder.getId());
		cloudTeacherOrder.setCreateTime(date);
		cloudTeacherOrder.setUpdateTime(date);
		cloudTeacherOrderService.insert(cloudTeacherOrder);

		Map result = studentPaymentOrderService.createOrder(studentPaymentOrder, null, "BUY_MEMBER");

		return result;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean orderCallback(StudentPaymentOrder studentPaymentOrder) {

		Integer userId = studentPaymentOrder.getUserId();

		Student student = studentService.getLocked(userId);
		if (student == null) {
			throw new BizException("学员信息不存在");
		}
		
		//查询原定的是否已处理
		StudentPaymentOrder orignStudentPaymentOrder = studentPaymentOrderService.get(studentPaymentOrder.getId());
		if(orignStudentPaymentOrder == null){
			return false;
		}
		if(orignStudentPaymentOrder.getStatus() != DealStatusEnum.ING){
			return false;
		}
		
		Date nowDate = new Date();
		// 更新订单信息
		studentPaymentOrder.setUpdateTime(nowDate);
		studentPaymentOrderService.update(studentPaymentOrder);

		if (studentPaymentOrder.getStatus() == DealStatusEnum.CLOSE || studentPaymentOrder.getStatus() == DealStatusEnum.FAILED) {

			if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
				sysUserCashAccountService.updateBalance(studentPaymentOrder.getUserId(), studentPaymentOrder.getBalancePaymentAmount(),
						PlatformCashAccountDetailTypeEnum.REFUNDS, "购买会员支付失败");
			}

			return true;
		}

		// 支付成功
		if (studentPaymentOrder.getStatus() == DealStatusEnum.SUCCESS) {
			// 查询会员订单信息
			CloudTeacherOrder cloudTeacherOrder = cloudTeacherOrderService.queryByOrderId(studentPaymentOrder.getId());
			cloudTeacherOrder.setStatus(2);
			cloudTeacherOrder.setUpdateTime(nowDate);

			PeriodEnum periodEnum = PeriodEnum.MONTH;
			switch (cloudTeacherOrder.getType()) {
			case 1:
				periodEnum = PeriodEnum.DAY;
				break;
			case 2:
				periodEnum = PeriodEnum.MONTH;
				break;
			case 3:
				periodEnum = PeriodEnum.YEAR;
				break;

			default:
				break;
			}

			if (student.getMemberRankSettingId() == null || nowDate.after(student.getMembershipEndTime())) {
				cloudTeacherOrder.setStartTime(nowDate);
				if (cloudTeacherOrder.getType() == 1) {
					cloudTeacherOrder.setEndTime(DateUtil.addDays(nowDate, cloudTeacherOrder.getTime()));
				} else if (cloudTeacherOrder.getType() == 2) {
					cloudTeacherOrder.setEndTime(DateUtil.addMonths(nowDate, cloudTeacherOrder.getTime()));
				} else if (cloudTeacherOrder.getType() == 3) {
					cloudTeacherOrder.setEndTime(DateUtil.addYears(nowDate, cloudTeacherOrder.getTime()));
				} else {
					throw new BizException("不支持的周期类型");
				}
			} else {
				cloudTeacherOrder.setStartTime(DateUtil.addDays(student.getMembershipEndTime(), 1));
				if (cloudTeacherOrder.getType() == 1) {
					cloudTeacherOrder.setEndTime(DateUtil.addDays(student.getMembershipEndTime(), cloudTeacherOrder.getTime()));
				} else if (cloudTeacherOrder.getType() == 2) {
					cloudTeacherOrder.setEndTime(DateUtil.addMonths(student.getMembershipEndTime(), cloudTeacherOrder.getTime()));
				} else if (cloudTeacherOrder.getType() == 3) {
					cloudTeacherOrder.setEndTime(DateUtil.addYears(student.getMembershipEndTime(), cloudTeacherOrder.getTime()));
				} else {
					throw new BizException("不支持的周期类型");
				}
			}

			cloudTeacherOrderService.update(cloudTeacherOrder);
			// 添加会员有效时长
			studentService.updateMemberRank(userId,cloudTeacherOrder.getLevel(), periodEnum, cloudTeacherOrder.getTime());

			// 插入交易明细
			BigDecimal amount = studentPaymentOrder.getActualAmount();
			if (amount.compareTo(BigDecimal.ZERO) > 0) {
				SysUserCashAccount cashAccount = sysUserCashAccountService.get(userId);
				// 充值
				SysUserCashAccountDetail rechargeDetail = new SysUserCashAccountDetail();
				rechargeDetail.setAmount(amount);
				rechargeDetail.setBalance(cashAccount.getBalance().add(amount));
				rechargeDetail.setComment("缴费前充值");
				rechargeDetail.setCreateTime(nowDate);
				rechargeDetail.setStatus(DealStatusEnum.SUCCESS);
				rechargeDetail.setTransNo(studentPaymentOrder.getTransNo());
				rechargeDetail.setType(PlatformCashAccountDetailTypeEnum.RECHARGE);
				rechargeDetail.setUpdateTime(nowDate);
				rechargeDetail.setUserId(userId);
				rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
				rechargeDetail.setComAmount(studentPaymentOrder.getComAmount());
				rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount());
				sysUserCashAccountDetailService.insert(rechargeDetail);

				// 缴费
				SysUserCashAccountDetail paymentDetail = new SysUserCashAccountDetail();
				paymentDetail.setAmount(amount.negate());
				paymentDetail.setBalance(cashAccount.getBalance());
				paymentDetail.setComment("购买会员");
				paymentDetail.setCreateTime(nowDate);
				paymentDetail.setStatus(DealStatusEnum.SUCCESS);
				paymentDetail.setTransNo(studentPaymentOrder.getTransNo());
				paymentDetail.setType(PlatformCashAccountDetailTypeEnum.PAY_FEE);
				paymentDetail.setUpdateTime(nowDate);
				paymentDetail.setUserId(userId);
				rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
				sysUserCashAccountDetailService.insert(paymentDetail);
			}

			try {
				contractService.transferProduceContract(userId, null);
			} catch (Exception e) {
				logger.error("产品协议生成失败", e);
			}
		}
		return true;
	}
}