package com.jeequan.jeepay.pay.ctrl.channel.alipay.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchApp;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRS;
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliBarOrderRQ;
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.WxBarOrderRQ;
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.YsfBarOrderRQ;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.core.utils.JsonKit;
import com.jeequan.jeepay.db.entity.MchStoreDevice;
import com.jeequan.jeepay.db.entity.PayOrder;
import com.jeequan.jeepay.pay.ctrl.channel.alipay.model.response.*;
import com.jeequan.jeepay.pay.ctrl.channel.alipay.util.AlipaySpiRuyiUtil;
import com.jeequan.jeepay.pay.ctrl.payorder.AbstractPayOrderController;
import com.jeequan.jeepay.service.impl.PayOrderService;
import com.jeequan.jeepay.service.impl.StatsTradeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 支付宝如意spi接口：下单、查单
 *
 * @author zx
 *
 * @date 2021-04-27 15:50
 */
@Slf4j
@Service
public class AlipaySpiRuyiPayOrderService extends AbstractPayOrderController {

	@Autowired private PayOrderService payOrderService;
	@Autowired private StatsTradeService statsTradeService;

	/** 下单  **/
	public AlipaySpiPayOrderResponse pay(MchStoreDevice mchStoreDevice) throws Exception {
		String logPrefix = "【支付宝如意Lite】下单";

		Long amountL = getRequiredAmountL("total_amount");
		String authCode = getValStringRequired("auth_code");
		String subject = getValStringDefault("subject", "支付宝如意Lite收款");
		String merchantOrderNo = getValStringRequired("merchant_order_no");
		String extendParams = getValString("extend_params");
		Integer payTimeout = getValInteger("pay_timeout"); // 订单有效时间，需要控制未支付超时关闭，单位为分钟，格式为整数。
		String attachParams = getValString("attach_params"); // 附加字段，在支付结果、查询、支付结果异步通知，原样返回。

		// 端上超时会相同参数重复调用
		PayOrder payOrder = payOrderService.queryMchOrder(mchStoreDevice.getMchNo(), null, merchantOrderNo);
		if (payOrder != null) {
			return AlipaySpiRuyiUtil.covertToAlipaySpiPayOrderResponse(payOrder);
		}

		// 封装下单参数
		UnifiedOrderRQ rq = buildRqByAuthCode(authCode);
		rq.setMchOrderNo(merchantOrderNo);
		rq.setCurrency("cny");
		rq.setAmount(amountL);
		rq.setSubject(subject);
		rq.setBody(subject);
		rq.setExtParam(attachParams);

		rq.setMchNo(mchStoreDevice.getMchNo());
		rq.setAppId(mchStoreDevice.getAppId());
		rq.setStoreId(mchStoreDevice.getStoreId());

		if (payTimeout != null) {
			rq.setExpiredTime(payTimeout * 60);
		}

		// 设备信息
		UnifiedOrderRQ.DeviceInfo deviceInfo = new UnifiedOrderRQ.DeviceInfo();
		deviceInfo.setDeviceNo(mchStoreDevice.getDeviceNo());
		deviceInfo.setDeviceType(PayOrder.DEVICE_TYPE_ALIPAY_RUYI_LITE);
		deviceInfo.setProvider(mchStoreDevice.getProvider());
		rq.setDeviceInfo(JSONObject.toJSONString(deviceInfo));

		rq.setSignType(MchApp.SIGN_TYPE_MD5); // 设置默认签名方式为MD5

		ApiRes apiRes = this.unifiedOrder(rq.getWayCode(), rq, null,null);
		logger.info("{}调起支付，返回apiRes：{}", logPrefix, JSON.toJSONString(apiRes));
		if (ApiCodeEnum.SUCCESS.getCode() != apiRes.getCode()) {
			throw new AlipayApiException("BIZ_ERROR", apiRes.getMsg());
		}

		UnifiedOrderRS aliBarOrderRS = (UnifiedOrderRS) apiRes.getData();

		PayOrder dbRecord = payOrderService.getById(aliBarOrderRS.getPayOrderId());

		AlipaySpiPayOrderResponse response = AlipaySpiRuyiUtil.covertToAlipaySpiPayOrderResponse(dbRecord);
		return response;
	}

	/** 查单  **/
	public AlipaySpiPayOrderQueryResponse payQuery(MchStoreDevice mchStoreDevice) throws AlipayApiException {
		String payOrderId = getValString("isv_order_no");
		String mchOrderNo = getValString("merchant_order_no");

		PayOrder payOrder = payOrderService.queryMchOrder(mchStoreDevice.getMchNo(), payOrderId, mchOrderNo);
		if (payOrder == null || !PayOrder.DEVICE_TYPE_ALIPAY_RUYI_LITE.equals(payOrder.getDeviceType()) || !payOrder.getDeviceNo().equals(mchStoreDevice.getDeviceNo())) {
			throw new AlipayApiException("ORDER_NOT_EXIST", "支付订单不存在");
		}
		return AlipaySpiRuyiUtil.covertToAlipaySpiPayOrderQueryResponse(payOrder);
	}

	/** 账单流水查询  **/
	public SpiBaseResponse billdetailQuery(MchStoreDevice mchStoreDevice, Integer pageNum, Integer pageSize, String queryDate) {
		PayOrder payOrderParams = new PayOrder();
		// payOrderParams.setDeviceNo(mchStoreDevice.getDeviceNo()); // 设备号
		// payOrderParams.setDeviceType(PayOrder.DEVICE_TYPE_ALIPAY_RUYI_LITE);  // 如意Lite设备类型
		payOrderParams.setMchNo(mchStoreDevice.getMchNo()); // 当前绑定的商户
		payOrderParams.setStoreId(mchStoreDevice.getStoreId()); // 当前绑定的门店
		payOrderParams.addExt("queryDateRange", covertQueryDateStr(getQueryDate(queryDate)));

		// 分页查询
		IPage<PayOrder> page = payOrderService.listByPage(new Page(pageNum, pageSize), payOrderParams, JsonKit.newJson("unionOrderState", "2,4,5"));

		List<AlipaySpiBilldetailQueryResponse.Order> orderList = new ArrayList<>();
		if (CollUtil.isNotEmpty(page.getRecords())) {
			page.getRecords().forEach(payOrder -> {
				AlipaySpiBilldetailQueryResponse.Order alipayOrder = new AlipaySpiBilldetailQueryResponse.Order();
				alipayOrder.setOrderType(payOrder.getState() == PayOrder.STATE_SUCCESS ? "PAY" : payOrder.getState() == PayOrder.STATE_REFUND ? "REFUND" : "PAY");
				alipayOrder.setMerchantOrderNo(payOrder.getMchOrderNo());
				alipayOrder.setIsvOrderNo(payOrder.getPayOrderId());
				alipayOrder.setChannelOrderNo(payOrder.getChannelOrderNo());
				alipayOrder.setChannelType(AlipaySpiRuyiUtil.covertPaywayTypeToChannelType(payOrder.getWayCodeType()));
				alipayOrder.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getAmount()));
				alipayOrder.setTerminalId(payOrder.getDeviceNo());
				alipayOrder.setSubject(payOrder.getSubject());

				if (payOrder.getState() == PayOrder.STATE_SUCCESS) {
					alipayOrder.setReceiptAmount(alipayOrder.getTotalAmount());
					alipayOrder.setBuyerPayAmount(alipayOrder.getTotalAmount());
					alipayOrder.setOrderTime(DateUtil.formatDateTime(payOrder.getSuccessTime()));
				}else if (payOrder.getState() == PayOrder.STATE_REFUND) {
					alipayOrder.setRefundAmount(AmountUtil.convertCent2Dollar(payOrder.getRefundAmount()));
					alipayOrder.setOrderTime(DateUtil.formatDateTime(payOrder.getSuccessTime()));
				}

				// alipayOrder.setMerchantRefundNo();
				// alipayOrder.setIsvRefundNo();
				// alipayOrder.setChannelRefundNo();
				orderList.add(alipayOrder);
			});
		}

		AlipaySpiBilldetailQueryResponse response = new AlipaySpiBilldetailQueryResponse();
		response.setTotalSize(String.valueOf(page.getTotal()));
		response.setOrderList(orderList);
		return response;
	}

	/** 账单统计查询  **/
	public SpiBaseResponse billstatisticsQuery(MchStoreDevice mchStoreDevice, String queryDateStr) {

		// 查询条件
		JSONObject paramJSON = new JSONObject();

		// 门店ID条件
		List<String> storeIdList = new ArrayList<>();
		storeIdList.add(mchStoreDevice.getStoreId());
		paramJSON.put("storeIdList", storeIdList);

		// 时间条件
		DateTime queryDate = getQueryDate(queryDateStr);
		paramJSON.put("queryDateRange", covertQueryDateStr(queryDate));

		PayOrderCount orderCount = statsTradeService.selectTotalByStore(paramJSON, null);

		AlipaySpiBillstatisticsQueryResponse response = new AlipaySpiBillstatisticsQueryResponse();
		response.setStatisticTime(DateUtil.formatDateTime(queryDate));
		Long payAmount = orderCount.getTotalSuccAmt();
		response.setReceiptAmount(BigDecimal.valueOf(payAmount).divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
		response.setReceiptCount(orderCount.getTotalNum().toString());

		Long refundAmt = orderCount.getTotalRefundAmt();
		response.setRefundAmount(BigDecimal.valueOf(refundAmt).divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
		response.setRefundCount(orderCount.getTotalRefundNum().toString());
		response.setTotalIncome(BigDecimal.valueOf(payAmount- refundAmt).divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
		return response;
	}


	private UnifiedOrderRQ buildRqByAuthCode(String authCode) {
		String wayCode = JeepayKit.getPayWayCodeByBarCode(authCode);
		if (CS.PAY_WAY_CODE.WX_BAR.equals(wayCode)) {
			WxBarOrderRQ wxBarOrderRQ = new WxBarOrderRQ();
			wxBarOrderRQ.setAuthCode(authCode);
			return wxBarOrderRQ;
		}else if (CS.PAY_WAY_CODE.ALI_BAR.equals(wayCode)) {
			AliBarOrderRQ aliBarOrderRQ = new AliBarOrderRQ();
			aliBarOrderRQ.setAuthCode(authCode);
			return aliBarOrderRQ;
		}else if (CS.PAY_WAY_CODE.YSF_BAR.equals(wayCode)) {
			YsfBarOrderRQ ysfBarOrderRQ = new YsfBarOrderRQ();
			ysfBarOrderRQ.setAuthCode(authCode);
			return ysfBarOrderRQ;
		}else {
			throw new BizException("不支持的条码");
		}
	}

	/**
	 * 获取查询时间范围
	 */
	private DateTime getQueryDate(String queryDateStr) {
		// 时间搜索条件，默认今天
		DateTime queryDate = DateUtil.date();
		if (StringUtils.isNotBlank(queryDateStr)) {
			queryDate = DateUtil.parseDate(queryDateStr);
		}
		return queryDate;
	}

	/**
	 * 转换查询时间范围
	 */
	private String covertQueryDateStr(DateTime queryDate) {
		return "customDate_"+DateUtil.formatDate(DateUtil.beginOfDay(queryDate))+"_"+DateUtil.formatDate(DateUtil.endOfDay(queryDate));
	}

}
