// ============================================
// [2026-02-17] 预种计划独立 Prisma Schema
// ============================================
//
// 本 schema 仅包含预种计划在 contribution-service 中的追踪表。
// 与主 schema (prisma/schema.prisma) 完全隔离，拥有独立的：
// - Prisma Client（生成到 src/pre-planting/infrastructure/prisma/generated/）
// - Migration 目录（prisma/pre-planting/migrations/）
//
// 预种的算力分配结果仍然写入主 schema 的 contribution_accounts、
// contribution_records 等表（通过现有 Repository），以便挖矿系统读取。
// 本 schema 仅负责预种 CDC 同步追踪、冻结状态等预种专属数据。

generator client {
  provider = "prisma-client-js"
  output   = "../../src/pre-planting/infrastructure/prisma/generated"
}

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

// ============================================
// 预种 CDC 同步追踪表
// ============================================

/// 预种订单同步记录（从 planting-service CDC 同步）
/// 用于追踪每笔预种订单的算力分配状态
model PrePlantingSyncedOrder {
  id              BigInt   @id @default(autoincrement())
  originalOrderId BigInt   @unique @map("original_order_id")
  orderNo         String   @unique @map("order_no") @db.VarChar(50)
  userId          BigInt   @map("user_id")
  accountSequence String   @map("account_sequence") @db.VarChar(20)
  portionCount    Int      @map("portion_count")
  pricePerPortion Decimal  @map("price_per_portion") @db.Decimal(20, 8)
  totalAmount     Decimal  @map("total_amount") @db.Decimal(20, 8)
  provinceCode    String   @map("province_code") @db.VarChar(10)
  cityCode        String   @map("city_code") @db.VarChar(10)
  status          String   @map("status") @db.VarChar(20) // CREATED, PAID, MERGED
  mergedToMergeId BigInt?  @map("merged_to_merge_id")
  paidAt          DateTime? @map("paid_at")
  createdAt       DateTime @map("created_at")

  // 算力追踪
  contributionPerPortion      Decimal   @map("contribution_per_portion") @db.Decimal(20, 10)
  contributionDistributed     Boolean   @default(false) @map("contribution_distributed")
  contributionDistributedAt   DateTime? @map("contribution_distributed_at")

  // CDC 同步元数据
  sourceTopic  String   @map("source_topic") @db.VarChar(200)
  sourceOffset BigInt   @map("source_offset")
  syncedAt     DateTime @default(now()) @map("synced_at")

  @@index([accountSequence])
  @@index([status])
  @@index([contributionDistributed])
  @@map("pre_planting_synced_orders")
}

/// 预种持仓同步记录（从 planting-service CDC 同步）
/// 用于追踪用户预种总量，判断冻结条件
model PrePlantingSyncedPosition {
  id              BigInt   @id @default(autoincrement())
  userId          BigInt   @unique @map("user_id")
  accountSequence String   @unique @map("account_sequence") @db.VarChar(20)
  totalPortions   Int      @default(0) @map("total_portions")
  mergedPortions  Int      @default(0) @map("merged_portions")
  totalTreesMerged Int     @default(0) @map("total_trees_merged")
  firstPurchaseAt DateTime? @map("first_purchase_at")

  // CDC 同步元数据
  sourceTopic  String   @map("source_topic") @db.VarChar(200)
  sourceOffset BigInt   @map("source_offset")
  syncedAt     DateTime @default(now()) @map("synced_at")

  @@map("pre_planting_synced_positions")
}

// ============================================
// 预种冻结状态表
// ============================================

/// 预种算力冻结状态（每用户一条）
///
/// 冻结规则：
/// - firstPurchaseAt + 1 年后仍未满 5 份 → 所有预种算力冻结（暂停分配）
/// - 后续累积满 5 份 → 解冻，恢复分配
/// - 解冻后的失效期 = 解冻日起算 + 2 年
/// - 未被冻结过的正常到期 = 首次产生挖矿收益日 + 2 年
model PrePlantingFreezeState {
  id              BigInt  @id @default(autoincrement())
  accountSequence String  @unique @map("account_sequence") @db.VarChar(20)
  totalPortions   Int     @default(0) @map("total_portions")
  totalTreesMerged Int    @default(0) @map("total_trees_merged")
  firstPurchaseAt DateTime? @map("first_purchase_at")

  // 冻结状态
  isFrozen  Boolean   @default(false) @map("is_frozen")
  frozenAt  DateTime? @map("frozen_at")
  unfrozenAt DateTime? @map("unfrozen_at")

  // 解冻后的过期日期（解冻日 + 2 年）
  postUnfreezeExpireDate DateTime? @map("post_unfreeze_expire_date")

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

  @@index([isFrozen])
  @@index([firstPurchaseAt])
  @@map("pre_planting_freeze_states")
}

// ============================================
// 预种 CDC 幂等性追踪表
// ============================================

// ============================================
// 预种合成树追踪表
// ============================================

/// 预种合成树算力切换记录（幂等标记）
///
/// 每当5份预种合成1棵树并签署合同后（mining_enabled_at 写入），
/// contribution-service 完成算力切换后写入本表作为幂等标记。
/// 记录旧份额的 sourceOrderNos 和新树的 newSourceAdoptionId，
/// 便于审计和追溯。
model PrePlantingSyncedMerge {
  id                  BigInt   @id @default(autoincrement())
  mergeNo             String   @unique @map("merge_no") @db.VarChar(50)
  accountSequence     String   @map("account_sequence") @db.VarChar(20)
  sourceOrderNos      Json     @map("source_order_nos")        // 原5份订单号（JSON 数组）
  newSourceAdoptionId BigInt   @map("new_source_adoption_id")  // 新树算力的 sourceAdoptionId（20B + mergeId）
  swappedAt           DateTime @default(now()) @map("swapped_at")

  // CDC 同步元数据
  sourceTopic  String @map("source_topic") @db.VarChar(200)
  sourceOffset BigInt @map("source_offset")

  @@index([accountSequence])
  @@map("pre_planting_synced_merges")
}

// ============================================
// 预种 CDC 幂等性追踪表
// ============================================

/// 已处理的预种 CDC 事件（幂等性保证）
/// 使用 (sourceTopic, offset) 作为复合唯一键
model PrePlantingProcessedCdcEvent {
  id          BigInt   @id @default(autoincrement())
  sourceTopic String   @map("source_topic") @db.VarChar(200)
  offset      BigInt   @map("offset")
  tableName   String   @map("table_name") @db.VarChar(100)
  operation   String   @map("operation") @db.VarChar(10)
  processedAt DateTime @default(now()) @map("processed_at")

  @@unique([sourceTopic, offset])
  @@index([processedAt])
  @@map("pre_planting_processed_cdc_events")
}

// ============================================
// 预种卖出限制表
// ============================================

/// 预种卖出限制手动解除记录
///
/// 判断逻辑：isRestricted = has_pre_planting_marker AND !has_real_tree AND !admin_override
/// 本表记录管理员手动解除的账户，写入后不会自动恢复。
model PrePlantingSellRestrictionOverride {
  accountSequence String   @id @map("account_sequence") @db.VarChar(20)
  unlockedBy      String   @map("unlocked_by") @db.VarChar(50) // 管理员 accountSequence 或 'ADMIN_MANUAL'
  reason          String?  @db.VarChar(200)
  createdAt       DateTime @default(now()) @map("created_at")

  @@map("pre_planting_sell_restriction_overrides")
}
