// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

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

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

// ============================================
// 监控地址表
// 存储需要监听充值的地址（用户地址和系统账户地址）
// ============================================
model MonitoredAddress {
  id BigInt @id @default(autoincrement()) @map("address_id")

  chainType String @map("chain_type") @db.VarChar(20) // KAVA, BSC
  address   String @db.VarChar(42) // 0x地址

  // 地址类型: USER (用户钱包) 或 SYSTEM (系统账户)
  addressType String @default("USER") @map("address_type") @db.VarChar(20)

  // 用户地址关联 (addressType = USER 时使用)
  accountSequence String? @map("account_sequence") @db.VarChar(20) // 跨服务关联标识 (格式: D + YYMMDD + 5位序号)
  userId          BigInt? @map("user_id") // 保留兼容

  // 系统账户关联 (addressType = SYSTEM 时使用)
  systemAccountType String? @map("system_account_type") @db.VarChar(50) // COST_ACCOUNT, OPERATION_ACCOUNT, etc.
  systemAccountId   BigInt? @map("system_account_id")
  regionCode        String? @map("region_code") @db.VarChar(10) // 省市代码（省市账户用）

  isActive Boolean @default(true) @map("is_active") // 是否激活监听

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

  deposits DepositTransaction[]

  @@unique([chainType, address], name: "uk_chain_address")
  @@index([accountSequence], name: "idx_account_sequence")
  @@index([userId], name: "idx_user")
  @@index([addressType, isActive], name: "idx_type_active")
  @@index([chainType, isActive], name: "idx_chain_active")
  @@index([systemAccountType], name: "idx_system_account_type")
  @@map("monitored_addresses")
}

// ============================================
// 充值交易表 (Append-Only)
// 记录检测到的所有充值交易
// ============================================
model DepositTransaction {
  id BigInt @id @default(autoincrement()) @map("deposit_id")

  chainType String @map("chain_type") @db.VarChar(20)
  txHash    String @unique @map("tx_hash") @db.VarChar(66)

  fromAddress String @map("from_address") @db.VarChar(42)
  toAddress   String @map("to_address") @db.VarChar(42)

  tokenContract   String  @map("token_contract") @db.VarChar(42) // USDT合约地址
  amount          Decimal @db.Decimal(78, 0) // 原始金额 (wei单位，无小数)
  amountFormatted Decimal @map("amount_formatted") @db.Decimal(36, 8) // 格式化金额 (支持大额)

  blockNumber    BigInt   @map("block_number")
  blockTimestamp DateTime @map("block_timestamp")
  logIndex       Int      @map("log_index")

  // 确认状态
  confirmations Int    @default(0)
  status        String @default("DETECTED") @db.VarChar(20) // DETECTED, CONFIRMING, CONFIRMED, NOTIFIED

  // 关联 - 使用 accountSequence 作为跨服务主键
  addressId   BigInt @map("address_id")
  addressType String @default("USER") @map("address_type") @db.VarChar(20) // USER 或 SYSTEM

  // 用户地址关联
  accountSequence String? @map("account_sequence") @db.VarChar(20) // 跨服务关联标识 (格式: D + YYMMDD + 5位序号)
  userId          BigInt? @map("user_id") // 保留兼容

  // 系统账户关联（当 addressType = SYSTEM 时）
  systemAccountType String? @map("system_account_type") @db.VarChar(50)
  systemAccountId   BigInt? @map("system_account_id")

  // 通知状态
  notifiedAt      DateTime? @map("notified_at")
  notifyAttempts  Int       @default(0) @map("notify_attempts")
  lastNotifyError String?   @map("last_notify_error") @db.Text

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

  monitoredAddress MonitoredAddress @relation(fields: [addressId], references: [id])

  @@index([chainType, status], name: "idx_chain_status")
  @@index([accountSequence], name: "idx_deposit_account")
  @@index([userId], name: "idx_deposit_user")
  @@index([blockNumber], name: "idx_block")
  @@index([status, notifiedAt], name: "idx_pending_notify")
  @@map("deposit_transactions")
}

// ============================================
// 区块扫描检查点 (每条链一条记录)
// 记录扫描进度，用于断点续扫
// ============================================
model BlockCheckpoint {
  id BigInt @id @default(autoincrement()) @map("checkpoint_id")

  chainType String @unique @map("chain_type") @db.VarChar(20)

  lastScannedBlock BigInt   @map("last_scanned_block")
  lastScannedAt    DateTime @map("last_scanned_at")

  // 健康状态
  isHealthy Boolean @default(true) @map("is_healthy")
  lastError String? @map("last_error") @db.Text

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

  @@map("block_checkpoints")
}

// ============================================
// 交易广播请求表
// 记录待广播和已广播的交易
// ============================================
model TransactionRequest {
  id BigInt @id @default(autoincrement()) @map("request_id")

  chainType String @map("chain_type") @db.VarChar(20)

  // 请求来源
  sourceService String @map("source_service") @db.VarChar(50)
  sourceOrderId String @map("source_order_id") @db.VarChar(100)

  // 交易数据
  fromAddress String  @map("from_address") @db.VarChar(42)
  toAddress   String  @map("to_address") @db.VarChar(42)
  value       Decimal @db.Decimal(36, 18)
  data        String? @db.Text // 合约调用数据

  // 签名数据 (由 MPC 服务提供)
  signedTx String? @map("signed_tx") @db.Text

  // 广播结果
  txHash String? @map("tx_hash") @db.VarChar(66)
  status String  @default("PENDING") @db.VarChar(20) // PENDING, SIGNED, BROADCASTED, CONFIRMED, FAILED

  // Gas 信息
  gasLimit BigInt?  @map("gas_limit")
  gasPrice Decimal? @map("gas_price") @db.Decimal(36, 18)
  nonce    Int?

  // 错误信息
  errorMessage String? @map("error_message") @db.Text
  retryCount   Int     @default(0) @map("retry_count")

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

  @@unique([sourceService, sourceOrderId], name: "uk_source_order")
  @@index([chainType, status], name: "idx_tx_chain_status")
  @@index([txHash], name: "idx_tx_hash")
  @@map("transaction_requests")
}

// ============================================
// 账户恢复助记词
// 与账户序列号关联，用于账户恢复验证
// ============================================
model RecoveryMnemonic {
  id              BigInt @id @default(autoincrement())
  accountSequence String @map("account_sequence") @db.VarChar(20) // 账户序列号 (格式: D + YYMMDD + 5位序号)
  publicKey       String @map("public_key") @db.VarChar(130) // 关联的钱包公钥

  // 助记词存储 (加密)
  encryptedMnemonic String @map("encrypted_mnemonic") @db.Text // AES加密的助记词
  mnemonicHash      String @map("mnemonic_hash") @db.VarChar(64) // SHA256哈希（用于验证）

  // 状态管理
  status     String  @default("ACTIVE") @db.VarChar(20) // ACTIVE, REVOKED, REPLACED
  isBackedUp Boolean @default(false) @map("is_backed_up") // 用户是否已备份

  // 挂失/更换相关
  revokedAt     DateTime? @map("revoked_at")
  revokedReason String?   @map("revoked_reason") @db.VarChar(200)
  replacedById  BigInt?   @map("replaced_by_id") // 被哪个新助记词替代

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

  @@unique([accountSequence, status], name: "uk_account_active_mnemonic") // 一个账户只有一个ACTIVE助记词
  @@index([accountSequence], name: "idx_recovery_account")
  @@index([publicKey], name: "idx_recovery_public_key")
  @@index([status], name: "idx_recovery_status")
  @@map("recovery_mnemonics")
}

// ============================================
// Outbox 事件表 (发件箱模式)
// 保证事件发布的可靠性
// ============================================
model OutboxEvent {
  id BigInt @id @default(autoincrement()) @map("event_id")

  // 事件信息
  eventType     String @map("event_type") @db.VarChar(100)
  aggregateId   String @map("aggregate_id") @db.VarChar(100)
  aggregateType String @map("aggregate_type") @db.VarChar(50)
  payload       Json   @map("payload")

  // 发送状态: PENDING -> SENT -> ACKED / FAILED
  status String @default("PENDING") @db.VarChar(20)

  // 重试信息
  retryCount  Int       @default(0) @map("retry_count")
  maxRetries  Int       @default(10) @map("max_retries")
  lastError   String?   @map("last_error") @db.Text
  nextRetryAt DateTime? @map("next_retry_at")

  // 时间戳
  createdAt DateTime  @default(now()) @map("created_at")
  sentAt    DateTime? @map("sent_at")
  ackedAt   DateTime? @map("acked_at")

  @@index([status, nextRetryAt], name: "idx_outbox_pending")
  @@index([aggregateType, aggregateId], name: "idx_outbox_aggregate")
  @@index([eventType], name: "idx_outbox_event_type")
  @@index([createdAt], name: "idx_outbox_created")
  @@map("outbox_events")
}

// ============================================
// 区块链事件日志 (Append-Only 审计)
// ============================================
model BlockchainEvent {
  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")

  chainType String? @map("chain_type") @db.VarChar(20)
  txHash    String? @map("tx_hash") @db.VarChar(66)

  occurredAt DateTime @default(now()) @map("occurred_at") @db.Timestamp(6)

  @@index([aggregateType, aggregateId], name: "idx_event_aggregate")
  @@index([eventType], name: "idx_event_type")
  @@index([chainType], name: "idx_event_chain")
  @@index([occurredAt], name: "idx_event_occurred")
  @@map("blockchain_events")
}

// ============================================
// 做市商充值交易表
// 记录检测到的做市商钱包 eUSDT/fUSDT 充值
// ============================================
model MarketMakerDeposit {
  id BigInt @id @default(autoincrement()) @map("deposit_id")

  chainType String @map("chain_type") @db.VarChar(20) // KAVA
  txHash    String @unique @map("tx_hash") @db.VarChar(66)

  fromAddress String @map("from_address") @db.VarChar(42)
  toAddress   String @map("to_address") @db.VarChar(42) // 做市商钱包地址

  // 代币类型: EUSDT (积分股) 或 FUSDT (积分值)
  assetType     String  @map("asset_type") @db.VarChar(10)
  tokenContract String  @map("token_contract") @db.VarChar(42)
  amount        Decimal @db.Decimal(78, 0) // 原始金额 (wei单位)
  amountFormatted Decimal @map("amount_formatted") @db.Decimal(36, 8) // 格式化金额

  blockNumber    BigInt   @map("block_number")
  blockTimestamp DateTime @map("block_timestamp")
  logIndex       Int      @map("log_index")

  // 确认状态
  confirmations Int    @default(0)
  status        String @default("DETECTED") @db.VarChar(20) // DETECTED, CONFIRMING, CONFIRMED, CREDITED, FAILED

  // 通知状态 (通知 trading-service 记账)
  notifiedAt      DateTime? @map("notified_at")
  notifyAttempts  Int       @default(0) @map("notify_attempts")
  lastNotifyError String?   @map("last_notify_error") @db.Text

  // 记账状态 (trading-service 确认)
  creditedAt      DateTime? @map("credited_at")
  creditReference String?   @map("credit_reference") @db.VarChar(100) // 记账流水号

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

  @@index([chainType, status], name: "idx_mm_chain_status")
  @@index([assetType], name: "idx_mm_asset_type")
  @@index([blockNumber], name: "idx_mm_block")
  @@index([status, notifiedAt], name: "idx_mm_pending_notify")
  @@map("market_maker_deposits")
}

// ============================================
// 做市商区块扫描检查点
// 独立于普通用户的扫描进度
// ============================================
model MarketMakerBlockCheckpoint {
  id BigInt @id @default(autoincrement()) @map("checkpoint_id")

  chainType String @map("chain_type") @db.VarChar(20)
  assetType String @map("asset_type") @db.VarChar(10) // EUSDT 或 FUSDT

  lastScannedBlock BigInt   @map("last_scanned_block")
  lastScannedAt    DateTime @map("last_scanned_at")

  isHealthy Boolean @default(true) @map("is_healthy")
  lastError String? @map("last_error") @db.Text

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

  @@unique([chainType, assetType], name: "uk_mm_chain_asset")
  @@map("market_maker_block_checkpoints")
}

// ============================================
// 认种 fUSDT 注入分类账（对账用）
// 记录每笔认种触发的 fUSDT 自动注入转账
// ============================================
model AdoptionInjectionRecord {
  id BigInt @id @default(autoincrement()) @map("record_id")

  // 认种信息
  adoptionId      String   @map("adoption_id") @db.VarChar(100) // 1.0 原始认种ID
  accountSequence String   @map("account_sequence") @db.VarChar(20) // 用户账户序列号
  treeCount       Int      @map("tree_count") // 认种数量（棵）
  adoptionDate    DateTime @map("adoption_date") // 认种时间

  // 转账信息
  fromAddress String  @map("from_address") @db.VarChar(42) // 注入钱包地址
  toAddress   String  @map("to_address") @db.VarChar(42) // 做市商钱包地址
  amount      Decimal @db.Decimal(36, 8) // 转账金额 (treeCount × 5760)
  chainType   String  @map("chain_type") @db.VarChar(20) // KAVA

  // 链上结果
  txHash      String? @map("tx_hash") @db.VarChar(66)
  blockNumber BigInt? @map("block_number")
  gasUsed     String? @map("gas_used") @db.VarChar(50)

  // 分类账备注
  memo String? @db.Text

  // 状态: PENDING → PROCESSING → CONFIRMED / FAILED
  status       String  @default("PENDING") @db.VarChar(20)
  errorMessage String? @map("error_message") @db.Text

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

  @@unique([adoptionId], name: "uk_adoption_id")
  @@index([accountSequence], name: "idx_injection_account")
  @@index([status], name: "idx_injection_status")
  @@index([txHash], name: "idx_injection_tx_hash")
  @@index([createdAt], name: "idx_injection_created")
  @@map("adoption_injection_records")
}

// ============================================
// 池账户充值交易表
// 记录检测到的100亿销毁池和200万挖矿池的 fUSDT 充值
// ============================================
model PoolAccountDeposit {
  id BigInt @id @default(autoincrement()) @map("deposit_id")

  chainType String @map("chain_type") @db.VarChar(20) // KAVA
  txHash    String @map("tx_hash") @db.VarChar(66)

  fromAddress String @map("from_address") @db.VarChar(42)
  toAddress   String @map("to_address") @db.VarChar(42) // 池钱包地址

  // 池类型: BURN_POOL (100亿销毁池) 或 MINING_POOL (200万挖矿池)
  poolType      String  @map("pool_type") @db.VarChar(20)
  tokenContract String  @map("token_contract") @db.VarChar(42)
  amount        Decimal @db.Decimal(78, 0) // 原始金额 (wei单位)
  amountFormatted Decimal @map("amount_formatted") @db.Decimal(36, 8) // 格式化金额

  blockNumber    BigInt   @map("block_number")
  blockTimestamp DateTime @map("block_timestamp")
  logIndex       Int      @map("log_index")

  // 确认状态
  confirmations Int    @default(0)
  status        String @default("DETECTED") @db.VarChar(20) // DETECTED, CONFIRMING, CONFIRMED, CREDITED, FAILED

  // 记账状态
  creditedAt      DateTime? @map("credited_at")
  creditReference String?   @map("credit_reference") @db.VarChar(100)

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

  @@unique([chainType, txHash, logIndex], name: "uk_pool_chain_tx_log")
  @@index([chainType, status], name: "idx_pool_chain_status")
  @@index([poolType], name: "idx_pool_type")
  @@index([blockNumber], name: "idx_pool_block")
  @@map("pool_account_deposits")
}

// ============================================
// 池账户区块扫描检查点
// 独立于做市商和用户的扫描进度
// ============================================
model PoolAccountBlockCheckpoint {
  id BigInt @id @default(autoincrement()) @map("checkpoint_id")

  chainType String @map("chain_type") @db.VarChar(20)
  poolType  String @map("pool_type") @db.VarChar(20) // BURN_POOL 或 MINING_POOL

  lastScannedBlock BigInt   @map("last_scanned_block")
  lastScannedAt    DateTime @map("last_scanned_at")

  isHealthy Boolean @default(true) @map("is_healthy")
  lastError String? @map("last_error") @db.Text

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

  @@unique([chainType, poolType], name: "uk_pool_chain_pool")
  @@map("pool_account_block_checkpoints")
}
