package com.liquidnet.commons.lang.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.liquidnet.commons.lang.util.spring.RestTemplateConfig;
import com.liquidnet.commons.lang.util.spring.RestTemplateOkConfig;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;

public class HttpUtil {
    private static final RestTemplate restTemplate;

    static {
        //apache httpClient
//        restTemplate = RestTemplateConfig.getRestTemplate();
        //okhttp3 client
        restTemplate = RestTemplateOkConfig.getRestTemplate();
    }

    /**
     * get请求
     *
     * @param url
     * @param params 请求参数
     * @return
     */
    public static String get(String url, MultiValueMap<String, String> params) {
        return get(url, params, null);
    }

    /**
     * get请求
     *
     * @param url
     * @param params  请求参数
     * @param headers 请求头
     * @return
     */
    public static String get(String url, MultiValueMap<String, String> params, MultiValueMap<String, String> headers) {
        return request(url, params, headers, HttpMethod.GET);
    }

    /**
     * get请求 通过uri 解决再次编码问题
     * @param url
     * @param headers
     * @return
     */
    public static String getByUri(String url, MultiValueMap<String, String> headers) {
        UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(url);
        URI uri = uriComponentsBuilder.build(true).toUri();
        return request(uri,headers, HttpMethod.GET);
    }

    /**
     * post请求
     *
     * @param url
     * @param params 请求参数
     * @return
     */
    public static String post(String url, MultiValueMap<String, String> params) {
        return post(url, params, null);
    }

    /**
     * post请求
     *
     * @param url
     * @param params  请求参数
     * @param headers 请求头
     * @return
     */
    public static String post(String url, MultiValueMap<String, String> params, MultiValueMap<String, String> headers) {
        return request(url, params, headers, HttpMethod.POST);
    }

    public static String postJson(String url, String jsonStr) {
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
        headers.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);

        if (url == null || url.trim().isEmpty()) {
            return null;
        }

        // header
        HttpHeaders httpHeaders = new HttpHeaders();
        if (headers != null) {
            httpHeaders.addAll(headers);
        }
        HttpEntity<Object> httpEntity = new HttpEntity(jsonStr, httpHeaders);

        // 提交方式：表单、json
        Object respObj = restTemplate.postForEntity(url, httpEntity, Object.class).getBody();
        ;
        return JsonUtils.toJson(respObj);
    }

    public static String postJson(String url, String jsonStr, MultiValueMap<String, String> headers) {
        MultiValueMap<String, String> commonHeader = CollectionUtil.linkedMultiValueMapStringString();
        commonHeader.add("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
        commonHeader.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);

        if (url == null || url.trim().isEmpty()) {
            return null;
        }

        // header
        HttpHeaders httpHeaders = new HttpHeaders();
        if (commonHeader != null) {
            httpHeaders.addAll(commonHeader);
        }
        if (headers != null) {
            httpHeaders.addAll(headers);
        }

        HttpEntity<Object> httpEntity = new HttpEntity(jsonStr, httpHeaders);

        // 提交方式：表单、json
//        ResponseEntity<String> response = restTemplate.exchange(url, method, httpEntity, String.class);
        Object respObj = restTemplate.postForEntity(url, httpEntity, Object.class).getBody();
        return JsonUtils.toJson(respObj);
    }

    /**
     * josn post提交
     *
     * @param url
     * @param jsonParam
     * @return
     */
    public static JSONObject httpPost(String url, JSONObject jsonParam) {
        JSONObject rsResultObj = null;
        String result = null;

        try {
            MultiValueMap<String, String> commonHeader = CollectionUtil.linkedMultiValueMapStringString();
            commonHeader.add("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
            commonHeader.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);

            if (url == null || url.trim().isEmpty()) {
                return null;
            }

            HttpEntity<String> httpEntity = new HttpEntity(jsonParam, new HttpHeaders(commonHeader));
            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
            if (response.getStatusCodeValue() == 200) {
                result = response.getBody();
            }
        } catch (Exception e) {
            System.out.println("posturl:" + url + ", err=" + e.getMessage());
        }
        if (result != null) {
            rsResultObj = JSONObject.parseObject(result);
        }
        return rsResultObj;
    }


    /**
     * post请求
     *
     * @param url
     * @param jsonString 请求参数
     * @param headers    请求头
     * @return
     */
    public static String getRaw(String url, String jsonString, MultiValueMap<String, String> headers) {
        return requestRaw(url, jsonString, headers, HttpMethod.GET);
    }

    /**
     * post请求
     *
     * @param url
     * @param jsonString 请求参数
     * @param headers    请求头
     * @return
     */
    public static String postRaw(String url, String jsonString, MultiValueMap<String, String> headers) {
        return requestRaw(url, jsonString, headers, HttpMethod.POST);
    }

    /**
     * put请求
     *
     * @param url
     * @param params 请求参数
     * @return
     */
    public static String put(String url, MultiValueMap<String, String> params) {
        return put(url, params, null);
    }

    /**
     * put请求
     *
     * @param url
     * @param params  请求参数
     * @param headers 请求头
     * @return
     */
    public static String put(String url, MultiValueMap<String, String> params, MultiValueMap<String, String> headers) {
        return request(url, params, headers, HttpMethod.PUT);
    }

    /**
     * delete请求
     *
     * @param url
     * @param params 请求参数
     * @return
     */
    public static String delete(String url, MultiValueMap<String, String> params) {
        return delete(url, params, null);
    }

    /**
     * delete请求
     *
     * @param url
     * @param params  请求参数
     * @param headers 请求头
     * @return
     */
    public static String delete(String url, MultiValueMap<String, String> params, MultiValueMap<String, String> headers) {
        return request(url, params, headers, HttpMethod.DELETE);
    }

    /**
     * 表单请求
     *
     * @param url
     * @param params  请求参数
     * @param headers 请求头
     * @param method  请求方式
     * @return
     */
    public static String request(String url, MultiValueMap<String, String> params, MultiValueMap<String, String> headers, HttpMethod method) {
        if (params == null) {
            params = new LinkedMultiValueMap<>();
        }
        return request(url, params, headers, method, MediaType.APPLICATION_FORM_URLENCODED);
    }

    /**
     * http请求 通过uri
     * @param url
     * @param headers
     * @param method
     * @return
     */
    public static String request(URI url,MultiValueMap<String, String> headers, HttpMethod method) {
        if (url == null) {
            return null;
        }

        // header
        HttpHeaders httpHeaders = new HttpHeaders();
        if (headers != null) {
            httpHeaders.addAll(headers);
        }
        HttpEntity<Object> httpEntity = new HttpEntity(httpHeaders);

//        RestTemplate restTemplate = new RestTemplate();
        // 提交方式：表单、json
        ResponseEntity<String> response = restTemplate.exchange(url, method, httpEntity, String.class);
        return response.getBody();
    }

    /**
     * 表单请求Raw
     *
     * @param url     请求地址
     * @param params  请求参数
     * @param headers 请求头
     * @param method  请求方式
     * @return
     */
    public static String requestRaw(String url, String params, MultiValueMap<String, String> headers, HttpMethod method) {
        if (params == null) {
            params = "";
        }
        return requestRaw(url, params, headers, method, MediaType.APPLICATION_JSON);
    }

    /**
     * http请求
     *
     * @param url
     * @param params    请求参数
     * @param headers   请求头
     * @param method    请求方式
     * @param mediaType 参数类型
     * @return
     */
    public static String request(String url, Object params, MultiValueMap<String, String> headers, HttpMethod method, MediaType mediaType) {
        if (url == null || url.trim().isEmpty()) {
            return null;
        }

        // header
        HttpHeaders httpHeaders = new HttpHeaders();
        if (headers != null) {
            httpHeaders.addAll(headers);
        }
        HttpEntity<Object> httpEntity = new HttpEntity(params, httpHeaders);

//        RestTemplate restTemplate = new RestTemplate();
        // 提交方式：表单、json
        ResponseEntity<String> response = restTemplate.exchange(url, method, httpEntity, String.class);
        return response.getBody();
    }

    public static String requestRaw(String url, Object params, MultiValueMap<String, String> headers, HttpMethod method, MediaType mediaType) {
        if (url == null || url.trim().isEmpty()) {
            return null;
        }

        // header
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
        httpHeaders.set("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
        if (headers != null) {
            httpHeaders.addAll(headers);
        }
        // 提交方式：表单、json
        ResponseEntity<String> response = null;
        HttpEntity httpEntity = new HttpEntity(params, httpHeaders);
        if (HttpMethod.POST == method) {
            response = restTemplate.postForEntity(url, httpEntity, String.class);
        } else if (HttpMethod.GET == method) {
            Map<String,Object> map = JSON.parseObject(params.toString());
            response = restTemplate.exchange(url,method,httpEntity,String.class,map);
        }
        return response.getBody();
    }


    private static final String PHP_API_KEY = "R7tXY9smPQPG9Ku5yI0u6sfnlckmk04V";

    public static String postToPhpApi(String url, MultiValueMap<String, String> params) {
        params.add("sign", processForPhpApi(params).concat("&key=").concat(PHP_API_KEY).toUpperCase());
        return post(url, params, null);
    }

    private static String processForPhpApi(MultiValueMap<String, String> map) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, List<String>> entry : map.entrySet()) {
            sb.append(entry.getKey()).append("=").append(entry.getValue().get(0)).append("&");
        }
        String targetStr = sb.substring(0, sb.length() - 1);
        try {
            targetStr = URLDecoder.decode(targetStr, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        targetStr = targetStr.replace("%3D", "=").replace("%26", "&");
        return targetStr;
    }

    public static void main(String[] args) {
        String s = HttpUtil.get("www.baidu.com", null);
        System.out.println(s);
    }
}
