/**
 * Runtime feature flags. Backed by a tiny single-row table so an admin
 * can flip a flag and have every Vibn pod pick it up within seconds (no
 * redeploy required).
 *
 * Currently used for:
 *   - path_b_disabled : kill switch for the Path B AI dev-container
 *                       architecture. When true, shell.exec / fs.* /
 *                       devcontainer.* tools return 503 and the chat
 *                       system prompt falls back to Path A guidance.
 *
 * See AI_PATH_B_EXECUTION_PLAN.md §7 for the rollback story.
 */

import { query, queryOne } from '@/lib/db-postgres';

let tableReady = false;
async function ensureFlagsTable(): Promise<void> {
  if (tableReady) return;
  await query(
    `CREATE TABLE IF NOT EXISTS fs_feature_flags (
       key   TEXT PRIMARY KEY,
       value JSONB NOT NULL,
       updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
     );`,
    [],
  );
  tableReady = true;
}

const TTL_MS = 10_000;
const cache = new Map<string, { value: any; expires: number }>();

export async function getFlag<T = unknown>(key: string, defaultValue: T): Promise<T> {
  const cached = cache.get(key);
  if (cached && cached.expires > Date.now()) return cached.value as T;
  await ensureFlagsTable();
  const row = await queryOne<{ value: T }>(
    `SELECT value FROM fs_feature_flags WHERE key = $1 LIMIT 1`,
    [key],
  );
  const value = row?.value ?? defaultValue;
  cache.set(key, { value, expires: Date.now() + TTL_MS });
  return value;
}

export async function setFlag(key: string, value: unknown): Promise<void> {
  await ensureFlagsTable();
  await query(
    `INSERT INTO fs_feature_flags (key, value, updated_at)
       VALUES ($1, $2::jsonb, now())
     ON CONFLICT (key) DO UPDATE
       SET value = EXCLUDED.value,
           updated_at = now()`,
    [key, JSON.stringify(value)],
  );
  cache.delete(key);
}

export async function isPathBDisabled(): Promise<boolean> {
  return Boolean(await getFlag<boolean>('path_b_disabled', false));
}
