package org.springblade.gateway.web_gateway.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springblade.common.cache.PaymentCache;
import org.springblade.common.constant.CallbackServeUrl;
import org.springblade.common.enums.*;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.api.R;
import org.springblade.gateway.client_gateway.entity.dto.ClientTradeDto;
import org.springblade.ldt.bills.entity.WithdrawRec;
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.entity.LoginUser;
import org.springblade.ldt.user.service.ILoginUserService;
import org.springblade.payment.entity.SuccessParams;
import org.springblade.payment.event.UserPayCsEvent;
import org.springblade.payment.event.UserPayEvent;
import org.springblade.payment.event.UserWithdrawEvent;
import org.springblade.payment.handle.Trade;
import org.springblade.payment.handle.entity.Order;
import org.springblade.payment.plugin.PaymentBuilder;
import org.springblade.wx.config.ConfigForShop;
import org.springblade.wx.constant.MessageTemplate;
import org.springblade.wx.constant.MiniProgramType;
import org.springblade.wx.service.WeChatService;
import org.springblade.yeePay.common.YeePayConst;
import org.springblade.yeePay.common.YeepayApiConstant;
import org.springblade.yeePay.service.YeePayService;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * @author July
 * @version 1.0.0
 * @ClassName WithdrawPressureTestController.java
 * @Description 提现压测控制层
 * @createTime 2021年10月30日 09:49:00
 */
@RestController
@RequestMapping("/pressure_test")
@AllArgsConstructor
public class PressureTestController {

	private IWithdrawRecService withdrawRecService;
	private IShopService shopService;
	private YeePayConst yeePayConst;
	private ApplicationEventPublisher eventPublisher;
	private ILoginUserService loginUserService;
	private Trade trade;
	private ConfigForShop configForShop;
	private WeChatService weChatService;
	private YeePayService yeePayService;

	@PostMapping("/userBalanceWithdraw")
	@ApiOperation(value = "用户余额提现（结算）")
	public R userBalanceWithdraw() {
		//保存提现数据
		WithdrawRec withdrawRec = new WithdrawRec();
		withdrawRec.setType(WithdrawType.BALANCE_WITHDRAW);
		withdrawRec.setReceiveType(YeepayApiConstant.receiveType.REAL_TIME.name());
		withdrawRec.setPrice(BigDecimal.ONE);
		withdrawRec.setOwnerType(AppConstant.USER_TYPE.商户.name());
		withdrawRec.setOwnerId(1440871712886366210L);
		withdrawRec.setWithdrawStatus(WithdrawStatus.WAITING.getValue());
		withdrawRec.setFee(BigDecimal.ZERO);
		withdrawRec.setReceiveAmount(withdrawRec.getPrice().subtract(withdrawRec.getFee()));
		withdrawRec.setFailReason("测试数据");
		withdrawRecService.saveOrUpdate(withdrawRec);
		//模拟易宝请求
		return R.data(simulationUserBalanceWithdraw(withdrawRec.getId()));
	}

	/**
	 * 模拟用户余额提现
	 *
	 * @param withdrawRecId 提现id
	 */
	private R simulationUserBalanceWithdraw(Long withdrawRecId) {
		WithdrawRec withdrawRec = withdrawRecService.getById(withdrawRecId);
		cn.hutool.core.lang.Assert.notNull(withdrawRec, "提现申请查询失败，无此申请信息！");

		Shop shop = shopService.getOne(Wrappers.<Shop>lambdaQuery().select(Shop::getMerchantNo).eq(Shop::getId, withdrawRec.getOwnerId()));
		cn.hutool.core.lang.Assert.notNull(shop, "提现申请查询失败，无此申请商户信息！");

		String settleRequestNo = IdUtil.simpleUUID();
		withdrawRec.setRequestNo(settleRequestNo);
		withdrawRecService.updateById(withdrawRec);
		String callbackServeUrl = CallbackServeUrl.CALL_BACK_SERVE_URL;

		//支付参数
		SuccessParams successParams = SuccessParams.builder()
			.orderType(OrderType.USER_WITHDRAW.name())
			.status(WithdrawStatus.WAITING.getValue())
			.userId(withdrawRec.getOwnerId())
			.totalPrice(withdrawRec.getActualPrice())
			.shopId(withdrawRec.getOwnerId())
			.tenantId(withdrawRec.getTenantId())
			.withdrawRecId(withdrawRec.getId())
			.build();
		JSONObject res = JSONObject.parseObject("{\n" +
			"    \"settleRequestNo\":\"" + settleRequestNo + "\",\n" +
			"    \"settleAmount\":\"" + withdrawRec.getReceiveAmount() + "\",\n" +
			"    \"feeAmount\":\"0.0\",\n" +
			"    \"settleStatus\":\"SUCCESS \",\n" +
			"    \"message\":\"\"\n" +
			"}");
		successParams.setRes(res);
		PaymentCache.putSuccessParams(Convert.toStr(settleRequestNo), successParams);

		eventPublisher.publishEvent(new UserWithdrawEvent(successParams));
		return R.data(res);
	}

	@PostMapping("/scanPay")
	public R scanPay(@RequestBody ClientTradeDto clientTradeDto) {
		clientTradeDto = new ClientTradeDto(){{
			setUserId(1459045479433236481L);
			setAppId("wx9ad53e8c83ae1a51");
			setBillsTitle("用户扫码支付");
			setExpireTime(LocalDateTime.now());
			setMoney(BigDecimal.ONE);
			setOpenId("ocWnO5VlzjXOaMj0YRE040GV3kEU");
			setShopId(1454256684796035073L);
		}};

		synchronized (clientTradeDto.getUserId().toString().intern()) {
			LoginUser loginUser = loginUserService.getById(clientTradeDto.getUserId());
			Assert.notNull(loginUser, () -> {
				throw new ServiceException(ResCode.USER_NOT_FOUNT);
			});

			//处理订单
			Order order = Order.builder()
				.appId(clientTradeDto.getAppId())
				.billsTitle(clientTradeDto.getBillsTitle())
				.loginUser(loginUser)
				.money(clientTradeDto.getMoney())
				.expireTime(clientTradeDto.getExpireTime())
				.secret(clientTradeDto.getSecret())
				.shopId(clientTradeDto.getShopId())
				.openId(loginUser.getOpenid())
				.build();

			SuccessParams successParams = trade.tradeForScanPay(order, clientTradeDto.getChannelId());

//			String res = "{\"channelOrderId\":\"4200001127202110301273440365\"," +
//				"\"orderId\":\"" + successParams.getBills().getId() + "\"," +
//				"\"bankOrderId\":\"5062869652211030\"," +
//				"\"paySuccessDate\":\"" + LocalDateTime.now() + "\"," +
//				"\"channel\":\"WECHAT\"," +
//				"\"payWay\":\"MINI_PROGRAM\"," +
//				"\"uniqueOrderNo\":\"1013202110300000002776327287\"," +
//				"\"orderAmount\":\"" + clientTradeDto.getMoney() + "\"," +
//				"\"payAmount\":\"" + clientTradeDto.getMoney() + "\"," +
//				"\"payerInfo\":\"{\\\"bankCardNo\\\":\\\"\\\"," +
//				"\\\"bankId\\\":\\\"CFT\\\"," +
//				"\\\"cardType\\\":\\\"CFT\\\"," +
//				"\\\"mobilePhoneNo\\\":\\\"\\\"," +
//				"\\\"userID\\\":\\\"" + clientTradeDto.getOpenId() + "\\\"}\"," +
//				"\"realPayAmount\":\"" + clientTradeDto.getMoney() + "\"," +
//				"\"parentMerchantNo\":\"10086160165\"," +
//				"\"merchantNo\":\"10086184256\"," +
//				"\"status\":\"SUCCESS\"}";
//			successParams.setRes(JSONObject.parseObject(res));
//			eventPublisher.publishEvent(new UserPayEvent(successParams));
//
//			res = "{\"feeMerchantNo\":\"10086184256\"," +
//				"\"orderAmount\":\"" + clientTradeDto.getMoney() + "\"," +
//				"\"csSuccessDate\":\"" + LocalDateTime.now() + "\"," +
//				"\"orderId\":\"" + successParams.getBills().getId() + "\"," +
//				"\"merchantFee\":\"" + BigDecimal.valueOf(0.01) + "\"," +
//				"\"customerFee\":\"\"," +
//				"\"parentMerchantNo\":\"10086160165\"," +
//				"\"uniqueOrderNo\":\"1013202110300000002776396034\"," +
//				"\"feeType\":\"REAL_TIME\"," +
//				"\"ypSettleAmount\":\"" + clientTradeDto.getMoney().subtract(BigDecimal.valueOf(0.01)) + "\"," +
//				"\"merchantNo\":\"10086184256\"," +
//				"\"status\":\"SUCCESS\"}";
//			successParams.setRes(JSONObject.parseObject(res));
//			eventPublisher.publishEvent(new UserPayCsEvent(successParams));
			return R.data(successParams);
		}
	}

	@PostMapping("/sendWXMessage")
	@ApiModelProperty("测试发送微信收款信息")
	public void sendWXMessage() {
		String openId = "ofVsB40EmE24bQP-ZhUV5I5hBB0M";
		String contentStr = String.format(MessageTemplate.PAYMENT_NOTICE.getContentString(), BigDecimal.valueOf(0.01), "付款成功", "1457649143315988481", DateUtil.format(LocalDateTime.now(), "yyyy年MM月dd日 HH:mm:ss"));
		JSONObject content = JSON.parseObject(contentStr);
		weChatService.sendTemplateMessage(openId, MessageTemplate.PAYMENT_NOTICE, content, configForShop.getPaymentPage(), MiniProgramType.SHOP);
	}

	@PostMapping("/deCodeNotifyData")
	@ApiModelProperty("回调消息解密")
	public R deCodeNotifyData(HttpServletRequest request) {
		JSONObject jsonObject = yeePayService.deCodeNotifyData(request.getParameterMap().get("cipherText")[0]);
		return R.data(jsonObject.toJSONString());
	}

}
