// DESTINATION delivery worker. Given a PENDING DestinationDeliveryLog outbox
// row, post to the shared surface via the destination adapter OUTSIDE any
// transaction, then record the terminal status on the log row in a short
// transaction. The adapter is handed the log id as an idempotency key so a
// redrain re-send collapses to a single post for a provider that honors it;
// Slack does not, so destination delivery is at-least-once (the redrain grace
// window keeps re-sends to genuinely stranded rows, not the inline path).

import type { DB } from "../generated/kysely-tailordb";
import type { DestinationAdapter } from "../lib/dispatchAdapters";

interface DestinationLogRow {
  id: string;
  eventType: string;
  sourceType: string;
  sourceId: string;
  channelId: string;
  externalChannelRef: string;
  subject: string;
  body: string;
  status: string;
}

export interface DeliverDestinationOutcome {
  status: "SENT" | "FAILED" | "SKIPPED";
  externalMessageId?: string;
  reason?: string;
}

export async function deliverDestinationLog(
  db: DB,
  logId: string,
  adapter: DestinationAdapter,
  now: Date,
): Promise<DeliverDestinationOutcome> {
  const row = (await db
    .selectFrom("DestinationDeliveryLog")
    .selectAll()
    .where("id", "=", logId)
    .executeTakeFirst()) as DestinationLogRow | undefined;
  if (!row || row.status !== "PENDING") return { status: "SKIPPED" };

  let outcome:
    | { ok: true; externalMessageId?: string; providerResponse?: string }
    | { ok: false; errorClass: string; errorDetail: string; providerResponse?: string };
  try {
    outcome = await adapter.send({
      channelId: row.channelId,
      idempotencyKey: row.id,
      externalChannelRef: row.externalChannelRef,
      subject: row.subject,
      body: row.body,
      metadata: {
        eventType: row.eventType,
        sourceType: row.sourceType,
        sourceId: row.sourceId,
      },
    });
  } catch (thrown) {
    outcome = {
      ok: false,
      errorClass: "DestinationAdapterThrew",
      errorDetail: thrown instanceof Error ? thrown.message : String(thrown),
    };
  }

  const patch = outcome.ok
    ? {
        status: "SENT" as const,
        providerMessageId: outcome.externalMessageId ?? null,
        providerResponse: outcome.providerResponse ?? null,
        failureReason: null,
        completedAt: now,
        updatedAt: now,
      }
    : {
        status: "FAILED" as const,
        providerMessageId: null,
        providerResponse: outcome.providerResponse ?? null,
        failureReason: outcome.errorDetail,
        completedAt: now,
        updatedAt: now,
      };

  await db
    .transaction()
    .execute((trx) =>
      trx
        .updateTable("DestinationDeliveryLog")
        .set(patch)
        .where("id", "=", row.id)
        .where("status", "=", "PENDING")
        .execute(),
    );

  return outcome.ok
    ? {
        status: "SENT",
        ...(outcome.externalMessageId ? { externalMessageId: outcome.externalMessageId } : {}),
      }
    : { status: "FAILED", reason: outcome.errorClass };
}
