import { OnModuleInit, DynamicModule } from '@nestjs/common';
import { JobWorkerModuleOptions } from '../jobs/job-worker.module.js';
import { BridgeRegistry } from './bridge.protocol.js';
import '@nestjs/core';
import '../../types/drizzle.js';
import 'drizzle-orm/node-postgres';
import '../jobs/jobs-domain.module.js';
import '../jobs/bullmq.config.js';
import '../jobs/pool-config.loader.js';
import '../../../job-orchestrator.protocol-ZuJ3ow-O.js';
import '../events/event-bus.protocol.js';
import '../jobs/job-orchestration.schema.js';
import 'drizzle-orm/pg-core';
import 'drizzle-orm';
import '../events/event-registry.js';
import '../jobs/job-run-service.protocol.js';
import '../jobs/job-step-service.protocol.js';
import '../jobs/job-worker.js';
import './bridge-delivery.schema.js';

/**
 * BridgeModule — `DynamicModule.forRoot({ backend, multiTenant })`
 * factory that wires the entire bridge subsystem (BRIDGE-8, ADR-023
 * Phase 2).
 *
 * The bridge is the formalized seam between events (ADR-024) and jobs
 * (ADR-022). It is owned by neither subsystem and consumes their tokens
 * via DI. `BridgeModule` is the *combiner* — neither `EventsModule` nor
 * `JobsDomainModule` know about it.
 *
 * Consumer wiring (must be imported AFTER `EventsModule`,
 * `JobsDomainModule`, and `JobWorkerModule`):
 * ```ts
 * @Module({
 *   imports: [
 *     EventsModule.forRoot({ backend: 'drizzle' }),
 *     JobWorkerModule.forRoot({
 *       mode: 'embedded',
 *       backend: 'drizzle',
 *       pools: ['interactive', 'batch', ...BRIDGE_RESERVED_POOLS],
 *     }),
 *     BridgeModule.forRoot({ backend: 'drizzle', multiTenant: false }),
 *   ],
 * })
 * class AppModule {}
 * ```
 *
 * Boot-time check: `onModuleInit` inspects `JobWorkerModule`'s active
 * pools and throws `BridgeReservedPoolsNotPolledError` when any of the
 * three reserved bridge pools isn't being polled. Converts the
 * "wrappers sit pending forever" footgun into a fail-fast.
 *
 * Handler registration: ONE `@JobHandler('@framework/bridge_delivery',
 * ...)` decorator on `BridgeDeliveryHandler` auto-registers it in
 * `JOB_HANDLER_REGISTRY` at module-load time. We declare the class as a
 * Nest provider here so DI resolves its constructor deps; per-direction
 * routing happens via `job_run.pool='events_<direction>'` set by
 * `BridgeOutboxDrainHook` (BRIDGE-4) — workers polling each reserved
 * pool independently claim wrappers from their own pool and dispatch to
 * the same handler class. The reserved-pool validator exemption
 * (BRIDGE-5) lets the framework handler legitimately target a reserved
 * pool.
 */

interface BridgeModuleOptions {
    /**
     * `'memory'` for unit tests (no Postgres), `'drizzle'` for production.
     * Switches `BRIDGE_DELIVERY_REPO` between
     * `MemoryBridgeDeliveryRepo` and `DrizzleBridgeDeliveryRepo`.
     */
    backend: 'memory' | 'drizzle';
    /**
     * Multi-tenancy opt-in. When `true`, the three enforcement sites
     * (`EventFlowService.publishAndStart`, `BridgeDeliveryHandler.run`,
     * `DrizzleBridgeDeliveryRepo.insertDelivery`) throw
     * `MissingTenantIdError` when `tenantId === undefined`. Explicit
     * `null` always passes (cross-tenant work). Defaults to `false`.
     */
    multiTenant?: boolean;
    /**
     * The codegen-emitted `Record<EventTypeName, BridgeTriggerEntry[]>` that
     * drives outbox-drain trigger lookup (BRIDGE-4) and the facade's Case B
     * dedup (BRIDGE-7).
     *
     * **Package mode (ADR-037).** When the runtime is imported from
     * `@pattern-stack/codegen` (not vendored), the bundled
     * `./generated/registry` is a frozen empty placeholder (`{}`) — a
     * consumer's `@JobHandler.triggers` are scanned into a registry that lives
     * in THEIR `src/generated/bridge-registry.ts`, which the package can't
     * import. The generated subsystem barrel therefore threads that registry in
     * here: `BridgeModule.forRoot({ ..., registry: bridgeRegistry })`. Omitted
     * (vendored mode / tests) ⇒ falls back to the bundled `./generated/registry`,
     * which in vendored mode IS the consumer's freshly-generated file.
     *
     * Without this, package-mode consumers' triggers never bind and the bridge
     * routes nothing (the "wrappers sit pending" footgun's silent twin —
     * nothing is ever enqueued in the first place).
     */
    registry?: BridgeRegistry;
}
declare class BridgeModule implements OnModuleInit {
    private readonly workerOpts?;
    static forRoot(opts: BridgeModuleOptions): DynamicModule;
    /**
     * `JOB_WORKER_MODULE_OPTIONS` is declared `@Optional()` so unit tests
     * that mount `BridgeModule` alone (no `JobWorkerModule`) boot
     * cleanly — the boot-time check skips when the token is undefined.
     */
    constructor(workerOpts?: JobWorkerModuleOptions | undefined);
    onModuleInit(): Promise<void>;
}

export { BridgeModule, type BridgeModuleOptions };
