package com.fs.pay.service.impl;

import com.fs.common.config.FSSysConfig;
import com.fs.common.utils.StringUtils;
import com.fs.common.utils.spring.SpringUtils;
import com.fs.huifuPay.sdk.opps.core.BasePay;
import com.fs.huifuPay.sdk.opps.core.utils.RsaUtils;
import com.fs.pay.pay.util.PayUtil;
import com.fs.pay.service.IPayNotifyVerifyService;
import com.fs.store.domain.FsPayConfig;
import com.fs.system.domain.SysConfig;
import com.fs.system.mapper.SysConfigMapper;
import com.google.gson.Gson;
import com.hc.openapi.tool.HcClient;
import com.hc.openapi.tool.HcGateway;
import com.tzbank.util.CallBackUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class PayNotifyVerifyServiceImpl implements IPayNotifyVerifyService
{
    private static final Logger log = LoggerFactory.getLogger(PayNotifyVerifyServiceImpl.class);

    private static final String PAY_CONFIG_KEY = "store.pay";

    @Autowired
    private FSSysConfig fsSysConfig;

    @Override
    public boolean verifyYibaoCallback(Map<String, String> params)
    {
        return verifyYibaoCallback(params, null);
    }

    @Override
    public boolean verifyYibaoCallback(Map<String, String> params, String appId)
    {
        if (params == null || !params.containsKey("sign"))
        {
            return false;
        }
        String receivedSign = params.get("sign");
        if (StringUtils.isBlank(receivedSign))
        {
            return false;
        }
        FsPayConfig payConfig = loadPayConfig();
        if (payConfig == null || StringUtils.isBlank(payConfig.getYbKey()))
        {
            log.warn("易宝支付回调验签失败：未配置 ybKey");
            return false;
        }
        try
        {
            String calculatedSign = PayUtil.sign(params, payConfig.getYbKey());
            return calculatedSign != null && calculatedSign.equals(receivedSign);
        }
        catch (Exception e)
        {
            log.warn("易宝支付回调验签异常", e);
            return false;
        }
    }

    @Override
    public boolean verifyHuifuCallback(String respData, String sign)
    {
        return verifyHuifuCallback(respData, sign, null);
    }

    @Override
    public boolean verifyHuifuCallback(String respData, String sign, String appId)
    {
        if (StringUtils.isBlank(respData) || StringUtils.isBlank(sign))
        {
            return false;
        }
        List<String> publicKeys = collectHuifuPublicKeys(appId);
        if (publicKeys.isEmpty())
        {
            log.error("汇付公钥未配置");
            return false;
        }
        for (String publicKey : publicKeys)
        {
            if (verifyWithPublicKey(respData, sign, publicKey))
            {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean verifyHcPayCallback(String rawJsonBody)
    {
        if (StringUtils.isBlank(rawJsonBody))
        {
            return false;
        }
        if (StringUtils.isBlank(fsSysConfig.getPayKey()))
        {
            log.warn("小雨点支付回调验签失败：未配置 fs-config.payKey");
            return false;
        }
        try
        {
            HcClient hcClient = HcGateway.getOpenApiClientService();
            return hcClient.verificationSign(rawJsonBody, fsSysConfig.getPayKey());
        }
        catch (Exception e)
        {
            log.warn("小雨点支付回调验签异常", e);
            return false;
        }
    }

    @Override
    public String decryptTzBankCallback(String decryptForm)
    {
        if (StringUtils.isBlank(decryptForm))
        {
            return null;
        }
        FsPayConfig payConfig = loadPayConfig();
        if (payConfig == null || StringUtils.isBlank(payConfig.getAppSecret()))
        {
            log.warn("台州银行回调验签失败：未配置 appSecret");
            return null;
        }
        try
        {
            return CallBackUtil.decrypt(payConfig.getAppSecret(), decryptForm);
        }
        catch (Exception e)
        {
            log.warn("台州银行回调解密失败", e);
            return null;
        }
    }

    private List<String> collectHuifuPublicKeys(String appId)
    {
        Set<String> keys = new LinkedHashSet<>();
        FsPayConfig payConfig = loadPayConfig();
        if (payConfig != null && StringUtils.isNotBlank(payConfig.getHfRsaPublicKey()))
        {
            keys.add(payConfig.getHfRsaPublicKey());
        }
        if (StringUtils.isNotBlank(BasePay.HUIFU_DEFAULT_PUBLIC_KEY))
        {
            keys.add(BasePay.HUIFU_DEFAULT_PUBLIC_KEY);
        }
        if (StringUtils.isNotBlank(appId))
        {
            log.debug("当前项目未配置多小程序汇付公钥，appId={} 将使用默认公钥列表验签", appId);
        }
        return new ArrayList<>(keys);
    }

    private boolean verifyWithPublicKey(String respData, String sign, String publicKey)
    {
        if (StringUtils.isBlank(publicKey))
        {
            return false;
        }
        try
        {
            return RsaUtils.verify(respData, publicKey, sign);
        }
        catch (Exception e)
        {
            log.warn("汇付验签异常: {}", e.getMessage());
            return false;
        }
    }

    private FsPayConfig loadPayConfig()
    {
        SysConfigMapper sysConfigMapper = SpringUtils.getBean(SysConfigMapper.class);
        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey(PAY_CONFIG_KEY);
        if (sysConfig == null || StringUtils.isBlank(sysConfig.getConfigValue()))
        {
            return null;
        }
        return new Gson().fromJson(sysConfig.getConfigValue(), FsPayConfig.class);
    }
}
