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

import com.neusoft.smart.pos.constants.DictionaryConstant;
import com.neusoft.smart.pos.dto.payment.request.PostInitFacePayRequest;
import com.neusoft.smart.pos.framework.constants.ApplicationConstants;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.utils.*;
import com.neusoft.smart.pos.payment.constants.PaymentErrorCode;
import com.neusoft.smart.pos.payment.constants.WXPayConstants;
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.payorder.persistent.domain.MchPayChannel;
import com.neusoft.smart.pos.payorder.persistent.domain.PayOrder;
import com.neusoft.smart.pos.payorder.persistent.domain.PayTypeDict;
import lombok.val;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.InputStream;

/**
 * @author zcf
 * @date 2019-01-10 10：43
 * @description 微信人脸支付管理使用Repository
 */
@Component("weiXinPayFaceRepository")
public class WeiXinPayFaceRepository implements IThirdPayRepository {

	/**
	 * 创建微信支付单使用方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	@Override
	public String createPayOrderToThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel, PayTypeDict payTypeDict){
		//1.处理数据
		String weixinRequestData =  weixinCreateOrderRequestDataHandle(payOrder,mchPayChannel,payTypeDict);
		//2.请求微信人脸支付接口
		String responseData = HttpClientUtils.postXMLData(WXPayConstants.DOMAIN_API+WXPayConstants.FACE_PAY_SUFFIX,weixinRequestData);
        //3.记录日志
		LogUtils.savePaymentTradeLog(payOrder.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_WX_FACE_PAY.getCode(),LogUtils.LOG_DESCRIPTION_DDSC,weixinRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());

		return weixinCreateOrderResponseDataHandle(payOrder,responseData);
	}

	/**
	 * 微信数据整理方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	private String weixinCreateOrderRequestDataHandle(PayOrder payOrder, MchPayChannel mchPayChannel,PayTypeDict payTypeDict){
		val weixinPayOrder = new WeixinFacePayCreateOrder();
		weixinPayOrder.setAppid(mchPayChannel.getAppid());
		weixinPayOrder.setMch_id(mchPayChannel.getMchId());
		weixinPayOrder.setNonce_str(WXPayUtils.generateNonceStr());
		weixinPayOrder.setBody(payOrder.getDescription());
		weixinPayOrder.setOut_trade_no(payOrder.getmOrderNumber());
		weixinPayOrder.setTotal_fee(String.valueOf(payOrder.getPayAmount()));
		JSONObject payInfoJsonObject  = JSONObject.fromObject(payOrder.getRequestDetailInfo());
		try {
			weixinPayOrder.setOpenid(payInfoJsonObject.getString("openId"));
			weixinPayOrder.setFace_code(payInfoJsonObject.getString("scanCode"));
			payOrder.setScanCode(weixinPayOrder.getFace_code());
            payOrder.setOpenId(weixinPayOrder.getOpenid());
		} catch (Exception e) {
			throw new BusinessCommonException(PaymentErrorCode.PAY_TYPE_INFO_NOT_EMPTY);
		}
//		weixinPayOrder.setOpenid(payOrder.getOpenId());
//		weixinPayOrder.setFace_code(payOrder.getScanCode());
		if(StringUtils.isEmpty(payOrder.getPayIp())){
			weixinPayOrder.setSpbill_create_ip(LocalIpUtils.getLocalIP());
		}else{
			weixinPayOrder.setSpbill_create_ip(payOrder.getPayIp());
		}
		
		return SignatureUtils.generateSignedXml(MapBeanUtils.beanToMap(weixinPayOrder),mchPayChannel.getSecretKey());
	}

	/**
	 * 微信支付响应数据处理
	 * @param payOrder
	 * @param responseData
	 * @return
	 */
	private String weixinCreateOrderResponseDataHandle(PayOrder payOrder, String responseData){
		val resultMap = SignatureUtils.xmlToMap(responseData);
		if(!resultMap.get("return_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR.getCode(),resultMap.get("err_code_des"));
		}
		if(!resultMap.get("result_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR.getCode(),resultMap.get("err_code_des"));
		}
//		val thirdPlatformOrder = new ThirdPlatformCreateOrder();
//		thirdPlatformOrder.setMcode(payOrder.getMcode());
//		thirdPlatformOrder.setTradeId(payOrder.getTradeId());
//		thirdPlatformOrder.setMOrderNumber(payOrder.getmOrderNumber());
//		thirdPlatformOrder.setOuterOrderNumber(resultMap.get("transaction_id"));
//		thirdPlatformOrder.setPayStatus(DictionaryConstant.PAY_STATUS_YFK.getCode());
//		return thirdPlatformOrder;
        payOrder.setOuterOrderNumber(resultMap.get("transaction_id"));
		payOrder.setPayStatus(DictionaryConstant.PAY_STATUS_YFK.getCode());
        JSONObject payResponseJsonObject = new JSONObject();
        return payResponseJsonObject.toString();
	}

	/**
	 * 微信预付订单查询方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	public ThirdPlatformQueryOrder queryPayOrderFromThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel){
		//1.处理数据
		val weixinPayQueryOrder = new WeixinPayQueryOrder();
		weixinPayQueryOrder.setAppid(mchPayChannel.getAppid());
		weixinPayQueryOrder.setMch_id(mchPayChannel.getMchId());
		weixinPayQueryOrder.setNonce_str(WXPayUtils.generateNonceStr());
		weixinPayQueryOrder.setOut_trade_no(payOrder.getmOrderNumber());
		String weixinRequestData = SignatureUtils.generateSignedXml(MapBeanUtils.beanToMap(weixinPayQueryOrder),mchPayChannel.getSecretKey());
		//2.请求微信预付单生成接口
		String responseData = HttpClientUtils.postXMLData(WXPayConstants.DOMAIN_API+WXPayConstants.FACE_PAY_QUERY_SUFFIX,weixinRequestData);
		//3.记录日志
		LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_WX_FACE_PAY.getCode(),LogUtils.LOG_DESCRIPTION_DDCS,weixinRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
		return weixinQueryOrderResponseDataHandle(mchPayChannel.getMcode(),payOrder.getmOrderNumber(),responseData);
	}

	/**
	 * 微信支付响应数据处理
	 * @return
	 */
	private ThirdPlatformQueryOrder weixinQueryOrderResponseDataHandle(String mcode,String orderNumber, String responseData){
		val resultMap = SignatureUtils.xmlToMap(responseData);
		if(!resultMap.get("return_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)||!resultMap.get("result_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR);
		}
		val thirdPlatformOrder = new ThirdPlatformQueryOrder();
		thirdPlatformOrder.setMcode(mcode);
		thirdPlatformOrder.setMOrderNumber(orderNumber);
		thirdPlatformOrder.setOuterTradeNumber(resultMap.get("transaction_id")==null?"":resultMap.get("transaction_id"));
		thirdPlatformOrder.setTradeStatus(getTradeStatus(resultMap.get("trade_state")));
		thirdPlatformOrder.setTimeEnd(resultMap.get("time_end"));
		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_TKZ.getCode();
				break;
			case "REVOKED":
				//已撤销（刷卡支付）
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
				break;
			case "ORDER_PAYING":
				//用户支付中
				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 = SignatureUtils.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_WX_FACE_PAY.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 = SignatureUtils.xmlToMap(responseData);
		val thirdPlatformCancelOrder = new ThirdPlatformCancelOrder();
		thirdPlatformCancelOrder.setMcode(mcode);
		thirdPlatformCancelOrder.setMOrderNumber(orderNumber);
		thirdPlatformCancelOrder.setPayType(DictionaryConstant.PAYMENT_PAY_TYPE_WX_FACE_PAY.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 weixinPayRefundOrder = new WeixinPayRefundOrder();
		weixinPayRefundOrder.setAppid(mchPayChannel.getAppid());
		weixinPayRefundOrder.setMch_id(mchPayChannel.getMchId());
		weixinPayRefundOrder.setNonce_str(WXPayUtils.generateNonceStr());
		weixinPayRefundOrder.setOut_trade_no(payOrder.getmOrderNumber());
		weixinPayRefundOrder.setOut_refund_no(refundNumber);
		weixinPayRefundOrder.setRefund_fee(refundAmount);
		weixinPayRefundOrder.setTotal_fee(payOrder.getPayAmount());
		weixinPayRefundOrder.setNotify_url(payTypeDict.getRefundNotifyUrl());
		String weixinRequestData = SignatureUtils.generateSignedXml(MapBeanUtils.beanToMap(weixinPayRefundOrder),mchPayChannel.getSecretKey());
		//2.请求微信退款申请接口
		InputStream instream = FileUtils.convertByteArrayToInputStream(mchPayChannel.getCert());
		String responseData = HttpClientUtils.postXmlDataWithCert(WXPayConstants.DOMAIN_API+WXPayConstants.ORDER_REFUND_URL_SUFFIX,weixinRequestData,weixinPayRefundOrder.getMch_id(),instream);
		//3.记录日志
		LogUtils.savePaymentTradeLog(payOrder.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_WX_FACE_PAY.getCode(),LogUtils.LOG_DESCRIPTION_SQTK,weixinRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());

		return weixinRefundOrderResponseDataHandle(payOrder,responseData);
	}

	/**
	 * 微信退款申请响应数据处理
	 * @param payOrder
	 * @param responseData
	 * @return
	 */
	private ThirdPlatformRefundOrder weixinRefundOrderResponseDataHandle(PayOrder payOrder, String responseData){
		val resultMap = SignatureUtils.xmlToMap(responseData);
		if(!resultMap.get("return_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_REFUND_ERROR);
		}
		val thirdPlatformOrder = new ThirdPlatformRefundOrder();
		thirdPlatformOrder.setMcode(payOrder.getMcode());
		thirdPlatformOrder.setMOrderNumber(payOrder.getmOrderNumber());
		thirdPlatformOrder.setPayType(payOrder.getPayType());
		if(!resultMap.get("result_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			if(resultMap.get("err_code").equalsIgnoreCase("ORDERNOTEXIST")){
				thirdPlatformOrder.setRefundStatus("3");
			}else{
				thirdPlatformOrder.setRefundStatus("0");
			}
		}else{
			thirdPlatformOrder.setRefundNumber(resultMap.get("out_refund_no"));
			thirdPlatformOrder.setThirdRefundNumber(resultMap.get("refund_id"));
			thirdPlatformOrder.setRefundAmount(Long.parseLong(resultMap.get("refund_fee")));
			thirdPlatformOrder.setRefundStatus("1");
		}
		return thirdPlatformOrder;
	}

	/**
	 * 预付单撤销使用方法
	 * @return
	 */
	public ThirdPlatformReverseOrder reversePayOrderFromThirdPlatform(PayOrder payOrder, String orderNumber, MchPayChannel mchPayChannel){
		//1.处理数据
		val weixinPayReverseOrder = new WeixinPayReverseOrder();
		weixinPayReverseOrder.setAppid(mchPayChannel.getAppid());
		weixinPayReverseOrder.setMch_id(mchPayChannel.getMchId());
		weixinPayReverseOrder.setNonce_str(WXPayUtils.generateNonceStr());
		weixinPayReverseOrder.setOut_trade_no(orderNumber);
		String weixinRequestData = SignatureUtils.generateSignedXml(MapBeanUtils.beanToMap(weixinPayReverseOrder),mchPayChannel.getSecretKey());
		InputStream instream = FileUtils.convertByteArrayToInputStream(mchPayChannel.getCert());
		//2.请求微信预付单生成接口
		String responseData = HttpClientUtils.postXmlDataWithCert(WXPayConstants.DOMAIN_API+WXPayConstants.ORDER_REVERSE_URL_SUFFIX,weixinRequestData,weixinPayReverseOrder.getMch_id(),instream);
		//3.记录日志
		LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),orderNumber, DictionaryConstant.PAYMENT_PAY_TYPE_WX_FACE_PAY.getCode(),LogUtils.LOG_DESCRIPTION_DDCX,weixinRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
		return weixinReverseOrderResponseDataHandle(mchPayChannel.getMcode(),orderNumber,responseData);
	}

	/**
	 * 微信支付订单撤销响应数据处理
	 * @return
	 */
	private ThirdPlatformReverseOrder weixinReverseOrderResponseDataHandle(String mcode,String orderNumber, String responseData){
		val resultMap = SignatureUtils.xmlToMap(responseData);
		val thirdPlatformReverseOrder = new ThirdPlatformReverseOrder();
		thirdPlatformReverseOrder.setMcode(mcode);
		thirdPlatformReverseOrder.setMOrderNumber(orderNumber);
		thirdPlatformReverseOrder.setPayType(DictionaryConstant.PAYMENT_PAY_TYPE_WX_FACE_PAY.getCode());
		if(!resultMap.get("return_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)||!resultMap.get("result_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			if(resultMap.get("err_code").equalsIgnoreCase("NOT_ALLOW")){
				throw new BusinessCommonException(PaymentErrorCode.WX_PAY_NOT_ALLOW);
			}
			thirdPlatformReverseOrder.setReverseStatus("1");
		}else{
			thirdPlatformReverseOrder.setReverseStatus("2");
		}
		return thirdPlatformReverseOrder;
	}
	
	/**
	 * 人脸支付初始化使用方法
	 * @return
	 */
	public ThirdPlatformInitFacePay initFaceLive(PostInitFacePayRequest initFacePayRequest, MchPayChannel mchPayChannel, PayTypeDict payTypeDict){
		return new ThirdPlatformInitFacePay();
	}

	@Override
	public boolean IsSupportPartialRefund() {
		return false;
	}

	/**
	 * 人脸支付初始化使用方法
	 * @return
	 */
	public ThirdPlatformInitFacePay initFacePay(PostInitFacePayRequest initFacePayRequest, MchPayChannel mchPayChannel, PayTypeDict payTypeDict){
		val weixinInitFacePay = new WeixinInitFacePay();
		weixinInitFacePay.setAppid(mchPayChannel.getAppid());
		weixinInitFacePay.setMch_id(mchPayChannel.getMchId());
		weixinInitFacePay.setNonce_str(WXPayUtils.generateNonceStr());
		weixinInitFacePay.setNow(DateUtils.getLinuxTimestamp());
		weixinInitFacePay.setStore_id(initFacePayRequest.getStoreId());
		weixinInitFacePay.setStore_name(initFacePayRequest.getStoreName());
		weixinInitFacePay.setDevice_id(initFacePayRequest.getDeviceId());
		weixinInitFacePay.setRawdata(initFacePayRequest.getZimmetainfo());
		String weixinRequestData = SignatureUtils.generateSignedXml(MapBeanUtils.beanToMap(weixinInitFacePay),mchPayChannel.getSecretKey());
		String responseData = HttpClientUtils.postXMLData(WXPayConstants.FACE_DOMAIN_API+WXPayConstants.INIT_PAY_FACE_SUFFIX,weixinRequestData);
		LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),"", DictionaryConstant.PAYMENT_PAY_TYPE_WX_FACE_PAY.getCode(),LogUtils.LOG_DESCRIPTION_RLCSH,weixinRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
		return initFacePayResponseDataHandle(initFacePayRequest,responseData);
	}
	
	/**
	 * 支付宝人脸支付初始化响应数据处理
	 * @param responseData
	 * @return
	 */
	private ThirdPlatformInitFacePay initFacePayResponseDataHandle(PostInitFacePayRequest initFacePayRequest, String responseData){
		val resultMap = SignatureUtils.xmlToMap(responseData);
		if(!resultMap.get("return_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			throw new BusinessCommonException(PaymentErrorCode.WEIXIN_PAY_INIT_FACE_PAY_ERROR.getCode(),resultMap.get("return_msg"));
		}
		val thirdPlatformOrder = new ThirdPlatformInitFacePay();
		thirdPlatformOrder.setMcode(initFacePayRequest.getMcode());
		thirdPlatformOrder.setInitStatus("1");
		thirdPlatformOrder.setAuthinfo(resultMap.get("authinfo"));
		thirdPlatformOrder.setExpiresIn(resultMap.get("expires_in"));
		return thirdPlatformOrder;
	}
}
