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

import com.google.common.collect.Maps;
import com.neusoft.smart.pos.constants.DictionaryConstant;
import com.neusoft.smart.pos.framework.constants.ApplicationConstants;
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.persistent.domain.PayOrder;
import com.neusoft.smart.pos.payment.persistent.domain.PayRefundOrder;
import com.neusoft.smart.pos.payment.persistent.ext.domain.WeixinPayNotify;
import com.neusoft.smart.pos.payment.persistent.ext.domain.WeixinPayRefundNotify;
import com.neusoft.smart.pos.payment.repository.MchPayChannelRepository;
import com.neusoft.smart.pos.payment.repository.MchPayInfoRepository;
import com.neusoft.smart.pos.payment.repository.PayNotifyRepository;
import com.neusoft.smart.pos.payment.repository.PayOrderRepository;
import com.neusoft.smart.pos.payment.utils.LogUtils;
import com.neusoft.smart.pos.payment.utils.WXPayUtils;
import lombok.val;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;

@Service("wxUsPayNotifyService")
public class WXUsPayNotifyService {

	@Autowired
    private MchPayChannelRepository mchPayChannelRepository;

    @Autowired
    private PayOrderRepository payOrderRepository;


    @Autowired
    private MchPayInfoRepository mchPayInfoRepository;

    @Autowired
    private PayNotifyRepository payNotifyRepository;

    /**
     * 微信支付完成通知数据处理方法
     * @param notifyXmlData：微信回调数据
     * @return
     */
    public String weixinNotifyDataHandle(String notifyXmlData){
        if(StringUtils.isEmpty(notifyXmlData)){
            return getWeixinResultData(ApplicationConstants.FALSE);
        }
        String resultData = getWeixinResultData(ApplicationConstants.TRUE);
        //1.转换数据格式
        Map<String,String> notifyMapData = WXPayUtils.xmlToMap(notifyXmlData);  //将xml数据转成Map
        val weixinPayNotify = MapBeanUtils.mapToBean(notifyMapData,WeixinPayNotify.class);  //将map转成bean对象

        //2.根据微信商户号查询微信商户信息
        String payType;
//        if(notifyMapData.containsKey("sub_mch_id")){
            payType = DictionaryConstant.PAYMENT_PAY_TYPE_WXZF_US_SERCIE.getCode();
//        }else{
//            payType = DictionaryConstant.PAYMENT_PAY_TYPE_WXSM.getCode();
//        }
        val mchPayChannel = mchPayChannelRepository.queryMchPayChannelByMcode(weixinPayNotify.getAttach(), payType);

        //3.校验微信回调签名信息
        if(!WXPayUtils.isSignatureValid(notifyMapData,mchPayChannel.getSecretKey())){
            resultData = getWeixinResultData(false);
            LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),weixinPayNotify.getOut_trade_no(), payType,LogUtils.LOG_DESCRIPTION_ZFCGHD,resultData,notifyXmlData,DictionaryConstant.PAYMENT_REQUEST_TYPE_BD.getCode());
            return resultData;
        }

        //4.更新聚合支付平台订单支付状态信息
        if(weixinPayNotify.getReturn_code().equalsIgnoreCase(ApplicationConstants.SUCCESS)&&weixinPayNotify.getResult_code().equalsIgnoreCase(ApplicationConstants.SUCCESS)){
            val payOrder = new PayOrder();
            payOrder.setPayTime(LocalDateTimeUtils.convertLocalDateTimeToDate(LocalDateTimeUtils.convertStringToLocalDateTime(weixinPayNotify.getTime_end(),LocalDateTimeUtils.SIMPLE_DATETIME_FORMAT)));
            payOrderRepository.updateOrderPayStatus(payOrder,mchPayChannel.getMcode(),weixinPayNotify.getOut_trade_no(),payType);
        }

        //5.回调业务系统通知方法(由于目前聚合支付平台不支持独立回调请求，所以暂时只做请求转发)
        val mchPayInfo = mchPayInfoRepository.queryMchPayInfoByMcode(mchPayChannel.getMcode(),DictionaryConstant.PAYMENT_MCH_STATUS_SHTG.getCode());
        val payOrder = payOrderRepository.queryPayOrder(mchPayChannel.getMcode(),weixinPayNotify.getOut_trade_no(),payType);
        Boolean bool = payNotifyRepository.sendPayNotify(payOrder,mchPayInfo.getSecretKey());
        resultData = getWeixinResultData(bool);
        LogUtils.savePaymentTradeLog(mchPayChannel.getMcode(),weixinPayNotify.getOut_trade_no(), payType,LogUtils.LOG_DESCRIPTION_ZFCGHD,resultData,notifyXmlData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
        return resultData;
    }

    /**
     * 微信退款完成通知数据处理方法
     * @param notifyXmlData：微信回调数据
     * @return
     */
    public String weixinRefundNotifyDataHandle(String notifyXmlData){
        if(StringUtils.isEmpty(notifyXmlData)){
            return getWeixinResultData(ApplicationConstants.FALSE);
        }

        //1.将微信通知数据转换成bean
        val weixinPayRefundNotify = getWeixinPayRefundNotifyData(notifyXmlData);

        //2.根据退款单号信息查询聚合平台退款单信息

        val payRefundOrder = payOrderRepository.queryPayRefundOrder(weixinPayRefundNotify.getOut_trade_no(),weixinPayRefundNotify.getRefund_id(),weixinPayRefundNotify.getOut_refund_no());
        //4.更新聚合支付平台订单支付状态信息
        String payType;
//        if(!StringUtils.isEmpty(weixinPayRefundNotify.getSub_mch_id())){
            payType = DictionaryConstant.PAYMENT_PAY_TYPE_WXZF_US_SERCIE.getCode();
//        }else{
//            payType = DictionaryConstant.PAYMENT_PAY_TYPE_WXSM.getCode();
//        }
        if(weixinPayRefundNotify.getRefund_status().equalsIgnoreCase(ApplicationConstants.SUCCESS)){
            //更新退款订单状态
            val payOrder = new PayOrder();
            payOrderRepository.updateOrderRefundStatus(payOrder,payRefundOrder.getMcode(),weixinPayRefundNotify.getOut_trade_no(),payType);

            //更新退款单状态
            if(payRefundOrder.getRefundStatus() != DictionaryConstant.REFUND_STATUS_TKWC.getCode()){
                val payRefundOrderTemp = new PayRefundOrder();
                payRefundOrderTemp.setRefundStatus(DictionaryConstant.REFUND_STATUS_TKWC.getCode());
                payRefundOrderTemp.setRefundedTime(DateUtils.parse(weixinPayRefundNotify.getSuccess_time(),DateUtils.FORMAT_LONG));
                payOrderRepository.updatePayRefundOrderStatus(payRefundOrderTemp,weixinPayRefundNotify.getOut_trade_no(),weixinPayRefundNotify.getRefund_id(),weixinPayRefundNotify.getOut_refund_no());
            }
        }
        payRefundOrder.setRefundStatus(DictionaryConstant.REFUND_STATUS_TKWC.getCode());
        payRefundOrder.setRefundedTime(DateUtils.parse(weixinPayRefundNotify.getSuccess_time(),DateUtils.FORMAT_LONG));
        //5.回调业务系统通知方法(由于目前聚合支付平台不支持独立回调请求，所以暂时只做请求转发)
        val mchPayInfo = mchPayInfoRepository.queryMchPayInfoByMcode(payRefundOrder.getMcode(),DictionaryConstant.PAYMENT_MCH_STATUS_SHTG.getCode());
        Boolean bool = payNotifyRepository.sendPayRefundNotify(payRefundOrder,mchPayInfo.getSecretKey());
        LogUtils.savePaymentTradeLog(payRefundOrder.getMcode(),weixinPayRefundNotify.getOut_trade_no(), payType,LogUtils.LOG_DESCRIPTION_TKCGHD,getWeixinResultData(bool),notifyXmlData,DictionaryConstant.PAYMENT_REQUEST_TYPE_ZD.getCode());
        return getWeixinResultData(bool);
    }

    /**
     * 微信回调数据返回对象整理
     * @param bool
     * @return
     */
    private String getWeixinResultData(Boolean bool){
        Map<String,String> resultMap = Maps.newHashMap();
        if(bool){
			resultMap.put("return_code","SUCCESS");
			resultMap.put("return_msg","OK");
		}else{
			resultMap.put("return_code","FAIL");
			resultMap.put("return_msg","FAIL");
		}
        return WXPayUtils.mapToXml(resultMap);
    }

    /**
     * 根据微信返回的xml数据获取Bean数据信息
     * @param notifyXmlData
     * @return
     */
    private WeixinPayRefundNotify getWeixinPayRefundNotifyData(String notifyXmlData){
        //1.获取未加密的数据信息
        Map<String,String> notifyMapData = WXPayUtils.xmlToMap(notifyXmlData);  //将xml数据转成Map
        val weixinPayRefundNotify = MapBeanUtils.mapToBean(notifyMapData,WeixinPayRefundNotify.class);  //将map转成bean对象

        String payType;
        if(!StringUtils.isEmpty(weixinPayRefundNotify.getSub_mch_id())){
            payType = DictionaryConstant.PAYMENT_PAY_TYPE_WXZF_SERCIE.getCode();
        }else{
            payType = DictionaryConstant.PAYMENT_PAY_TYPE_WXSM.getCode();
        }

        val mchPayChannel = mchPayChannelRepository.queryMchPayChannelByMchId(weixinPayRefundNotify.getMch_id(), payType);

        //2.获取加密的数据信息
        String notifyDetailData = notifyMapData.get("req_info");
        Map<String,String> notifyDetailMapData = WXPayUtils.xmlToMap(WXPayUtils.getRefundDecrypt(notifyDetailData,mchPayChannel.getSecretKey()));
        val weixinPayRefundNotifyDetails = MapBeanUtils.mapToBean(notifyDetailMapData,WeixinPayRefundNotify.class);
        weixinPayRefundNotifyDetails.setAppid(weixinPayRefundNotify.getAppid());
        weixinPayRefundNotifyDetails.setMch_id(weixinPayRefundNotify.getMch_id());
        weixinPayRefundNotifyDetails.setSub_mch_id(weixinPayRefundNotify.getSub_mch_id());
        BeanUtils.copyProperties(weixinPayRefundNotifyDetails,weixinPayRefundNotify);
        return weixinPayRefundNotify;
    }
}
