package com.house365.ws.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.house365.rest.exception.ServiceException;
import com.house365.web.util.MemoryPropertyPlaceholderConfigurer;
import com.house365.web.util.StringUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
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.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
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.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author jay
 */
public class HttpUtil {

    private static final Logger logger = LoggerFactory.getLogger("HttpUtil");
    private static final String DEFAULT_ENCODING = "UTF-8";


    public static String getToken(String secret) {
        //获取acceToken接口URl
        String getAccessTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
        List<NameValuePair> tokenInParam = new ArrayList<>();
        String cropId = MemoryPropertyPlaceholderConfigurer.getContextProperty("WECHAT.CROP_ID");
//        String secret = MemoryPropertyPlaceholderConfigurer.getContextProperty("WECHAT.IM.SECRET");
        tokenInParam.add(new BasicNameValuePair("corpid", cropId));
        tokenInParam.add(new BasicNameValuePair("corpsecret", secret));
        List<String> newTokenParams = new ArrayList<>();
        Map<String, String> tokenMap = new HashMap<>(5);
        for (NameValuePair pair : tokenInParam) {
            newTokenParams.add(pair.getName() + "=" + pair.getValue());
        }
        String newTokenUrl = getAccessTokenUrl + "?" + Joiner.on("&").join(newTokenParams);
        String tokenResult = "";
        try {
            tokenResult = HttpUtil.getHttpRequest(newTokenUrl, tokenMap, 100000, "utf-8");
            if (Strings.isNullOrEmpty(tokenResult)) {
                throw new ServiceException("获取imtoken失败");
            }
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> map = mapper.readValue(tokenResult, Map.class);
            int code = Integer.parseInt(map.get("errcode").toString());
            if (code == 0) {
                String token = map.get("access_token").toString();
                return token;
            } else {
                logger.error("获取imtoken失败");
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 新post请求
     * @param jsonArray
     * @param url
     * @return
     */
    public static String postWithJsonNew(JSONArray jsonArray, String url) {
        HttpPost post = null;
        try {
            HttpClient httpClient = new DefaultHttpClient();

            post = new HttpPost(url);
            // 构建消息实体
            StringEntity entity = new StringEntity(jsonArray.toString(), "UTF-8");
            // 发送Json格式的数据请求
            entity.setContentType("application/json");
            post.setEntity(entity);

            HttpResponse response = httpClient.execute(post);

            // 检验返回码
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity httpEntity = response.getEntity();
            String body = null;
            if (httpEntity != null && statusCode == HttpStatus.SC_OK) {
                if (StringUtils.isNotBlank(DEFAULT_ENCODING)) {
                    body = EntityUtils.toString(httpEntity, DEFAULT_ENCODING);
                } else {
                    body = EntityUtils.toString(httpEntity, DEFAULT_ENCODING);
                }
                EntityUtils.consume(httpEntity);
            }
            return body;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (post != null) {
                try {
                    post.releaseConnection();
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static String postWithJson(JSONObject jsonObj, String url, String token) {
        HttpPost post = null;
        try {
            HttpClient httpClient = new DefaultHttpClient();

            post = new HttpPost(url);
            // 构造消息头
            post.setHeader("access_token", token);

            // 构建消息实体
            StringEntity entity = new StringEntity(jsonObj.toString(), Charset.forName("UTF-8"));
            entity.setContentEncoding("UTF-8");
            // 发送Json格式的数据请求
            entity.setContentType("application/json");
            post.setEntity(entity);

            HttpResponse response = httpClient.execute(post);

            // 检验返回码
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity httpEntity = response.getEntity();
            String body = null;
            if (httpEntity != null && statusCode == HttpStatus.SC_OK) {
                if (org.apache.commons.lang3.StringUtils.isNotBlank(DEFAULT_ENCODING)) {
                    body = EntityUtils.toString(httpEntity, DEFAULT_ENCODING);
                } else {
                    body = EntityUtils.toString(httpEntity, DEFAULT_ENCODING);
                }
                EntityUtils.consume(httpEntity);
            }
            return body;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (post != null) {
                try {
                    post.releaseConnection();
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 新:get请求
     *
     * @param url
     * @param timeOut
     * @param charSet
     * @return
     * @throws IOException
     */
    public static String getHttpRequest(String url, Map<String, String> map, int timeOut, String charSet) throws IOException {

        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse httpResponse = null;
        long beginTime = System.currentTimeMillis();
        try {
            HttpGet httpGet = new HttpGet();
            URIBuilder builder = new URIBuilder(url);
            httpGet.setURI(builder.build());
            if (StringUtils.isNotBlank(map.get("version"))) {
                httpGet.addHeader("version", "v3.0");
            }
            if (StringUtils.isNotBlank(map.get("access-token"))) {
                httpGet.addHeader("access-token", map.get("access-token"));
            }
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeOut).setConnectTimeout(timeOut).build();//设置请求和传输超时时间
            httpGet.setConfig(requestConfig);
            httpResponse = httpClient.execute(httpGet);
            HttpEntity httpEntity = httpResponse.getEntity();

            String body = null;
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK && httpEntity != null) {
                if (StringUtils.isNotBlank(charSet)) {
                    body = EntityUtils.toString(httpEntity, charSet);
                } else {
                    body = EntityUtils.toString(httpEntity, DEFAULT_ENCODING);
                }
                EntityUtils.consume(httpEntity);
            }
            if (logger.isInfoEnabled()) {
                logUrlInfo(beginTime, url);
            }
            return body;
        } catch (Exception e) {
            logger.error(e.toString(), e);
        } finally {
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    logger.error(e.toString(), e);
                }
            }

            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    logger.error(e.toString(), e);
                }
            }
        }
        return null;
    }

    private static void logUrlInfo(long beginTime, String url) {
        if (System.currentTimeMillis() - beginTime > 1000) {
            logger.info("call url [{}] , use [{}] ms", url, System.currentTimeMillis() - beginTime);
        }
    }
}
