/**
 * Configuration Loader - Secure Configuration Loading Pattern
 *
 * This implements the expert-recommended blocking initialization pattern:
 * 1. loadConfig() fetches from /api/config and stores it
 * 2. getConfig() returns config or throws if not loaded
 * 3. Application only initializes after loadConfig() completes
 *
 * This prevents race conditions where components try to access config
 * before it's been fetched from the server.
 */

/**
 * Module-scoped variable to hold the fetched server configuration.
 * @type {Object|null}
 */
let serverConfig = null;

/**
 * Fetches configuration from the server and stores it.
 * This MUST be called before the application initializes any components
 * that depend on the configuration.
 *
 * @async
 * @returns {Promise<void>}
 * @throws {Error} If the config endpoint is unreachable or returns an error
 */
export async function loadConfig() {
  // Prevent double-loading
  if (serverConfig) {
    console.warn('[ConfigLoader] Configuration already loaded.');
    return;
  }

  try {
    const response = await fetch('/api/config');

    if (!response.ok) {
      throw new Error(`Server returned status ${response.status}: ${response.statusText}`);
    }

    serverConfig = await response.json();

    console.log('[ConfigLoader] Configuration loaded successfully', {
      dssHost: serverConfig.dssHost,
      dssPort: serverConfig.dssPort,
      storybookPort: serverConfig.storybookPort,
    });

  } catch (error) {
    console.error('[ConfigLoader] Failed to load configuration:', error);
    // Re-throw to be caught by the bootstrap function
    throw new Error(`Failed to load server configuration: ${error.message}`);
  }
}

/**
 * Returns the entire configuration object.
 * MUST ONLY be called after loadConfig() has completed successfully.
 *
 * @returns {Object} The server configuration
 * @throws {Error} If called before loadConfig() has completed
 */
export function getConfig() {
  if (!serverConfig) {
    throw new Error('[ConfigLoader] getConfig() called before configuration was loaded. Did you forget to await loadConfig()?');
  }
  return serverConfig;
}

/**
 * Convenience getter for just the DSS host.
 * @returns {string} The DSS host
 */
export function getDssHost() {
  const config = getConfig();
  return config.dssHost;
}

/**
 * Convenience getter for DSS port.
 * @returns {string} The DSS port
 */
export function getDssPort() {
  const config = getConfig();
  return config.dssPort;
}

/**
 * Convenience getter for Storybook port.
 * @returns {number} The Storybook port (always 6006)
 */
export function getStorybookPort() {
  const config = getConfig();
  return config.storybookPort;
}

/**
 * Builds the full Storybook URL from config.
 * Points to Storybook running on port 6006 on the current host.
 *
 * @returns {string} The full Storybook URL (e.g., "http://dss.overbits.luz.uy:6006")
 */
export function getStorybookUrl() {
  const dssHost = getDssHost();
  const protocol = window.location.protocol; // "http:" or "https:"
  // Point to Storybook on port 6006
  return `${protocol}//${dssHost}:6006`;
}

/**
 * TESTING ONLY: Reset the configuration state
 * This allows tests to load different configurations
 * @internal
 */
export function __resetForTesting() {
  serverConfig = null;
}

export default {
  loadConfig,
  getConfig,
  getDssHost,
  getDssPort,
  getStorybookPort,
  getStorybookUrl,
  __resetForTesting,
};
