package org.springblade.payment.callback.trade;


import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yeepay.yop.sdk.service.common.response.YopResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.enums.AppConstant;
import org.springblade.common.enums.GoodsConstant;
import org.springblade.common.enums.PaymentScene;
import org.springblade.common.enums.ResCode;
import org.springblade.common.utils.TradeException;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.ldt.bills.entity.Bills;
import org.springblade.ldt.bills.entity.GoodsBills;
import org.springblade.ldt.bills.service.IBillsService;
import org.springblade.ldt.bills.service.IGoodsBillsService;
import org.springblade.ldt.shop.entity.Shop;
import org.springblade.ldt.shop.service.IShopService;
import org.springblade.payment.entity.PaymentVO;
import org.springblade.payment.entity.SuccessParams;
import org.springblade.payment.event.UserPayEvent;
import org.springblade.webSocket.WebSocketServer;
import org.springblade.yeePay.common.YeePayConst;
import org.springblade.yeePay.entity.saas.trade.TradeOrderQueryDto;
import org.springblade.yeePay.service.YeepaySaasService;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

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

/**
 * @author: lianghanqiang
 * @description: 用户付款回调
 * @since: 8/5/21 -- 3:01 PM
 */
@Component
@AllArgsConstructor
@Slf4j
public class UserPayCallback {

	private IBillsService billsService;
	private WebSocketServer webSocketServer;
	private IGoodsBillsService goodsBillsService;
	private UserPayCS userPayCS;
	private IShopService shopService;
	private YeepaySaasService yeepaySaasService;
	private YeePayConst yeePayConst;


	@EventListener
	public void PaySuccess(UserPayEvent userPayEvent) {
		SuccessParams successParams = userPayEvent.getSuccessParams();
		Bills bills = billsService.getById(successParams.getBills().getId());

		Assert.notNull(bills, () -> {
			throw new ServiceException("订单不存在！");
		});

		//回调已处理，忽略后续回调
		if (!Objects.equals(bills.getPayStatus(), AppConstant.BillPayStatus.待付款.name())) {
			return;
		}

		PaymentScene paymentScene = PaymentScene.valueOf(bills.getPayScene());
		switch (paymentScene) {
			case SCAN_CODE:
				sceneForDirectScan(successParams, bills);
				break;
			case MINI_PROGRAM:
				sceneForApp(successParams, bills);
				break;
			default:
		}
	}

	/**
	 * 直接扫码支付
	 *
	 * @param successParams
	 * @param bills
	 */
	private void sceneForDirectScan(SuccessParams successParams, Bills bills) {
		JSONObject res = successParams.getRes();
		//记录第三方支付平台订单号
		bills.setPayStatus(AppConstant.BillPayStatus.付款成功.name());
		bills.setThirdOrderId(res.getString("uniqueOrderNo"));
		bills.setPayWay(res.getString("channel"));
		Shop shop = userPayCS.updateShopBalance(bills, res.getBigDecimal("realPayAmount"));
		//查询订单
		try {
			TradeOrderQueryDto tradeOrderQueryDto = TradeOrderQueryDto.builder()
				.merchantNo(shop.getMerchantNo())
				.parentMerchantNo(yeePayConst.getPlatformServiceNo())
				.orderId(Convert.toStr(bills.getId()))
				.build();
			YopResponse yopResponse = yeepaySaasService.tradeOrderQuery(tradeOrderQueryDto);
			JSONObject orderInfo = JSON.parseObject(yopResponse.getStringResult());
			bills.setPayStatus(AppConstant.BillPayStatus.付款成功.name());

			BigDecimal merchantFee = orderInfo.getBigDecimal("merchantFee");
			BigDecimal ypSettleAmount = orderInfo.getBigDecimal("realPayAmount").subtract(merchantFee);

			bills.setMerchantFee(merchantFee);
			bills.setReceiveNumYp(ypSettleAmount);
			bills.setReceiveNumTotal(bills.getBalanceNum().add(bills.getPointNum().add(ypSettleAmount)));
			if (Objects.isNull(bills.getReceiveNumTotal())) {
				bills.setActualIncome(bills.getCost());
			} else {
				bills.setActualIncome(bills.getReceiveNumTotal());
			}
		} catch (Exception e) {
			log.error(String.format("商户支付回调查询订单异常，%s", bills.getId()));
			throw new TradeException(ResCode.TRADE_ERROR, successParams);
		}


		Assert.isTrue(shopService.saveOrUpdate(shop) && billsService.saveOrUpdate(bills)
			, () -> {
				throw new TradeException(ResCode.TRADE_ERROR, successParams);
			});
	}

	/**
	 * 小程序内扫码场景
	 */
	private void sceneForApp(SuccessParams successParams, Bills bills) {
		PaymentVO paymentVO = PaymentVO.builder().isSuccess(Boolean.FALSE).msg("订单付款异常！").build();
		try {

			//更新商品订单
			this.updateGoodsBills(bills.getId());

			//记录第三方支付平台订单号
			bills.setThirdOrderId(successParams.getRes().getString("uniqueOrderNo"));
			bills.setPayWay(successParams.getRes().getString("channel"));
			bills.setPayStatus(AppConstant.BillPayStatus.付款成功.name());
			paymentVO.setIsSuccess(Boolean.TRUE);
			paymentVO.setMsg("交易成功！");
			paymentVO.setTotalPrice(successParams.getTotalPrice());
			billsService.saveOrUpdate(bills);

		} catch (Exception e) {
			log.error("用户支付回调异常：");
			e.printStackTrace();
			throw e;
		} finally {
			webSocketServer.sendInfo(
				AppConstant.SOCKET_PRE.USER.getName() + successParams.getUserId(),
				JSON.toJSONString(paymentVO)
			);
			webSocketServer.sendInfo(
				AppConstant.SOCKET_PRE.SHOP.getName() + successParams.getShopId(),
				JSON.toJSONString(paymentVO)
			);
		}
	}

	private void updateGoodsBills(Long billsId) {
		GoodsBills goodsBills = goodsBillsService.getOne(Condition.getQueryWrapper(new GoodsBills()).lambda().eq(GoodsBills::getBillsId, billsId));
		if (!Objects.isNull(goodsBills)) {
			goodsBills.setPayStatus(AppConstant.BillPayStatus.付款成功.name());
			goodsBills.setOrderStatus(GoodsConstant.GOODS_STATUS.制作中.name());
			goodsBills.setPayTime(LocalDateTime.now());
			goodsBillsService.updateById(goodsBills);
		}
	}
}
