import {
  BRIDGE_DELIVERY_JOB_TYPE
} from "./chunk-NXNVTXKG.js";
import {
  bridgeDelivery
} from "./chunk-2TVVBC53.js";
import {
  JOBS_LISTEN_NOTIFY
} from "./chunk-ZPL74UQN.js";
import {
  jobRuns
} from "./chunk-OKXZ63IA.js";
import {
  JOBS_WAKE_CHANNEL,
  pgNotify
} from "./chunk-MYQIQ27N.js";
import {
  BRIDGE_REGISTRY
} from "./chunk-4LH67P4U.js";
import {
  __decorateClass,
  __decorateParam
} from "./chunk-2E224ZSN.js";

// runtime/subsystems/bridge/bridge-outbox-drain-hook.ts
import { Inject, Injectable, Logger, Optional } from "@nestjs/common";
import { randomUUID } from "crypto";
import { eq } from "drizzle-orm";
var POOL_BY_DIRECTION = {
  inbound: "events_inbound",
  change: "events_change",
  outbound: "events_outbound"
};
var BridgeOutboxDrainHook = class {
  constructor(registry = {}, listenNotify = false) {
    this.registry = registry;
    this.listenNotify = listenNotify;
  }
  registry;
  listenNotify;
  logger = new Logger(BridgeOutboxDrainHook.name);
  warnedNullDirection = false;
  warnedAuditTypes = /* @__PURE__ */ new Set();
  async processEvent(event, tx) {
    if (event.metadata?.["tier"] === "audit") {
      this.warnAuditBlockedOnce(event);
      return {
        delivered: 0,
        dedupSkips: 0,
        triggerCount: 0,
        auditBlocked: 1
      };
    }
    const triggers = this.lookupTriggers(event.type);
    if (triggers.length === 0) {
      return {
        delivered: 0,
        dedupSkips: 0,
        triggerCount: 0,
        auditBlocked: 0
      };
    }
    const direction = event.metadata?.["direction"] ?? null;
    const tenantId = event.metadata?.["tenantId"] ?? null;
    const wrapperPool = direction ? POOL_BY_DIRECTION[direction] : void 0;
    if (!wrapperPool) {
      if (!this.warnedNullDirection) {
        this.warnedNullDirection = true;
        this.logger.warn(
          `Skipping bridge fanout for events with null/unknown direction. event.id=${event.id} event.type=${event.type} direction=${String(direction)}. The wrapper pool is derived from direction (events_<direction>); publishers must use TypedEventBus.publish() so direction is stamped on the outbox row.`
        );
      }
      return {
        delivered: 0,
        dedupSkips: 0,
        triggerCount: triggers.length,
        auditBlocked: 0
      };
    }
    let delivered = 0;
    let dedupSkips = 0;
    const client = tx;
    for (const trigger of triggers) {
      const deliveryId = randomUUID();
      const wrapperRunId = randomUUID();
      await tx.insert(jobRuns).values({
        id: wrapperRunId,
        jobType: BRIDGE_DELIVERY_JOB_TYPE,
        jobVersion: 1,
        rootRunId: wrapperRunId,
        pool: wrapperPool,
        status: "pending",
        input: { deliveryId },
        triggerSource: "event",
        triggerRef: event.id,
        tenantId
      });
      const inserted = await tx.insert(bridgeDelivery).values({
        id: deliveryId,
        eventId: event.id,
        triggerId: trigger.triggerId,
        wrapperRunId,
        status: "pending",
        tenantId
      }).onConflictDoNothing({
        target: [bridgeDelivery.eventId, bridgeDelivery.triggerId]
      }).returning({ id: bridgeDelivery.id });
      if (inserted.length === 0) {
        await tx.delete(jobRuns).where(eq(jobRuns.id, wrapperRunId));
        dedupSkips++;
        continue;
      }
      if (this.listenNotify) {
        try {
          await pgNotify(tx, JOBS_WAKE_CHANNEL, wrapperPool);
        } catch (err) {
          this.logger.warn(
            `pg_notify(${JOBS_WAKE_CHANNEL}, ${wrapperPool}) failed for wrapper run ${wrapperRunId}: ${err.message} (non-fatal \u2014 the reserved-pool worker still polls).`
          );
        }
      }
      delivered++;
    }
    return {
      delivered,
      dedupSkips,
      triggerCount: triggers.length,
      auditBlocked: 0
    };
  }
  warnAuditBlockedOnce(event) {
    if (this.warnedAuditTypes.has(event.type)) return;
    this.warnedAuditTypes.add(event.type);
    this.logger.warn(
      `Bridge guard blocked audit-tier event '${event.type}' (event.id=${event.id}). Registry says this event is not bridge-eligible; a bridge_trigger row exists out-of-band. Investigate registry/runtime drift.`
    );
  }
  lookupTriggers(eventType) {
    const candidates = this.registry[eventType];
    return candidates ?? [];
  }
};
BridgeOutboxDrainHook = __decorateClass([
  Injectable(),
  __decorateParam(0, Optional()),
  __decorateParam(0, Inject(BRIDGE_REGISTRY)),
  __decorateParam(1, Optional()),
  __decorateParam(1, Inject(JOBS_LISTEN_NOTIFY))
], BridgeOutboxDrainHook);

export {
  BridgeOutboxDrainHook
};
//# sourceMappingURL=chunk-DTXH24LR.js.map