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

import com.alibaba.fastjson.JSON;
import com.neusoft.smart.pos.constants.DictionaryConstant;
import com.neusoft.smart.pos.dto.payment.request.PostInitFacePayRequest;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.utils.BeanUtil;
import com.neusoft.smart.pos.payment.constants.PaymentErrorCode;
import com.neusoft.smart.pos.payment.constants.UnionPayConstants;
import com.neusoft.smart.pos.payment.persistent.ext.domain.*;
import com.neusoft.smart.pos.payment.utils.LogUtils;
import com.neusoft.smart.pos.payment.utils.UnionPayHttpClientUtils;
import com.neusoft.smart.pos.payment.utils.UnionPayUtils;
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 com.neusoft.smart.pos.payorder.repository.MchPayChannelRepository;
import lombok.val;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @author tjm
 * @date 2018-02-24 
 * @description 银联云闪付管理使用Repository
 */
@Component("unionPayRepository")
public class UnionPayRepository implements IThirdPayRepository {

	@Resource
	public MchPayChannelRepository mchPayChannelRepository;

	/**
	 * 创建银联支付单使用方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	@Override
	public String createPayOrderToThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel, PayTypeDict payTypeDict){
		//1.处理数据
		Map<String,String> unionPayCreateOrderMap;
		//2.请求银联预付单生成接口
		String responseData = "";
		if(StringUtils.isEmpty(payOrder.getScanCode())){
			unionPayCreateOrderMap =  unionCreateOrderRequestDataHandle(payOrder,mchPayChannel,payTypeDict);
			//用户主动扫码支付
			responseData = UnionPayHttpClientUtils.send(UnionPayConstants.DOMAIN_API+UnionPayConstants.UNIFIEDORDER_URL_SUFFIX,unionPayCreateOrderMap);
		}else{
			unionPayCreateOrderMap =  unionCreateOrderScanRequestDataHandle(payOrder,mchPayChannel,payTypeDict);
			//商户扫码支付
			responseData = UnionPayHttpClientUtils.send(UnionPayConstants.DOMAIN_API+UnionPayConstants.MICROPAY_URL_SUFFIX,unionPayCreateOrderMap);
		}
		Map<String,String> resultMap =  UnionPayUtils.convertResultStringToMap(responseData);

		//3.记录日志
		LogUtils.savePaymentTradeLog(payOrder.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_YLSM.getCode(),LogUtils.LOG_DESCRIPTION_DDSC,JSON.toJSONString(unionPayCreateOrderMap),responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());

		return unionPayCreateOrderResponseDataHandle(payOrder,resultMap);
	}

	/**
	 * 银联数据整理方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	private Map<String,String> unionCreateOrderRequestDataHandle(PayOrder payOrder, MchPayChannel mchPayChannel, PayTypeDict payTypeDict){
		val unionPayCreateOrder = new UnionPayCreateOrder();
		unionPayCreateOrder.setMerId(mchPayChannel.getMchId());
		unionPayCreateOrder.setOrderId(payOrder.getmOrderNumber());
		unionPayCreateOrder.setTxnTime(payOrder.getTimeExpire());
		unionPayCreateOrder.setTxnAmt(String.valueOf(payOrder.getPayAmount()));
		unionPayCreateOrder.setBackUrl(payTypeDict.getNotifyUrl());

//		FileInputStream fis = null;
//		try {
//			fis = new FileInputStream("D:/certs/acp_test_sign.pfx");
//		} catch (FileNotFoundException e) {
//			e.printStackTrace();
//		}
//		byte [] cert = FileUtils.convertInputStreamToByteArray(fis);
		unionPayCreateOrder.setCertId(UnionPayUtils.getSignCertId(mchPayChannel.getCert(),mchPayChannel.getSecretKey()));	//生成证书ID

//		MchPayChannelWithBLOBs channel = new MchPayChannelWithBLOBs();
//		channel.setMcode(mchPayChannel.getMcode());
//		channel.setPayType(mchPayChannel.getPayType());
//		channel.setSignCert(mchPayChannel.getCert());
//		Boolean bool = mchPayChannelRepository.updateMchPayChannelByMcode(channel);

		Map<String,String> resultMap = BeanUtil.parse(unionPayCreateOrder,Map.class);
		String signature = UnionPayUtils.generateSignature(resultMap,mchPayChannel.getCert(),mchPayChannel.getSecretKey());//生成签名信息
		resultMap.put("signature",signature);
		return resultMap;
	}

	/**
	 * 银联数据整理方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	private Map<String,String> unionCreateOrderScanRequestDataHandle(PayOrder payOrder, MchPayChannel mchPayChannel, PayTypeDict payTypeDict){
		val unionPayCreateOrderScan = new UnionPayCreateOrderScan();
		unionPayCreateOrderScan.setMerId(mchPayChannel.getMchId());
		unionPayCreateOrderScan.setOrderId(payOrder.getmOrderNumber());
		unionPayCreateOrderScan.setTxnTime(payOrder.getTimeExpire());
		unionPayCreateOrderScan.setTxnAmt(String.valueOf(payOrder.getPayAmount()));
		unionPayCreateOrderScan.setBackUrl(payTypeDict.getNotifyUrl());
		JSONObject payInfoJsonObject  = JSONObject.fromObject(payOrder.getRequestDetailInfo());
		try {
			unionPayCreateOrderScan.setQrNo(payInfoJsonObject.getString("scanCode"));
			payOrder.setScanCode(unionPayCreateOrderScan.getQrNo());
		} catch (Exception e) {
			throw new BusinessCommonException(PaymentErrorCode.PAY_TYPE_INFO_NOT_EMPTY);
		}
//		unionPayCreateOrderScan.setQrNo(payOrder.getScanCode());
		unionPayCreateOrderScan.setCertId(UnionPayUtils.getSignCertId(mchPayChannel.getCert(),mchPayChannel.getSecretKey()));	//生成证书ID

		Map<String,String> resultMap = BeanUtil.parse(unionPayCreateOrderScan,Map.class);
		String signature = UnionPayUtils.generateSignature(resultMap,mchPayChannel.getCert(),mchPayChannel.getSecretKey());//生成签名信息
		resultMap.put("signature",signature);
		return resultMap;
	}

	/**
	 * 银联支付响应数据处理
	 * @param payOrder
	 * @param responseData
	 * @return
	 */
	private String unionPayCreateOrderResponseDataHandle(PayOrder payOrder, Map<String,String> responseData){
		if(!responseData.get("respCode").equalsIgnoreCase("00")){
			throw new BusinessCommonException(responseData.get("respCode"),responseData.get("respMsg"));
		}
//		val thirdPlatformOrder = new ThirdPlatformCreateOrder();
//		thirdPlatformOrder.setMcode(payOrder.getMcode());
//		thirdPlatformOrder.setTradeId(payOrder.getTradeId());
//		thirdPlatformOrder.setMOrderNumber(payOrder.getmOrderNumber());
//		thirdPlatformOrder.setOuterOrderNumber(responseData.get("orderId"));
        payOrder.setOuterOrderNumber(responseData.get("orderId"));
		if(responseData.containsKey("qrCode")){
            payOrder.setCodeUrl(responseData.get("qrCode"));
//			thirdPlatformOrder.setOuterCodeUrl(responseData.get("qrCode"));
		}else{
//			thirdPlatformOrder.setOuterCodeUrl("");
            payOrder.setCodeUrl("");
		}
        JSONObject payResponseJsonObject = new JSONObject();
        payResponseJsonObject.put("codeUrl",payOrder.getCodeUrl());
        return payResponseJsonObject.toString();
//		return thirdPlatformOrder;
	}

	/**
	 * 银联预付订单查询方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	public ThirdPlatformQueryOrder queryPayOrderFromThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel){
        //1.处理数据
        val unionPayQueryOrder = new UnionPayQueryOrder();
		unionPayQueryOrder.setMerId(mchPayChannel.getMchId());
		unionPayQueryOrder.setOrderId(payOrder.getmOrderNumber());
		unionPayQueryOrder.setTxnTime(payOrder.getTimeExpire());
		unionPayQueryOrder.setCertId(UnionPayUtils.getSignCertId(mchPayChannel.getCert(),mchPayChannel.getSecretKey()));	//生成证书ID
		Map<String,String> unionPayQueryOrderMap = BeanUtil.parse(unionPayQueryOrder,Map.class);
		String signature = UnionPayUtils.generateSignature(unionPayQueryOrderMap,mchPayChannel.getCert(),mchPayChannel.getSecretKey());//生成签名信息
		unionPayQueryOrderMap.put("signature",signature);

		String responseData = UnionPayHttpClientUtils.send(UnionPayConstants.DOMAIN_API+UnionPayConstants.ORDER_QUERY_URL_SUFFIX,unionPayQueryOrderMap);
		Map<String,String> resultMap =  UnionPayUtils.convertResultStringToMap(responseData);
        //3.记录日志
        LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_YLSM.getCode(),LogUtils.LOG_DESCRIPTION_DDCS,JSON.toJSONString(unionPayQueryOrder),responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
        return unionPayQueryOrderResponseDataHandle(mchPayChannel.getMcode(),payOrder.getmOrderNumber(),resultMap);
	}

	/**
	 * 银联二维码支付数据处理
	 * @return
	 */
	private ThirdPlatformQueryOrder unionPayQueryOrderResponseDataHandle(String mcode,String orderNumber, Map<String,String> responseData){
		if(!responseData.get("respCode").equalsIgnoreCase("00")){
			throw new BusinessCommonException(responseData.get("respCode"),responseData.get("respMsg"));
		}
		val thirdPlatformOrder = new ThirdPlatformQueryOrder();
		thirdPlatformOrder.setMcode(mcode);
		thirdPlatformOrder.setMOrderNumber(orderNumber);
		thirdPlatformOrder.setOuterTradeNumber(responseData.get("queryId")==null?"":responseData.get("queryId"));
		thirdPlatformOrder.setTradeStatus(getTradeStatus(responseData.get("origRespCode")));
		thirdPlatformOrder.setTimeEnd(responseData.get("txnTime"));

		String origRespCode = responseData.get("origRespCode");

		return thirdPlatformOrder;
	}

	/**
	 * 根据微信交易状态返回支付平台订单状态
	 * @param tradeState
	 * @return
	 */
	private String getTradeStatus(String tradeState){
//		if(("00").equals(origRespCode)){
//			//交易成功，更新商户订单状态
//			//TODO
//		}else if(("03").equals(origRespCode)||
//				("04").equals(origRespCode)||
//				("05").equals(origRespCode)){
//			//订单处理中或交易状态未明，需稍后发起交易状态查询交易 【如果最终尚未确定交易是否成功请以对账文件为准】
//			//TODO
//		}else{
//			//其他应答码为交易失败
//			//TODO
//		}
		String tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
		switch(tradeState){
			case "00":
				//支付成功
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_YZF.getCode();
				break;
			case "03":
				//转入退款
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
				break;
			case "04":
				//未支付
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
				break;
			case "05":
				//已关闭
				tradeStatus = DictionaryConstant.PAYMENT_ORDER_STATUS_DZF.getCode();
				break;
		}
		return tradeStatus;
	}

	/**
	 * 银联预付订单取消方法
	 * @param payOrder
	 * @param mchPayChannel
	 * @return
	 */
	public ThirdPlatformCancelOrder cannelPayOrderFromThirdPlatform(PayOrder payOrder, MchPayChannel mchPayChannel){
		return null;
	}

	/**
	 * 银联预付订单退款申请方法
	 * @return
	 */
	@Override
	public ThirdPlatformRefundOrder refundPayOrderFromThirdPlatform(PayOrder payOrder,String refundNumber,Long refundAmount, MchPayChannel mchPayChannel,PayTypeDict payTypeDict){
		val unionPayRefundOrder = new UnionPayRefundOrder();
		unionPayRefundOrder.setMerId(mchPayChannel.getMchId());
		unionPayRefundOrder.setOrderId(refundNumber);
		unionPayRefundOrder.setTxnTime(payOrder.getTimeExpire());
		unionPayRefundOrder.setBackUrl(payTypeDict.getRefundNotifyUrl());
		unionPayRefundOrder.setTxnAmt(payOrder.getPayAmount().toString());
		unionPayRefundOrder.setOrigOrderId(payOrder.getmOrderNumber());
		unionPayRefundOrder.setOrigQryId(payOrder.getOuterOrderNumber());
//		unionPayRefundOrder.setOrigTxnTime(payOrder.getTimeExpire());
		unionPayRefundOrder.setCertId(UnionPayUtils.getSignCertId(mchPayChannel.getCert(),mchPayChannel.getSecretKey()));	//生成证书ID
		Map<String,String> unionPayQueryOrderMap = BeanUtil.parse(unionPayRefundOrder,Map.class);
		String signature = UnionPayUtils.generateSignature(unionPayQueryOrderMap,mchPayChannel.getCert(),mchPayChannel.getSecretKey());//生成签名信息
		unionPayQueryOrderMap.put("signature",signature);

		String responseData = UnionPayHttpClientUtils.send(UnionPayConstants.DOMAIN_API+UnionPayConstants.ORDER_REFUND_URL_SUFFIX,unionPayQueryOrderMap);
		Map<String,String> resultMap =  UnionPayUtils.convertResultStringToMap(responseData);
		//3.记录日志
		LogUtils.savePaymentTradeLog(payOrder.getMcode(),payOrder.getmOrderNumber(), DictionaryConstant.PAYMENT_PAY_TYPE_YLSM.getCode(),LogUtils.LOG_DESCRIPTION_SQTK,JSON.toJSONString(unionPayQueryOrderMap),responseData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());

		return unionPayRefundOrderResponseDataHandle(payOrder,refundNumber,resultMap);
	}

	/**
	 * 微信退款申请响应数据处理
	 * @param payOrder
	 * @param responseData
	 * @return
	 */
	private ThirdPlatformRefundOrder unionPayRefundOrderResponseDataHandle(PayOrder payOrder,String refundNumber, Map<String,String> responseData){
		if(!responseData.get("respCode").equalsIgnoreCase("00")){
			throw new BusinessCommonException(responseData.get("respCode"),responseData.get("respMsg"));
		}
		val thirdPlatformOrder = new ThirdPlatformRefundOrder();
		thirdPlatformOrder.setMcode(payOrder.getMcode());
		thirdPlatformOrder.setMOrderNumber(payOrder.getmOrderNumber());
		thirdPlatformOrder.setPayType(payOrder.getPayType());
		thirdPlatformOrder.setRefundNumber(refundNumber);
		thirdPlatformOrder.setRefundAmount(Long.parseLong(responseData.get("txnAmt")));
		thirdPlatformOrder.setRefundStatus("1");

		return thirdPlatformOrder;
	}

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

	@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;
	}

}
