package com.yutou.qqbot.utlis;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.RollingFileAppender;
import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy;
import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy;
import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.layout.PatternLayout;

import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class DynamicLogFile {
    // 创建一个缓存，用于存储Logger对象，最大容量为1000，过期时间为10分钟
    static Cache<String, Logger> cache = CacheBuilder.newBuilder()
            .maximumSize(1000)
            .expireAfterAccess(10, TimeUnit.MINUTES)
            .removalListener(it -> {
                if (it.wasEvicted()) {
                    if (it.getKey() != null) {
                        String loggerName = (String) it.getKey();
                        remove(loggerName, true);
                    }
                }
            })
            .build();

    // 根据loggerName获取Logger对象，如果缓存中不存在，则创建一个新的Logger对象并放入缓存
    public static Logger getLogger(String loggerName) {
        try {
            return cache.get(loggerName, () -> {
                configureLogger(loggerName);
                return LogManager.getLogger(loggerName);
            });
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    // 配置Logger对象
    private static void configureLogger(String loggerName) {

        LoggerContext context = (LoggerContext) LogManager.getContext(false);
        Configuration config = context.getConfiguration();

        // 创建日志格式
        Layout<String> layout = PatternLayout.newBuilder()
                .withPattern("%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %-5p [%thread] (%F:%L) : %m%n")
                .build();

        // 创建时间触发策略
        TimeBasedTriggeringPolicy timePolicy = TimeBasedTriggeringPolicy.newBuilder()
                .build();

        // 创建文件大小触发策略
        SizeBasedTriggeringPolicy sizePolicy = SizeBasedTriggeringPolicy.createPolicy("100 MB");

        // 创建组合触发策略
        CompositeTriggeringPolicy triggeringPolicy = CompositeTriggeringPolicy.createPolicy(timePolicy, sizePolicy);


        // 创建滚动文件Appender
        RollingFileAppender appender = RollingFileAppender.newBuilder()
                .setName(loggerName)
                .withFileName("logs" + "/" + DateFormatUtils.getInstance().format(new Date(), "yyyy-MM-dd") + "/" + loggerName + ".log")
                .withFilePattern("logs" + "/" + "%d{yyyy-MM-dd}" + "/" + loggerName + "-%i.log.gz")
                .setLayout(layout)
                .setImmediateFlush(true)
                .withAppend(true)
                .setIgnoreExceptions(false)
                .withPolicy(triggeringPolicy)
                .build();

        appender.start();
        config.addAppender(appender);

        // 获取Logger对象
        org.apache.logging.log4j.core.Logger coreLogger = context.getLogger(loggerName);
        if (coreLogger == null) {
            throw new IllegalStateException("Logger with name " + loggerName + " does not exist.");
        }

        // 将Appender添加到Logger对象中
        coreLogger.addAppender(appender);
        coreLogger.setLevel(Level.ALL);
        coreLogger.setAdditive(false);

        // 更新Logger对象
        context.updateLoggers();

    }

    // 移除Logger对象
    public static void remove(String loggerName) {
        remove(loggerName, false);
    }

    // 私有方法，移除Logger对象，isAuto参数用于判断是否是自动移除
    private static void remove(String loggerName, boolean isAuto) {
        if (!isAuto) {
            cache.invalidate(loggerName);
        }
        LoggerContext context = (LoggerContext) LogManager.getContext(false);
        Configuration config = context.getConfiguration();
        org.apache.logging.log4j.core.Logger coreLogger = context.getLogger(loggerName);
        Appender appender = config.getAppender(loggerName);
        if (appender != null) {
            appender.stop();
            coreLogger.removeAppender(appender);
        }
        config.getAppenders().remove(loggerName);
        context.updateLoggers();
    }

}
