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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.IConfigContextQueryService;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams;
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.db.entity.MchStoreDevice;
import com.jeequan.jeepay.pay.ctrl.channel.alipay.model.response.AlipaySpiRes;
import com.jeequan.jeepay.pay.ctrl.channel.alipay.model.response.SpiBaseResponse;
import com.jeequan.jeepay.pay.ctrl.channel.alipay.service.AlipaySpiRuyiCashierService;
import com.jeequan.jeepay.pay.ctrl.channel.alipay.service.AlipaySpiRuyiPayOrderService;
import com.jeequan.jeepay.pay.ctrl.channel.alipay.service.AlipaySpiRuyiRefundOrderService;
import com.jeequan.jeepay.pay.ctrl.channel.alipay.util.AlipaySpiRuyiUtil;
import com.jeequan.jeepay.pay.ctrl.payorder.AbstractPayOrderController;
import com.jeequan.jeepay.service.impl.MchStoreDeviceService;
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

/**
 * 支付宝如意spi接口
 *
 * @author zx
 *
 * @date 2021-04-27 15:50
 */
@Slf4j
@RestController
@RequestMapping("/api/alipay/ruyi/spi")
public class AlipayRuyiSpiController extends AbstractPayOrderController {

	@Autowired private AlipaySpiRuyiCashierService alipaySpiRuyiCashierService;
	@Autowired private AlipaySpiRuyiPayOrderService alipaySpiRuyiPayOrderService;
	@Autowired private AlipaySpiRuyiRefundOrderService alipaySpiRuyiRefundOrderService;
	@Autowired private MchStoreDeviceService mchStoreDeviceService;
	@Autowired private IConfigContextQueryService configContextQueryService;
	@Autowired private ChannelCertConfigKitBean channelCertConfigKitBean;

	/** 支付宝如意 spi入口  **/
	@PostMapping
	public AlipaySpiRes ruyiSpiEntry() {
		String logPrefix = "【支付宝如意Lite】";
		AlipayIsvParams alipayParams = null;

		try {
			JSONObject reqParamJSON = getReqParamJSON();
			String method = getValStringDefault("method", AlipaySpiRuyiUtil.SPI_RUYI_UNKNOWN);
			log.info("{}请求参数：{}", logPrefix + AlipaySpiRuyiUtil.spiMap.get(method), reqParamJSON.toJSONString());

			String terminalBindInfo = getValStringRequired("terminal_bind_info"); // 绑定设备传的自定义参数
			UnifiedOrderRQ.DeviceInfo deviceInfo = JSON.parseObject(terminalBindInfo, UnifiedOrderRQ.DeviceInfo.class);

			// 查询设备信息
			MchStoreDevice mchStoreDevice = mchStoreDeviceService.getByUniqueKey(deviceInfo.getProvider(), Byte.valueOf(deviceInfo.getDeviceType()), deviceInfo.getDeviceNo());
			if (mchStoreDevice == null || mchStoreDevice.getBindState() != CS.YES) {
				throw new BizException("设备不存在");
			}

			// 验签&&获取服务商参数
			alipayParams = this.alipaySpiCheckSign(reqParamJSON, mchStoreDevice.getMchNo(), mchStoreDevice.getAppId());

			// 分发spi请求
			SpiBaseResponse response;
			switch (method) {
				case AlipaySpiRuyiUtil.SPI_RUYI_PAY:
					response = alipaySpiRuyiPayOrderService.pay(mchStoreDevice);
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_PAY_QUERY:
					response = alipaySpiRuyiPayOrderService.payQuery(mchStoreDevice);
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_BILL_DETAIL_QUERY:
					response = alipaySpiRuyiPayOrderService.billdetailQuery(mchStoreDevice,
							getValIntegerDefault("page_num", 1), getValIntegerDefault("page_size", 1), getValString("date"));
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_BILL_STATISTICS_QUERY:
					response = alipaySpiRuyiPayOrderService.billstatisticsQuery(mchStoreDevice, getValString("date"));
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_BILL_QUERY:
					response = alipaySpiRuyiRefundOrderService.billQuery(mchStoreDevice);
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_REFUND_AUTHCODE_APPLY:
					response = alipaySpiRuyiRefundOrderService.refundAuthCodeApply(mchStoreDevice);
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_REFUND:
					response = alipaySpiRuyiRefundOrderService.refund(mchStoreDevice);
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_REFUND_QUERY:
					response = alipaySpiRuyiRefundOrderService.refundQuery(mchStoreDevice);
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_CASHIER_SIGN:
					response = alipaySpiRuyiCashierService.cashierSign(mchStoreDevice);
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_CASHIER_UNSIGN:
					response = alipaySpiRuyiCashierService.cashierUnsign(mchStoreDevice);
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_CASHIER_BATCH_QUERY:
					response = alipaySpiRuyiCashierService.batchQuery(mchStoreDevice);
					break;
				case AlipaySpiRuyiUtil.SPI_RUYI_CASHIER_QUERY:
					response = alipaySpiRuyiCashierService.cashierQuery(mchStoreDevice);
					break;
				default:
					throw new BizException("如意Lite SPI请求未接入");
			}

			return AlipaySpiRes.okWithSign(logPrefix, response, alipayParams.getPrivateKey());

		}catch (AlipayApiException e) {
			log.error("{}异常：{}", logPrefix, e.getMessage(), e);
			if (alipayParams == null) {
				return AlipaySpiRes.fail(logPrefix,  "BIZ_ERROR", StringUtils.defaultString(e.getMessage(), "服务商参数未配置"));
			}
			return AlipaySpiRes.failWithSign(logPrefix, alipayParams.getPrivateKey(), StringUtils.defaultString(e.getErrCode(), "SYSTEM_ERROR"),
					StringUtils.defaultString(e.getErrMsg(), "系统繁忙"));
		}catch (BizException e) {
			if (alipayParams == null) {
				return AlipaySpiRes.fail(logPrefix,  "BIZ_ERROR", StringUtils.defaultString(e.getMessage(), "服务商参数未配置"));
			}
			log.error("{}异常：{}", logPrefix, e.getMessage(), e);
			return AlipaySpiRes.failWithSign(logPrefix, alipayParams.getPrivateKey(), "BIZ_ERROR", StringUtils.defaultString(e.getMessage(), "系统繁忙"));
		}catch (Exception e) {
			log.error("{}异常：{}", logPrefix, e.getMessage(), e);
			return AlipaySpiRes.failWithSign(logPrefix, alipayParams.getPrivateKey(), "SYSTEM_ERROR", "系统繁忙");
		}

	}

	/** spi请求参数验签 **/
	public AlipayIsvParams alipaySpiCheckSign(JSONObject reqParamJSON, String mchNo, String appId) throws AlipayApiException {

		//查询出商户应用的配置信息
		MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfo(mchNo, appId);
		if(!mchAppConfigContext.isIsvsubMch()){
			throw new AlipayApiException("BIZ_ERROR", "仅支持特约商户");
		}

		// 获取支付参数
        AlipayIsvParams alipayParams = (AlipayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), CS.IF_CODE.ALIPAY);
		if (alipayParams == null) {
			throw new AlipayApiException("BIZ_ERROR", "服务商参数未配置");
		}

		boolean verifyResult;
		if(alipayParams.getUseCert() != null && alipayParams.getUseCert() == CS.YES){  //证书方式
			verifyResult = AlipaySignature.rsaCertCheckV1(reqParamJSON.toJavaObject(Map.class), getCertFilePath(alipayParams.getAlipayPublicCert()),
					com.jeequan.jeepay.core.model.params.alipay.AlipayConfig.CHARSET, alipayParams.getSignType());
		}else{
			verifyResult = AlipaySignature.rsaCheckV1(reqParamJSON.toJavaObject(Map.class),
					alipayParams.getAlipayPublicKey(), com.jeequan.jeepay.core.model.params.alipay.AlipayConfig.CHARSET, alipayParams.getSignType());
		}
		//验签失败
		if(!verifyResult){
			throw new AlipayApiException("BIZ_ERROR", "alipay spi请求验签失败");
		}
		return alipayParams;

	}

	/** 获取文件路径 **/
	protected String getCertFilePath(String certFilePath) {
		return channelCertConfigKitBean.getCertFilePath(certFilePath);
	}

}
