package com.friday.custody.service.trustService.cmsc.utils;

import cfca.sadk.algorithm.common.Mechanism;
import cfca.sadk.lib.crypto.JCrypto;
import cfca.sadk.lib.crypto.Session;
import cfca.sadk.util.CertUtil;
import cfca.sadk.util.KeyUtil;
import cfca.sadk.util.Signature;
import cfca.sadk.x509.certificate.X509Cert;
import com.alibaba.fastjson.JSON;
import com.friday.custody.service.trustService.htsc.utils.HTSCGetDataUtil;
import com.friday.custody.dto.CmscAppSecretDTO;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.service.trustService.cmsc.dto.CMPageDto;
import com.friday.custody.utils.PullDataFailureUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 招商证券
 */

@Slf4j
@Service("httpUtil")
public class HttpUtil {

    @Value("${custody.remote.url.cmsc.cmscUrlPrefix}")
    private String url;
    @Autowired
    HTSCGetDataUtil htscGetDataUtil;

    /**
     *
     * @param requestNo 请求号 例如 1004，1005
     * @param parentPath  文件父路径
     * @param today  timestamp
     * @param businessparam  json格式的参数
     * @param returnDtoClass 用什么dto类接受参数
     * @param tenant 验权信息
     * @return
     */
    public  <T> Map<String,Object> sendMessage(CmscAppSecretDTO cmscAppSecretDTO, String requestNo, String parentPath, String today, String businessparam, Class<T> returnDtoClass, TenantEscrowAuthorizationInfoDto tenant){
        log.info("requestNo={},businessparam={}",requestNo,businessparam);

        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }

        HashMap hashMap= new HashMap();

        String pxfFilePath = parentPath + File.separator + cmscAppSecretDTO.getPxfFilePath();
        String uapUserNo = cmscAppSecretDTO.getUapUserNo();
        String uapLicenceKey = cmscAppSecretDTO.getUapLicenceKey();
        String pxfPsw = cmscAppSecretDTO.getUnzipCode();
        String companyId = cmscAppSecretDTO.getCompanyId();
        String uapServerType = cmscAppSecretDTO.getUapServerType();
        String uapRequestId = cmscAppSecretDTO.getUapRequestId();

        log.info("pxfFilePath"+pxfFilePath);

        //1.创建HttpClient对象
        try(CloseableHttpClient httpClient = HttpClients.createDefault()){
            //2.创建HttpPost对象，设置URL地址
            HttpPost httpPost = new HttpPost(url);
            //声明list集合，用来分装表单中的参数
            //要求：设置请求的地址是：http://yun.itheima.com/search?keys=java
            Header[] headers = new Header[5];
            headers[0] = new BasicHeader("uap-server-type", uapServerType);
            headers[1] = new BasicHeader("uap-request-no", requestNo);
            headers[2] = new BasicHeader("uap-user-no", uapUserNo);
            headers[3] = new BasicHeader("uap-licence-key", uapLicenceKey);
            headers[4] = new BasicHeader("uap-request-id", uapRequestId);
            httpPost.setHeaders(headers);

            try {
                X509Cert cert = CertUtil.getCertFromPFX(pxfFilePath, pxfPsw);
                PrivateKey priKey = KeyUtil.getPrivateKeyFromPFX(pxfFilePath, pxfPsw);

                String deviceName = JCrypto.JSOFT_LIB;
                JCrypto.getInstance().initialize(deviceName, null);
                Session session = JCrypto.getInstance().openSession(deviceName);

                log.info("timeStramp---->--->-->->" + today);
                // 待签名消息
                String waitSingn = MD5Utils.MD5Upper(companyId.concat(today));
                byte[] sourceData = waitSingn.getBytes(StandardCharsets.UTF_8);
                Signature util = new Signature();
                String signAlg = Mechanism.SHA256_RSA;
                // 签名，必须指定签名算法，返回BASE64签名结果
                byte[] base64P7SignedData = util.p7SignMessageDetach(signAlg, sourceData,
                        priKey, cert, session); //使用证书和私钥进行签名
                String sign = new String(base64P7SignedData);//            StringBuffer sb = new StringBuffer();

                List<BasicNameValuePair> params = new ArrayList<>();
                params.add(new BasicNameValuePair("companyid", companyId));
                params.add(new BasicNameValuePair("timestamp", today));
                params.add(new BasicNameValuePair("signature", sign));
                params.add(new BasicNameValuePair("businessparam", businessparam));
                UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, "utf8");
                httpPost.setEntity(formEntity);
                CloseableHttpResponse response = null;
                try {
                    response = httpClient.execute(httpPost);
                    //4.解析响应，获取数据
                    //判断状态码是否是200
                    if (response==null || response.getStatusLine()==null) {
                        hashMap.put("error","statusCode为null");
                        throw new IllegalArgumentException("更新失败!");
                    }
                    if (response.getStatusLine().getStatusCode() == 200) {
                        org.apache.http.HttpEntity httpEntity = response.getEntity();
                        String content = EntityUtils.toString(httpEntity, "utf8");
                        hashMap = JSON.parseObject(content,
                                HashMap.class);
                        log.info("sendMessage调用的接口={}，使用的参数={},返回的结果={}",requestNo,businessparam,JSON.toJSONString(hashMap));

                        if(( (String)hashMap.get("resultcode")).equals("10000")){

                            htscGetDataUtil.saveInvokeRecord(tenant,tenant.getTrustNo(),requestNo,"",businessparam,hashMap);
                            String remoteData =(String) hashMap.get("data");
                            String page =(String) hashMap.get("page");
                            List<T> returnDtos = JSON.parseArray(remoteData, returnDtoClass);
                            CMPageDto cmPageDto = JSON.parseObject(page, CMPageDto.class);
                            if(returnDtos==null){
                                returnDtos = new ArrayList<>();
                            }
                            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
                            stringObjectHashMap.put("result",true);
                            stringObjectHashMap.put("data",returnDtos);
                            stringObjectHashMap.put("page",cmPageDto);
                            return stringObjectHashMap;
                        }else{
                            log.error("sendMessage_resultcode不为10000,入参="+JSON.toJSONString(params));
                        }
                    }else{
                        hashMap.put("error","statusCode为"+response.getStatusLine().getStatusCode());
                        log.error("招商调用失败：requestNo:{},param:{},response{}",requestNo,businessparam,EntityUtils.toString(response.getEntity(),"utf8"));
                    }
                } catch (Exception e) {
                    log.error("招商调用接口失败: requestNo:{},param:{},exception:{}",requestNo,businessparam,e);
                }finally {
                    try {
                        if(response!=null){
                            response.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        httpClient.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }catch (Exception e){
                log.error("招商验权失败：",e);
            }
            String trustNo = tenant.getTrustNo();
            Map<String,String> headerMap =new HashMap<>();
            headerMap.put("uap-server-type", uapServerType);
            headerMap.put("uap-request-no", requestNo);
            headerMap.put("uap-user-no", uapUserNo);
            headerMap.put("uap-licence-key", uapLicenceKey);
            headerMap.put("uap-request-id", uapRequestId);

            Map<String, Object> errorMap = PullDataFailureUtil.createErrorMap(trustNo, requestNo, JSON.toJSONString(headerMap), "appId=" + tenant.getAppKey(), hashMap);

            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            stringObjectHashMap.put("result",false);
            stringObjectHashMap.put("data",errorMap);
            return stringObjectHashMap;
        } catch (IOException e) {
            e.printStackTrace();
        }
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        stringObjectHashMap.put("result",false);
        stringObjectHashMap.put("data",null);
        return stringObjectHashMap;

    }
}
