package xtools.boot.log.holder;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import xtools.base.exception.CommonException;
import xtools.boot.api.enums.BootError;
import xtools.boot.api.enums.ThreadType;
import xtools.boot.api.model.dto.log.HolderLogTrack;
import xtools.boot.api.model.dto.log.LogTrack;
import xtools.core.UuidUtils;
import xtools.core.encrypt.Base64Utils;

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

/**
 * <p>Title : LogTrackHolder</p>
 * <p>Description : LogTrackHolder</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 : 2026/1/6 16:36
 */
public class LogTrackHolder {

    /**
     * 日志追踪信息
     */
    private static final ScopedValue<HolderLogTrack> LOG_TRACK_INFO = ScopedValue.newInstance();

    /**
     * 获取日志追踪保持信息
     *
     * @return 日志追踪保持信息
     */
    public static ScopedValue<HolderLogTrack> getScoped() {
        return LOG_TRACK_INFO;
    }


    /**
     * 新建主线程日志追踪信息
     *
     * @return 日志追踪信息
     */
    public static HolderLogTrack newMain() {
        ThreadType main = ThreadType.MAIN;
        return new HolderLogTrack(UuidUtils.get(), main.name(), main);
    }

    /**
     * 新建线程日志追踪信息
     *
     * @param mainLogTrack 主线程日志追踪信息
     * @return 日志追踪信息
     */
    public static HolderLogTrack newThread(LogTrack mainLogTrack) {
        HolderLogTrack holderLogTrack = new HolderLogTrack(mainLogTrack.traceId(), mainLogTrack.id(), ThreadType.THREAD);
        holderLogTrack.setSave(mainLogTrack.save());
        return holderLogTrack;
    }

    /**
     * 新建 Holder 日志追踪信息
     *
     * @param logTrack 日志追踪信息
     * @return 日志追踪信息
     */
    public static HolderLogTrack newHolderLogTrack(LogTrack logTrack) {
        HolderLogTrack holderLogTrack = new HolderLogTrack(logTrack.traceId(), logTrack.parentId(), logTrack.type(), logTrack.index());
        holderLogTrack.setSave(logTrack.save());
        return holderLogTrack;
    }

    /**
     * 新建 Holder 日志追踪信息
     *
     * @param base64 日志追踪信息
     * @return 日志追踪信息
     */
    public static HolderLogTrack newByBase64(String base64) {
        String log = Base64Utils.decodeToStr(base64.getBytes(StandardCharsets.UTF_8));
        LogTrack logTrack = JSONObject.parseObject(log, LogTrack.class);
        return newThread(logTrack);
    }

    /**
     * 获取日志追踪信息
     *
     * @return 日志追踪信息
     */
    public static LogTrack get() {
        Instant now = Instant.now();
        return packageLogTrack(now, getHolder());
    }

    /**
     * 获取日志追踪信息
     *
     * @return 日志追踪信息
     */
    public static LogTrack getDefNull() {
        Instant now = Instant.now();
        HolderLogTrack holder = getHolderDefNull();
        if (Objects.isNull(holder)) {
            return null;
        }
        return packageLogTrack(now, holder);
    }

    /**
     * 获取新建Main日志追踪信息
     *
     * @return 新建Main日志追踪信息
     */
    public static LogTrack getNewMain() {
        Instant now = Instant.now();
        return packageLogTrack(now, newMain());
    }

    /**
     * 包装日志追踪信息
     *
     * @param now    时间
     * @param holder 日志追踪信息
     * @return 日志追踪信息
     */
    private static LogTrack packageLogTrack(Instant now, HolderLogTrack holder) {
        holder.getCount().getAndIncrement();
        return new LogTrack(
                UuidUtils.get(),
                now.toEpochMilli(),
                holder.getTraceId(),
                holder.getParentId(),
                holder.getType(),
                holder.getCount().get(),
                holder.isSave()
        );
    }

    /**
     * 获取日志追踪信息
     *
     * @return 日志追踪信息
     */
    public static String getBase64() {
        LogTrack logTrack = getDefNull();
        return getBase64(logTrack);
    }

    /**
     * 获取日志追踪信息
     *
     * @param logTrack 日志追踪信息
     * @return 日志追踪信息
     */
    public static String getBase64(LogTrack logTrack) {
        if (Objects.isNull(logTrack)) {
            return null;
        }
        String logTxt = JSONObject.toJSONString(logTrack, JSONWriter.Feature.IgnoreEmpty);
        return Base64Utils.encodeToStr(logTxt.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 是否保存日志
     *
     * @param save true 保存日志, false 不保存日志
     */
    public static void saveLog(boolean save) {
        getHolder().setSave(save);
    }

    /**
     * 获取 Holder 日志追踪信息
     *
     * @return Holder 日志追踪信息
     */
    private static HolderLogTrack getHolder() {
        if (!LOG_TRACK_INFO.isBound()) {
            throw CommonException.create(BootError.LOG_HOLDER);
        }
        return LOG_TRACK_INFO.get();
    }

    /**
     * 获取 Holder 日志追踪信息
     *
     * @return Holder 日志追踪信息
     */
    private static HolderLogTrack getHolderDefNull() {
        if (!LOG_TRACK_INFO.isBound()) {
            return null;
        }
        return LOG_TRACK_INFO.get();
    }

}
