package xtools.boot.elasticsearch.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import xtools.boot.api.exection.BizError;
import xtools.boot.api.exection.BizWarning;
import xtools.boot.core.utils.SpringContextUtils;
import xtools.boot.log.LogBus;
import xtools.boot.log.enums.LogBusBaseType;
import xtools.core.BytesUtils;
import xtools.core.CollectionUtils;
import xtools.core.StringUtils;
import xtools.core.encrypt.Base64Utils;
import xtools.core.enums.LogLevel;
import xtools.core.extend.HttpUtils;
import xtools.extend.JsonUtils;

import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * <p>Title : EsUtils</p>
 * <p>Description : EsUtils</p>
 * <p>DevelopTools : Idea_x64_v2026.1</p>
 * <p>DevelopSystem : macOS Sequoia 15.7.5</p>
 * <p>Company : org.xujun</p>
 *
 * @author : XuJun
 * @version : 5.0.0
 * @date : 2025年8月17日 下午6:24:22
 */
@Component
public class EsUtils {

    /**
     * 超时时间
     */
    private static final long TIMEOUT = 60 * 1000 * 5;

    /**
     * 查询服务器地址
     */
    private static String host;

    /**
     * 授权信息
     */
    private static String auth;


    @Value("${spring.elasticsearch.uris:#{null}}")
    private String uris;
    @Value("${spring.elasticsearch.username:#{null}}")
    private String username;
    @Value("${spring.elasticsearch.password:#{null}}")
    private String password;

    /**
     * 执行
     *
     * @param uri 执行的uri
     * @return 执行结果
     */
    public static String exec(String uri) {
        return exec(uri, null, String.class, false);
    }

    /**
     * 执行
     *
     * @param uri 执行的uri
     * @param req 请求参数
     * @return 执行结果
     */
    public static JSONObject exec(String uri, JSONObject req) {
        return exec(uri, req, JSONObject.class, false);
    }

    /**
     * 执行
     *
     * @param <T>   结果类型
     * @param uri   执行的uri
     * @param req   请求参数
     * @param clazz 结果类型
     * @param isGet 是否为get请求
     * @return 结果
     */
    public static <T> T exec(String uri, JSONObject req, Class<T> clazz, boolean isGet) {
        // 参数校验
        if (StringUtils.isBlank(uri)) {
            throw new BizWarning("uri不能为空");
        }
        if (StringUtils.isBlank(host)) {
            // 初始化
            EsUtils bean = SpringContextUtils.getBean(EsUtils.class);
            bean.init();
        }
        HttpUtils http = HttpUtils.init(host + uri).addHeader("Content-Type", "application/json").timeOut(TIMEOUT);
        if (StringUtils.isNotBlank(auth)) {
            http.addHeader("Authorization", "Basic " + auth);
        }
        http.setLogCallBack(log -> {
            byte[] resp = log.resp();
            String respData = BytesUtils.isEmpty(resp) ? null : new String(resp);
            JSONObject logData = JSONObject.of(
                    "req", log.reqParam(),
                    "resp", JsonUtils.isJson(respData) ? JSONObject.parseObject(respData) : respData,
                    "execTime", log.execTime()
            );
            Throwable error = log.error();
            // 保存日志
            LogBus.init(Objects.isNull(error) ? LogLevel.INFO : LogLevel.ERROR, LogBusBaseType.ELASTICSEARCH)
                    .data(logData)
                    .error(error)
                    .save();
        });
        // 查询结果
        String result;
        if (isGet) {
            result = http.get();
        } else {
            result = http.post(CollectionUtils.isEmpty(req) ? null : req.toString());
        }
        if (StringUtils.isBlank(result)) {
            throw new BizWarning("ES执行结果为空");
        }
        return JSON.to(clazz, result);
    }

    /**
     * 获取授权信息
     *
     * @param username 用户名
     * @param password 密码
     * @return 授权信息
     */
    private static String getAuth(String username, String password) {
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            return null;
        }
        return Base64Utils.encodeToStr((username + ":" + password).getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 初始化
     */
    public void init() {
        if (StringUtils.isNotBlank(host)) {
            return;
        }
        if (StringUtils.isBlank(uris)) {
            throw new BizError("Es工具类初始化失败, spring.elasticsearch.uris 不能为空");
        }
        EsUtils.host = uris;
        EsUtils.auth = getAuth(username, password);
    }

}
