package com.neusoft.smart.pos.payment.repository;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.neusoft.smart.pos.constants.DictionaryConstant;
import com.neusoft.smart.pos.framework.constants.ApplicationConstants;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.utils.MapBeanUtils;
import com.neusoft.smart.pos.payment.constants.PaymentErrorCode;
import com.neusoft.smart.pos.payment.constants.WXPayConstants;
import com.neusoft.smart.pos.payment.constants.XYHFPayConstants;
import com.neusoft.smart.pos.payment.persistent.domain.MchPayChannel;
import com.neusoft.smart.pos.payment.persistent.domain.PayOrder;
import com.neusoft.smart.pos.payment.persistent.domain.PayTypeDict;
import com.neusoft.smart.pos.payment.persistent.ext.domain.*;
import com.neusoft.smart.pos.payment.utils.HttpClientUtils;
import com.neusoft.smart.pos.payment.utils.LogUtils;
import com.neusoft.smart.pos.payment.utils.WXPayUtils;
import com.neusoft.smart.pos.payment.utils.XYHYFormatUtils;
import lombok.val;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashMap;

/**
 * @author zcf
 * @date 2018-09-25 10：43
 * @description 西银惠付支付管理使用Repository
 */
@Component("xyhfPayRepository")
public class XYHFPayRepository implements IThirdPayRepository {

	/**
	 * 创建西银惠付单使用方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	@Override
	public ThirdPlatformCreateOrder createPayOrderToThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel, PayTypeDict payTypeDict){
		//1.处理数据
		String xyhfRequestData =  xyhfCreateOrderRequestDataHandle(payOrder,mchPayChannel,payTypeDict);
		//2.请求微信预付单生成接口
        String responseData = "";
        if(StringUtils.isEmpty(payOrder.getScanCode())){
        	//用户主动扫码支付
//			responseData = HttpClientUtils.postXMLData(WXPayConstants.DOMAIN_API+WXPayConstants.UNIFIEDORDER_URL_SUFFIX,weixinRequestData);
		}else{
        	//商户扫码支付
			responseData = HttpClientUtils.postData(XYHFPayConstants.DOMAIN_API+XYHFPayConstants.MCH_SCAN_URL_SUFFIX,xyhfRequestData);
		}
        //3.记录日志
		LogUtils.savePaymentTradeLog(payOrder.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_XYHF.getCode(),LogUtils.LOG_DESCRIPTION_DDSC,xyhfRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());

		return xyhfCreateOrderResponseDataHandle(payOrder,responseData);
	}

	/**
	 * 微信数据整理方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	private String xyhfCreateOrderRequestDataHandle(PayOrder payOrder, MchPayChannel mchPayChannel,PayTypeDict payTypeDict){
		val xahfPayOrder = new XYHFPayCreateOrder();
		xahfPayOrder.setOPENPL_APPID(mchPayChannel.getAppid());
		xahfPayOrder.setOUT_TRADE_NO(payOrder.getmOrderNumber());
		xahfPayOrder.setTOTAL_FEE(String.valueOf(payOrder.getOrderAmount()));
		xahfPayOrder.setAUTH_CODE(payOrder.getScanCode());
		xahfPayOrder.setVALIDITYTIME("120");
		Gson gson = new Gson();
		String postMessage = XYHYFormatUtils.encryptMessageByPrivateKey(mchPayChannel.getSecretKey(),mchPayChannel.getPrivateKey(),gson.toJson(xahfPayOrder));
		return postMessage;
	}

	/**
	 * 西银惠付响应数据处理
	 * @param payOrder
	 * @param responseData
	 * @return
	 */
	private ThirdPlatformCreateOrder xyhfCreateOrderResponseDataHandle(PayOrder payOrder, String responseData){
		val resultMap = JSON.parseObject(responseData, HashMap.class);
		if(!resultMap.get("H_RSP_CODE").toString().equalsIgnoreCase("0000")){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR.getCode(),resultMap.get("H_RSP_MSG").toString());
		}
		//			'SUCCESS' => '支付成功',
//			'ERROR' => '错误',
//			'AUTH_CODE_INVALID' => '二维码已过期,请刷新再试',
//			'USERPAYING' =>'等待客户验证密码',
//			'TRADE_ERROR' =>'暂无可用的支付方式,请绑定其它银行卡完成支付',
//			'REFUND' => '转入退款',
//			'NOTPAY' => '未支付',
//			'CLOSED' => '已关闭',
//			'REVOKED' => '已撤销'//刷卡支付
		String tradeState = resultMap.get("TRADE_STATE").toString();
		String payStatus = DictionaryConstant.PAY_STATUS_WFK.getCode();
		switch (tradeState){
			case "SUCCESS":
				payStatus = DictionaryConstant.PAY_STATUS_YFK.getCode();
				break;
			case "ERROR":
				throw new BusinessCommonException(PaymentErrorCode.XYHF_CREATE_ORDER_ERROR);
			case "AUTH_CODE_INVALID":
				throw new BusinessCommonException(PaymentErrorCode.XYHF_CREATE_ORDER_AUTH_CODE_INVALID);
			case "USERPAYING":
				payStatus = DictionaryConstant.PAY_STATUS_WFK.getCode();
				break;
			case "TRADE_ERROR":
				throw new BusinessCommonException(PaymentErrorCode.XYHF_CREATE_ORDER_TRADE_ERROR);
			case "REFUND":
				throw new BusinessCommonException(PaymentErrorCode.XYHF_CREATE_ORDER_REFUND);
			case "NOTPAY":
				throw new BusinessCommonException(PaymentErrorCode.XYHF_CREATE_ORDER_NOTPAY);
			case "CLOSED":
				throw new BusinessCommonException(PaymentErrorCode.XYHF_CREATE_ORDER_CLOSED);
			case "REVOKED":
				throw new BusinessCommonException(PaymentErrorCode.XYHF_CREATE_ORDER_REVOKED);
		}

		val thirdPlatformOrder = new ThirdPlatformCreateOrder();
		thirdPlatformOrder.setMcode(payOrder.getMcode());
		thirdPlatformOrder.setTradeId(payOrder.getTradeId());
		thirdPlatformOrder.setMOrderNumber(payOrder.getmOrderNumber());
		if(resultMap.containsKey("OUT_TRADE_NO")){
			thirdPlatformOrder.setOuterOrderNumber(resultMap.get("OUT_TRADE_NO").toString());
		}else{
			thirdPlatformOrder.setOuterOrderNumber("");
		}
		thirdPlatformOrder.setOuterCodeUrl("");
		thirdPlatformOrder.setPayStatus(payStatus);
		return thirdPlatformOrder;
	}

	/**
	 * 微信预付订单查询方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	public ThirdPlatformQueryOrder queryPayOrderFromThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel){
		//1.处理数据
		val xyhfPayQueryOrder = new XYHFPayQueryOrder();
		xyhfPayQueryOrder.setOPENPL_APPID(mchPayChannel.getAppid());
		xyhfPayQueryOrder.setOUT_TRADE_NO(payOrder.getmOrderNumber());
		Gson gson = new Gson();
		String postMessage = XYHYFormatUtils.encryptMessageByPrivateKey(mchPayChannel.getSecretKey(),mchPayChannel.getPrivateKey(),gson.toJson(xyhfPayQueryOrder));
		String responseData = HttpClientUtils.postData(XYHFPayConstants.DOMAIN_API+XYHFPayConstants.QUERY_ORDER_URL_SUFFIX,postMessage);
		//3.记录日志
		LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_XYHF.getCode(),LogUtils.LOG_DESCRIPTION_DDCS,postMessage,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
		return xyhfQueryOrderResponseDataHandle(mchPayChannel.getMcode(),payOrder.getmOrderNumber(),responseData);
	}

	/**
	 * 西银惠付响应数据处理
	 * @return
	 */
	private ThirdPlatformQueryOrder xyhfQueryOrderResponseDataHandle(String mcode,String orderNumber, String responseData){
		val resultMap = JSON.parseObject(responseData, HashMap.class);
		if(!resultMap.get("H_RSP_CODE").toString().equalsIgnoreCase("0000")){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR.getCode(),resultMap.get("H_RSP_MSG").toString());
		}

		val thirdPlatformOrder = new ThirdPlatformQueryOrder();
		thirdPlatformOrder.setMcode(mcode);
		thirdPlatformOrder.setMOrderNumber(orderNumber);
		thirdPlatformOrder.setOuterTradeNumber(resultMap.get("TRANSACTION_ID")==null?"":resultMap.get("TRANSACTION_ID").toString());
		thirdPlatformOrder.setTradeStatus(getTradeStatus(resultMap.get("TRADE_STATE").toString()));
		thirdPlatformOrder.setTimeEnd(resultMap.get("TIME_END").toString());
		return thirdPlatformOrder;
	}

	/**
	 * 根据微信交易状态返回支付平台订单状态
	 * @param tradeState
	 * @return
	 */
	private String getTradeStatus(String tradeState){
		String tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
		switch(tradeState){
			case "SUCCESS":
				//支付成功
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_YZF.getCode();
				break;
			case "REFUND":
				//转入退款
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_YTK.getCode();
				break;
			case "PARTREFUND":
				//转入退款
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_YTK.getCode();
				break;
			case "NOTPAY":
				//未支付
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
				break;
			case "CLOSED":
				//已关闭
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_JYGB.getCode();
				break;
			case "USERPAYING":
				//用户支付中
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
				break;
			case "PAYERROR":
				//支付失败(其他原因，如银行返回失败)
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
				break;
		}
		return tradeStatus;
	}

	/**
	 * 微信预付订单取消方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	public ThirdPlatformCancelOrder cannelPayOrderFromThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel){
		//1.处理数据
		val weixinPayCannelOrder = new WeixinPayCannelOrder();
		weixinPayCannelOrder.setAppid(mchPayChannel.getAppid());
		weixinPayCannelOrder.setMch_id(mchPayChannel.getMchId());
		weixinPayCannelOrder.setNonce_str(WXPayUtils.generateNonceStr());
		weixinPayCannelOrder.setOut_trade_no(payOrder.getmOrderNumber());
		String weixinRequestData =  WXPayUtils.generateSignedXml(MapBeanUtils.beanToMap(weixinPayCannelOrder),mchPayChannel.getSecretKey());
		//2.请求微信预付单生成接口
		String responseData = HttpClientUtils.postXMLData(WXPayConstants.DOMAIN_API+WXPayConstants.ORDER_CANNEL_URL_SUFFIX,weixinRequestData);
		//3.记录日志
		LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_XYHF.getCode(),LogUtils.LOG_DESCRIPTION_DDQX,weixinRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
		return weixinCannelOrderResponseDataHandle(mchPayChannel.getMcode(),payOrder.getmOrderNumber(),responseData);
	}

	/**
	 * 西银惠付订单取消响应数据处理
	 * @return
	 */
	private ThirdPlatformCancelOrder weixinCannelOrderResponseDataHandle(String mcode,String orderNumber, String responseData){
		val resultMap = WXPayUtils.xmlToMap(responseData);
		val thirdPlatformCancelOrder = new ThirdPlatformCancelOrder();
		thirdPlatformCancelOrder.setMcode(mcode);
		thirdPlatformCancelOrder.setMOrderNumber(orderNumber);
		thirdPlatformCancelOrder.setPayType(DictionaryConstant.PAYMENT_PAY_TYPE_XYHF.getCode());
		if(!resultMap.get("return_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)||!resultMap.get("result_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			thirdPlatformCancelOrder.setCancelStatus("0");
		}else{
			thirdPlatformCancelOrder.setCancelStatus("1");
		}
		return thirdPlatformCancelOrder;
	}

	/**
	 * 微信预付订单退款申请方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @param refundAmount:退款金额
	 * @return
	 */
	@Override
	public ThirdPlatformRefundOrder refundPayOrderFromThirdPlatform(PayOrder payOrder,String refundNumber,Long refundAmount, MchPayChannel mchPayChannel,PayTypeDict payTypeDict) {
		val xyhfPayRefundOrder = new XYHFPayRefundOrder();
		xyhfPayRefundOrder.setREFUND_SEQ(refundNumber);
		xyhfPayRefundOrder.setOUT_TRADE_NO(payOrder.getmOrderNumber());
		xyhfPayRefundOrder.setTRAN_AMT(payOrder.getOrderAmount().toString());
		if(null == refundAmount){
			xyhfPayRefundOrder.setREFUND_FEE(payOrder.getOrderAmount().toString());
		}else{
			xyhfPayRefundOrder.setREFUND_FEE(refundAmount.toString());
		}
		xyhfPayRefundOrder.setREFUND_TYPE("0");
		xyhfPayRefundOrder.setOPENPL_APPID(mchPayChannel.getAppid());

		Gson gson = new Gson();
		String postMessage = XYHYFormatUtils.encryptMessageByPrivateKey(mchPayChannel.getSecretKey(),mchPayChannel.getPrivateKey(),gson.toJson(xyhfPayRefundOrder));
		String responseData = HttpClientUtils.postData(XYHFPayConstants.DOMAIN_API+XYHFPayConstants.REFUND_ORDER_URL_SUFFIX,postMessage);
		//3.记录日志
		LogUtils.savePaymentTradeLog(payOrder.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_XYHF.getCode(),LogUtils.LOG_DESCRIPTION_SQTK,postMessage,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());

		return xyhfRefundOrderResponseDataHandle(payOrder,responseData);
	}

	/**
	 * 西银惠付退款申请响应数据处理
	 * @param payOrder
	 * @param responseData
	 * @return
	 */
	private ThirdPlatformRefundOrder xyhfRefundOrderResponseDataHandle(PayOrder payOrder, String responseData){
		val resultMap = JSON.parseObject(responseData, HashMap.class);
		if(!resultMap.get("H_RSP_CODE").toString().equalsIgnoreCase("0000")){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR.getCode(),resultMap.get("H_RSP_MSG").toString());
		}

		val thirdPlatformOrder = new ThirdPlatformRefundOrder();
		thirdPlatformOrder.setMcode(payOrder.getMcode());
		thirdPlatformOrder.setMOrderNumber(payOrder.getmOrderNumber());
		thirdPlatformOrder.setPayType(payOrder.getPayType());
		if(resultMap.get("REFUND_STATUS").toString().equalsIgnoreCase("0")){
			thirdPlatformOrder.setRefundStatus("2");
			thirdPlatformOrder.setRefundNumber(resultMap.get("REFUND_SEQ").toString());
			thirdPlatformOrder.setThirdRefundNumber(resultMap.get("TRANSACTION_ID").toString());
			thirdPlatformOrder.setRefundAmount(Long.parseLong(resultMap.get("REFUNDED_AMT").toString()));
		}else{
			thirdPlatformOrder.setRefundStatus("1");
		}
		return thirdPlatformOrder;
	}

	/**
	 * 预付单撤销使用方法
	 * @return
	 */
	public ThirdPlatformReverseOrder reversePayOrderFromThirdPlatform(PayOrder payOrder, String orderNumber, MchPayChannel mchPayChannel){
		//1.处理数据
		val xyhfPayReverseOrder = new XYHFPayReverseOrder();
		xyhfPayReverseOrder.setOPENPL_APPID(mchPayChannel.getAppid());
		xyhfPayReverseOrder.setOUT_TRADE_NO(payOrder.getmOrderNumber());
		xyhfPayReverseOrder.setPAY_PASS(queryPayPass(payOrder.getmOrderNumber(),mchPayChannel.getAppid(),mchPayChannel.getSecretKey(),mchPayChannel.getPrivateKey()));
		Gson gson = new Gson();
		String postMessage = XYHYFormatUtils.encryptMessageByPrivateKey(mchPayChannel.getSecretKey(),mchPayChannel.getPrivateKey(),gson.toJson(xyhfPayReverseOrder));
		String responseData = HttpClientUtils.postData(XYHFPayConstants.DOMAIN_API+XYHFPayConstants.REVERSE_ORDER_URL_SUFFIX,postMessage);
		//3.记录日志
		LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),orderNumber, DictionaryConstant.PAYMENT_PAY_TYPE_XYHF.getCode(),LogUtils.LOG_DESCRIPTION_DDCX,postMessage,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
		return xyhfReverseOrderResponseDataHandle(mchPayChannel.getMcode(),orderNumber,responseData);
	}

	/**
	 * 西银惠付订单撤销响应数据处理
	 * @return
	 */
	private ThirdPlatformReverseOrder xyhfReverseOrderResponseDataHandle(String mcode,String orderNumber, String responseData){
		val resultMap = JSON.parseObject(responseData, HashMap.class);
		if(!resultMap.get("H_RSP_CODE").toString().equalsIgnoreCase("0000")){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR.getCode(),resultMap.get("H_RSP_MSG").toString());
		}

		val thirdPlatformReverseOrder = new ThirdPlatformReverseOrder();
		thirdPlatformReverseOrder.setMcode(mcode);
		thirdPlatformReverseOrder.setMOrderNumber(orderNumber);
		thirdPlatformReverseOrder.setPayType(DictionaryConstant.PAYMENT_PAY_TYPE_XYHF.getCode());
		if(!resultMap.get("ACTION").toString().equalsIgnoreCase("FAIL")&&!resultMap.get("ACTION").toString().equalsIgnoreCase("REVOKE_UNKNOW")){
			thirdPlatformReverseOrder.setReverseStatus("2");
		}else{
			thirdPlatformReverseOrder.setReverseStatus("1");
		}
		return thirdPlatformReverseOrder;
	}

	private String queryPayPass(String orderNumber,String appid,String secretKey,String privateKey){
		val xyhfPayQueryOrder = new XYHFPayQueryOrder();
		xyhfPayQueryOrder.setOPENPL_APPID(appid);
		xyhfPayQueryOrder.setOUT_TRADE_NO(orderNumber);
		Gson gson = new Gson();
		String postMessage = XYHYFormatUtils.encryptMessageByPrivateKey(secretKey,privateKey,gson.toJson(xyhfPayQueryOrder));
		String responseData = HttpClientUtils.postData(XYHFPayConstants.DOMAIN_API+XYHFPayConstants.QUERY_ORDER_URL_SUFFIX,postMessage);
		val resultMap = JSON.parseObject(responseData, HashMap.class);
		if(!resultMap.get("H_RSP_CODE").toString().equalsIgnoreCase("0000")){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR.getCode(),resultMap.get("H_RSP_MSG").toString());
		}
		String tradeStatus = getTradeStatus(resultMap.get("TRADE_STATE").toString());
		if(tradeStatus.equals(DictionaryConstant.PAYMENT_ORDER_STATUS_YZF.getCode())||
				tradeStatus.equals(DictionaryConstant.PAYMENT_ORDER_STATUS_YTK.getCode())||
				tradeStatus.equals(DictionaryConstant.PAYMENT_ORDER_STATUS_JYGB.getCode())){
			return resultMap.get("PAY_PASS").toString();
		}else{
			return "";
		}
	}
}
