// 定义日志级别
export const LogLevel = {
  DEBUG: { value: 0, name: "DEBUG", color: "#6495ED" }, // 宝蓝色
  INFO: { value: 1, name: "INFO", color: "#4CAF50" }, // 绿色
  WARN: { value: 2, name: "WARN", color: "#FFC107" }, // 琥珀色
  ERROR: { value: 3, name: "ERROR", color: "#F44336" }, // 红色
  SILENT: { value: 4, name: "SILENT" }, // 特殊级别，用于关闭所有日志
};

function findLogLevelByValue(value) {
  return Object.values(LogLevel).find((level) => level.value === value);
}

function findLogLevelByName(name) {
  if (typeof name !== "string" || name.length === 0) return undefined;
  const upperCaseName = name.toUpperCase();
  return Object.values(LogLevel).find((level) => level.name === upperCaseName);
}

class Logger {
  /**
   * @param {object} [options={}] 配置选项
   * @param {LogLevel} [options.level=LogLevel.INFO]  要显示的最低日志级别
   * @param {string}   [options.prefix='App']         日志前缀，用于区分模块
   */
  constructor(options = {}) {
    this.config = {
      level: options.level || LogLevel.INFO,
      prefix: options.prefix || "KISS-Translator",
    };
  }

  /**
   * 动态设置日志级别
   * @param {LogLevel} level - 新的日志级别
   */
  setLevel(level) {
    let newLevelObject;

    if (typeof level === "string") {
      newLevelObject = findLogLevelByName(level);
      if (!newLevelObject) {
        this.warn(
          `Invalid log level name provided: "${level}". Keeping current level.`
        );
        return;
      }
    } else if (typeof level === "number") {
      newLevelObject = findLogLevelByValue(level);
      if (!newLevelObject) {
        this.warn(
          `Invalid log level value provided: ${level}. Keeping current level.`
        );
        return;
      }
    } else if (level && typeof level.value === "number") {
      newLevelObject = level;
    } else {
      this.warn(
        "Invalid argument passed to setLevel. Must be a LogLevel object, number, or string."
      );
      return;
    }

    if (this.config.level.value !== newLevelObject.value) {
      this.config.level = newLevelObject;
      console.log(
        `[${this.config.prefix}] Log level dynamically set to ${this.config.level.name}`
      );
    }
  }

  /**
   * 核心日志记录方法
   * @private
   * @param {LogLevel} level - 当前消息的日志级别
   * @param {...any} args - 要记录的多个参数，可以是任何类型
   */
  _log(level, ...args) {
    // 如果当前级别低于配置的最低级别，则不打印
    if (level.value < this.config.level.value) {
      return;
    }

    const timestamp = new Date().toISOString();
    const prefixStr = `[${this.config.prefix}]`;
    const levelStr = `[${level.name}]`;

    // 判断是否在浏览器环境并且浏览器支持 console 样式
    const isBrowser =
      typeof window !== "undefined" && typeof window.document !== "undefined";

    if (isBrowser) {
      // 在浏览器中使用颜色高亮
      const consoleMethod = this._getConsoleMethod(level);
      consoleMethod(
        `%c${timestamp} %c${prefixStr} %c${levelStr}`,
        "color: gray; font-weight: lighter;", // 时间戳样式
        "color: #7c57e0; font-weight: bold;", // 前缀样式 (紫色)
        `color: ${level.color}; font-weight: bold;`, // 日志级别样式
        ...args
      );
    } else {
      // 在 Node.js 或不支持样式的环境中，输出纯文本
      const consoleMethod = this._getConsoleMethod(level);
      consoleMethod(timestamp, prefixStr, levelStr, ...args);
    }
  }

  /**
   * 根据日志级别获取对应的 console 方法
   * @private
   */
  _getConsoleMethod(level) {
    switch (level) {
      case LogLevel.ERROR:
        return console.error;
      case LogLevel.WARN:
        return console.warn;
      case LogLevel.INFO:
        return console.info;
      default:
        return console.log;
    }
  }

  /**
   * 记录 DEBUG 级别的日志
   * @param {...any} args
   */
  debug(...args) {
    this._log(LogLevel.DEBUG, ...args);
  }

  /**
   * 记录 INFO 级别的日志
   * @param {...any} args
   */
  info(...args) {
    this._log(LogLevel.INFO, ...args);
  }

  /**
   * 记录 WARN 级别的日志
   * @param {...any} args
   */
  warn(...args) {
    this._log(LogLevel.WARN, ...args);
  }

  /**
   * 记录 ERROR 级别的日志
   * @param {...any} args
   */
  error(...args) {
    this._log(LogLevel.ERROR, ...args);
  }
}

export const logger = new Logger();
export const kissLog = logger.info.bind(logger);

// todo：debug日志埋点
