import { PlatformError } from './errors.mjs';

const FLAG_PATTERN = /^[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+$/;

function envKey(flag) {
  return `VENDOO_FEATURE_${flag.replace(/[^a-z0-9]/gi, '_').toUpperCase()}`;
}

function parseBoolean(value, fallback) {
  if (value === undefined || value === null || value === '') return fallback;
  if (/^(1|true|yes|on)$/i.test(String(value))) return true;
  if (/^(0|false|no|off)$/i.test(String(value))) return false;
  throw new PlatformError(`Ungültiger Feature-Flag-Wert: ${value}`, { code: 'FEATURE_FLAG_VALUE_INVALID', status: 500 });
}

export class FeatureFlagRegistry {
  #flags = new Map();

  define(name, { defaultValue = false, owner = 'vendoo.system', description = '', mutable = false } = {}) {
    const normalized = String(name || '');
    if (!FLAG_PATTERN.test(normalized)) {
      throw new PlatformError(`Ungültiger Feature-Flag: ${normalized}`, { code: 'FEATURE_FLAG_NAME_INVALID', status: 500 });
    }
    if (this.#flags.has(normalized)) {
      throw new PlatformError(`Feature-Flag bereits definiert: ${normalized}`, { code: 'FEATURE_FLAG_DUPLICATE', status: 500 });
    }
    const configured = parseBoolean(process.env[envKey(normalized)], Boolean(defaultValue));
    this.#flags.set(normalized, {
      name: normalized,
      value: configured,
      defaultValue: Boolean(defaultValue),
      owner: String(owner),
      description: String(description),
      mutable: Boolean(mutable),
      source: process.env[envKey(normalized)] === undefined ? 'default' : 'environment',
    });
    return configured;
  }

  isEnabled(name) {
    if (!this.#flags.has(name)) {
      throw new PlatformError(`Unbekannter Feature-Flag: ${name}`, { code: 'FEATURE_FLAG_UNKNOWN', status: 500 });
    }
    return this.#flags.get(name).value;
  }

  set(name, value) {
    const flag = this.#flags.get(name);
    if (!flag) throw new PlatformError(`Unbekannter Feature-Flag: ${name}`, { code: 'FEATURE_FLAG_UNKNOWN', status: 404, expose: true });
    if (!flag.mutable) throw new PlatformError(`Feature-Flag ist nicht zur Laufzeit änderbar: ${name}`, { code: 'FEATURE_FLAG_IMMUTABLE', status: 409, expose: true });
    flag.value = Boolean(value);
    flag.source = 'runtime';
    return flag.value;
  }

  list() {
    return [...this.#flags.values()].map(flag => ({ ...flag }));
  }
}
