import { asValue } from "awilix";
import { createEventBus } from "@open-mercato/events/index";
import { setGlobalEventBus } from "@open-mercato/shared/modules/events";
import { createCacheService } from "@open-mercato/cache";
import { createKmsService } from "@open-mercato/shared/lib/encryption/kms";
import { TenantDataEncryptionService } from "@open-mercato/shared/lib/encryption/tenantDataEncryptionService";
import { registerTenantEncryptionSubscriber } from "@open-mercato/shared/lib/encryption/subscriber";
import { isTenantDataEncryptionEnabled } from "@open-mercato/shared/lib/encryption/toggles";
import { getSearchModuleConfigs } from "@open-mercato/shared/modules/search";
import {
  registerSearchModule,
  createSearchDeleteSubscriber,
  searchDeleteMetadata
} from "@open-mercato/search";
import { RateLimiterService } from "@open-mercato/shared/lib/ratelimit/service";
import { readRateLimitConfig } from "@open-mercato/shared/lib/ratelimit/config";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("core");
const RL_GLOBAL_KEY = "__openMercatoRateLimiterService__";
const RL_SHUTDOWN_KEY = "__openMercatoRateLimiterShutdown__";
const CACHE_GLOBAL_KEY = "__openMercatoCacheService__";
const CACHE_SHUTDOWN_KEY = "__openMercatoCacheShutdown__";
function isCacheSingletonEnabled() {
  const raw = process.env.OM_CACHE_SINGLETON;
  if (raw === void 0) return true;
  const normalized = raw.trim().toLowerCase();
  if (!normalized.length) return true;
  return !(normalized === "0" || normalized === "off" || normalized === "false" || normalized === "no");
}
function getCachedCacheService() {
  if (!isCacheSingletonEnabled()) return null;
  let service = globalThis[CACHE_GLOBAL_KEY] ?? null;
  if (!service) {
    try {
      try {
        service = createCacheService();
      } catch (err) {
        logger.warn("Cache service initialization failed; falling back to memory strategy", { err });
        service = createCacheService({ strategy: "memory" });
      }
      ;
      globalThis[CACHE_GLOBAL_KEY] = service;
      if (!globalThis[CACHE_SHUTDOWN_KEY]) {
        const shutdown = () => {
          service?.close?.().catch(() => {
          });
        };
        process.once("SIGTERM", shutdown);
        process.once("SIGINT", shutdown);
        globalThis[CACHE_SHUTDOWN_KEY] = true;
      }
    } catch (err) {
      logger.warn("Failed to create cache service", { component: "cache", err });
    }
  }
  return service;
}
function getCachedRateLimiterService() {
  let service = globalThis[RL_GLOBAL_KEY] ?? null;
  if (!service) {
    try {
      const rateLimitConfig = readRateLimitConfig();
      service = new RateLimiterService(rateLimitConfig);
      service.initialize().catch((err) => {
        logger.warn("Async initialization failed", { component: "ratelimit", err });
      });
      globalThis[RL_GLOBAL_KEY] = service;
      if (!globalThis[RL_SHUTDOWN_KEY]) {
        const shutdown = () => {
          service?.destroy().catch(() => {
          });
        };
        process.once("SIGTERM", shutdown);
        process.once("SIGINT", shutdown);
        globalThis[RL_SHUTDOWN_KEY] = true;
      }
    } catch (err) {
      logger.warn("Failed to create rate limiter service", { component: "ratelimit", err });
    }
  }
  return service;
}
async function bootstrap(container) {
  let cache = getCachedCacheService();
  if (!cache) {
    try {
      cache = createCacheService();
    } catch (err) {
      logger.warn("Cache service initialization failed; falling back to memory strategy", { err });
      cache = createCacheService({ strategy: "memory" });
    }
  }
  container.register({ cache: asValue(cache) });
  let eventBus;
  try {
    const strategyEnv = process.env.QUEUE_STRATEGY || process.env.EVENTS_STRATEGY;
    const queueStrategy = strategyEnv === "async" || strategyEnv === "redis" ? "async" : "local";
    eventBus = createEventBus({ resolve: container.resolve.bind(container), queueStrategy });
  } catch (err) {
    logger.warn("Event bus initialization failed; falling back to local strategy", { err });
    try {
      eventBus = createEventBus({ resolve: container.resolve.bind(container), queueStrategy: "local" });
    } catch {
      eventBus = {
        emit: async () => {
        },
        on: () => {
        },
        registerModuleSubscribers: () => {
        },
        clearQueue: async () => ({ removed: 0 })
      };
    }
  }
  container.register({ eventBus: asValue(eventBus) });
  setGlobalEventBus(eventBus);
  try {
    let loadedModules = [];
    try {
      const { getModules } = await import("@open-mercato/shared/lib/i18n/server");
      loadedModules = getModules();
    } catch {
    }
    const subs = loadedModules.flatMap(
      (m) => (m.subscribers || []).map((subscriber) => ({
        ...subscriber,
        moduleId: subscriber.moduleId ?? m.id
      }))
    );
    if (subs.length) container.resolve("eventBus").registerModuleSubscribers(subs);
    const syncSubs = subs.filter((s) => s.sync === true);
    if (syncSubs.length) {
      try {
        const { registerSyncSubscribers } = await import("@open-mercato/shared/lib/crud/sync-subscriber-store");
        registerSyncSubscribers(
          syncSubs.map((s) => ({
            metadata: { event: s.event, sync: true, priority: s.priority, id: s.id },
            handler: s.handler
          }))
        );
      } catch {
      }
    }
  } catch (err) {
    logger.error("Failed to register module subscribers:", { err });
  }
  const kmsService = createKmsService();
  container.register({ kmsService: asValue(kmsService) });
  try {
    const em = container.resolve("em");
    const cacheService = (() => {
      try {
        return container.resolve("cache");
      } catch {
        return null;
      }
    })();
    const tenantEncryptionService = new TenantDataEncryptionService(em, { cache: cacheService, kms: kmsService });
    container.register({ tenantEncryptionService: asValue(tenantEncryptionService) });
    if (isTenantDataEncryptionEnabled() && kmsService.isHealthy()) {
      try {
        registerTenantEncryptionSubscriber(em, tenantEncryptionService);
      } catch (err) {
        logger.warn("Failed to register MikroORM encryption subscriber", { component: "encryption", err });
      }
    } else if (isTenantDataEncryptionEnabled() && !kmsService.isHealthy()) {
      logger.warn("Vault/KMS unhealthy - tenant data encryption is disabled until recovery", { component: "encryption" });
    }
  } catch (err) {
    logger.warn("Failed to initialize tenant encryption service", { component: "encryption", err });
  }
  const rateLimiterService = getCachedRateLimiterService();
  if (rateLimiterService) {
    container.register({ rateLimiterService: asValue(rateLimiterService) });
  }
  try {
    const searchModuleConfigs = getSearchModuleConfigs();
    registerSearchModule(container, { moduleConfigs: searchModuleConfigs });
    container.register({
      searchModuleConfigs: asValue(searchModuleConfigs)
    });
    try {
      const searchIndexer = container.resolve("searchIndexer");
      if (searchIndexer && eventBus) {
        eventBus.registerModuleSubscribers([
          {
            event: searchDeleteMetadata.event,
            persistent: searchDeleteMetadata.persistent,
            handler: createSearchDeleteSubscriber(searchIndexer)
          }
        ]);
      }
    } catch {
    }
  } catch (err) {
    logger.warn("Failed to register search module", { component: "search", err });
  }
}
export {
  bootstrap,
  getCachedCacheService,
  getCachedRateLimiterService
};
//# sourceMappingURL=bootstrap.js.map
