/**
 * Logger utility with configurable log levels and debug categories.
 *
 * Levels: 1 (info), 3 (warning), 5 (error).
 *
 * Default behaviour (logLevel 3): only warnings and errors reach the
 * console; info logs are suppressed to keep production consoles quiet.
 *
 * Debug switch: info logs can be re-enabled at runtime, without touching
 * the embed code, by setting a debug variable from the browser console:
 *
 *   window.VJSD_DEBUG = 1;                          // all categories
 *   window.VJSD_DEBUG = "drm,quality";              // specific categories
 *   localStorage.setItem("VJSD_DEBUG", "1");        // persists across reloads
 *   localStorage.setItem("VJSD_DEBUG", "drm,ui");   // persists, per category
 *   localStorage.removeItem("VJSD_DEBUG");          // turn off again
 *
 * Categories used by the player:
 *   player  - player lifecycle, options, source handling (index.js)
 *   shaka   - Shaka tech init, events, text tracks
 *   drm     - DRM setup, license/certificate requests, key statuses
 *   quality - quality (rendition) tracks and switching
 *   ui      - control bar components (settings popup, progress bar)
 */

// Default log level: warnings and errors only.
let globalLogLevel = 3;

// Log level constants
export const LOG_LEVELS = {
  INFO: 1,
  WARNING: 3,
  ERROR: 5,
};

/**
 * Set the global log level
 * @param {number} level - Log level (1, 3, or 5)
 */
export function setLogLevel(level) {
  if ([1, 2, 3, 4, 5].includes(level)) {
    globalLogLevel = level;
  } else {
    console.warn(`Invalid log level: ${level}. Using default level 3.`);
    globalLogLevel = 3;
  }
}

/**
 * Get the current global log level
 * @returns {number} Current log level
 */
export function getLogLevel() {
  return globalLogLevel;
}

/**
 * Read the runtime debug flag (window.VJSD_DEBUG or localStorage VJSD_DEBUG).
 * Re-read on every call so it can be toggled live from the console.
 * @returns {string|number|null}
 */
function readDebugFlag() {
  try {
    if (typeof window !== "undefined" && window.VJSD_DEBUG !== undefined) {
      return window.VJSD_DEBUG;
    }
    if (typeof localStorage !== "undefined") {
      return localStorage.getItem("VJSD_DEBUG");
    }
  } catch (e) {
    // localStorage can throw in privacy modes; treat as "debug off".
  }
  return null;
}

/**
 * Whether debug (info-level) output is enabled for a category.
 * @param {string} category
 * @returns {boolean}
 */
export function isDebugEnabled(category) {
  const flag = readDebugFlag();
  if (flag === null || flag === undefined || flag === "" || flag === 0 || flag === false) {
    return false;
  }
  if (flag === 1 || flag === true || flag === "1" || flag === "all" || flag === "true") {
    return true;
  }
  if (typeof flag === "string") {
    return flag
      .split(",")
      .map((s) => s.trim().toLowerCase())
      .includes((category || "").toLowerCase());
  }
  return false;
}

/**
 * Check if a log level should be displayed.
 * `globalLogLevel` is the minimum severity threshold to show.
 * @param {number} level - Log level to check
 * @returns {boolean} True if should display
 */
function shouldLog(level) {
  return level >= globalLogLevel;
}

/**
 * Log info message (level 1)
 * @param {...any} args - Arguments to log
 */
export function logInfo(...args) {
  if (shouldLog(LOG_LEVELS.INFO) || isDebugEnabled("player")) {
    console.log(...args);
  }
}

/**
 * Log warning message (level 3)
 * @param {...any} args - Arguments to log
 */
export function logWarning(...args) {
  if (shouldLog(LOG_LEVELS.WARNING)) {
    console.warn(...args);
  }
}

/**
 * Log error message (level 5)
 * @param {...any} args - Arguments to log
 */
export function logError(...args) {
  if (shouldLog(LOG_LEVELS.ERROR)) {
    console.error(...args);
  }
}

/**
 * Logger instance with a display prefix and a debug category.
 */
export class Logger {
  /**
   * @param {string} prefix - Display prefix, e.g. "Shaka-DRM"
   * @param {string} [category] - Debug category ("player" | "shaka" | "drm"
   *   | "quality" | "ui"). Defaults to "player".
   */
  constructor(prefix = "", category = "player") {
    this.prefix = prefix;
    this.category = category;
  }

  /**
   * Set or update the prefix for this logger instance
   * @param {string} prefix - New prefix to use
   */
  setPrefix(prefix) {
    this.prefix = prefix || "";
  }

  /**
   * Get the current prefix
   * @returns {string} Current prefix
   */
  getPrefix() {
    return this.prefix;
  }

  /**
   * Log info with prefix. Shown when the global log level allows INFO
   * (logLevel: 1 in player options) or when the runtime debug flag enables
   * this logger's category (see file header).
   * @param {...any} args - Arguments to log
   */
  info(...args) {
    if (shouldLog(LOG_LEVELS.INFO) || isDebugEnabled(this.category)) {
      const message = this.prefix ? `[${this.category}][${this.prefix}]` : `[${this.category}]`;
      console.log(message, ...args);
    }
  }

  /**
   * Log warning with prefix (always shown at the default log level)
   * @param {...any} args - Arguments to log
   */
  warn(...args) {
    if (shouldLog(LOG_LEVELS.WARNING)) {
      const message = this.prefix ? `[${this.prefix}]` : "";
      console.warn(message, ...args);
    }
  }

  /**
   * Log error with prefix (always shown at the default log level)
   * @param {...any} args - Arguments to log
   */
  error(...args) {
    if (shouldLog(LOG_LEVELS.ERROR)) {
      const message = this.prefix ? `[${this.prefix}]` : "";
      console.error(message, ...args);
    }
  }
}

// Export default logger instance
export default {
  setLogLevel,
  getLogLevel,
  isDebugEnabled,
  info: logInfo,
  warn: logWarning,
  error: logError,
  Logger,
  LOG_LEVELS,
};
