package com.hs.admin.util;

import com.hs.admin.base.CodeMessageEnum;
import com.hs.admin.base.HsRuntimeException;
import com.hs.admin.base.Result;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
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.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 功能描述:
 *
 * @author: Mr.XIE
 * @date: 2018/9/4 18:11
 * @param:
 * @return:
 */
public class HttpUtil {


    private static final Header[] defaultHeaders = new Header[]{new BasicHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)")};


    /**
     * 封装HTTP POST方法
     *
     * @param
     * @param （如JSON串）
     * @return
     */
    public static String post(String url, String data) {
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "text/json; charset=utf-8");
        HttpResponse response = null;
        try {
            httpPost.setEntity(new StringEntity(URLEncoder.encode(data, "UTF-8")));
            response = httpClient.execute(httpPost);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String httpEntityContent = getHttpEntityContent(response);
        httpPost.abort();
        return httpEntityContent;
    }

    /**
     * 封装HTTP POST方法
     *
     * @param
     * @param
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String post(String url, Map<String, Object> paramMap) {
        HttpResponse response = null;
        HttpPost httpPost = null;
        try {
            HttpClient httpClient = HttpClients.createDefault();
            httpPost = new HttpPost(url);
            List<NameValuePair> formparams = setHttpParams(paramMap);
            UrlEncodedFormEntity param = new UrlEncodedFormEntity(formparams, "UTF-8");
            httpPost.setEntity(param);
            response = httpClient.execute(httpPost);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String httpEntityContent = getHttpEntityContent(response);
        httpPost.abort();
        return httpEntityContent;
    }

    /**
     * 封装HTTP POST方法
     *
     * @param
     * @param （如JSON串）
     * @return
     */
    public static String post(String url, Map<String, Object> paramMap, Header[] headers) {
        HttpResponse response = null;
        HttpPost httpPost = null;
        try {
            HttpClient httpClient = HttpClients.createDefault();
            httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "text/json; charset=utf-8");
            if (!ObjectUtils.isEmpty(headers)) {
                httpPost.setHeaders(headers);
            }
            List<NameValuePair> formparams = setHttpParams(paramMap);
            UrlEncodedFormEntity param = new UrlEncodedFormEntity(formparams, "UTF-8");
            httpPost.setEntity(param);
            response = httpClient.execute(httpPost);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String httpEntityContent = getHttpEntityContent(response);
        httpPost.abort();
        return httpEntityContent;
    }

    /**
     * 封装HTTP GET方法
     *
     * @param
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String get(String url) {
        return getWithHeader(url, null, "UTF8");
    }

    public static String getWithDefaultHeader(String url) {
        return getWithHeader(url, defaultHeaders, "UTF8");
    }

    public static String getWithHeader(String url, Header[] headers, String charset) {
        HttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet();
        httpGet.setHeaders(headers);
        httpGet.setURI(URI.create(url));
        HttpResponse response = null;
        try {
            response = httpClient.execute(httpGet);
        } catch (IOException e) {
            LogUtil.info("url 请求失败" + url);
        }
        String httpEntityContent = getHttpEntityContent(response, charset);
        httpGet.abort();
        return httpEntityContent;
    }

    private static String getHttpEntityContent(HttpResponse response, String charset) {
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            try {
                InputStream is = entity.getContent();
                BufferedReader br = null;
                br = new BufferedReader(new InputStreamReader(is, charset));
                String line = br.readLine();
                StringBuilder sb = new StringBuilder();
                while (line != null) {
                    sb.append(line + "\n");
                    line = br.readLine();
                }
                return sb.toString();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "";
    }

    /**
     * 封装HTTP GET方法
     *
     * @param
     * @param
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String get(String url, Map<String, Object> paramMap) {
        HttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet();
        List<NameValuePair> formparams = setHttpParams(paramMap);
        String param = URLEncodedUtils.format(formparams, "UTF-8");
        httpGet.setURI(URI.create(url + "?" + param));
        HttpResponse response = null;
        try {
            response = httpClient.execute(httpGet);
        } catch (IOException e) {
            LogUtil.error(e, String.format("调用接口（%s）异常>>>", url));
        }
        String httpEntityContent = getHttpEntityContent(response);
        httpGet.abort();
        return httpEntityContent;
    }

    /**
     * 封装HTTP PUT方法
     *
     * @param
     * @param
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String put(String url, Map<String, Object> paramMap) {
        HttpClient httpClient = HttpClients.createDefault();
        HttpPut httpPut = new HttpPut(url);
        List<NameValuePair> formparams = setHttpParams(paramMap);
        UrlEncodedFormEntity param = null;
        HttpResponse response = null;
        try {
            param = new UrlEncodedFormEntity(formparams, "UTF-8");
            httpPut.setEntity(param);
            response = httpClient.execute(httpPut);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String httpEntityContent = getHttpEntityContent(response);
        httpPut.abort();
        return httpEntityContent;
    }

    /**
     * 封装HTTP DELETE方法
     *
     * @param
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String delete(String url) {
        HttpClient httpClient = HttpClients.createDefault();
        HttpDelete httpDelete = new HttpDelete();
        httpDelete.setURI(URI.create(url));
        HttpResponse response = null;
        try {
            response = httpClient.execute(httpDelete);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String httpEntityContent = getHttpEntityContent(response);
        httpDelete.abort();
        return httpEntityContent;
    }

    /**
     * 设置请求参数
     *
     * @param
     * @return
     */
    private static List<NameValuePair> setHttpParams(Map<String, Object> paramMap) {
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        Set<Map.Entry<String, Object>> set = paramMap.entrySet();
        for (Map.Entry<String, Object> entry : set) {
            formparams.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
        }
        return formparams;
    }

    /**
     * 获得响应HTTP实体内容
     *
     * @param response
     * @return
     * @throws IOException
     * @throws UnsupportedEncodingException
     */
    private static String getHttpEntityContent(HttpResponse response) {
        return getHttpEntityContent(response, "UTF8");
    }


    public static String postJson(String url, String data) {
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "application/json; charset=utf-8");
        HttpResponse response = null;
        try {
            httpPost.setEntity(new StringEntity(data, "UTF-8"));
            response = httpClient.execute(httpPost);
            String httpEntityContent = EntityUtils.toString(response.getEntity());
            httpPost.abort();
            return httpEntityContent;
        } catch (Exception e) {
            LogUtil.error(e, "请求失败 url:" + url + ", data:" + data);
            throw new HsRuntimeException(CodeMessageEnum.SERVICE_ERROR.getCode(), "请求接口失败");
        }
    }

    public static HttpResponse head(String url) {
        return headWithHeader(url, null);
    }

    public static HttpResponse headWithDefaultHeader(String url) {
        return headWithHeader(url, defaultHeaders);
    }

    public static HttpResponse headWithHeader(String url, Header[] headers) {
        HttpClient httpClient = HttpClients.createDefault();
        HttpHead httpHead = new HttpHead();
        httpHead.setHeaders(headers);

        httpHead.setURI(URI.create(url));
        HttpResponse response = null;
        try {
            response = httpClient.execute(httpHead);
        } catch (IOException e) {
            LogUtil.error(e, "HttpHead 失败");
        }
        httpHead.abort();
        return response;
    }

    public static HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    public static HttpServletResponse getResponse() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
    }

    public static String getSchemeAndDomain(HttpServletRequest request) {
        return request.getScheme() + "://" + getServerName(request)
                + (request.getServerPort() == 443 || request.getServerPort() == 80
                ? "" : ":" + request.getServerPort());
    }

    public static String getServerName(HttpServletRequest request) {
        //先从attribute取
        if (request.getAttribute("targetServerNameForOverride") != null) {
            return request.getAttribute("targetServerNameForOverride").toString();
        }
        //再从param取
        String targetServerName = request.getParameter("targetServerNameForOverride");
        //param没有才用host的值
        String serverName = StringUtils.isEmpty(targetServerName) ? request.getServerName() : targetServerName;
        //写到attribute
        request.setAttribute("targetServerNameForOverride", serverName);
        return serverName;
    }

    public static String postJsonWithHead(String url, Header[] headers, String data) {
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeaders(headers);
        HttpResponse response = null;
        try {
            httpPost.setEntity(new StringEntity(data, "UTF-8"));
            response = httpClient.execute(httpPost);
            String httpEntityContent = EntityUtils.toString(response.getEntity());
            httpPost.abort();
            return httpEntityContent;
        } catch (Exception e) {
            LogUtil.error(e, "请求失败 url:" + url + ", data:" + data);
        }
        return "";
    }

    public static Header[] getBaseHeader(String token) {
        return new Header[]{
                new BasicHeader("Content-Type", "application/json; charset=utf-8"),
                new BasicHeader("token", token)
        };
    }


    private static Pattern domainPattern = Pattern.compile("http[s]?://([^#?/]*)[/?]+\\w+");

    /**
     * @Description: 获取域名
     * @params: [url]
     * @Return: java.lang.String
     * @Author: ckx
     * @Date: 2020/10/29 9:10
     * @Modified:
     */
    public static String getDomainFromUrl(String url) {
        Matcher matcher = domainPattern.matcher(url);
        if (matcher.find()) {
            System.out.println(matcher.group());
            System.out.println(matcher.group(0));
            System.out.println(matcher.group(1));
            return matcher.group(1);
        }
        return null;
    }

    /**
     * @Description: 获取content-length
     * @params: [response]
     * @Return: long
     * @Author: ckx
     * @Date: 2020/10/29 11:59
     * @Modified:
     */
    public static long getContentLength(HttpResponse response) {
        Header firstHeader = response.getFirstHeader("content-length");
        if (firstHeader == null) {
            return -1;
        }
        try {
            String sizeValue = firstHeader.getValue();
            return Long.parseLong(sizeValue);
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * @Description: 页面相对路径
     * @params: [url]
     * @Return: java.lang.String
     * @Author: ckx
     * @Date: 2020/11/3 14:51
     * @Modified:
     */
    public static String getBasePath(String url) {
        if (url.contains("?")) {
            url = url.substring(0, url.indexOf("?"));
        }
        if (!url.contains("/")) {
            return url;
        }
        return url.substring(0, url.lastIndexOf("/") + 1);
    }

    private static Pattern charsetPattern = Pattern.compile("charset=([a-zA-Z0-9_\\-]+)");

    public static String postWithToken(String url, Map map, String token) {
        String result = null;
        try {
            HttpClient httpClient = HttpClients.createDefault();
            HttpPost post = new HttpPost(url);
            post.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
            post.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
            post.setEntity(new StringEntity(JsonUtils.beanToJson(map), "UTF-8"));
            HttpResponse httpResponse = null;
            httpResponse = httpClient.execute(post);
            result = EntityUtils.toString(httpResponse.getEntity());
            post.abort();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * @Description: 获取编码
     * @params: [response]
     * @Return: java.lang.String
     * @Author: ckx
     * @Date: 2020/11/9 11:22
     * @Modified:
     */
    public static String getCharset(HttpResponse response) {
        Header lastHeader = response.getFirstHeader("content-type");
        if (lastHeader == null) {
            return null;
        }
        String value = lastHeader.getValue();
        Matcher matcher = charsetPattern.matcher(value);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return "";
    }
}
