/*
 * Copyright (c) 2025 SimcuTeam. All rights reserved.
 * 遵循 MIT 许可证。
 */

package simcu::simapi.logger

import std.collection.concurrent.*
import std.env.*
import std.time.*
import soulsoft_extensions_logging.*

/**
 * SimApi 日志记录器。
 * 格式：`[ 分类 ][ 时间 ][ 级别 ]\n消息\n[异常]`
 * 按日志级别着色输出。
 */
public class SimApiLogger <: ILogger {
    private let _name: String

    public init(name: String) {
        _name = name
    }

    public func log<TState>(logLevel: LogLevel, _: EventId, state: TState, exception: ?Exception,
        _: (TState, ?Exception) -> String): Unit where TState <: ToString {
        if (!isEnabled(logLevel)) {
            return
        }

        let now = DateTime.now()
        let timeStr = formatTime(now)
        let levelStr = levelName(logLevel)

        var sb = StringBuilder()
        sb.append("${color(levelColor(logLevel))}[ ${_name} ][ ${timeStr} ][ ${levelStr} ]\n")
        sb.append("${state}\n")
        if (let Some(ex) <- exception) {
            sb.append("${ex}\n")
        }
        sb.append(resetColor())
        // message 末尾 \n 之后再补一个 \n，形成空行分隔
        sb.append("\n")

        let writer = getStdOut()
        writer.write(sb.toString())
        writer.flush()
    }

    public func isEnabled(_: LogLevel): Bool {
        true
    }

    /**
     * 级别名称。
     */
    private static func levelName(logLevel: LogLevel): String {
        match (logLevel) {
            case LogLevel.Trace => "Trace"
            case LogLevel.Debug => "Debug"
            case LogLevel.Info => "Information"
            case LogLevel.Warn => "Warning"
            case LogLevel.Error => "Error"
            case LogLevel.Fatal => "Critical"
            case _ => "None"
        }
    }

    /**
     * 级别对应 ANSI 前景色：
     * Debug→DarkMagenta, Info→DarkCyan, Warn→Yellow, Error→Red, Fatal→DarkRed, 其他→White
     */
    private static func levelColor(logLevel: LogLevel): String {
        match (logLevel) {
            case LogLevel.Debug => "35"      // DarkMagenta
            case LogLevel.Info => "36"       // DarkCyan
            case LogLevel.Warn => "33"       // Yellow
            case LogLevel.Error => "31"      // Red
            case LogLevel.Fatal => "31;1"    // DarkRed(粗体近似)
            case _ => "37"                   // White
        }
    }

    private static func color(code: String): String {
        "\u{1b}[${code}m"
    }

    private static func resetColor(): String {
        "\u{1b}[0m"
    }

    private static func formatTime(dt: DateTime): String {
        let year = dt.year
        let month = pad2(dt.monthValue)
        let day = pad2(dt.dayOfMonth)
        let hour = pad2(dt.hour)
        let minute = pad2(dt.minute)
        let second = pad2(dt.second)
        let millis = pad4(dt.nanosecond / 100000)
        "${year}-${month}-${day} ${hour}:${minute}:${second}:${millis}"
    }

    private static func pad2(v: Int64): String {
        if (v < 10) {
            return "0${v}"
        }
        "${v}"
    }

    private static func pad4(v: Int64): String {
        if (v < 10) {
            return "000${v}"
        }
        if (v < 100) {
            return "00${v}"
        }
        if (v < 1000) {
            return "0${v}"
        }
        "${v}"
    }
}

/**
 * SimApi 日志提供程序：按分类缓存日志记录器。
 */
public class SimApiLoggerProvider <: ILoggerProvider {
    private let _loggers = ConcurrentHashMap<String, SimApiLogger>()

    public func createLogger(categoryName: String): ILogger {
        if (let Some(logger) <- _loggers.get(categoryName)) {
            return logger
        }
        return _loggers.entryView(categoryName) {
            view => if (view.value.isNone()) {
                view.value = SimApiLogger(categoryName)
            }
        }.getOrThrow()
    }

    public func close(): Unit {}

    public func isClosed(): Bool {
        false
    }
}
