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

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

// ============================================
// 奖励流水表 (聚合根1 - 行为表, append-only)
// 记录每一笔奖励的创建、领取、结算、过期
// ============================================
model RewardLedgerEntry {
  id              BigInt   @id @default(autoincrement()) @map("entry_id")
  userId          BigInt   @map("user_id")  // 接收奖励的用户ID
  accountSequence String   @map("account_sequence") @db.VarChar(20)  // 账户序列号

  // === 奖励来源 ===
  sourceOrderNo         String   @map("source_order_no") @db.VarChar(50)  // 来源认种订单号(字符串格式如PLT1765391584505Q0Q6QD)
  sourceUserId          BigInt   @map("source_user_id")    // 触发奖励的用户ID(认种者)
  sourceAccountSequence String?  @map("source_account_sequence") @db.VarChar(20)  // 触发奖励的用户账户序列号
  rightType             String   @map("right_type") @db.VarChar(50)  // 权益类型

  // === 奖励金额 ===
  usdtAmount      Decimal  @map("usdt_amount") @db.Decimal(20, 8)
  hashpowerAmount Decimal  @default(0) @map("hashpower_amount") @db.Decimal(20, 8)

  // === 奖励状态 ===
  rewardStatus    String   @default("PENDING") @map("reward_status") @db.VarChar(20)

  // === 时间戳 ===
  createdAt       DateTime @default(now()) @map("created_at") @db.Timestamp(6)
  expireAt        DateTime? @map("expire_at")       // 过期时间(24h后)
  claimedAt       DateTime? @map("claimed_at")      // 领取时间(用户认种)
  settledAt       DateTime? @map("settled_at")      // 结算时间
  expiredAt       DateTime? @map("expired_at")      // 实际过期时间

  // === 备注 ===
  memo            String?  @map("memo") @db.VarChar(500)

  @@map("reward_ledger_entries")
  @@index([userId, rewardStatus], name: "idx_user_status")
  @@index([userId, createdAt(sort: Desc)], name: "idx_user_created")
  @@index([accountSequence, rewardStatus], name: "idx_account_status")
  @@index([accountSequence, createdAt(sort: Desc)], name: "idx_account_created")
  @@index([sourceOrderNo], name: "idx_source_order")
  @@index([sourceUserId], name: "idx_source_user")
  @@index([sourceAccountSequence], name: "idx_source_account_seq")
  @@index([rightType], name: "idx_right_type")
  @@index([rewardStatus], name: "idx_status")
  @@index([expireAt], name: "idx_expire")
  @@index([createdAt], name: "idx_created")
}

// ============================================
// 奖励汇总表 (聚合根2 - 状态表)
// 每个用户的收益汇总，从流水表聚合
// ============================================
model RewardSummary {
  id              BigInt   @id @default(autoincrement()) @map("summary_id")
  userId          BigInt   @unique @map("user_id")
  accountSequence String   @unique @map("account_sequence") @db.VarChar(20)  // 账户序列号

  // === 待领取收益 (24h倒计时) ===
  pendingUsdt         Decimal  @default(0) @map("pending_usdt") @db.Decimal(20, 8)
  pendingHashpower    Decimal  @default(0) @map("pending_hashpower") @db.Decimal(20, 8)
  pendingExpireAt     DateTime? @map("pending_expire_at")  // 最早过期时间

  // === 可结算收益 ===
  settleableUsdt      Decimal  @default(0) @map("settleable_usdt") @db.Decimal(20, 8)
  settleableHashpower Decimal  @default(0) @map("settleable_hashpower") @db.Decimal(20, 8)

  // === 已结算收益 (累计) ===
  settledTotalUsdt      Decimal  @default(0) @map("settled_total_usdt") @db.Decimal(20, 8)
  settledTotalHashpower Decimal  @default(0) @map("settled_total_hashpower") @db.Decimal(20, 8)

  // === 已过期收益 (累计) ===
  expiredTotalUsdt      Decimal  @default(0) @map("expired_total_usdt") @db.Decimal(20, 8)
  expiredTotalHashpower Decimal  @default(0) @map("expired_total_hashpower") @db.Decimal(20, 8)

  // === 时间戳 ===
  lastUpdateAt    DateTime @default(now()) @updatedAt @map("last_update_at")
  createdAt       DateTime @default(now()) @map("created_at")

  @@map("reward_summaries")
  @@index([userId], name: "idx_summary_user")
  @@index([accountSequence], name: "idx_summary_account")
  @@index([settleableUsdt(sort: Desc)], name: "idx_settleable_desc")
  @@index([pendingExpireAt], name: "idx_pending_expire")
}

// ============================================
// 权益定义表 (配置表)
// 定义每种权益的奖励规则
// ============================================
model RightDefinition {
  id              BigInt   @id @default(autoincrement()) @map("definition_id")
  rightType       String   @unique @map("right_type") @db.VarChar(50)

  // === 奖励规则 ===
  usdtPerTree       Decimal  @map("usdt_per_tree") @db.Decimal(20, 8)
  hashpowerPercent  Decimal  @default(0) @map("hashpower_percent") @db.Decimal(5, 2)

  // === 分配目标 ===
  payableTo         String   @map("payable_to") @db.VarChar(50)  // USER_ACCOUNT/SYSTEM_ACCOUNT/HEADQUARTERS

  // === 规则描述 ===
  ruleDescription   String?  @map("rule_description") @db.Text

  // === 启用状态 ===
  isEnabled         Boolean  @default(true) @map("is_enabled")

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

  @@map("right_definitions")
  @@index([rightType], name: "idx_def_right_type")
  @@index([isEnabled], name: "idx_def_enabled")
}

// ============================================
// 结算记录表 (行为表)
// 记录每次结算的详情
// ============================================
model SettlementRecord {
  id              BigInt   @id @default(autoincrement()) @map("settlement_id")
  userId          BigInt   @map("user_id")
  accountSequence String   @map("account_sequence") @db.VarChar(20)  // 账户序列号

  // === 结算金额 ===
  usdtAmount      Decimal  @map("usdt_amount") @db.Decimal(20, 8)
  hashpowerAmount Decimal  @map("hashpower_amount") @db.Decimal(20, 8)

  // === 结算币种 ===
  settleCurrency  String   @map("settle_currency") @db.VarChar(10)  // BNB/OG/USDT/DST
  receivedAmount  Decimal  @map("received_amount") @db.Decimal(20, 8)  // 实际收到的币种数量

  // === 交易信息 ===
  swapTxHash      String?  @map("swap_tx_hash") @db.VarChar(100)
  swapRate        Decimal? @map("swap_rate") @db.Decimal(20, 8)  // SWAP汇率

  // === 状态 ===
  status          String   @default("PENDING") @map("status") @db.VarChar(20)  // PENDING/SUCCESS/FAILED

  // === 时间戳 ===
  createdAt       DateTime @default(now()) @map("created_at")
  completedAt     DateTime? @map("completed_at")

  // === 关联的奖励条目ID列表 ===
  rewardEntryIds  BigInt[] @map("reward_entry_ids")

  @@map("settlement_records")
  @@index([userId], name: "idx_settlement_user")
  @@index([accountSequence], name: "idx_settlement_account")
  @@index([status], name: "idx_settlement_status")
  @@index([createdAt], name: "idx_settlement_created")
}

// ============================================
// 奖励事件表 (行为表, append-only)
// 用于事件溯源和审计
// ============================================
model RewardEvent {
  id            BigInt   @id @default(autoincrement()) @map("event_id")
  eventType     String   @map("event_type") @db.VarChar(50)

  // 聚合根信息
  aggregateId   String   @map("aggregate_id") @db.VarChar(100)
  aggregateType String   @map("aggregate_type") @db.VarChar(50)

  // 事件数据
  eventData     Json     @map("event_data")

  // 元数据
  userId        BigInt?  @map("user_id")
  occurredAt    DateTime @default(now()) @map("occurred_at") @db.Timestamp(6)
  version       Int      @default(1) @map("version")

  @@map("reward_events")
  @@index([aggregateType, aggregateId], name: "idx_reward_event_aggregate")
  @@index([eventType], name: "idx_reward_event_type")
  @@index([userId], name: "idx_reward_event_user")
  @@index([occurredAt], name: "idx_reward_event_occurred")
}

// ============================================
// Outbox 事件发件箱表 (Outbox Pattern)
// 保证事件发布的可靠性：
// 1. 业务数据和 Outbox 记录在同一个事务中写入
// 2. 后台任务轮询 Outbox 表并发布到 Kafka
// 3. 消费方确认后标记为 CONFIRMED
// ============================================
model OutboxEvent {
  id BigInt @id @default(autoincrement()) @map("outbox_id")

  // 事件信息
  eventType String @map("event_type") @db.VarChar(100)
  topic     String @map("topic") @db.VarChar(100)
  key       String @map("key") @db.VarChar(200)
  payload   Json   @map("payload")

  // 聚合根信息 (用于幂等性检查)
  aggregateId   String @map("aggregate_id") @db.VarChar(100)
  aggregateType String @map("aggregate_type") @db.VarChar(50)

  // 发布状态: PENDING -> SENT -> CONFIRMED 或 FAILED
  status     String  @default("PENDING") @map("status") @db.VarChar(20)
  retryCount Int     @default(0) @map("retry_count")
  maxRetries Int     @default(5) @map("max_retries")
  lastError  String? @map("last_error") @db.Text

  // 时间戳
  createdAt   DateTime  @default(now()) @map("created_at")
  publishedAt DateTime? @map("published_at")
  nextRetryAt DateTime? @map("next_retry_at")

  @@map("outbox_events")
  @@index([status, createdAt], name: "idx_outbox_status_created")
  @@index([status, nextRetryAt], name: "idx_outbox_status_retry")
  @@index([aggregateType, aggregateId], name: "idx_outbox_aggregate")
  @@index([topic], name: "idx_outbox_topic")
}
