import {
  assertTenantId
} from "./chunk-6DWFJNIK.js";
import {
  bridgeDelivery
} from "./chunk-2TVVBC53.js";
import {
  BRIDGE_MULTI_TENANT
} from "./chunk-4LH67P4U.js";
import {
  DRIZZLE
} from "./chunk-U64T4YZE.js";
import {
  __decorateClass,
  __decorateParam
} from "./chunk-2E224ZSN.js";

// runtime/subsystems/bridge/bridge-delivery.drizzle-backend.ts
import { Inject, Injectable, Optional } from "@nestjs/common";
import { eq, and, gte, isNull, sql } from "drizzle-orm";
var DrizzleBridgeDeliveryRepo = class {
  constructor(db, multiTenant = false) {
    this.db = db;
    this.multiTenant = multiTenant;
  }
  db;
  multiTenant;
  async insertDelivery(row, tx) {
    assertTenantId(
      "DrizzleBridgeDeliveryRepo.insertDelivery",
      this.multiTenant,
      row.tenantId
    );
    const client = tx ?? this.db;
    await client.insert(bridgeDelivery).values(row).onConflictDoNothing({
      target: [bridgeDelivery.eventId, bridgeDelivery.triggerId]
    });
  }
  async findDelivery(eventId, triggerId) {
    const rows = await this.db.select().from(bridgeDelivery).where(
      and(
        eq(bridgeDelivery.eventId, eventId),
        eq(bridgeDelivery.triggerId, triggerId)
      )
    ).limit(1);
    return rows[0] ?? null;
  }
  async findDeliveryById(id) {
    const rows = await this.db.select().from(bridgeDelivery).where(eq(bridgeDelivery.id, id)).limit(1);
    return rows[0] ?? null;
  }
  async markDelivered(id, userRunId, tx) {
    const client = tx ?? this.db;
    await client.update(bridgeDelivery).set({
      status: "delivered",
      userRunId,
      deliveredAt: /* @__PURE__ */ new Date()
    }).where(eq(bridgeDelivery.id, id));
  }
  async markSkipped(id, reason, tx) {
    const client = tx ?? this.db;
    await client.update(bridgeDelivery).set({ status: "skipped", skipReason: reason }).where(eq(bridgeDelivery.id, id));
  }
  async markFailed(id, error, tx) {
    const client = tx ?? this.db;
    await client.update(bridgeDelivery).set({ status: "failed", error }).where(eq(bridgeDelivery.id, id));
  }
  /**
   * Observability read — see `IJobBridge.getStatusHistogram` JSDoc for the
   * tenant-filter and windowHours contract.
   *
   * Tenant-filter note: this method intentionally does NOT call
   * `assertTenantId`. The write methods on this repo (`insertDelivery`)
   * treat `tenantId === undefined` as a misconfiguration and fail fast.
   * Reads are different — `undefined` is the supported "cross-tenant
   * admin view" mode that OBS-5 uses to render a framework-wide health
   * panel. Callers that need strict tenant scoping pass an explicit
   * string or `null`.
   *
   * Cast note: `count(*)::int` is applied in SQL so the node-pg driver
   * returns a `number` instead of the default `bigint → string` for
   * `count(*)`. Don't relax this cast — consumers (and the protocol)
   * type the result as `number`.
   */
  async getStatusHistogram(windowHours, tenantId) {
    if (!Number.isFinite(windowHours) || windowHours <= 0) {
      throw new RangeError("windowHours must be positive");
    }
    const cutoff = sql`now() - make_interval(hours => ${windowHours})`;
    const conditions = [gte(bridgeDelivery.attemptedAt, cutoff)];
    if (tenantId === null) {
      conditions.push(isNull(bridgeDelivery.tenantId));
    } else if (typeof tenantId === "string") {
      conditions.push(eq(bridgeDelivery.tenantId, tenantId));
    }
    const rows = await this.db.select({
      status: bridgeDelivery.status,
      count: sql`count(*)::int`
    }).from(bridgeDelivery).where(and(...conditions)).groupBy(bridgeDelivery.status);
    const histogram = {
      pending: 0,
      delivered: 0,
      skipped: 0,
      failed: 0
    };
    for (const row of rows) {
      histogram[row.status] = Number(row.count);
    }
    return histogram;
  }
};
DrizzleBridgeDeliveryRepo = __decorateClass([
  Injectable(),
  __decorateParam(0, Inject(DRIZZLE)),
  __decorateParam(1, Optional()),
  __decorateParam(1, Inject(BRIDGE_MULTI_TENANT))
], DrizzleBridgeDeliveryRepo);

export {
  DrizzleBridgeDeliveryRepo
};
//# sourceMappingURL=chunk-K2I6XIK5.js.map