package net.northking.cctp.element.internal.keywords;

import com.alibaba.fastjson.JSON;
import net.northking.cctp.element.core.IExecuteContext;
import net.northking.cctp.element.core.annotation.*;
import net.northking.cctp.element.core.exception.ExecuteException;
import net.northking.cctp.element.core.type.DataType;
import net.northking.cctp.element.core.type.ParamScope;
import net.northking.cctp.element.internal.protocol.http.HttpClient;
import net.northking.cctp.element.internal.protocol.http.RequestMethod;
import net.northking.cctp.element.internal.protocol.http.RequestParam;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * HTTP请求组件
 *
 * @author fengxiang.zhang
 * @since 1.0
 */
@Keywords
public class HttpRequest {

    @Autowired
    protected HttpClient rc;

    private static final Logger logger = LoggerFactory.getLogger(HttpRequest.class);

    /**
     * <p>发送http请求</p>
     * <b>组件参数说明如下：</b>
     * <b>请求类型</b>
     * <p class="p8 m0 h5">
     * GET, POST, DELETE, HEAD, OPTIONS, PUT, PATCH
     * </p>
     * <b>请求地址</b>
     * <p class="p8 m0 h5">
     * http://demo/get
     * </p>
     * <b>URL参数</b>
     * <p class="p8 m0 h5">
     * {"name1":"value1","name2":"value2"}
     * </p>
     * <b>请求头信息</b>
     * <p class="p8 m0 h5">
     * {"Content-Type":"application/json"}
     * </p>
     * <b>请求体信息</b>
     * <p class="p8 m0 h5">
     * 1、RAW格式：
     *    {"type":"RAW","content":"content"}
     * </p>
     * <b>请求超时</b>
     * <p class="p8 m0 h5">
     * 单位秒
     * </p>
     * <b>重定向类型</b>
     * <p class="p8 m0 h5">
     * 0：无重定向，1：自动重定向，2：跟随重定向
     * </p>
     * <b>代理设置</b>
     * <p class="p8 m0 h5">
     * {"host":"127.0.0.1","port":80,"username":"username","password":"password"}
     * </p>
     * <b>认证设置</b>
     * <p class="p8 m0 h5">
     * 1、Basic认证：
     *    {"scheme":"Basic","schemeParam":{"username":"user","password":"pd123"}}
     * </p>
     * @param method        Http请求类型
     * @param url           请求地址
     * @param params        URL参数
     * @param headers       请求头信息
     * @param bodySet       请求体信息
     * @param timeout       请求超时(单位秒)
     * @param redirectType  重定向类型，0（无重定向）、1（自动重定向）、2（跟随重定向）
     * @param authorization 认证设置
     * @return 请求响应结果 ->
     * {"statusCode":200, "content":responseBody, "headers":{"Content-Type":"application/json;charset=UTF-8"}}
     */
    @Keyword(alias = "HTTP请求",attributes = "1")
    @Return(name = "__response", comment = "请求响应结果", type = DataType.OBJECT)
    public Object httpRequest(
            IExecuteContext context,
            @Argument(name = "method", comment = "请求类型", type = DataType.STRING) String method,
            @Argument(name = "protocol", comment = "协议", type = DataType.STRING) String protocol,
            @Argument(name = "url", comment = "服务器地址", type = DataType.STRING) String url,
            @Argument(name = "path", comment = "请求路径", type = DataType.STRING) String path,
            @Argument(name = "params", comment = "URL参数设置", type = DataType.STRING, required = false,
                    defaultValue = "{}", notNull = false) String params,
            @Argument(name = "headers", comment = "请求头设置", type = DataType.STRING, required = false,
                    defaultValue = "{}", notNull = false) String headers,
            @Argument(name = "bodySet", comment = "请求体设置", type = DataType.STRING, required = false,
                    defaultValue = "{}", notNull = false) String bodySet,
            @Argument(name = "contentEncoding", comment = "字符集", type = DataType.STRING, required = false,
                    defaultValue = "UTF-8") String contentEncoding,
            @Argument(name = "timeout", comment = "超时时间", type = DataType.INTEGER, required = false) int timeout,
            @Argument(name = "redirectType", comment = "重定向类型", type = DataType.STRING, required = false,
                    defaultValue = "2") int redirectType,
            @Argument(name = "authorization", comment = "认证设置", type = DataType.STRING, required = false,
                    defaultValue = "{}", notNull = false) String authorization,
            @Argument(name = "result", comment = "响应结果", type = DataType.STRING, required = false,scope = ParamScope.OUTPUT,
                    defaultValue = "{}", notNull = false) String result) throws Exception {

        RequestParam requestParam = RequestParam.build()
                .setUrl((StringUtils.startsWithAny(url, "http://", "https://") ? url : protocol + "://" + url)+path)
                .setMethod(RequestMethod.from(method))
                .setContentEncoding(contentEncoding)
                .setQueryParams(JSON.parseObject(params, Map.class))
                .setHeaders(JSON.parseObject(headers, Map.class))
                .setAuthentication(JSON.parseObject(authorization, RequestParam.Authentication.class))
                .setBodySet(JSON.parseObject(bodySet, RequestParam.BodySet.class))
                .setRedirectType(redirectType)
                .setTimeout(timeout*1000);
        //https挡板特殊处理
        String paramUrl = requestParam.getUrl();
        if(paramUrl.startsWith("https://")&&paramUrl.contains("/AtuApiBaffleInfos/handleHttpMessage")){
            String replace = paramUrl.replace("https://", "http://");
            requestParam.setUrl(replace);
        }
        Object toJson = rc.executeRequest(requestParam,context).toJson();
        try {
            String outResult = result.substring(2,result.length()-1);
            if (result.contains("#{") && result.contains("}")){
                // #{} 全局变量
                context.setProjectGlobalVariable(outResult,JSON.toJSONString(toJson));
            }
            if (result.contains("${") && result.contains("}")){
                // ${} 脚本变量
                context.setVariable(outResult,JSON.toJSONString(toJson));
            }
        } catch (Exception e) {
            throw new ExecuteException("上下文参数{"+result+"}设置异常");
        }
        return toJson;
    }



}