package com.jeequan.jeepay.core.beans;

import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.service.ISysConfigService;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.Map;

/**
 * 基于spring的 req 工具类
 *
 * @author terrfly
 * @date 2021/6/7 12:16
 */
@Slf4j
@Component
public class RequestKitBean {

    @Setter(onMethod_ = @Autowired(required = false))
    protected HttpServletRequest request;   //自动注入request

    @Setter(onMethod_ = @Autowired(required = false))
    private ISysConfigService sysConfigService;

    /**
     * reqContext对象中的key: 转换好的json对象
     */
    private static final String REQ_CONTEXT_KEY_PARAMJSON = "REQ_CONTEXT_KEY_PARAMJSON";

    /**
     * JSON 格式通过请求主体（BODY）传输  获取参数
     **/
    public String getReqParamFromBody() {

        StringBuilder body = new StringBuilder();

        if (isConvertJSON()) {

            try {
                String str;
                while ((str = request.getReader().readLine()) != null) {
                    body.append(str);
                }

                return body.toString();

            } catch (Exception e) {
                log.error("请求参数转换异常！ params=[{}]", body);
                throw new BizException(ApiCodeEnum.PARAMS_ERROR, "转换异常");
            }
        } else {
            return body.toString();
        }
    }


    /**
     * request.getParameter 获取参数 并转换为JSON格式
     **/
    public JSONObject reqParam2JSON() {
        if (isConvertJSON()) {
            return getApplicationJson();
        }

        // Process parameters from request.getParameterMap()
        return getFormData();
    }

    private JSONObject getApplicationJson() {
        JSONObject returnObject = new JSONObject();
        String str = "";
        try (BufferedReader reader = request.getReader()) {
            StringBuilder body = new StringBuilder();
            while ((str = reader.readLine()) != null && !str.equals("null")) {
                body.append(str);
            }

            if (StringUtils.isEmpty(body.toString())) {
                return returnObject;
            }

            JSONObject result = JSON.parseObject(body.toString());

            // Check for encrypted data and decrypt if necessary
            if (result.size() == 1 && result.containsKey("encryptData")) {
                String encryptedData = result.getString("encryptData");
                return JSON.parseObject(sysConfigService.getHttpMessageSM4().decryptStr(encryptedData));
            }

            return result;
        } catch (Exception e) {
            log.error("请求参数转换异常！ params=[{}], error: {}", str, e.getMessage());
            throw new BizException(ApiCodeEnum.PARAMS_ERROR, "Conversion exception");
        }
    }

    private JSONObject getFormData() {
        JSONObject returnObject = new JSONObject();
        Map<String, String[]> properties = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : properties.entrySet()) {
            String name = entry.getKey();
            String[] values = entry.getValue();

            if (ArrayUtil.isNotEmpty(values)) {
                // Handle array values efficiently
                String value = String.join(",", values);
                if (!name.contains("[")) {
                    returnObject.put(name, value);
                } else {
                    String mainKey = name.substring(0, name.indexOf("["));
                    String subKey = name.substring(name.indexOf("[") + 1, name.indexOf("]"));
                    JSONObject subJson = returnObject.containsKey(mainKey)
                            ? returnObject.getJSONObject(mainKey)
                            : new JSONObject();
                    subJson.put(subKey, value);
                    returnObject.put(mainKey, subJson);
                }
            }
        }
        return returnObject;
    }


    /**
     * 获取json格式的请求参数
     **/
    public JSONObject getReqParamJSON() {

        //将转换好的reqParam JSON格式的对象保存在当前请求上下文对象中进行保存；
        // 注意1： springMVC的CTRL默认单例模式， 不可使用局部变量保存，会出现线程安全问题；
        // 注意2： springMVC的请求模式为线程池，如果采用ThreadLocal保存对象信息，可能会出现不清空或者被覆盖的问题。
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        Assert.notNull(requestAttributes, "非web环境下该参数可能为空");

        Object reqParamObject = requestAttributes.getAttribute(REQ_CONTEXT_KEY_PARAMJSON, RequestAttributes.SCOPE_REQUEST);
        if (reqParamObject == null) {
            JSONObject reqParam = reqParam2JSON();
            requestAttributes.setAttribute(REQ_CONTEXT_KEY_PARAMJSON, reqParam, RequestAttributes.SCOPE_REQUEST);
            return reqParam;
        }
        return (JSONObject) reqParamObject;
    }

    /**
     * 判断请求参数是否转换为json格式
     */
    private boolean isConvertJSON() {

        String contentType = request.getContentType();

        //有contentType  && json格式，  get请求不转换
        //application/json 需要转换为json格式；
        return contentType != null
                && contentType.toLowerCase().contains("application/json")
                && !request.getMethod().equalsIgnoreCase("GET");
    }

    /**
     * 获取客户端ip地址
     **/
    public String getClientIp() {
        String ipAddress;
        ipAddress = request.getHeader("x-forwarded-for");
        String unknown = "unknown";
        if (ipAddress == null || ipAddress.isEmpty() || unknown.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.isEmpty() || unknown.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.isEmpty() || unknown.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
        }

        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > 15 && (ipAddress.contains(","))) {
            ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));

        }
        return ipAddress;
    }

    /**
     * 贴牌获取域名
     **/
    public String getdomainName() {
        String domainName;
        domainName = request.getHeader("Referer");
        return domainName;
    }

}
