import { Column, Entity, Index } from "typeorm";
import { BaseEntity } from "@edr/api-common";
import {
  PaymentEvent,
  PaymentEventType,
  PaymentReferenceType,
  PaymentService,
} from "@edr/types";

export type OutboxStatus = "PENDING" | "SENT" | "FAILED";

/**
 * Transactional outbox: a row is inserted in the SAME transaction that finalizes an intent,
 * so "payment succeeded" and "a notification is owed" commit or roll back together. The relay
 * drains PENDING rows and retries until acked (at-least-once delivery; consumers are idempotent).
 */
@Entity({ name: "notification_outbox" })
@Index("idx_notification_outbox_relay", ["status", "nextRetryAt"])
export class NotificationOutbox extends BaseEntity {
  @Column({ name: "event_type", type: "varchar", length: 32 })
  eventType!: PaymentEventType;

  /** Routing discriminator — which app's mark-paid endpoint the relay delivers to. */
  @Column({ name: "service", type: "varchar", length: 16 })
  service!: PaymentService;

  @Index("idx_notification_outbox_intent")
  @Column({ name: "intent_id", type: "uuid" })
  intentId!: string;

  @Column({ name: "reference_type", type: "varchar", length: 16 })
  referenceType!: PaymentReferenceType;

  @Column({ name: "reference_id", type: "varchar", length: 64 })
  referenceId!: string;

  /** The full versioned event envelope delivered verbatim to the consumer. */
  @Column({ name: "payload", type: "jsonb" })
  payload!: PaymentEvent;

  @Column({ name: "status", type: "varchar", length: 16, default: "PENDING" })
  status!: OutboxStatus;

  @Column({ name: "attempts", type: "integer", default: 0 })
  attempts!: number;

  @Column({ name: "next_retry_at", type: "timestamptz", nullable: true })
  nextRetryAt?: Date | null;

  @Column({ name: "last_error", type: "text", nullable: true })
  lastError?: string | null;

  @Column({ name: "sent_at", type: "timestamptz", nullable: true })
  sentAt?: Date | null;
}
