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

import com.alibaba.fastjson.JSON;
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.DateUtils;
import com.neusoft.smart.pos.framework.utils.LocalDateTimeUtils;
import com.neusoft.smart.pos.framework.utils.MapBeanUtils;
import com.neusoft.smart.pos.payment.constants.ChinaumsPayConstants;
import com.neusoft.smart.pos.payment.constants.PaymentErrorCode;
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.ChinaumsUtils;
import com.neusoft.smart.pos.payment.utils.HttpClientUtils;
import com.neusoft.smart.pos.payment.utils.LogUtils;
import lombok.val;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;

/**
 * @author zcf
 * @date 2018-07-19 10：43
 * @description 银联商务公众号支付使用Repository
 */
@Component("chinaumsPayServiceRepository")
public class ChinaumsPayServiceRepository implements IThirdPayRepository {

	/**
	 * 创建银联商务支付单使用方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	@Override
	public ThirdPlatformCreateOrder createPayOrderToThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel, PayTypeDict payTypeDict){
		//1.处理数据
		String url =  chinaumsCreateOrderRequestDataHandle(payOrder,mchPayChannel,payTypeDict);
		val thirdPlatformOrder = new ThirdPlatformCreateOrder();
		thirdPlatformOrder.setMcode(payOrder.getMcode());
		thirdPlatformOrder.setTradeId(payOrder.getTradeId());
		thirdPlatformOrder.setMOrderNumber(payOrder.getmOrderNumber());

		thirdPlatformOrder.setOuterCodeUrl(url);
		thirdPlatformOrder.setPayStatus(DictionaryConstant.PAY_STATUS_WFK.getCode());
		return thirdPlatformOrder;
	}

	/**
	 * 银联商务数据整理方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	private String chinaumsCreateOrderRequestDataHandle(PayOrder payOrder, MchPayChannel mchPayChannel,PayTypeDict payTypeDict){
		val chinaumsPayOrder = new ChinaumsPayServiceCreateOrder();
		chinaumsPayOrder.setMsgSrc(mchPayChannel.getAppSecretKey());
		chinaumsPayOrder.setRequestTimestamp(LocalDateTimeUtils.getDateTime());
		chinaumsPayOrder.setMid(mchPayChannel.getMchId());
		chinaumsPayOrder.setMerOrderId(ChinaumsPayConstants.ORDER_NUMBER_PREFIX+payOrder.getmOrderNumber());
		chinaumsPayOrder.setTid(mchPayChannel.getAppid());
		chinaumsPayOrder.setNotifyUrl(payTypeDict.getNotifyUrl());
		chinaumsPayOrder.setReturnUrl(payTypeDict.getNotifyUrl());
		chinaumsPayOrder.setTotalAmount(String.valueOf(payOrder.getOrderAmount()));
		chinaumsPayOrder.setMsgType("WXPay.jsPay");
		chinaumsPayOrder.setInstMid("YUEDANDEFAULT");
		String sign = ChinaumsUtils.makeSign(mchPayChannel.getSecretKey(), MapBeanUtils.beanToMap(chinaumsPayOrder));
		chinaumsPayOrder.setSign(sign);
		String url = ChinaumsUtils.makeOrderRequest(MapBeanUtils.beanToMap(chinaumsPayOrder), mchPayChannel.getSecretKey(), ChinaumsPayConstants.DOMAIN_API_PAY);
		return url;
	}

	/**
	 * 银联商务预付订单查询方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	public ThirdPlatformQueryOrder queryPayOrderFromThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel){
		//1.处理数据
		val chinaumsPayServiceQueryOrder = new ChinaumsPayServiceQueryOrder();
		chinaumsPayServiceQueryOrder.setMsgSrc(mchPayChannel.getAppSecretKey());
		chinaumsPayServiceQueryOrder.setRequestTimestamp(LocalDateTimeUtils.getDateTime());
		chinaumsPayServiceQueryOrder.setMid(mchPayChannel.getMchId());
		chinaumsPayServiceQueryOrder.setTid(mchPayChannel.getAppid());
		chinaumsPayServiceQueryOrder.setMsgType("query");
		chinaumsPayServiceQueryOrder.setInstMid("YUEDANDEFAULT");
		chinaumsPayServiceQueryOrder.setMerOrderId(ChinaumsPayConstants.ORDER_NUMBER_PREFIX+payOrder.getmOrderNumber());
		String sign = ChinaumsUtils.makeSign(mchPayChannel.getSecretKey(), MapBeanUtils.beanToMap(chinaumsPayServiceQueryOrder));
		chinaumsPayServiceQueryOrder.setSign(sign);
		String chinaumsRequestData = JSON.toJSONString(chinaumsPayServiceQueryOrder);
		//2.请求银商预付单生成接口
		String responseData = HttpClientUtils.postData(ChinaumsPayConstants.DOMAIN_API,chinaumsRequestData);
		//3.记录日志
		LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_YLSW_SERCIE.getCode(),LogUtils.LOG_DESCRIPTION_DDCS,chinaumsRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
		return chinaumsQueryOrderResponseDataHandle(mchPayChannel.getMcode(),payOrder.getmOrderNumber(),responseData);
	}

	/**
	 * 银联商务支付响应数据处理
	 * @return
	 */
	private ThirdPlatformQueryOrder chinaumsQueryOrderResponseDataHandle(String mcode,String orderNumber, String responseData){
		val resultMap = JSON.parseObject(responseData, HashMap.class);
		if(!resultMap.get("errCode").toString().equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR.getCode(),resultMap.get("errMsg").toString());
		}
		val thirdPlatformOrder = new ThirdPlatformQueryOrder();
		thirdPlatformOrder.setMcode(mcode);
		thirdPlatformOrder.setMOrderNumber(orderNumber);
		thirdPlatformOrder.setTradeStatus(getTradeStatus(resultMap.get("status").toString()));

		//处理支付信息
		if(resultMap.get("payTime") != null){
			Date payDate = DateUtils.parse(resultMap.get("payTime").toString(),DateUtils.FORMAT_LONG);
			String payTime = DateUtils.format(payDate,DateUtils.FORMAT_LONG_UNMARK);
			thirdPlatformOrder.setTimeEnd(payTime);
		}
		return thirdPlatformOrder;
	}

	/**
	 * 根据银联商务交易状态返回支付平台订单状态
	 * @param tradeState
	 * @return
	 */
	private String getTradeStatus(String tradeState){
		String tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
		switch(tradeState){
			case "TRADE_SUCCESS":
				//支付成功
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_YZF.getCode();
				break;
			case "TRADE_REFUND":
				//转入退款
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_YTK.getCode();
				break;
			case "NEW_ORDER":
				//未支付
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
				break;
			case "TRADE_CLOSED":
				//已关闭
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_JYGB.getCode();
				break;
		}
		return tradeStatus;
	}

	/**
	 * 银联商务预付订单取消方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	public ThirdPlatformCancelOrder cannelPayOrderFromThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel){
		//1.处理数据
		val chinaumsPayServiceCannelOrder = new ChinaumsPayServiceCannelOrder();
		chinaumsPayServiceCannelOrder.setMsgSrc(mchPayChannel.getAppSecretKey());
		chinaumsPayServiceCannelOrder.setRequestTimestamp(LocalDateTimeUtils.getDateTime());
		chinaumsPayServiceCannelOrder.setMid(mchPayChannel.getMchId());
		chinaumsPayServiceCannelOrder.setTid(mchPayChannel.getAppid());
		chinaumsPayServiceCannelOrder.setMsgType("close");
		chinaumsPayServiceCannelOrder.setInstMid("YUEDANDEFAULT");
		chinaumsPayServiceCannelOrder.setMerOrderId(ChinaumsPayConstants.ORDER_NUMBER_PREFIX+payOrder.getmOrderNumber());
		String sign = ChinaumsUtils.makeSign(mchPayChannel.getSecretKey(), MapBeanUtils.beanToMap(chinaumsPayServiceCannelOrder));
		chinaumsPayServiceCannelOrder.setSign(sign);
		String chinaumsRequestData = JSON.toJSONString(chinaumsPayServiceCannelOrder);
		String responseData = HttpClientUtils.postData(ChinaumsPayConstants.DOMAIN_API,chinaumsRequestData);
		//3.记录日志
		LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_WXZF_SERCIE.getCode(),LogUtils.LOG_DESCRIPTION_DDQX,chinaumsRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
		return chinaumsCannelOrderResponseDataHandle(mchPayChannel.getMcode(),payOrder.getmOrderNumber(),responseData);
	}

	/**
	 * 银联商务支付订单取消响应数据处理
	 * @return
	 */
	private ThirdPlatformCancelOrder chinaumsCannelOrderResponseDataHandle(String mcode,String orderNumber, String responseData){
		val resultMap = JSON.parseObject(responseData, HashMap.class);
		if(!resultMap.get("errCode").toString().equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR.getCode(),resultMap.get("errMsg").toString());
		}
		val thirdPlatformCancelOrder = new ThirdPlatformCancelOrder();
		thirdPlatformCancelOrder.setMcode(mcode);
		thirdPlatformCancelOrder.setMOrderNumber(orderNumber);
		thirdPlatformCancelOrder.setPayType(DictionaryConstant.PAYMENT_PAY_TYPE_YLSW_GZH_SERCIE.getCode());
		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 chinaumsPayServiceRefundOrder = new ChinaumsPayServiceRefundOrder();
		chinaumsPayServiceRefundOrder.setMsgSrc(mchPayChannel.getAppSecretKey());
		chinaumsPayServiceRefundOrder.setRequestTimestamp(LocalDateTimeUtils.getDateTime());
		chinaumsPayServiceRefundOrder.setMid(mchPayChannel.getMchId());
		chinaumsPayServiceRefundOrder.setTid(mchPayChannel.getAppid());
		chinaumsPayServiceRefundOrder.setMerOrderId(ChinaumsPayConstants.ORDER_NUMBER_PREFIX+payOrder.getmOrderNumber());
		chinaumsPayServiceRefundOrder.setMsgType("refund");
		chinaumsPayServiceRefundOrder.setInstMid("YUEDANDEFAULT");
		chinaumsPayServiceRefundOrder.setRefundAmount(payOrder.getOrderAmount().toString());
		String sign = ChinaumsUtils.makeSign(mchPayChannel.getSecretKey(), MapBeanUtils.beanToMap(chinaumsPayServiceRefundOrder));
		chinaumsPayServiceRefundOrder.setSign(sign);
		String chinaumsRequestData = JSON.toJSONString(chinaumsPayServiceRefundOrder);
		String responseData = HttpClientUtils.postData(ChinaumsPayConstants.DOMAIN_API,chinaumsRequestData);
		//3.记录日志
		LogUtils.savePaymentTradeLog(payOrder.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_YLSW_GZH_SERCIE.getCode(),LogUtils.LOG_DESCRIPTION_SQTK,chinaumsRequestData,responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
		return chinaumsRefundOrderResponseDataHandle(payOrder,refundNumber,responseData);
	}

	/**
	 * 银联商务退款申请响应数据处理
	 * @param payOrder
	 * @param responseData
	 * @return
	 */
	private ThirdPlatformRefundOrder chinaumsRefundOrderResponseDataHandle(PayOrder payOrder,String refundNumber, String responseData){
		val resultMap = JSON.parseObject(responseData, HashMap.class);
		if(!resultMap.get("errCode").toString().equalsIgnoreCase(ApplicationConstants.SUCCESS)){
			throw new BusinessCommonException(PaymentErrorCode.MCH_ORDER_GENERATE_ERROR.getCode(),resultMap.get("errMsg").toString());
		}
		val thirdPlatformOrder = new ThirdPlatformRefundOrder();
		thirdPlatformOrder.setMcode(payOrder.getMcode());
		thirdPlatformOrder.setMOrderNumber(payOrder.getmOrderNumber());
		thirdPlatformOrder.setPayType(payOrder.getPayType());
		thirdPlatformOrder.setRefundNumber(refundNumber);
		thirdPlatformOrder.setRefundAmount(payOrder.getOrderAmount());
		if(resultMap.get("refundStatus").toString().equalsIgnoreCase("SUCCESS")){
			thirdPlatformOrder.setRefundStatus("2");
			thirdPlatformOrder.setThirdRefundNumber(resultMap.get("refundOrderId").toString());
		}else if(resultMap.get("refundStatus").toString().equalsIgnoreCase("PROCESSING")){
			thirdPlatformOrder.setRefundStatus("1");
			thirdPlatformOrder.setThirdRefundNumber(resultMap.get("refundOrderId").toString());
		}else{
			thirdPlatformOrder.setRefundStatus("0");
		}
		return thirdPlatformOrder;
	}

	/**
	 * 预付单撤销使用方法
	 * @return
	 */
	public ThirdPlatformReverseOrder reversePayOrderFromThirdPlatform(PayOrder payOrder, String orderNumber, MchPayChannel mchPayChannel){
		return null;
	}

}
