import {
  UniqueConstraintError
} from "./chunk-NXXDZ6ZF.js";

// runtime/subsystems/bridge/bridge-delivery.memory-backend.ts
import { randomUUID } from "crypto";
var BRIDGE_DELIVERY_UNIQUE_CONSTRAINT = "uq_bridge_delivery_event_trigger";
function key(eventId, triggerId) {
  return `${eventId}::${triggerId}`;
}
var MemoryBridgeDeliveryRepo = class {
  deliveries = /* @__PURE__ */ new Map();
  async insertDelivery(row) {
    const k = key(row.eventId, row.triggerId);
    if (this.deliveries.has(k)) {
      throw new UniqueConstraintError(
        BRIDGE_DELIVERY_UNIQUE_CONSTRAINT,
        row.eventId,
        row.triggerId
      );
    }
    const record = {
      id: row.id ?? randomUUID(),
      eventId: row.eventId,
      triggerId: row.triggerId,
      wrapperRunId: row.wrapperRunId ?? null,
      userRunId: row.userRunId ?? null,
      status: row.status ?? "pending",
      skipReason: row.skipReason ?? null,
      error: row.error ?? null,
      tenantId: row.tenantId ?? null,
      attemptedAt: row.attemptedAt instanceof Date ? row.attemptedAt : /* @__PURE__ */ new Date(),
      deliveredAt: row.deliveredAt instanceof Date ? row.deliveredAt : null
    };
    this.deliveries.set(k, record);
  }
  async findDelivery(eventId, triggerId) {
    return this.deliveries.get(key(eventId, triggerId)) ?? null;
  }
  async findDeliveryById(id) {
    for (const record of this.deliveries.values()) {
      if (record.id === id) return record;
    }
    return null;
  }
  async markDelivered(id, userRunId) {
    const record = this.findById(id);
    record.status = "delivered";
    record.userRunId = userRunId;
    record.deliveredAt = /* @__PURE__ */ new Date();
  }
  async markSkipped(id, reason) {
    const record = this.findById(id);
    record.status = "skipped";
    record.skipReason = reason;
  }
  async markFailed(id, error) {
    const record = this.findById(id);
    record.status = "failed";
    record.error = error;
  }
  /**
   * Observability read — see `IJobBridge.getStatusHistogram` JSDoc for the
   * tenant-filter and windowHours contract.
   *
   * Unlike `insertDelivery`, this read does NOT call `assertTenantId`:
   * `tenantId === undefined` is the supported cross-tenant admin view.
   */
  async getStatusHistogram(windowHours, tenantId, nowMs = Date.now()) {
    if (!Number.isFinite(windowHours) || windowHours <= 0) {
      throw new RangeError("windowHours must be positive");
    }
    const cutoffMs = nowMs - windowHours * 36e5;
    const histogram = {
      pending: 0,
      delivered: 0,
      skipped: 0,
      failed: 0
    };
    for (const record of this.deliveries.values()) {
      if (record.attemptedAt.getTime() < cutoffMs) continue;
      if (tenantId === null && record.tenantId !== null) continue;
      if (typeof tenantId === "string" && record.tenantId !== tenantId) {
        continue;
      }
      histogram[record.status] += 1;
    }
    return histogram;
  }
  // ─── Test helpers ────────────────────────────────────────────────────────
  /** All deliveries for a given event (any status, declaration order). */
  getDeliveriesForEvent(eventId) {
    return [...this.deliveries.values()].filter((r) => r.eventId === eventId);
  }
  /** All deliveries currently in the given status. */
  getByStatus(status) {
    return [...this.deliveries.values()].filter((r) => r.status === status);
  }
  /** Reset the store. Tests use this in `beforeEach`. */
  clear() {
    this.deliveries.clear();
  }
  // ─── Internals ───────────────────────────────────────────────────────────
  findById(id) {
    for (const record of this.deliveries.values()) {
      if (record.id === id) return record;
    }
    throw new Error(
      `MemoryBridgeDeliveryRepo: no delivery with id '${id}' (transition methods may not be called for unknown rows; the framework handler should always findDelivery first or operate on a row it just inserted).`
    );
  }
};

export {
  MemoryBridgeDeliveryRepo
};
//# sourceMappingURL=chunk-4DOJBQTP.js.map