package com.salesforce.httpclient;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.salesforce.httpclient.exception.SalesForceApiException;
import net.sf.json.util.JSONTokener;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class HttpClient {
    private String host = "";
    private final Logger logger = LoggerFactory.getLogger(HttpClient.class);

    public HttpClient setHost(String specifiedHost) {
        host = specifiedHost;
        return this;
    }

    public String post(String api, Map<String, String> params, String accessToken) {
        String url = getApiUri(api);
        HttpClientBuilder builder = HttpClientBuilder.create();
        CloseableHttpClient client = builder.build();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(getRequestConfig());
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
        httpPost.addHeader("Authorization", "Bearer " + accessToken);

        //装填参数
        List<NameValuePair> nvps = new ArrayList<>();
        if (params != null) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
        }
        //设置参数到请求对象中
        try {
            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nvps, "UTF-8");
            httpPost.setEntity(urlEncodedFormEntity);
        } catch (Exception e) {

        }

        return execute(client, httpPost);
    }

    public RequestConfig getRequestConfig(){
        return RequestConfig.custom()
                .setConnectionRequestTimeout(1000)   //从连接池中获取连接的超时时间
                //与服务器连接超时时间：httpclient会创建一个异步线程用以创建socket连接，此处设置该socket的连接超时时间
                .setConnectTimeout(5000)
                .setSocketTimeout(5000)               //socket读数据超时时间：从服务器获取响应数据的超时时间
                .build();
    }

    public JSONObject post(String api, Map<String, Object> params) throws Exception {
        String entityString = "";
        String url = getApiUri(api);
        logger.info("请求的URL："+url);
        HttpClientBuilder builder = HttpClientBuilder.create();
        CloseableHttpClient client = builder.build();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(getRequestConfig());
        httpPost.addHeader("Content-Type", "application/json");
        String jsonString = JSONObject.toJSONString(params);
        System.out.println(jsonString);
        StringEntity stringEntity;
            stringEntity = new StringEntity(jsonString);
            stringEntity.setContentType("text/json");
            httpPost.setEntity(stringEntity);
            CloseableHttpResponse response = client.execute(httpPost);
            try {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    entityString = EntityUtils.toString(entity, "UTF-8");
                }
            }catch (Exception e){
                e.printStackTrace();
                throw e;
            }finally {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        JSONObject responseEntityCustom = parseResponseEntityCustom(entityString);
        return responseEntityCustom;
    }

    public JSONObject postUtf8(String api, Map<String, Object> params) throws Exception {
        String entityString = "";
        //String url = getApiUri(api);
        logger.info("请求的URL："+api);
        HttpClientBuilder builder = HttpClientBuilder.create();
        CloseableHttpClient client = builder.build();
        HttpPost httpPost = new HttpPost(api);
        httpPost.setConfig(getRequestConfig());
        httpPost.addHeader("Content-Type", "application/json");
        String jsonString = JSONObject.toJSONString(params);
        System.out.println(jsonString);
        StringEntity stringEntity;
        stringEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
        //stringEntity.setContentType("text/json");
        httpPost.setEntity(stringEntity);
        CloseableHttpResponse response = client.execute(httpPost);
        try {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                entityString = EntityUtils.toString(entity, "UTF-8");
            }
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        JSONObject responseEntityCustom = parseResponseEntityCustom(entityString);
        return responseEntityCustom;
    }
    public String query(String api, String query, String accessToken) {
        String url = getQueryApiUri(api, query);
        HttpClientBuilder builder = HttpClientBuilder.create();
        CloseableHttpClient client = builder.build();
//        logger.debug("salesforce request : " + url);
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(getRequestConfig());
        httpGet.addHeader("Accept", "application/json");
        httpGet.addHeader("Content-Type", "application/json;charset=utf-8");
        httpGet.addHeader("Authorization", "Bearer " + accessToken);

        return execute(client, httpGet);
    }

    private String execute(CloseableHttpClient httpClient, HttpRequestBase httpRequest) {
        String responseEntityString = "";

        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpRequest);
            try {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    responseEntityString = EntityUtils.toString(entity, "UTF-8");
                }
            } finally {
                httpClient.close();
                response.close();
            }
        } catch (Exception e) {
            logger.debug("salesforce Exception : " + e.getMessage());
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    logger.debug("salesforce Exception : " + e.getMessage());
                }
            }
        }

//        logger.debug("salesforce response : " + responseEntityString);
        return parseResponseEntity(responseEntityString);
    }

    private String getApiUri(String api) {
        return host + "/" + api;
    }

    private String getQueryApiUri(String api, String query) {
        return host + "/" + api + "?q=" + query;
    }


    /**
     * 解析返回数据
     *
     * @param responseEntityString
     * @return
     */
    private String parseResponseEntity(String responseEntityString) {
        if (responseEntityString == null || responseEntityString.equals("")) {
            throw new SalesForceApiException("[salesforce]接口异常：无数据返回");
        }

        String responseText = "";

        // 错误信息处理
        boolean ok = false;
        try {
            JSONObject jsonObject = JSONObject.parseObject(responseEntityString);
            String accessToken = jsonObject.getString("access_token");
            if (accessToken != null && !accessToken.isEmpty()) {
                return responseEntityString;
            }

            String done = jsonObject.getString("done");
            if (done != null) {
                ok = done.equals("true");
            }

            responseText = jsonObject.getString("records");
        } catch (JSONException jsonException) {
            logger.debug("[salesforce]返回数据解析异常：" + jsonException.getMessage());
        }


        if (ok != true) {
            JSONArray jsonArray = JSON.parseArray(responseEntityString);
            JSONObject errorObject = (JSONObject) jsonArray.get(0);
            String message = errorObject.getString("message");
            logger.debug("[salesforce]接口异常：" + message);
            throw new SalesForceApiException("[salesforce]接口异常：" + message);
        }

        return responseText;
    }

    /**
     * 自定义解析返回数据
     *
     * @param responseEntityString
     * @return
     */
    private JSONObject parseResponseEntityCustom(String responseEntityString) {
        logger.debug("[salesforce]服务响应数据： "+responseEntityString);
        if (responseEntityString == null || responseEntityString.equals("")) {
            throw new SalesForceApiException("[salesforce]接口异常：无数据返回");
        }

        JSONObject responseText = null;

        // 错误信息处理
        boolean ok = false;
        try {
            JSONObject jsonObject = JSON.parseObject(responseEntityString);
            String accessToken = jsonObject.getString("access_token");
            if (accessToken != null && !accessToken.isEmpty()) {
                return jsonObject;
            }

            String done = jsonObject.getString("errcode");
            if (done != null) {
                ok = done.equals("0");
            }
            String jsonObjectString = jsonObject.getString("data");
            if(StringUtils.isBlank(jsonObjectString)){
                return null;
            }
            Object data = new JSONTokener(jsonObjectString).nextValue();
            if(data instanceof net.sf.json.JSONArray){
                JSONArray array = jsonObject.getJSONArray("data");
                if(CollectionUtils.isEmpty(array)){
                    return null;
                }
                responseText = array.getJSONObject(0);
            }else if(data instanceof net.sf.json.JSONObject){
                responseText = jsonObject.getJSONObject("data");
            }else{
                return null;
            }
        } catch (JSONException jsonException) {
            logger.debug("[salesforce]返回数据解析异常：" + jsonException.getMessage());
        }


        if (ok != true) {
            String message="";
            try{
                JSONArray jsonArray = JSON.parseArray(responseEntityString);
                JSONObject errorObject = (JSONObject) jsonArray.get(0);
                 message = errorObject.getString("message");
            }catch (JSONException e){
                JSONObject jsonObject = JSON.parseObject(responseEntityString);
                message = jsonObject.getString("errmsg");
            }
            if("成功".equals(message)){
                return null;
            }else{
                logger.error("[salesforce]接口异常：" + message);
                return null;
            }

        }

        return responseText;
    }

    public static void main(String[] args) {
    }
}
