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

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

// ============================================
// CDC 同步数据表（从其他服务同步）
// ============================================

// 同步的用户数据
model SyncedUser {
  id              BigInt   @id @default(autoincrement())
  accountSequence String   @unique @map("account_sequence") @db.VarChar(20)
  originalUserId  BigInt   @map("original_user_id")
  phone           String?  @db.VarChar(20)
  status          String?  @db.VarChar(20)

  // CDC 同步元数据
  sourceSequenceNum BigInt   @map("source_sequence_num")
  syncedAt          DateTime @default(now()) @map("synced_at")

  // 算力计算状态
  contributionCalculated   Boolean   @default(false) @map("contribution_calculated")
  contributionCalculatedAt DateTime? @map("contribution_calculated_at")

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

  @@map("synced_users")
  @@index([originalUserId])
  @@index([contributionCalculated])
}

// 同步的认种数据
model SyncedAdoption {
  id                BigInt   @id @default(autoincrement())
  originalAdoptionId BigInt  @unique @map("original_adoption_id")
  accountSequence   String   @map("account_sequence") @db.VarChar(20)
  treeCount         Int      @map("tree_count")
  adoptionDate      DateTime @map("adoption_date") @db.Date
  status            String?  @db.VarChar(20)

  // 贡献值计算参数（从认种时的配置）
  contributionPerTree Decimal @map("contribution_per_tree") @db.Decimal(20, 10)

  // CDC 同步元数据
  sourceSequenceNum BigInt   @map("source_sequence_num")
  syncedAt          DateTime @default(now()) @map("synced_at")

  // 算力分配状态
  contributionDistributed   Boolean   @default(false) @map("contribution_distributed")
  contributionDistributedAt DateTime? @map("contribution_distributed_at")

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

  @@map("synced_adoptions")
  @@index([accountSequence])
  @@index([adoptionDate])
  @@index([contributionDistributed])
}

// 同步的推荐关系数据
model SyncedReferral {
  id                      BigInt   @id @default(autoincrement())
  accountSequence         String   @unique @map("account_sequence") @db.VarChar(20)
  referrerAccountSequence String?  @map("referrer_account_sequence") @db.VarChar(20)

  // 预计算的层级路径（便于快速查询上下级）
  ancestorPath String? @map("ancestor_path") @db.Text
  depth        Int     @default(0)

  // CDC 同步元数据
  sourceSequenceNum BigInt   @map("source_sequence_num")
  syncedAt          DateTime @default(now()) @map("synced_at")

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

  @@map("synced_referrals")
  @@index([referrerAccountSequence])
}

// ============================================
// 算力账户与明细表
// ============================================

// 算力账户表（汇总）
model ContributionAccount {
  id              BigInt @id @default(autoincrement())
  accountSequence String @unique @map("account_sequence") @db.VarChar(20)

  // 算力汇总
  personalContribution  Decimal @default(0) @map("personal_contribution") @db.Decimal(30, 10)
  teamLevelContribution Decimal @default(0) @map("team_level_contribution") @db.Decimal(30, 10)
  teamBonusContribution Decimal @default(0) @map("team_bonus_contribution") @db.Decimal(30, 10)
  totalContribution     Decimal @default(0) @map("total_contribution") @db.Decimal(30, 10)
  effectiveContribution Decimal @default(0) @map("effective_contribution") @db.Decimal(30, 10)

  // 用户条件（决定能获得多少团队算力）
  hasAdopted                  Boolean @default(false) @map("has_adopted")
  directReferralAdoptedCount  Int     @default(0) @map("direct_referral_adopted_count")

  // 解锁状态
  unlockedLevelDepth Int @default(0) @map("unlocked_level_depth")
  unlockedBonusTiers Int @default(0) @map("unlocked_bonus_tiers")

  // 乐观锁
  version Int @default(1)

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

  @@map("contribution_accounts")
  @@index([totalContribution(sort: Desc)])
  @@index([effectiveContribution(sort: Desc)])
}

// 算力明细表（分类账）
model ContributionRecord {
  id              BigInt @id @default(autoincrement())
  accountSequence String @map("account_sequence") @db.VarChar(20)

  // 来源信息（可追溯）
  sourceType             String @map("source_type") @db.VarChar(30)  // PERSONAL / TEAM_LEVEL / TEAM_BONUS
  sourceAdoptionId       BigInt @map("source_adoption_id")
  sourceAccountSequence  String @map("source_account_sequence") @db.VarChar(20)

  // 计算参数（审计用）
  treeCount        Int     @map("tree_count")
  baseContribution Decimal @map("base_contribution") @db.Decimal(20, 10)
  distributionRate Decimal @map("distribution_rate") @db.Decimal(10, 6)
  levelDepth       Int?    @map("level_depth")
  bonusTier        Int?    @map("bonus_tier")

  // 结果
  amount Decimal @map("amount") @db.Decimal(30, 10)

  // 有效期
  effectiveDate DateTime @map("effective_date") @db.Date
  expireDate    DateTime @map("expire_date") @db.Date
  isExpired     Boolean  @default(false) @map("is_expired")
  expiredAt     DateTime? @map("expired_at")

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

  @@map("contribution_records")
  @@index([accountSequence, createdAt(sort: Desc)])
  @@index([sourceAdoptionId])
  @@index([sourceAccountSequence])
  @@index([sourceType])
  @@index([expireDate])
  @@index([isExpired])
}

// 未分配算力记录（归总部）
model UnallocatedContribution {
  id                  BigInt @id @default(autoincrement())
  sourceAdoptionId    BigInt @map("source_adoption_id")
  sourceAccountSequence String @map("source_account_sequence") @db.VarChar(20)

  unallocType               String  @map("unalloc_type") @db.VarChar(30)  // LEVEL_OVERFLOW / BONUS_TIER_1/2/3
  wouldBeAccountSequence    String? @map("would_be_account_sequence") @db.VarChar(20)
  levelDepth                Int?    @map("level_depth")

  amount  Decimal  @map("amount") @db.Decimal(30, 10)
  reason  String?  @db.VarChar(200)

  // 归总部后的处理
  allocatedToHeadquarters Boolean   @default(false) @map("allocated_to_headquarters")
  allocatedAt             DateTime? @map("allocated_at")

  effectiveDate DateTime @map("effective_date") @db.Date
  expireDate    DateTime @map("expire_date") @db.Date

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

  @@map("unallocated_contributions")
  @@index([sourceAdoptionId])
  @@index([unallocType])
  @@index([allocatedToHeadquarters])
}

// 系统账户（运营/省/市/总部）
model SystemAccount {
  id          BigInt @id @default(autoincrement())
  accountType String @unique @map("account_type") @db.VarChar(20)  // OPERATION / PROVINCE / CITY / HEADQUARTERS
  name        String @db.VarChar(100)

  contributionBalance      Decimal @default(0) @map("contribution_balance") @db.Decimal(30, 10)
  contributionNeverExpires Boolean @default(false) @map("contribution_never_expires")

  version Int @default(1)

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

  records SystemContributionRecord[]

  @@map("system_accounts")
}

// 系统账户算力明细
model SystemContributionRecord {
  id                    BigInt @id @default(autoincrement())
  systemAccountId       BigInt @map("system_account_id")
  sourceAdoptionId      BigInt @map("source_adoption_id")
  sourceAccountSequence String @map("source_account_sequence") @db.VarChar(20)

  distributionRate Decimal @map("distribution_rate") @db.Decimal(10, 6)
  amount           Decimal @map("amount") @db.Decimal(30, 10)

  effectiveDate DateTime  @map("effective_date") @db.Date
  expireDate    DateTime? @map("expire_date") @db.Date
  isExpired     Boolean   @default(false) @map("is_expired")

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

  systemAccount SystemAccount @relation(fields: [systemAccountId], references: [id])

  @@map("system_contribution_records")
  @@index([systemAccountId])
  @@index([sourceAdoptionId])
}

// ============================================
// 快照与统计表
// ============================================

// 每日算力快照（用于挖矿分配计算）
model DailyContributionSnapshot {
  id            BigInt   @id @default(autoincrement())
  snapshotDate  DateTime @map("snapshot_date") @db.Date
  accountSequence String @map("account_sequence") @db.VarChar(20)

  effectiveContribution      Decimal @map("effective_contribution") @db.Decimal(30, 10)
  networkTotalContribution   Decimal @map("network_total_contribution") @db.Decimal(30, 10)
  contributionRatio          Decimal @map("contribution_ratio") @db.Decimal(30, 18)

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

  @@unique([snapshotDate, accountSequence])
  @@map("daily_contribution_snapshots")
  @@index([snapshotDate])
  @@index([accountSequence])
}

// 用户团队统计（缓存，定期更新）
model UserTeamStats {
  id              BigInt   @id @default(autoincrement())
  accountSequence String   @map("account_sequence") @db.VarChar(20)
  statsDate       DateTime @map("stats_date") @db.Date

  // 各级认种统计
  level1Trees  Int @default(0) @map("level_1_trees")
  level2Trees  Int @default(0) @map("level_2_trees")
  level3Trees  Int @default(0) @map("level_3_trees")
  level4Trees  Int @default(0) @map("level_4_trees")
  level5Trees  Int @default(0) @map("level_5_trees")
  level6Trees  Int @default(0) @map("level_6_trees")
  level7Trees  Int @default(0) @map("level_7_trees")
  level8Trees  Int @default(0) @map("level_8_trees")
  level9Trees  Int @default(0) @map("level_9_trees")
  level10Trees Int @default(0) @map("level_10_trees")
  level11Trees Int @default(0) @map("level_11_trees")
  level12Trees Int @default(0) @map("level_12_trees")
  level13Trees Int @default(0) @map("level_13_trees")
  level14Trees Int @default(0) @map("level_14_trees")
  level15Trees Int @default(0) @map("level_15_trees")

  totalTeamTrees          Int @default(0) @map("total_team_trees")
  directAdoptedReferrals  Int @default(0) @map("direct_adopted_referrals")

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

  @@unique([accountSequence, statsDate])
  @@map("user_team_stats")
  @@index([accountSequence])
  @@index([statsDate])
}

// ============================================
// CDC 同步状态追踪
// ============================================

// CDC 同步进度表
model CdcSyncProgress {
  id             BigInt   @id @default(autoincrement())
  sourceTopic    String   @unique @map("source_topic") @db.VarChar(100)
  lastSequenceNum BigInt  @default(0) @map("last_sequence_num")
  lastSyncedAt   DateTime? @map("last_synced_at")

  updatedAt DateTime @updatedAt @map("updated_at")

  @@map("cdc_sync_progress")
}

// 已处理事件表（幂等性）
model ProcessedEvent {
  id            BigInt   @id @default(autoincrement())
  eventId       String   @unique @map("event_id") @db.VarChar(100)
  eventType     String   @map("event_type") @db.VarChar(50)
  sourceService String?  @map("source_service") @db.VarChar(50)

  processedAt DateTime @default(now()) @map("processed_at")

  @@map("processed_events")
  @@index([eventType])
  @@index([processedAt])
}

// ============================================
// 配置表
// ============================================

// 贡献值递增配置
model ContributionConfig {
  id BigInt @id @default(autoincrement())

  baseContribution     Decimal @default(22617) @map("base_contribution") @db.Decimal(20, 10)
  incrementPercentage  Decimal @default(0.003) @map("increment_percentage") @db.Decimal(10, 6)
  unitSize             Int     @default(100) @map("unit_size")
  startTreeNumber      Int     @default(1000) @map("start_tree_number")

  isActive Boolean @default(true) @map("is_active")

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

  @@map("contribution_configs")
  @@index([isActive])
}

// 分配比例配置
model DistributionRateConfig {
  id BigInt @id @default(autoincrement())

  rateType    String  @unique @map("rate_type") @db.VarChar(30)
  rateValue   Decimal @map("rate_value") @db.Decimal(10, 6)
  description String? @db.VarChar(100)

  isActive Boolean @default(true) @map("is_active")

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

  @@map("distribution_rate_configs")
  @@index([isActive])
}

// ============================================
// Outbox 事件表（可靠事件发布）
// ============================================

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)

  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])
  @@index([status, nextRetryAt])
  @@index([aggregateType, aggregateId])
  @@index([topic])
}
