package com.propertyManagement.pay.support.pay.wx;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.propertyManagement.common.utils.StringUtils;
import com.propertyManagement.pay.domain.CmsPayApp;
import com.propertyManagement.pay.support.pay.CmsPayMerchantDto;
import com.propertyManagement.pay.support.pay.ICmsUnipayProvider;
import com.propertyManagement.pay.support.pay.PayChannelDto;
import com.siashan.unipay4j.biz.PayBiz;
import com.siashan.unipay4j.biz.PayBizUtil;
import com.siashan.unipay4j.core.PayChannel;
import com.siashan.unipay4j.core.pay.*;
import com.siashan.unipay4j.core.transfer.ITransfer;
import com.siashan.unipay4j.wx.WxPayConfig;
import com.siashan.unipay4j.wx.WxPayFactory;
import com.siashan.unipay4j.wx.conf.WxApp;
import com.siashan.unipay4j.wx.conf.WxMchConfig;
import org.springframework.beans.BeanUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CmsWxPayProvider implements ICmsUnipayProvider {


    private static Map<String, WxPayConfInfo> mchMap = new HashMap<>();


    public static void init(PayChannelDto channelDto) {
        List<CmsPayMerchantDto> merchantList = channelDto.getMerchantList();
        if (CollUtil.isNotEmpty(merchantList)) {
            for (CmsPayMerchantDto merchant : merchantList) {
                WxPayConfInfo wxPayConfInfo = new WxPayConfInfo();
                WxMchConfig wxMchConfig = initWxMchConfig(merchant);
                wxPayConfInfo.setMchConfig(wxMchConfig);

                List<CmsPayApp> appList = merchant.getAppList();
                if (CollUtil.isNotEmpty(appList)) {
                    Map<String, WxApp> appMap = new HashMap<>();
                    for (CmsPayApp payApp : appList) {
                        WxApp app = new WxApp();
                        BeanUtils.copyProperties(payApp, app);
                        appMap.put(payApp.getAppCode(), app);
                    }
                    wxPayConfInfo.setAppMap(appMap);
                }
                mchMap.put(merchant.getMerchantCode(), wxPayConfInfo);
            }
        }
    }


    private static WxMchConfig initWxMchConfig(CmsPayMerchantDto merchant) {
        WxMchConfig wxMchConfig = JSON.parseObject(merchant.getMerchantConfig(), WxMchConfig.class);
        return wxMchConfig;
    }


    /**
     * 获取支付对象
     *
     * @param mchCode 商户code
     * @param appCode 应用code
     * @param bizCode 业务代码
     * @return 支付类
     */
    @Override
    public IPayment getPayment(Long orderId, Map<String, PayBiz> bizMap, String mchCode, String appCode, String bizCode) {
        WxPayConfInfo wxPayConfInfo = mchMap.get(mchCode);
        Map<String, WxApp> appMap = wxPayConfInfo.getAppMap();
        WxApp wxApp = appMap.get(appCode);
        return new WxPayFactory().getPayment(wxApp.getTradeType(), initPayConfig(orderId, mchCode, wxPayConfInfo.getMchConfig(), wxApp, PayBizUtil.getPayNotifyUrl(bizMap, bizCode)));
    }

    @Override
    public IQuery getQuery(Map<String, PayBiz> bizMap, String mchCode, String appCode, String bizCode) {
        WxPayConfInfo wxPayConfInfo = mchMap.get(mchCode);
        Map<String, WxApp> appMap = wxPayConfInfo.getAppMap();
        WxApp wxApp = appMap.get(appCode);
        return new WxPayFactory().getQuery(initPayConfig(null, mchCode, wxPayConfInfo.getMchConfig(), wxApp, PayBizUtil.getPayNotifyUrl(bizMap, bizCode)));
    }

    @Override
    public IClose getClose(Map<String, PayBiz> bizMap, String mchCode, String appCode, String bizCode) {
        WxPayConfInfo wxPayConfInfo = mchMap.get(mchCode);
        Map<String, WxApp> appMap = wxPayConfInfo.getAppMap();
        WxApp wxApp = appMap.get(appCode);
        return new WxPayFactory().getClose(initPayConfig(null, mchCode, wxPayConfInfo.getMchConfig(), wxApp, PayBizUtil.getPayNotifyUrl(bizMap, bizCode)));
    }

    @Override
    public IRefund getRefund(Long orderId, Map<String, PayBiz> bizMap, String mchCode, String appCode, String bizCode) {
        WxPayConfInfo wxPayConfInfo = mchMap.get(mchCode);
        Map<String, WxApp> appMap = wxPayConfInfo.getAppMap();
        WxApp wxApp = appMap.get(appCode);
        return new WxPayFactory().getRefund(initPayConfig(orderId, mchCode, wxPayConfInfo.getMchConfig(), wxApp, PayBizUtil.getRefundNotifyUrl(bizMap, bizCode)));
    }

    @Override
    public INotify getNotify(String mchCode, String appCode) {
        WxPayConfInfo wxPayConfInfo = mchMap.get(mchCode);
        Map<String, WxApp> appMap = wxPayConfInfo.getAppMap();
        WxApp wxApp = appMap.get(appCode);
        return new WxPayFactory().getNotify(initPayConfig(null, mchCode, wxPayConfInfo.getMchConfig(), wxApp, null));
    }

    @Override
    public ITransfer getTransfer(String mchCode, String appCode) {
        WxPayConfInfo wxPayConfInfo = mchMap.get(mchCode);
        Map<String, WxApp> appMap = wxPayConfInfo.getAppMap();
        WxApp wxApp = appMap.get(appCode);
        return new WxPayFactory().getTransfer(initPayConfig(null, mchCode, wxPayConfInfo.getMchConfig(), wxApp, null));
    }


    private static WxPayConfig initPayConfig(Long orderId, String mchCode, WxMchConfig wxMchConfig, WxApp wxApp, String notifyUrl) {
        WxPayConfig wxPayConfig = new WxPayConfig();
        // set mch config
        wxPayConfig.setMchId(wxMchConfig.getMchId());
        wxPayConfig.setKey(wxMchConfig.getKey());
        wxPayConfig.setV3Key(wxMchConfig.getV3Key());
        wxPayConfig.setCertPath(wxMchConfig.getCertPath());
        wxPayConfig.setSignType(wxMchConfig.getSignType());
        wxPayConfig.setMerchantPrivateKeyPath(wxMchConfig.getMerchantPrivateKeyPath());
        wxPayConfig.setMerchantSerialNumber(wxMchConfig.getMerchantSerialNumber());
        wxPayConfig.setRsaPubKey(wxMchConfig.getRsaPubKey());
        wxPayConfig.setVersion(wxMchConfig.getVersion());
        // set appId
        wxPayConfig.setAppId(wxApp.getAppId());
        // set notifyUrl
        if (StringUtils.isNotEmpty(notifyUrl)) {
            notifyUrl = notifyUrl + "/" + orderId + "/" + PayChannel.WX.getCode() + "/" + mchCode + "/" + wxApp.getAppCode();
        }
        wxPayConfig.setNotifyurl(notifyUrl);
        System.out.println("notifyUrl:" + notifyUrl);
        return wxPayConfig;
    }

}
