package org.springblade.point.listener;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.enums.OrderType;
import org.springblade.common.enums.ResCode;
import org.springblade.common.enums.SystemConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.gateway.common_gateway.entity.BillSuccessEvent;
import org.springblade.ldt.bills.entity.BalanceBills;
import org.springblade.ldt.bills.entity.Bills;
import org.springblade.ldt.bills.entity.PointBills;
import org.springblade.ldt.bills.service.IBalanceBillsService;
import org.springblade.ldt.bills.service.IBillsService;
import org.springblade.ldt.bills.service.IPointBillsService;
import org.springblade.ldt.mall.entity.Mall;
import org.springblade.ldt.mall.service.IMallService;
import org.springblade.ldt.shop.entity.Shop;
import org.springblade.ldt.shop.service.IShopService;
import org.springblade.ldt.user.entity.LoginUser;
import org.springblade.ldt.user.entity.UserChannelPoint;
import org.springblade.ldt.user.service.ILoginUserService;
import org.springblade.ldt.user.service.IUserChannelPointService;
import org.springblade.payment.entity.SuccessParams;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.Objects;

/**
 * @author: lianghanqiang
 * @description: 交易成功后，商家以及商户赠送相应积分给用户
 * @since: 8/31/21 -- 9:57 AM
 */
@Component
@Slf4j
public class SendPointHandle  {
	private ILoginUserService loginUserService;
	private IBalanceBillsService balanceBillsService;
	private IShopService shopService;
	private IMallService mallService;
	private IPointBillsService pointBillsService;
	private IUserChannelPointService userChannelPointService;
	private IBillsService billsService;
	
	@EventListener
	@Transactional
	@Async
	public void handleSendPoint(BillSuccessEvent billSuccessEvent){
		SuccessParams successParams = billSuccessEvent.getSuccessParams();
		Bills bill = successParams.getBills();
		LoginUser user = loginUserService.getById(successParams.getUserId());
		Assert.isTrue(sendPoint(bill,user),() -> {throw new ServiceException(ResCode.SEND_POINT_ERROR);});
	}

	/**
	 * 	商家赠送积分
	 * */
	public boolean shopSendPoint(Shop shop, LoginUser user, BigDecimal payNum){
		//商家若是开启了会员中心则赠送积分
		if(shop.getIsOpenMember()!=0){
			BalanceBills sendBill = new BalanceBills();
			sendBill.setType(OrderType.SHOP_SEND.name());
			sendBill.setStatus(SystemConstant.BillPayStatus.待付款.name());
			sendBill.setTitle("商家赠送积分");
			sendBill.setReceiveId(user.getId());
			sendBill.setPayId(shop.getId());

			if(!Objects.isNull(shop)){
				BigDecimal balance = shop.getBalance();
				BigDecimal pointRate = shop.getPointRate();
				BigDecimal sendNum = payNum.multiply(pointRate).multiply(shop.getSendPointUnit());


				if( sendNum.compareTo(BigDecimal.ONE)>=0 && balance.compareTo(sendNum)>=0 ){
					sendBill.setBillDesc("账户余额不足或赠送积分值小于1");
				}else{
					user.setBalance(user.getBalance().add(sendNum));
					shop.setBalance(shop.getBalance().subtract(sendNum));
					sendBill.setStatus(SystemConstant.BillPayStatus.付款成功.name());
					Assert.isTrue(loginUserService.saveOrUpdate(user),() ->{throw new ServiceException(ResCode.USER_PAY_CALLBACK_ERROR);});
					Assert.isTrue(shopService.saveOrUpdate(shop),() ->{throw new ServiceException(ResCode.USER_PAY_CALLBACK_ERROR);});
				}

			}else{
				sendBill.setBillDesc("商家不存在");
			}
			Assert.isTrue(balanceBillsService.saveOrUpdate(sendBill),() ->{throw new ServiceException(ResCode.USER_PAY_CALLBACK_ERROR);});
		}
		return true;
	}

	/**
	 * 	商场赠送积分
	 * */
	public boolean mallSendPoint(Mall mall, LoginUser user, BigDecimal payNum){
		//商场若是开启了会员中心则赠送积分
		if(mall.getUseMember()!=0){
			PointBills sendBill = new PointBills();
			sendBill.setType(OrderType.MALL_SEND.name());
			sendBill.setStatus(SystemConstant.BillPayStatus.待付款.name());
			sendBill.setTitle("商场赠送积分");
			sendBill.setReceiveId(user.getId());
			sendBill.setPayId(mall.getId());

			if(!Objects.isNull(mall)){
				BigDecimal balance = mall.getBalance();
				BigDecimal pointRate = mall.getPointRate();
				BigDecimal sendNum = payNum.multiply(pointRate).multiply(mall.getSendPointUnnit());

				if( sendNum.compareTo(BigDecimal.ONE)>=0 && balance.compareTo(sendNum)>=0 ){
					sendBill.setBillsDesc("账户余额不足或赠送积分值小于1");
				}else{
					user.setChannelPoint(user.getChannelPoint().add(sendNum));
					mall.setBalance(mall.getBalance().subtract(sendNum));
					updateChannelAccount(mall,sendNum,user);
					sendBill.setStatus(SystemConstant.BillPayStatus.付款成功.name());
					Assert.isTrue(loginUserService.saveOrUpdate(user),() ->{throw new ServiceException(ResCode.USER_PAY_CALLBACK_ERROR);});
					Assert.isTrue(updateChannelAccount(mall,sendNum,user),() ->{throw new ServiceException(ResCode.USER_PAY_CALLBACK_ERROR);});
					Assert.isTrue(mallService.saveOrUpdate(mall),() ->{throw new ServiceException(ResCode.USER_PAY_CALLBACK_ERROR);});
				}

			}else{
				sendBill.setBillsDesc("商场不存在");
			}
			Assert.isTrue(pointBillsService.saveOrUpdate(sendBill),() ->{throw new ServiceException(ResCode.USER_PAY_CALLBACK_ERROR);});
			Assert.isTrue(loginUserService.saveOrUpdate(user),() ->{throw new ServiceException(ResCode.USER_PAY_CALLBACK_ERROR);});
			Assert.isTrue(mallService.saveOrUpdate(mall),() ->{throw new ServiceException(ResCode.USER_PAY_CALLBACK_ERROR);});
		}
		return true;
	}

	/**
	 * 	修改渠道积分账户
	 *  @param mall
	 * @param sendNum
	 * @param user*/
	private boolean updateChannelAccount(Mall mall, BigDecimal sendNum, LoginUser user){
		UserChannelPoint channelPoint = userChannelPointService.getOne(new QueryWrapper<UserChannelPoint>()
			.lambda()
			.eq(UserChannelPoint::getChannelId, mall.getId())
			.eq(UserChannelPoint::getUserId, user.getId()));

		if(Objects.isNull(channelPoint)){
			channelPoint = new UserChannelPoint();
			channelPoint.setChannelId(mall.getId());
			channelPoint.setUserId(user.getId());
			channelPoint.setTotalPoint(BigDecimal.ZERO);
			channelPoint.setAvailable(BigDecimal.ZERO);
			channelPoint.setChannelLogo(mall.getLogo());
			channelPoint.setChannelName(mall.getMallName());
			channelPoint.setPointRate(mall.getPointRate());
			channelPoint.setUsedPoint(BigDecimal.ZERO);
		}
		channelPoint.setAvailable(channelPoint.getAvailable().add(sendNum));
		channelPoint.setTotalPoint(channelPoint.getTotalPoint().add(sendNum));
		return userChannelPointService.saveOrUpdate(channelPoint);
	}

	/**
	 * 商场、商家赠送用户积分
	 **/
	private boolean sendPoint(Bills bills, LoginUser user){
		if(!Objects.isNull(bills)){
			//赠送用户积分
			BigDecimal payNum = bills.getPrice();
			Shop shop = shopService.getById(bills.getReceiveId());
			Mall mall = mallService.getById(shop.getMallId());

			mallSendPoint(mall,user,payNum);
			shopSendPoint(shop,user,payNum);
		}
		return true;
	}
}
