package org.springblade.payment.plugin;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yeepay.yop.sdk.service.common.response.YopResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.cache.PaymentCache;
import org.springblade.common.enums.OrderType;
import org.springblade.common.enums.PaymentType;
import org.springblade.common.enums.TransferStatus;
import org.springblade.common.enums.WithdrawStatus;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.ldt.bills.entity.Bills;
import org.springblade.ldt.bills.entity.TransferRec;
import org.springblade.ldt.bills.entity.WithdrawRec;
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.event.UserPointTransferWithdrawEvent;
import org.springblade.payment.handle.entity.HandleTransferData;
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.entity.saas.account.TransferB2bQueryDto;
import org.springblade.yeePay.entity.saas.account.TransferOrderDto;
import org.springblade.yeePay.entity.saas.settlement.SettleSelfSettleApplyDto;
import org.springblade.yeePay.service.YeePayService;
import org.springblade.yeePay.service.YeepaySaasService;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.Set;


/**
 * @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;


	@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 bill = getOrderDetail(payParam, billsService);
		Assert.notNull(bill, "订单查询失败，无此订单信息！");

		InitOrderDto initOrderDto = InitOrderDto.builder()
			.payWay(YeepayApiConstant.payWayType.MINI_PROGRAM.name())
			.channel(YeepayApiConstant.channelType.WECHAT.name())
			.scene(YeepayApiConstant.sceneType.OFFLINE.name())
			.goodsName(bill.getTitle())
			.orderId(Convert.toStr(bill.getId()))
			.orderAmount(bill.getPrice().doubleValue())
			.appId(bill.getAppid())
			.userId(bill.getOpenid())
			.userIp("127.0.0.1")
			.fundProcessType(YeepayApiConstant.fundProcessType.REAL_TIME.name())
			.notifyUrl(callbackUrl(PaymentType.YEE_PAY.name()))
			.csUrl(csUrl(PaymentType.YEE_PAY.name()))
			.build();

		orderTypeHandle(initOrderDto, OrderType.valueOf(bill.getType()), bill);
		YopResponse yopResponse = yeepaySaasService.aggPrepay(initOrderDto);
		System.out.println(initOrderDto);
		return R.data(JSON.parseObject(yopResponse.getStringResult()));
	}

	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:
		}
	}

}
