package cn.iocoder.yudao.framework.http.core;

import cn.iocoder.yudao.framework.http.collection.MapUtils;
import cn.iocoder.yudao.framework.http.util.StrUtils;
import lombok.Getter;
import lombok.Setter;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSocketFactory;
import java.io.File;
import java.util.*;

/**
 * 请求所需要参数
 *
 * @author Erwin Feng
 * @since 2022-11-18
 */
@Getter
@Setter
public class Request {
    private static final String PARAM_DEFAULT_KEY = "__default__";
    /**
     * 请求地址
     */
    private String url;
    /**
     * 请求方式
     */
    private Method method;
    /**
     * 请求参数
     */
    @Getter
    private Map<String, Object> param;
    private ParamFormat paramFormat = ParamFormat.STRING;
    private List<FileBo> fileList;
    /**
     * 请求工具
     */
    private Util util = Util.OkHttp;

    public enum ParamFormat {
        STRING, FORM, JSON
    }
    /**
     * 请求方法枚举
     */
    public enum Method {
        GET, POST, PUT, PATCH, DELETE
    }
    /**
     * 请求工具枚举
     */
    public enum Util {
        // JDK,
        OkHttp,
        // AsyncHttpClient
    }
    /**
     * 日志级别枚举
     */
    public enum LogLevel {

        DEBUG, INFO, ERROR
    }
    /**
     * 创建 Request
     *
     * @param url    请求地址
     * @param method 请求方法
     * @param param  请求参数
     * @return Request
     */
    public static Request create(String url, Method method, String param) {
        Request request = new Request();
        request.setUrl(url);
        request.setMethod(method);
        request.setParam(param);
        return request;
    }
    /**
     * 创建 Request
     *
     * @param url    请求地址
     * @param method 请求方法
     * @param param  请求参数
     * @return Request
     */
    public static Request create(String url, Method method, Map<String, Object> param) {
        Request request = new Request();
        request.setUrl(url);
        request.setMethod(method);
        request.setParam(param);
        return request;
    }

    /**
     * 请求可选参数
     */
    @Getter
    @Setter
    public static class Option {
        /**
         * 连接超时时间，秒，默认5秒
         */
        private Integer connectTimeoutSecond = 5;
        /**
         * 读取超时时间，秒，默认45秒
         */
        private Integer readTimeoutSecond = 45;
        /**
         * 请求头
         */
        private Map<String, String> headers = new HashMap<>();
        /**
         * ssl
         */
        private SSLSocketFactory sslContextFactory;
        /**
         * HostnameVerifier
         */
        private HostnameVerifier hostnameVerifier;
        /**
         * 日志级别
         */
        private LogLevel logLevel;

        /**
         * 创建 Request.Option
         *
         * @param connectTimeoutSecond 连接超时时间，秒
         * @param readTimeoutSecond    读取超时时间，秒
         * @return Request.Option
         */
        public static Option create(Integer connectTimeoutSecond, Integer readTimeoutSecond) {
            Option option = new Option();
            Optional.ofNullable(connectTimeoutSecond).ifPresent(option::setConnectTimeoutSecond);
            Optional.ofNullable(readTimeoutSecond).ifPresent(option::setReadTimeoutSecond);
            return option;
        }
        /**
         * 创建 Request.Option
         *
         * @param connectTimeoutSecond 连接超时时间，秒
         * @param readTimeoutSecond    读取超时时间，秒
         * @param headers              http headers
         * @return Request.Option
         */
        public static Option create(Integer connectTimeoutSecond, Integer readTimeoutSecond, Map<String, String> headers) {
            Option option = new Option();
            Optional.ofNullable(connectTimeoutSecond).ifPresent(option::setConnectTimeoutSecond);
            Optional.ofNullable(readTimeoutSecond).ifPresent(option::setReadTimeoutSecond);
            Optional.ofNullable(headers).ifPresent(option::setHeaders);
            return option;
        }

    }
    public Request setParam(String param) {
        if (StrUtils.isNotBlank(param)) {
            Map<String, Object> map = new HashMap<>();
            map.put(PARAM_DEFAULT_KEY, param);
            this.param = map;
        }
        return this;
    }
    public Request setParam(Map<String, Object> map) {
        this.param = map;
        return this;
    }
    public Request bak(Map<String, Object> map) {
        if (MapUtils.isEmpty(map)) {
            return this;
        }
        StringJoiner stringJoiner = new StringJoiner("&", "", "");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (StrUtils.isNotBlank(entry.getKey())) {
                stringJoiner.add(entry.getKey() + "=" + entry.getValue());
            }
        }
        String param = stringJoiner.toString();
        return setParam(param);
    }


    public static class MediaConstant {
        /**
         * application/json
         */
        public static final String APPLICATION_JSON_VALUE = "application/json";
        /**
         * application/...form...
         */
        public static final String APPLICATION_FORM_VALUE = "application/x-www-form-urlencoded";
    }

    @Getter
    @Setter
    public static class FileBo {
        private String paramName = "file";
        private String fileName;
        private File file;
    }
}