package org.springblade.payment.plugin;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Assert;
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.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springblade.common.cache.PaymentCache;
import org.springblade.common.constant.CallbackServeUrl;
import org.springblade.common.enums.AppConstant;
import org.springblade.common.enums.OrderType;
import org.springblade.common.enums.PaymentType;
import org.springblade.common.enums.ResCode;
import org.springblade.common.utils.TradeException;
import org.springblade.core.log.logger.BladeLogger;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.ldt.agent.entity.AgentLeagueRecord;
import org.springblade.ldt.agent.service.IAgentLeagueRecordService;
import org.springblade.ldt.bills.entity.Bills;
import org.springblade.ldt.bills.service.IBillsService;
import org.springblade.ldt.bills.service.ITransferRecService;
import org.springblade.ldt.bills.service.IWithdrawRecService;
import org.springblade.ldt.shop.entity.Shop;
import org.springblade.ldt.shop.service.IShopService;
import org.springblade.ldt.user.service.ILoginUserService;
import org.springblade.payment.entity.PayParam;
import org.springblade.payment.entity.SuccessParams;
import org.springblade.payment.service.impl.PaymentService;
import org.springblade.yeePay.common.YeePayConst;
import org.springblade.yeePay.common.YeepayApiConstant;
import org.springblade.yeePay.entity.InitOrderDto;
import org.springblade.yeePay.entity.MerchantInfo;
import org.springblade.yeePay.entity.saas.PayLinkOrderDto;
import org.springblade.yeePay.service.YeePayService;
import org.springblade.yeePay.service.YeepaySaasService;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;


/**
 * @author: lianghanqiang
 * @description: 易宝支付插件
 * @since: 7/29/21 -- 2:56 PM
 */
@Component
@Slf4j
@AllArgsConstructor
public class YeePayPlugin implements Payment {

	YeePayService yeePayService;
	IBillsService billsService;
	ILoginUserService loginUserService;
	PaymentService paymentService;
	YeepaySaasService yeepaySaasService;
	IWithdrawRecService withdrawRecService;
	YeePayConst yeePayConst;
	IShopService shopService;
	ApplicationEventPublisher eventPublisher;
	ITransferRecService transferRecService;
	IAgentLeagueRecordService agentLeagueRecordService;
	BladeLogger bladeLogger;

	@Override
	public String callbackUrl(String paymentType) {
		return CallbackServeUrl.CALL_BACK_SERVE_URL + CALLBACK_PREFIX + paymentType;
	}

	@Override
	public String csUrl(String paymentType) {
		return CallbackServeUrl.CALL_BACK_SERVE_URL + CSURL_PREFIX + paymentType;
	}


	@Override
	public R nativePay(PayParam payParam) {
		Bills bills = billsService.getById(payParam.getOrderId());

		PayLinkOrderDto payLinkOrderDto = PayLinkOrderDto.builder()
			.orderId(Convert.toStr(bills.getId()))
			.goodsName(bills.getTitle())
			.amount(bills.getPrice())
			.expiredTime(DateUtil.formatDateTime(bills.getExTime()))
			.notifyUrl(callbackUrl(PaymentType.YEE_PAY.name()))
			.scene(YeepayApiConstant.sceneType.OFFLINE.name())
			.build();

		orderTypeHandle(payLinkOrderDto, OrderType.valueOf(bills.getType()), bills);
		return R.data(yeepaySaasService.payLinkOrder(payLinkOrderDto));
	}


	@Override
	public R payCode(PayParam payParam) {
		return R.data("我还没有实现，你等等");
	}

	@Override
	public R transfer(PayParam payParam) {
		return null;
	}

	@Override
	public void callback(HttpServletRequest request) {

		log.info("易宝网关支付回调： map" + JSON.toJSONString(request.getParameterMap()));

		JSONObject jsonObject = yeePayService.deCodeNotifyData(request.getParameterMap().get("cipherText")[0]);
		log.info("易宝网关支付解密回调密文：" + jsonObject.toJSONString());

		SuccessParams successParams = PaymentCache.getSuccessParams(jsonObject.getString("orderId"));

		Assert.notNull(successParams, "订单超时，请重新支付！！");
		successParams.setRes(jsonObject);
		successParams.setStatus(
			"SUCCESS".equals(jsonObject.getString("status")) ?
				SuccessParams.PAY_STATUS_SUCCESS :
				SuccessParams.PAY_STATUS_FAIL);
		//处理付款后业务流程
		paymentService.success(successParams);
	}

	@Override
	public void csUrl(HttpServletRequest request) {
		log.info("易宝网关支付回调： map" + JSON.toJSONString(request.getParameterMap()));

		JSONObject jsonObject = yeePayService.deCodeNotifyData(request.getParameterMap().get("cipherText")[0]);
		log.info("易宝网关支付解密回调密文：" + jsonObject.toJSONString());

		SuccessParams successParams = PaymentCache.getSuccessParams(jsonObject.getString("orderId"));

		Assert.notNull(successParams, "订单超时，请重新支付！！");
		successParams.setRes(jsonObject);
		successParams.setStatus(
			"SUCCESS".equals(jsonObject.getString("status")) ?
				SuccessParams.PAY_STATUS_SUCCESS :
				SuccessParams.PAY_STATUS_FAIL);
		//处理付款后业务流程
		paymentService.cs(successParams);
	}

	@Override
	public R miniProgram(PayParam payParam) {
		Bills bills = billsService.getById(payParam.getOrderId());
		//判断订单是否超时(默认90s)
		if (ObjectUtils.isNotEmpty(bills)) {
			//判断支付状态
			if (StringUtils.equals(bills.getPayStatus(), AppConstant.BillPayStatus.待付款.name())) {
				//判断超时时间
				if (DateTime.now().getTime() >
					DateTime.of(bills.getCreateTime()).offset(DateField.SECOND, 90).getTime()) {
					SuccessParams successParams = PaymentCache.getSuccessParams(payParam.getOrderId());
					throw new TradeException(ResCode.TRADE_TIME_OUT, successParams);
				}
			}
		}


		InitOrderDto initOrderDto = InitOrderDto.builder()
			.payWay(YeepayApiConstant.payWayType.MINI_PROGRAM.name())
			.channel(YeepayApiConstant.channelType.WECHAT.name())
			.scene(YeepayApiConstant.sceneType.OFFLINE.name())
			.userIp("127.0.0.1")
			.fundProcessType(YeepayApiConstant.fundProcessType.REAL_TIME.name())
			.notifyUrl(callbackUrl(PaymentType.YEE_PAY.name()))
			.csUrl(csUrl(PaymentType.YEE_PAY.name()))
			.build();

		setDtoInfo(payParam, initOrderDto);
		bladeLogger.info("微信支付请求参数", initOrderDto.toString());
		YopResponse yopResponse = yeepaySaasService.aggPrepay(initOrderDto);
		return R.data(JSON.parseObject(yopResponse.getStringResult()));

	}

	/**
	 * 根据订单类型设置DTO请求数据
	 *
	 * @param payParam
	 * @param initOrderDto
	 */
	private void setDtoInfo(PayParam payParam, InitOrderDto initOrderDto) {
		if (payParam.getOrderType().equalsIgnoreCase(OrderType.AGENT_CHARGE.getName())) {
			AgentLeagueRecord agentLeagueRecord = agentLeagueRecordService.getOne(Condition.getQueryWrapper(new AgentLeagueRecord()).lambda()
				.eq(AgentLeagueRecord::getTradeNo, payParam.getOrderId()));

			Assert.notNull(agentLeagueRecord, "订单查询失败，无此订单信息！");
			initOrderDto.setGoodsName("代理加盟缴费");
			initOrderDto.setOrderId(payParam.getOrderId());
			initOrderDto.setOrderAmount(agentLeagueRecord.getLeague().doubleValue());
			initOrderDto.setAppId(agentLeagueRecord.getAppid());
			initOrderDto.setUserId(agentLeagueRecord.getOpenid());
			initOrderDto.setParentMerchantNo(yeePayConst.getParentMerchantNo());
			initOrderDto.setMerchantNo(yeePayConst.getPlatformServiceNo());
		} else {
			//查询订单状态
			Bills bill = getOrderDetail(payParam, billsService);
			Assert.notNull(bill, "订单查询失败，无此订单信息！");
			initOrderDto.setGoodsName(bill.getTitle());
			initOrderDto.setOrderId(String.valueOf(bill.getId()));
			initOrderDto.setOrderAmount(bill.getPrice().doubleValue());
			initOrderDto.setAppId(bill.getAppid());
			initOrderDto.setUserId(bill.getOpenid());
			initOrderDto.setFundProcessType(YeepayApiConstant.fundProcessType.DELAY_SETTLE.name());
			Shop shop = shopService.getById(bill.getReceiveId());
			initOrderDto.setParentMerchantNo(yeePayConst.getPlatformServiceNo());
			initOrderDto.setMerchantNo(shop.getMerchantNo());
		}
	}

	private void orderTypeHandle(MerchantInfo merchantInfo, OrderType orderType, Bills bills) {
		switch (orderType) {
			case WECHAT_PAY:
			case USER_PAY:
				if (merchantInfo instanceof InitOrderDto) {
					InitOrderDto initOrderDto = (InitOrderDto) merchantInfo;
					//
//				//营销信息(商户赠送的用户积分以及单笔 交易的国信服务费通过分账的形式到国信账户)
//				InitOrderDto.YpPromotionInfo ypPromotionInfo = initOrderDto.new YpPromotionInfo();
//				ypPromotionInfo.setAmount(bills.getPointNum().add(bills.getBalanceNum()).toString());
//				ypPromotionInfo.setType(YeepayApiConstant.ypPromotionInfo.CUSTOM_ALLOWANCE.name());
//				initOrderDto.setOrderAmount(bills.getCost().doubleValue());
//				initOrderDto.setYpPromotionInfo(new InitOrderDto.YpPromotionInfo[]{ypPromotionInfo});
					//分账
					initOrderDto.setFundProcessType(YeepayApiConstant.fundProcessType.DELAY_SETTLE.name());
				}

				Shop shop = shopService.getById(bills.getReceiveId());
				merchantInfo.setParentMerchantNo(yeePayConst.getPlatformServiceNo());
				merchantInfo.setMerchantNo(shop.getMerchantNo());
				break;
			case AGENT_CHARGE:
				merchantInfo.setParentMerchantNo(yeePayConst.getParentMerchantNo());
				merchantInfo.setMerchantNo(yeePayConst.getPlatformServiceNo());
				break;
			default:
		}
	}

}
