/*
 *  Copyright 2025-2026 R3944Realms
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package top.r3944realms.eroticdungeongame.util;

import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.fml.loading.FMLPaths;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;

/**
 * NORP Logger - 简单的日志记录工具
 * 仅在调用时检查并写入日志，自动按天轮换
 */
public class NorpLogger {

    private static final Logger LOGGER = LoggerFactory.getLogger("NorpLogger");

    // 日志文件配置
    private static final String LOG_DIR = "norp";
    private static final String LOG_FILE_PREFIX = "norp_";
    private static final String LOG_FILE_SUFFIX = ".log";
    private static final String DATE_FORMAT = "yyyy-MM-dd";
    private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss";

    // 日志级别枚举
    public enum LogLevel {
        INFO, WARNING, ERROR, DEBUG, SUCCESS
    }

    private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
    private static final DateTimeFormatter timestampFormatter = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT);
    private static final ReentrantLock lock = new ReentrantLock();

    // 当前日志文件信息缓存
    private static Path currentLogPath = null;
    private static String currentDateStr = null;

    /**
     * 私有构造函数 - 工具类不需要实例化
     */
    private NorpLogger() {}

    /**
     * 获取今天的日志文件路径
     */
    private static Path getTodayLogPath() {
        Path mcPath = FMLPaths.GAMEDIR.get();
        String today = LocalDate.now().format(dateFormatter);
        String fileName = LOG_FILE_PREFIX + today + LOG_FILE_SUFFIX;
        return mcPath.resolve(LOG_DIR).resolve(fileName);
    }

    /**
     * 确保日志目录存在
     */
    private static void ensureLogDirectoryExists() {
        try {
            Path logDir = FMLPaths.GAMEDIR.get().resolve(LOG_DIR);
            if (!Files.exists(logDir)) {
                Files.createDirectories(logDir);
            }
        } catch (IOException e) {
            LOGGER.error("Failed to create log directory", e);
        }
    }

    /**
     * 检查是否需要切换日志文件
     */
    private static boolean shouldRotateLog() {
        String today = LocalDate.now().format(dateFormatter);
        return !today.equals(currentDateStr) || currentLogPath == null;
    }

    /**
     * 获取当前应该写入的文件路径
     */
    private static Path getCurrentLogPath() {
        lock.lock();
        try {
            if (shouldRotateLog()) {
                currentDateStr = LocalDate.now().format(dateFormatter);
                currentLogPath = getTodayLogPath();
                ensureLogDirectoryExists();
            }
            return currentLogPath;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 写入日志到文件
     */
    private static void writeToFile(String content) {
        Path logPath = getCurrentLogPath();

        lock.lock();
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(
                        new FileOutputStream(logPath.toFile(), true),
                        StandardCharsets.UTF_8
                )
        )) {
            writer.write(content);
            writer.newLine();
            writer.flush();
        } catch (IOException e) {
            LOGGER.error("Failed to write to log file: {}", logPath, e);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 格式化日志消息
     */
    private static String formatMessage(String level, String message, Object... args) {
        String formattedMsg = args.length > 0 ? String.format(message, args) : message;
        return String.format("%s [%s] %s",
                LocalDateTime.now().format(timestampFormatter),
                level,
                formattedMsg);
    }

    /**
     * 记录日志（核心方法）
     */
    public static void log(String level, String message, Object... args) {
        String formattedMessage = formatMessage(level, message, args);
        writeToFile(formattedMessage);
    }

    /**
     * 使用LogLevel枚举记录日志
     */
    public static void log(LogLevel level, String message, Object... args) {
        log(level.name(), message, args);
    }

    /**
     * 记录INFO级别日志
     */
    public static void info(String message, Object... args) {
        log(LogLevel.INFO, message, args);
    }

    /**
     * 记录WARNING级别日志
     */
    public static void warning(String message, Object... args) {
        log(LogLevel.WARNING, message, args);
    }

    /**
     * 记录ERROR级别日志
     */
    public static void error(String message, Object... args) {
        log(LogLevel.ERROR, message, args);
    }

    /**
     * 记录DEBUG级别日志
     */
    public static void debug(String message, Object... args) {
        log(LogLevel.DEBUG, message, args);
    }

    /**
     * 记录SUCCESS级别日志
     */
    public static void success(String message, Object... args) {
        log(LogLevel.SUCCESS, message, args);
    }

    /**
     * 记录NORP事件
     */
    public static void logNorpEvent(String playerName, String info, String result) {
        info("NORP Event - Player: %s, Info: %s, Result: %s", playerName, info, result);
    }

    public static void logNorpSuccess(@NotNull Player player) {
        logNorpSuccess(
                player.getName().getString(),
                String.format("Pos: %s Near Players: [%s]", player.getOnPos(), player.level().getEntitiesOfClass(Player.class, AABB.ofSize(player.getOnPos().getCenter(), 10d, 10d, 10d), i -> Objects.equals(player.getUUID(), i.getUUID())).stream().map(Entity::toString).toList())
        );
    }

    /**
     * 记录NORP成功
     */
    public static void logNorpSuccess(String playerName, String info) {
        success("NORP Success - Player: %s, Info: %s", playerName, info);
    }

    /**
     * 记录带标题的分隔线
     */
    public static void logSeparator(String title) {
        String separator = "════════════════════════════════════════════";
        info("%s %s %s", separator, title, separator);
    }

    /**
     * 记录空行
     */
    public static void logEmptyLine() {
        writeToFile("");
    }

    /**
     * 获取当前日志文件路径
     */
    public static Path getCurrentLogFilePath() {
        return getCurrentLogPath();
    }

    /**
     * 检查指定日期的日志文件是否存在
     */
    public static boolean logExistsForDate(LocalDate date) {
        String fileName = LOG_FILE_PREFIX + date.format(dateFormatter) + LOG_FILE_SUFFIX;
        Path logPath = FMLPaths.GAMEDIR.get().resolve(LOG_DIR).resolve(fileName);
        return Files.exists(logPath);
    }
}
