'use strict';

/** Reads and validates configuration. Fails loudly and early on bad values. */

function num(env, key, fallback) {
  const raw = env[key];
  if (raw == null || String(raw).trim() === '') return fallback;
  const n = Number(raw);
  if (!Number.isFinite(n)) {
    throw new Error(`${key} must be a number, got "${raw}"`);
  }
  return n;
}

function bool(env, key, fallback) {
  const raw = env[key];
  if (raw == null || String(raw).trim() === '') return fallback;
  const v = String(raw).trim().toLowerCase();
  if (['true', '1', 'yes', 'on'].includes(v)) return true;
  if (['false', '0', 'no', 'off'].includes(v)) return false;
  throw new Error(`${key} must be true or false, got "${raw}"`);
}

function loadConfig(env = process.env) {
  const cfg = {
    // DRY_RUN defaults to TRUE. Turning it off is an explicit, deliberate act.
    dryRun: bool(env, 'DRY_RUN', true),
    minProfitPct: num(env, 'MIN_PROFIT_THRESHOLD_PCT', 0.5),
    maxTradeSizeSol: num(env, 'MAX_TRADE_SIZE_SOL', 0.1),
    pollIntervalMs: num(env, 'POLL_INTERVAL_MS', 3000),
    slippageBps: num(env, 'SLIPPAGE_BPS', 50),
    maxPriceImpactPct: num(env, 'MAX_PRICE_IMPACT_PCT', 1.0),
    maxProfitDegradationPct: num(env, 'MAX_PROFIT_DEGRADATION_PCT', 0.2),
    enableJitoBundles: bool(env, 'ENABLE_JITO_BUNDLES', false),
    // When true, the bot refuses to start without a valid licence (no key,
    // unknown key, revoked, or already-in-use). A merely UNREACHABLE licence
    // server still lets the bot run — that failure mode is a published promise
    // in the storefront FAQ and stays fail-open in both modes. Defaults false
    // so tests and dev runs are not gated; the distributed .env sets it true.
    requireLicense: bool(env, 'REQUIRE_LICENSE', false),
    jitoTipLamports: num(env, 'JITO_TIP_LAMPORTS', 100000),
    priorityLamports:
      env.PRIORITY_LAMPORTS && String(env.PRIORITY_LAMPORTS).trim()
        ? num(env, 'PRIORITY_LAMPORTS')
        : null,
  };

  if (cfg.maxTradeSizeSol <= 0) throw new Error('MAX_TRADE_SIZE_SOL must be greater than 0');
  if (cfg.pollIntervalMs < 200) throw new Error('POLL_INTERVAL_MS below 200 will hammer rate limits');
  if (cfg.maxPriceImpactPct <= 0) throw new Error('MAX_PRICE_IMPACT_PCT must be greater than 0');
  if (cfg.maxProfitDegradationPct < 0) throw new Error('MAX_PROFIT_DEGRADATION_PCT cannot be negative');
  if (cfg.jitoTipLamports < 0) throw new Error('JITO_TIP_LAMPORTS cannot be negative');

  return cfg;
}

module.exports = { loadConfig };
