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.FileUtils;
import com.neusoft.smart.pos.framework.utils.LocalIpUtils;
import com.neusoft.smart.pos.framework.utils.MapBeanUtils;
import com.neusoft.smart.pos.framework.utils.SignatureUtils;
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 2018-01-09 10：43
 * @description 支付管理使用Repository
 */
@Component("weiXinPayRepository")
public class WeiXinPayRepository 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 = "";
        if(StringUtils.isEmpty(payOrder.getScanCode())){
        	//用户主动扫码支付
			responseData = HttpClientUtils.postXMLData(WXPayConstants.DOMAIN_API+WXPayConstants.UNIFIEDORDER_URL_SUFFIX,weixinRequestData);
		}else{
        	//商户扫码支付
			responseData = HttpClientUtils.postXMLData(WXPayConstants.DOMAIN_API+WXPayConstants.MICROPAY_URL_SUFFIX,weixinRequestData);
		}
        //3.记录日志
		LogUtils.savePaymentTradeLog(payOrder.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_WXSM.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 WeixinPayCreateOrder();
		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()));
//		weixinPayOrder.setOpenid(payOrder.getOpenId());
		JSONObject payInfoJsonObject  = JSONObject.fromObject(payOrder.getRequestDetailInfo());
		try {
			weixinPayOrder.setOpenid(payInfoJsonObject.getString("openId"));
			payOrder.setOpenId(weixinPayOrder.getOpenid());
		} catch (Exception e) {
//			throw new BusinessCommonException(PaymentErrorCode.PAY_TYPE_INFO_NOT_EMPTY);//TODO openId没有是不是也可以？
		}
		if(StringUtils.isEmpty(payOrder.getPayIp())){
			weixinPayOrder.setSpbill_create_ip(LocalIpUtils.getLocalIP());
		}else{
			weixinPayOrder.setSpbill_create_ip(payOrder.getPayIp());
		}
		weixinPayOrder.setTime_expire(WXPayUtils.convertTimeExpireToWXFormat(payOrder.getTimeExpire()));
		weixinPayOrder.setAttach(payOrder.getMcode());
		try {
			weixinPayOrder.setAuth_code(payInfoJsonObject.getString("scanCode"));
			payOrder.setScanCode(weixinPayOrder.getAuth_code());
		} catch (Exception e) {
            weixinPayOrder.setNotify_url(payTypeDict.getNotifyUrl());
			weixinPayOrder.setProduct_id(payOrder.getmOrderNumber());
			weixinPayOrder.setTrade_type(payOrder.getTradeType());
		}
		weixinPayOrder.setTrade_type("JSAPI");
		weixinPayOrder.setNotify_url(payTypeDict.getNotifyUrl());
//		if(!StringUtils.isEmpty(payOrder.getScanCode())){
//			weixinPayOrder.setAuth_code(payOrder.getScanCode());
//		}else{
//			weixinPayOrder.setNotify_url(payTypeDict.getNotifyUrl());
//			weixinPayOrder.setProduct_id(payOrder.getmOrderNumber());
//			weixinPayOrder.setTrade_type(payOrder.getTradeType());
//		}
		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);
		}
		if(!resultMap.get("result_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			if(resultMap.get("err_code").equalsIgnoreCase("AUTH_CODE_INVALID")){
				throw new BusinessCommonException(PaymentErrorCode.WX_AUTH_CODE_INVALID);
			}
			if(resultMap.get("err_code").equalsIgnoreCase("USERPAYING")){
				//等待用户支付
//				throw new BusinessCommonException(PaymentErrorCode.WX_AUTH_CODE_INVALID);
			}
		}
//		val thirdPlatformOrder = new ThirdPlatformCreateOrder();
//		thirdPlatformOrder.setMcode(payOrder.getMcode());
//		thirdPlatformOrder.setTradeId(payOrder.getTradeId());
//		thirdPlatformOrder.setMOrderNumber(payOrder.getmOrderNumber());
//		thirdPlatformOrder.setOuterOrderNumber(resultMap.get("prepay_id"));
        payOrder.setOuterOrderNumber(resultMap.get("prepay_id"));

		if(payOrder.getTradeType().equals("NATIVE")){
//			thirdPlatformOrder.setOuterCodeUrl(resultMap.get("code_url"));
            payOrder.setCodeUrl(resultMap.get("code_url"));
		}else{
//			thirdPlatformOrder.setOuterCodeUrl(resultMap.get("mweb_url"));
            payOrder.setCodeUrl(resultMap.get("mweb_url"));
		}
		if(!StringUtils.isEmpty(payOrder.getScanCode())){
			if(resultMap.get("result_code").equalsIgnoreCase(ApplicationConstants.SUCCESS)){
//				thirdPlatformOrder.setPayStatus(DictionaryConstant.PAY_STATUS_YFK.getCode());
                payOrder.setPayStatus(DictionaryConstant.PAY_STATUS_YFK.getCode());
			}
		}
//		return thirdPlatformOrder;
        JSONObject payResponseJsonObject = new JSONObject();
        payResponseJsonObject.put("codeUrl",payOrder.getCodeUrl());
        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.ORDER_QUERY_URL_SUFFIX,weixinRequestData);
		//3.记录日志
		LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_WXSM.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 "NOTPAY":
				//未支付
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
				break;
			case "CLOSED":
				//已关闭
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_JYGB.getCode();
				break;
			case "REVOKED":
				//已撤销（刷卡支付）
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.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 = 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_WXSM.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_WXSM.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_WXSM.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_WXSM.getCode(),LogUtils.LOG_DESCRIPTION_DDCX,weixinRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
		return weixinReverseOrderResponseDataHandle(mchPayChannel.getMcode(),orderNumber,responseData);
	}

	@Override
	public ThirdPlatformInitFacePay initFacePay(PostInitFacePayRequest initFacePayRequest, MchPayChannel mchPayChannel, PayTypeDict payTypeDict) {
		return null;
	}

	@Override
	public ThirdPlatformInitFacePay initFaceLive(PostInitFacePayRequest initFacePayRequest, MchPayChannel mchPayChannel, PayTypeDict payTypeDict) {
		return null;
	}

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

	/**
	 * 微信支付订单撤销响应数据处理
	 * @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_WXSM.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;
	}
}
