/**
 * Outbox Event Repository Interface
 *
 * 发件箱模式 - 保证事件发布的可靠性
 */

export const OUTBOX_EVENT_REPOSITORY = Symbol('OUTBOX_EVENT_REPOSITORY');

export enum OutboxEventStatus {
  PENDING = 'PENDING',   // 待发送
  SENT = 'SENT',         // 已发送，等待确认
  ACKED = 'ACKED',       // 已确认
  FAILED = 'FAILED',     // 发送失败（超过最大重试次数）
}

export interface OutboxEventData {
  eventType: string;
  aggregateId: string;
  aggregateType: string;
  payload: Record<string, unknown>;
}

export interface OutboxEvent {
  id: bigint;
  eventType: string;
  aggregateId: string;
  aggregateType: string;
  payload: Record<string, unknown>;
  status: OutboxEventStatus;
  retryCount: number;
  maxRetries: number;
  lastError: string | null;
  nextRetryAt: Date | null;
  createdAt: Date;
  sentAt: Date | null;
  ackedAt: Date | null;
}

export interface IOutboxEventRepository {
  /**
   * 创建新的 outbox 事件
   */
  create(data: OutboxEventData): Promise<OutboxEvent>;

  /**
   * 批量创建 outbox 事件
   */
  createMany(data: OutboxEventData[]): Promise<void>;

  /**
   * 根据 ID 查找
   */
  findById(id: bigint): Promise<OutboxEvent | null>;

  /**
   * 查找待发送的事件（PENDING 状态且到达重试时间）
   */
  findPendingEvents(limit?: number): Promise<OutboxEvent[]>;

  /**
   * 查找已发送但未确认的事件（SENT 状态且超时）
   */
  findUnackedEvents(timeoutSeconds: number, limit?: number): Promise<OutboxEvent[]>;

  /**
   * 标记为已发送
   */
  markAsSent(id: bigint): Promise<void>;

  /**
   * 标记为已确认
   */
  markAsAcked(id: bigint): Promise<void>;

  /**
   * 根据聚合ID标记为已确认（用于接收 ACK 时）
   */
  markAsAckedByAggregateId(aggregateType: string, aggregateId: string, eventType: string): Promise<void>;

  /**
   * 记录发送失败，增加重试计数
   */
  recordFailure(id: bigint, error: string): Promise<void>;

  /**
   * 标记为最终失败（超过最大重试次数）
   */
  markAsFailed(id: bigint, error: string): Promise<void>;

  /**
   * 重置为待发送状态（用于手动重试）
   */
  resetToPending(id: bigint): Promise<void>;

  /**
   * 清理已确认的旧事件
   */
  cleanupAckedEvents(olderThanDays: number): Promise<number>;
}
