package com.cm.common.utils.http;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: AbstractRestTemplateUtil
 * @Description:
 * @Author: wanggeng
 * @Date: 2021/3/31 12:18 下午
 * @Version: 1.0
 */
public abstract class AbstractRestTemplate<SuccessResultType, BodyType> {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractRestTemplate.class);
    private RestTemplate restTemplate;

    public AbstractRestTemplate() {
        SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
        simpleClientHttpRequestFactory.setConnectTimeout(20 * 1000);
        simpleClientHttpRequestFactory.setReadTimeout(60 * 1000);
        this.restTemplate = new RestTemplate(simpleClientHttpRequestFactory);
    }

    /**
     * 请求头
     *
     * @return
     */
    public HttpHeaders headers() {
        return new HttpHeaders();
    }

    /**
     * json请求头
     *
     * @return
     */
    public HttpHeaders jsonHeaders() {
        HttpHeaders httpHeaders = headers();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
        return httpHeaders;
    }

    public HttpHeaders formHeaders() {
        HttpHeaders httpHeaders = headers();
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        return httpHeaders;
    }

    /**
     * 请求主体
     *
     * @return
     */
    public abstract BodyType body();

    /**
     * 成功返回类型
     *
     * @return
     */
    public abstract Class<SuccessResultType> successResultType();

    /**
     * GET请求
     *
     * @param url
     */
    public void get(String url) {
        Class<SuccessResultType> successResultTypeClass = successResultType();
        if (successResultTypeClass == null) {
            LOG.error("method successResultType can not return null");
            return;
        }
        try {
            ResponseEntity<SuccessResultType> responseEntity = restTemplate.getForEntity(url, successResultTypeClass);
            SuccessResultType result = responseEntity.getBody();
            if (HttpStatus.OK.value() == responseEntity.getStatusCodeValue()) {
                success200(result);
            }
        } catch (Exception e) {
            if (e instanceof HttpClientErrorException) {
                HttpClientErrorException exception = (HttpClientErrorException) e;
                if (exception.getRawStatusCode() == HttpStatus.BAD_REQUEST.value()) {
                    error400(exception);
                    return;
                }
            }
            e.printStackTrace();
        }
    }

    /**
     * DELETE请求
     *
     * @param url
     */
    public void delete(String url) {
        Class<SuccessResultType> successResultTypeClass = successResultType();
        if (successResultTypeClass == null) {
            LOG.error("method successResultType can not return null");
            return;
        }
        try {
            ResponseEntity<SuccessResultType> responseEntity = restTemplate.exchange(url, HttpMethod.DELETE, null, successResultTypeClass);
            SuccessResultType result = responseEntity.getBody();
            if (HttpStatus.OK.value() == responseEntity.getStatusCodeValue()) {
                success200(result);
            }
        } catch (Exception e) {
            if (e instanceof HttpClientErrorException) {
                HttpClientErrorException exception = (HttpClientErrorException) e;
                if (exception.getRawStatusCode() == HttpStatus.BAD_REQUEST.value()) {
                    error400(exception);
                    return;
                }
            }
            e.printStackTrace();
        }
    }

    /**
     * POST提交FORM
     *
     * @param url
     */
    public void post(String url) {
        post(url, false);
    }

    /**
     * POST提交JSON
     *
     * @param url
     */
    public void postJson(String url) {
        post(url, true);
    }

    /**
     * put
     *
     * @param url
     */
    public void put(String url) {
        post(url, true);
    }

    private void post(String url, boolean isJson) {
        BodyType bodyType = body();
        Class<SuccessResultType> successResultTypeClass = successResultType();
        if (bodyType == null) {
            LOG.error("method postBody can not return null");
            return;
        }
        if (successResultTypeClass == null) {
            LOG.error("method successResultType can not return null");
            return;
        }
        try {
            HttpEntity<BodyType> httpEntity = new HttpEntity<>(bodyType, isJson ? jsonHeaders() : formHeaders());
            ResponseEntity<SuccessResultType> responseEntity = restTemplate.postForEntity(url, httpEntity, successResultTypeClass);
            SuccessResultType result = responseEntity.getBody();
            if (HttpStatus.OK.value() == responseEntity.getStatusCodeValue()) {
                success200(result);
            }
        } catch (Exception e) {
            if (e instanceof HttpClientErrorException) {
                HttpClientErrorException exception = (HttpClientErrorException) e;
                if (exception.getRawStatusCode() == HttpStatus.BAD_REQUEST.value()) {
                    error400(exception);
                    return;
                }
            }
            e.printStackTrace();
        }
    }

    /**
     * 成功结果
     *
     * @param result
     */
    public abstract void success200(SuccessResultType result);

    /**
     * 错误
     *
     * @param error
     */
    public abstract void error400(HttpClientErrorException error);

}
