import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
import { FeatureToggle } from "./data/entities.js";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { toggleCreateSchemaList } from "./data/validators.js";
import { parseBooleanToken } from "@open-mercato/shared/lib/boolean";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const defaultFilePath = path.resolve(__dirname, "defaults.json");
function parseArgs(rest) {
  const args = {};
  for (let index = 0; index < rest.length; index += 1) {
    const part = rest[index];
    if (!part?.startsWith("--")) continue;
    const [rawKey, rawValue] = part.slice(2).split("=");
    if (!rawKey) continue;
    if (rawValue !== void 0) {
      args[rawKey] = rawValue;
      continue;
    }
    const next = rest[index + 1];
    if (next && !next.startsWith("--")) {
      args[rawKey] = next;
      index += 1;
      continue;
    }
    args[rawKey] = true;
  }
  return args;
}
function stringOption(args, ...keys) {
  for (const key of keys) {
    const raw = args[key];
    if (typeof raw !== "string") continue;
    const trimmed = raw.trim();
    if (trimmed.length > 0) return trimmed;
  }
  return void 0;
}
function booleanOption(args, ...keys) {
  for (const key of keys) {
    const raw = args[key];
    if (raw === void 0) continue;
    if (raw === true) return true;
    if (raw === false) return false;
    if (typeof raw === "string") {
      const trimmed = raw.trim();
      if (!trimmed) return true;
      const parsed = parseBooleanToken(trimmed);
      if (parsed !== null) return parsed;
    }
  }
  return void 0;
}
function parseValue(type, value) {
  if (value === void 0) return void 0;
  switch (type) {
    case "boolean":
      if (value === "true" || value === "1") return true;
      if (value === "false" || value === "0") return false;
      return Boolean(value);
    case "number":
      const num = Number(value);
      if (isNaN(num)) throw new Error(`Invalid number value: ${value}`);
      return num;
    case "json":
      try {
        return JSON.parse(value);
      } catch (e) {
        throw new Error(`Invalid JSON value: ${value}`);
      }
    case "string":
    default:
      return value;
  }
}
function buildCommandContext(container) {
  return {
    container,
    auth: null,
    organizationScope: null,
    selectedOrganizationId: null,
    organizationIds: null,
    request: void 0,
    // CLI invocations (seed-defaults, toggle-create/update/delete) are trusted
    // server-side calls with no end-user actor. Global feature toggles are a
    // platform-wide table whose writes are restricted to super admins (#2266);
    // this flag lets the command-level guard recognize the system caller so
    // `yarn initialize` can seed defaults without an authenticated super admin.
    systemActor: true
  };
}
const createToggle = {
  command: "toggle-create",
  async run(rest) {
    const args = parseArgs(rest);
    const identifier = stringOption(args, "identifier", "id");
    const name = stringOption(args, "name");
    if (!identifier || !name) {
      console.error("Usage: mercato feature_toggles toggle-create --identifier <id> --name <name> [--type boolean|string|number|json] [--defaultValue <value>] [--category <value>] [--description <value>]");
      return;
    }
    const type = stringOption(args, "type") || "boolean";
    const defaultValueRaw = stringOption(args, "defaultValue");
    const category = stringOption(args, "category");
    const description = stringOption(args, "description");
    let defaultValue = void 0;
    try {
      defaultValue = parseValue(type, defaultValueRaw);
    } catch (e) {
      console.error(e.message);
      return;
    }
    const container = await createRequestContainer();
    try {
      const commandBus = container.resolve("commandBus");
      const ctx = buildCommandContext(container);
      const { result } = await commandBus.execute("feature_toggles.global.create", {
        input: {
          identifier,
          name,
          type,
          defaultValue,
          category: category ?? null,
          description: description ?? null
        },
        ctx
      });
      console.log("\u2705 Feature toggle created:", "Identifier: " + identifier);
    } finally {
      const disposable = container;
      if (typeof disposable.dispose === "function") {
        await disposable.dispose();
      }
    }
  }
};
const updateToggle = {
  command: "toggle-update",
  async run(rest) {
    const args = parseArgs(rest);
    const identifier = stringOption(args, "identifier");
    if (!identifier) {
      console.error("Usage: mercato feature_toggles toggle-update --identifier <id> [--name <name>] [--defaultValue <value>] [--category <value>] [--description <value>]");
      return;
    }
    const container = await createRequestContainer();
    const em = container.resolve("em");
    const toggle = await em.findOne(FeatureToggle, { identifier });
    if (!toggle) {
      console.error("Feature toggle not found:", identifier);
      return;
    }
    const name = stringOption(args, "name");
    const defaultValueRaw = stringOption(args, "defaultValue");
    const category = stringOption(args, "category");
    const description = stringOption(args, "description");
    let defaultValue = void 0;
    if (defaultValueRaw !== void 0) {
      try {
        defaultValue = parseValue(toggle.type, defaultValueRaw);
      } catch (e) {
        console.error(e.message);
        return;
      }
    }
    const toggleId = toggle.id;
    try {
      const commandBus = container.resolve("commandBus");
      const ctx = buildCommandContext(container);
      await commandBus.execute("feature_toggles.global.update", {
        input: {
          ...toggleId ? { id: toggleId } : {},
          ...identifier ? { identifier } : {},
          ...name ? { name } : {},
          ...defaultValue !== void 0 ? { defaultValue } : {},
          ...category !== void 0 ? { category } : {},
          ...description !== void 0 ? { description } : {}
        },
        ctx
      });
      console.log("\u2705 Feature toggle updated:", "Identifier: " + identifier);
    } finally {
      const disposable = container;
      if (typeof disposable.dispose === "function") {
        await disposable.dispose();
      }
    }
  }
};
const deleteToggle = {
  command: "toggle-delete",
  async run(rest) {
    const args = parseArgs(rest);
    const identifier = stringOption(args, "identifier");
    if (!identifier) {
      console.error("Usage: mercato feature_toggles toggle-delete --identifier <id>");
      return;
    }
    const container = await createRequestContainer();
    const em = container.resolve("em");
    const toggle = await em.findOne(FeatureToggle, { identifier });
    if (!toggle) {
      console.error("Feature toggle not found:", identifier);
      return;
    }
    const toggleId = toggle.id;
    try {
      const commandBus = container.resolve("commandBus");
      const ctx = buildCommandContext(container);
      await commandBus.execute("feature_toggles.global.delete", {
        input: {
          ...toggleId ? { id: toggleId } : {},
          ...identifier ? { identifier } : {}
        },
        ctx
      });
      console.log("\u2705 Feature toggle deleted:", identifier ?? toggleId);
    } finally {
      const disposable = container;
      if (typeof disposable.dispose === "function") {
        await disposable.dispose();
      }
    }
  }
};
const setOverrideValue = {
  command: "override-set-value",
  async run(rest) {
    const args = parseArgs(rest);
    const identifier = stringOption(args, "identifier");
    const tenantId = stringOption(args, "tenantId", "tenant", "tenantId");
    const valueRaw = stringOption(args, "value");
    if (!identifier || !tenantId) {
      console.error("Usage: mercato feature_toggles override-set-value --identifier <id> --tenantId <uuid> --value <value>");
      return;
    }
    const container = await createRequestContainer();
    const em = container.resolve("em");
    const toggle = await em.findOne(FeatureToggle, { identifier });
    if (!toggle) {
      console.error("Feature toggle not found:", identifier);
      return;
    }
    let value = void 0;
    if (valueRaw !== void 0) {
      try {
        value = parseValue(toggle.type, valueRaw);
      } catch (e) {
        console.error(e.message);
        return;
      }
    }
    const toggleId = toggle.id;
    try {
      const commandBus = container.resolve("commandBus");
      const ctx = buildCommandContext(container);
      await commandBus.execute("feature_toggles.overrides.changeState", {
        input: {
          toggleId,
          tenantId,
          isOverride: true,
          overrideValue: value
        },
        ctx
      });
      console.log("\u2705 Feature toggle override updated:", identifier, "Tenant ID: " + tenantId, "Value: " + (valueRaw || "unchanged"));
    } finally {
      const disposable = container;
      if (typeof disposable.dispose === "function") {
        await disposable.dispose();
      }
    }
  }
};
const seedDefaults = {
  command: "seed-defaults",
  async run(rest) {
    const args = parseArgs(rest);
    const filePathFromArgs = stringOption(args, "filePath");
    const filePath = filePathFromArgs ?? defaultFilePath;
    const raw = fs.readFileSync(filePath, "utf8");
    const parsedJson = JSON.parse(raw);
    const data = Array.isArray(parsedJson) ? parsedJson : parsedJson.toggles;
    const toggles = toggleCreateSchemaList.parse(data);
    const container = await createRequestContainer();
    const commandBus = container.resolve("commandBus");
    const em = container.resolve("em");
    const ctx = buildCommandContext(container);
    let created = 0;
    let skipped = 0;
    for (const toggle of toggles) {
      const existing = await em.findOne(FeatureToggle, { identifier: toggle.identifier, deletedAt: null });
      if (existing) {
        skipped += 1;
        continue;
      }
      await commandBus.execute("feature_toggles.global.create", {
        input: {
          identifier: toggle.identifier,
          name: toggle.name,
          description: toggle.description ?? null,
          category: toggle.category ?? null,
          type: toggle.type,
          defaultValue: toggle.defaultValue
        },
        ctx
      });
      created += 1;
      console.log(`\u2705 Created feature toggle ${toggle.identifier}`);
    }
    console.log(`\u2705 Feature toggle defaults seeded (created: ${created}, skipped: ${skipped})`);
  }
};
var cli_default = [createToggle, updateToggle, deleteToggle, setOverrideValue, seedDefaults];
export {
  cli_default as default
};
//# sourceMappingURL=cli.js.map
