generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

// ============================================
// 转让订单表 (Saga 聚合根)
// ============================================
model TransferOrder {
  id                     BigInt    @id @default(autoincrement())
  transferOrderNo        String    @unique @map("transfer_order_no") @db.VarChar(50)

  // ========== 卖方信息 ==========
  sellerUserId           BigInt    @map("seller_user_id")
  sellerAccountSequence  String    @map("seller_account_sequence") @db.VarChar(20)

  // ========== 买方信息 ==========
  buyerUserId            BigInt    @map("buyer_user_id")
  buyerAccountSequence   String    @map("buyer_account_sequence") @db.VarChar(20)

  // ========== 转让标的 ==========
  sourceOrderNo          String    @map("source_order_no") @db.VarChar(50)
  sourceAdoptionId       BigInt    @map("source_adoption_id")
  treeCount              Int       @map("tree_count")
  contributionPerTree    Decimal   @map("contribution_per_tree") @db.Decimal(20, 10)
  originalAdoptionDate   DateTime  @map("original_adoption_date") @db.Date
  originalExpireDate     DateTime  @map("original_expire_date") @db.Date
  selectedProvince       String    @map("selected_province") @db.VarChar(10)
  selectedCity           String    @map("selected_city") @db.VarChar(10)

  // ========== 价格与费用 ==========
  transferPrice          Decimal   @map("transfer_price") @db.Decimal(20, 8)
  platformFeeRate        Decimal   @map("platform_fee_rate") @db.Decimal(5, 4)
  platformFeeAmount      Decimal   @map("platform_fee_amount") @db.Decimal(20, 8)
  sellerReceiveAmount    Decimal   @map("seller_receive_amount") @db.Decimal(20, 8)

  // ========== Saga 状态 ==========
  status                 String    @default("PENDING") @map("status") @db.VarChar(30)
  sagaStep               String    @default("INIT") @map("saga_step") @db.VarChar(30)
  failReason             String?   @map("fail_reason") @db.VarChar(500)
  retryCount             Int       @default(0) @map("retry_count")

  // ========== 各步骤确认时间戳 ==========
  sellerConfirmedAt      DateTime? @map("seller_confirmed_at")
  paymentFrozenAt        DateTime? @map("payment_frozen_at")
  treesLockedAt          DateTime? @map("trees_locked_at")
  ownershipTransferredAt DateTime? @map("ownership_transferred_at")
  contributionAdjustedAt DateTime? @map("contribution_adjusted_at")
  statsUpdatedAt         DateTime? @map("stats_updated_at")
  paymentSettledAt       DateTime? @map("payment_settled_at")
  completedAt            DateTime? @map("completed_at")
  cancelledAt            DateTime? @map("cancelled_at")
  rolledBackAt           DateTime? @map("rolled_back_at")

  createdAt              DateTime  @default(now()) @map("created_at")
  updatedAt              DateTime  @updatedAt @map("updated_at")

  statusLogs             TransferStatusLog[]

  @@index([sellerUserId])
  @@index([buyerUserId])
  @@index([sourceOrderNo])
  @@index([status])
  @@index([createdAt])
  @@map("transfer_orders")
}

// ============================================
// 状态变更日志表 (审计)
// ============================================
model TransferStatusLog {
  id               BigInt   @id @default(autoincrement())
  transferOrderNo  String   @map("transfer_order_no") @db.VarChar(50)
  fromStatus       String   @map("from_status") @db.VarChar(30)
  toStatus         String   @map("to_status") @db.VarChar(30)
  fromSagaStep     String   @map("from_saga_step") @db.VarChar(30)
  toSagaStep       String   @map("to_saga_step") @db.VarChar(30)
  operatorType     String   @map("operator_type") @db.VarChar(20)
  operatorId       String?  @map("operator_id") @db.VarChar(50)
  remark           String?  @db.VarChar(500)
  createdAt        DateTime @default(now()) @map("created_at")

  transferOrder    TransferOrder @relation(fields: [transferOrderNo], references: [transferOrderNo])

  @@index([transferOrderNo])
  @@map("transfer_status_logs")
}

// ============================================
// Outbox 事件表 (标准 Outbox Pattern)
// ============================================
model OutboxEvent {
  id             BigInt    @id @default(autoincrement())
  eventType      String    @map("event_type") @db.VarChar(100)
  topic          String    @db.VarChar(200)
  key            String    @db.VarChar(200)
  payload        Json
  aggregateId    String    @map("aggregate_id") @db.VarChar(100)
  aggregateType  String    @map("aggregate_type") @db.VarChar(100)
  status         String    @default("PENDING") @db.VarChar(20)
  retryCount     Int       @default(0) @map("retry_count")
  maxRetries     Int       @default(5) @map("max_retries")
  lastError      String?   @map("last_error") @db.VarChar(1000)
  publishedAt    DateTime? @map("published_at")
  nextRetryAt    DateTime? @map("next_retry_at")
  createdAt      DateTime  @default(now()) @map("created_at")

  @@index([status, createdAt])
  @@index([status, nextRetryAt])
  @@map("outbox_events")
}

// ============================================
// 已处理事件表 (幂等性保证)
// ============================================
model ProcessedEvent {
  id             BigInt   @id @default(autoincrement())
  eventId        String   @unique @map("event_id") @db.VarChar(200)
  eventType      String   @map("event_type") @db.VarChar(100)
  processedAt    DateTime @default(now()) @map("processed_at")

  @@map("processed_events")
}
