#!/usr/bin/env node
/**
 * Precompute Feature Flags — PR-5 + PR-9 Controlled Rollout
 * 
 * Single source of truth for precompute feature flags.
 * All flags default to DISABLED. Flags are env-var driven.
 * 
 * Safety:
 *   - Default OFF → system behavior unchanged by default
 *   - All flag checks are synchronous, never throw
 *   - No side effects on read
 * 
 * Flags:
 *   ACTIVE_MEMORY_PRECOMPUTE_ENABLED           (PR-5) Shadow observer mode
 *   ACTIVE_MEMORY_PRECOMPUTE_REPLACE_ENABLED   (PR-9) Replace primary recall
 *   ACTIVE_MEMORY_PRECOMPUTE_KILL_SWITCH       (PR-10) Emergency kill switch
 *   ACTIVE_MEMORY_PRECOMPUTE_ROLLOUT_PERCENT   (PR-11) Rollout percentage 0-100
 * 
 * Env var truthy values: "true" | "1" | "yes" | "on"
 * Anything else → disabled (default)
 * 
 * @module precompute-flag
 */

const FLAG_ENV = "ACTIVE_MEMORY_PRECOMPUTE_ENABLED";
const REPLACE_FLAG_ENV = "ACTIVE_MEMORY_PRECOMPUTE_REPLACE_ENABLED";
const KILL_SWITCH_ENV = "ACTIVE_MEMORY_PRECOMPUTE_KILL_SWITCH";
const ROLLOUT_PERCENT_ENV = "ACTIVE_MEMORY_PRECOMPUTE_ROLLOUT_PERCENT";

/**
 * Parse an env var string as a boolean flag.
 * Safe: never throws.
 * 
 * @param {string} value - Raw env var value
 * @returns {boolean} true if value is truthy (true/1/yes/on)
 */
function _parseBooleanFlag(value) {
  try {
    const normalized = (value || "").trim().toLowerCase();
    return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on";
  } catch {
    return false;
  }
}

/**
 * Check if precompute shadow observer feature is enabled (PR-5).
 * Safe: never throws, always returns boolean.
 * 
 * @returns {boolean} true if enabled, false if disabled (default)
 */
export function isPrecomputeEnabled() {
  try {
    return _parseBooleanFlag(process.env[FLAG_ENV]);
  } catch {
    return false;
  }
}

/**
 * Get the raw precompute shadow flag value for diagnostic purposes.
 * 
 * @returns {string} The raw env var value or "unset"
 */
export function getPrecomputeFlagRaw() {
  try {
    const val = process.env[FLAG_ENV];
    return val === undefined ? "unset" : val;
  } catch {
    return "error";
  }
}

/**
 * Check if precompute replacement is enabled (PR-9).
 * Only effective when isPrecomputeEnabled() is also true.
 * Safe: never throws, always returns boolean.
 * 
 * @returns {boolean} true if enabled, false if disabled (default)
 */
export function isPrecomputeReplaceEnabled() {
  try {
    return _parseBooleanFlag(process.env[REPLACE_FLAG_ENV]);
  } catch {
    return false;
  }
}

/**
 * Get the raw replacement flag value for diagnostic purposes.
 * 
 * @returns {string} The raw env var value or "unset"
 */
export function getReplaceFlagRaw() {
  try {
    const val = process.env[REPLACE_FLAG_ENV];
    return val === undefined ? "unset" : val;
  } catch {
    return "error";
  }
}

/**
 * Check if emergency kill switch is active (PR-10).
 * When active, replacement MUST be forcibly disabled.
 * Shadow mode MAY continue or be independently disabled.
 * Safe: never throws, always returns boolean.
 * 
 * @returns {boolean} true if kill switch is active, false otherwise
 */
export function isKillSwitchActive() {
  try {
    return _parseBooleanFlag(process.env[KILL_SWITCH_ENV]);
  } catch {
    return false;
  }
}

/**
 * Get the raw kill switch flag value for diagnostic purposes.
 * 
 * @returns {string} The raw env var value or "unset"
 */
export function getKillSwitchRaw() {
  try {
    const val = process.env[KILL_SWITCH_ENV];
    return val === undefined ? "unset" : val;
  } catch {
    return "error";
  }
}

/**
 * Get the rollout percentage for controlled rollout validation (PR-11).
 * 
 * Rules:
 *   - Unset → 0 (rollout disabled, no replacement)
 *   - Less than 0 → 0
 *   - Greater than 100 → 100
 *   - Non-numeric → 0
 *   - Never throws
 * 
 * @returns {number} Integer in range [0, 100]
 */
export function getRolloutPercent() {
  try {
    const raw = process.env[ROLLOUT_PERCENT_ENV];
    if (raw === undefined) return 0;
    const n = Number(raw);
    if (Number.isNaN(n)) return 0;
    const floored = Math.floor(n);
    if (floored < 0) return 0;
    if (floored > 100) return 100;
    return floored;
  } catch {
    return 0;
  }
}

/**
 * Get the raw rollout percent flag value for diagnostic purposes.
 * 
 * @returns {string} The raw env var value or "unset"
 */
export function getRolloutPercentRaw() {
  try {
    const val = process.env[ROLLOUT_PERCENT_ENV];
    return val === undefined ? "unset" : val;
  } catch {
    return "error";
  }
}

export { isPrecomputeEnabled as default };
