package com.younike.common.wxpay.service;

import com.younike.common.wxpay.config.Configure;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.List;

import static com.younike.common.wxpay.sdk.WXPayConstants.USER_AGENT;

@Service
public class WechatPayService {

    RestTemplate restTemplate = new RestTemplate();

    @Value("${wechatpay.unified-order-url}")
    private String unifiedOrderUrl;
    @Value("${wechatpay.order-query-url}")
    private String orderQueryUrl;
    @Value("${wechatpay.refund-query-url}")
    private String refundQueryUrl;
    @Value("${wechatpay.close-order-url}")
    private String closeOrderUrl;
    @Value("${wechatpay.refund-url}")
    private String refundUrl;
    @Value("${wechatpay.transfers-url}")
    private String transfersUrl;

    @Value("${wechatpay.mchid}")
    private String mchid;
    @Value("${wechatpay.certpath}")
    private String certpath;

    @Resource
    Configure configure;

    /**
     * 微信支付统一下单接口
     * @return
     */
    public String unifiedorder(String paraMap) {
       return weChatAPI(paraMap,unifiedOrderUrl);
    }

    /**
     * 微信支付统一查询订单接口
     * @return
     */
    public String orderQuery(String paraMap) {
        return weChatAPI(paraMap,orderQueryUrl);
    }

    /**
     * 微信支付退款接口
     * @return
     */
    public String refund(String paraMap) {
        return weChatAPI(paraMap,refundUrl);
    }

    /**
     * 微信支付统一查询退款接口
     * @return
     */
    public String refundQuery(String paraMap) {
        return weChatAPI(paraMap,refundQueryUrl);
    }

    /**
     * 微信支付统一关闭订单接口
     * @return
     */
    public String closeOrder(String paraMap) {
        return weChatAPI(paraMap,closeOrderUrl);
    }

    /**
     * 微信支付统一API请求接口
     * @return
     */
    public String weChatAPI(String paraMap, String apiUrl) {
        List<HttpMessageConverter<?>> converterList=restTemplate.getMessageConverters();
        HttpMessageConverter<?> converterTarget = null;
        for (HttpMessageConverter<?> item : converterList) {
            if (item.getClass() == StringHttpMessageConverter.class) {
                converterTarget = item;
                break;
            }
        }
        if (converterTarget != null) {
            converterList.remove(converterTarget);
        }
        HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
        converterList.add(converter);
        String res = null;
        try {
            res = restTemplate.postForObject(apiUrl, paraMap, String.class);
        }catch (Exception e){
            System.out.println(e);
        }

        return res;
    }


    public String requestWithCert(String domain, String urlSuffix, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert) throws Exception {
        BasicHttpClientConnectionManager connManager;
        if (useCert) {
            // 证书
            char[] password = mchid.toCharArray();
            // 加载本地的证书进行https加密传输
//            File file = new File("D:\\FreshLife\\Sources\\Store\\store-payment\\src\\main\\resources\\cert\\apiclient_cert.p12");
//            FileInputStream instream = new FileInputStream(file);
            InputStream resourceAsStream = this.getClass().getResourceAsStream("/" + certpath);
            KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(resourceAsStream, password);

            // 实例化密钥库 & 初始化密钥工厂
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, password);

            // 创建 SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());

            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                    sslContext,
                    new String[]{"TLSv1"},
                    null,
                    new DefaultHostnameVerifier());

            connManager = new BasicHttpClientConnectionManager(
                    RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", sslConnectionSocketFactory)
                            .build(),
                    null,
                    null,
                    null
            );
        } else {
            connManager = new BasicHttpClientConnectionManager(
                    RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", SSLConnectionSocketFactory.getSocketFactory())
                            .build(),
                    null,
                    null,
                    null
            );
        }

        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();

        String url = "https://" + domain + urlSuffix;
        HttpPost httpPost = new HttpPost(url);

        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
        httpPost.setConfig(requestConfig);

        StringEntity postEntity = new StringEntity(data, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent", USER_AGENT + " " + mchid);
        httpPost.setEntity(postEntity);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");
    }

    /**
     * 付款给用户
     *
     * @param paraMap 帕拉图
     * @return {@link String}
     */
    public String transfers(String paraMap) {
        return weChatAPI(paraMap,transfersUrl);
    }

}
