import { pgTable, text, timestamp, index } from 'drizzle-orm/pg-core';
import { ports } from './ports';

/**
 * Bounce-monitoring storage. The IMAP poller writes one row per parsed
 * DSN (Delivery Status Notification) it finds in a monitored sender's
 * inbox. Consumers (admin/bounces page, notifications worker, UI badges
 * on document_sends rows) join in via `originalSendType` /
 * `originalSendId`.
 */
export const emailBounces = pgTable(
  'email_bounces',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    portId: text('port_id')
      .notNull()
      .references(() => ports.id, { onDelete: 'cascade' }),
    /** The mailbox we polled to find this bounce. */
    mailboxAddress: text('mailbox_address').notNull(),
    /** The address that bounced (the original recipient). */
    bouncedAddress: text('bounced_address').notNull(),
    /** One of `document_send` / `notification` / `email_thread` / `null`. */
    originalSendType: text('original_send_type'),
    /** The id of the original send row, when resolvable. */
    originalSendId: text('original_send_id'),
    /** RFC 3464 DSN fields. Null when the upstream provider uses a
     *  non-RFC bounce format (some providers send HTML-only bounces). */
    dsnAction: text('dsn_action'),
    dsnStatus: text('dsn_status'),
    dsnDiagnostic: text('dsn_diagnostic'),
    receivedAt: timestamp('received_at', { withTimezone: true }).notNull().defaultNow(),
    /** Full raw message for forensics. Trimmed to ~32KB before insert. */
    rawMessage: text('raw_message'),
    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (table) => [
    index('idx_email_bounces_port_received').on(table.portId, table.receivedAt),
    index('idx_email_bounces_bounced_address').on(table.bouncedAddress),
    index('idx_email_bounces_original_send').on(table.originalSendType, table.originalSendId),
  ],
);

export type EmailBounce = typeof emailBounces.$inferSelect;
export type NewEmailBounce = typeof emailBounces.$inferInsert;
