package org.springblade.payment.handle;

import cn.hutool.core.convert.Convert;
import lombok.AllArgsConstructor;
import org.springblade.common.enums.OrderType;
import org.springblade.common.enums.PaymentScene;
import org.springblade.common.enums.ResCode;
import org.springblade.common.enums.SystemConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.ldt.bills.entity.Bills;
import org.springblade.ldt.user.service.IUserChannelPointService;
import org.springblade.payment.handle.entity.HandleData;
import org.springblade.payment.handle.entity.Order;
import org.springblade.payment.handle.handler.*;
import org.springblade.ldt.activity.service.IActivityService;
import org.springblade.ldt.activity.service.IJoinRecordService;
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.shop.service.IShopService;
import org.springblade.payment.entity.SuccessParams;
import org.springblade.payment.service.IPaymentService;
import org.springblade.webSocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: lianghanqiang
 * @description: 交易处理,总控交易处理链
 * @since: 8/26/21 -- 5:53 PM
 */
@Component
public class Trade {
	@Autowired
	private IBillsService billsService;
	@Autowired
	private IPointBillsService pointBillsService;
	@Autowired
	private IBalanceBillsService balanceBillsService;
	@Autowired
	private WebSocketServer webSocketServer;
	@Autowired
	private IPaymentService paymentService;
	@Autowired
	private IShopService shopService;
	@Autowired
	private IActivityService activityService;
	@Autowired
	private IJoinRecordService joinRecordService;
	@Autowired
	private IUserChannelPointService userChannelPointService ;


	@Transactional
	public boolean trade(Order order, long channelId) throws Exception {
		/**
		 * 	交易处理链，每个handle处理负责一个业务节点
		 * 	1、处理各种商家折扣,计算实际交易金额
		 * 	2、用户渠道积分用以抵消交易金额
		 * 	3、用户账户余额抵消交易金额
		 * 	4、剩余金额用户微信支付
		 * */
		List<BaseHandle> chain = new ArrayList(){{
			add(new DiscountHandle(shopService,activityService,joinRecordService));
			add(new ChannelPointHandle(pointBillsService,userChannelPointService));
			add(new BalanceHandle(balanceBillsService));
			add(new WxPayHandle(billsService,webSocketServer));
		}} ;

	 	BigDecimal remain = order.getMoney();

		Bills bills = initBill(order,channelId);

		//支付参数
		SuccessParams successParams  = SuccessParams.builder()
			.orderType(OrderType.USER_PAY.name())
			.status(SystemConstant.BillPayStatus.待付款.name())
			.userId(order.getLoginUser().getId())
			.totalPrice(order.getMoney())
			.bills(bills)
			.shopId(order.getShopId())
			.channelId(channelId)
			.build();

		//处理各个节点
		for (BaseHandle node: chain) {
			HandleData res = node.handle(remain, order,successParams);
			Assert.isTrue(res.isSuccess(),()->{throw new ServiceException(ResCode.TRADE_ERROR);});
			remain = res.getRemain();
			successParams = res.getSuccessParams();

			if(remain.compareTo(BigDecimal.ZERO)==0){
				//处理积分余额数据变更
				paymentService.success(successParams);
				break;
			}
		}

	 	return true;
	}


	/**
	 * 初始化交易账单
	 * */
	private Bills initBill(Order order, long channelId){
		Bills bills = new Bills();
		bills.setPaystatus(SystemConstant.BillPayStatus.待付款.name());
		bills.setAppid(order.getAppId());
		bills.setCost(Convert.toStr(order.getMoney()));
		bills.setOpenid(order.getOpenId());
		bills.setChannelId(Convert.toStr(channelId));
		bills.setPrice(BigDecimal.ZERO);
		bills.setFee(BigDecimal.ZERO);
		bills.setPointFee(BigDecimal.ZERO);
		bills.setTitle(order.getBillsTitle());
		bills.setPayId(order.getLoginUser().getId());
		bills.setReceiveId(order.getShopId());
		return bills;
	}
}
