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

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

// ==================== 交易账户 ====================

// 用户交易账户
model TradingAccount {
  id              String   @id @default(uuid())
  accountSequence String   @unique
  shareBalance    Decimal  @default(0) @db.Decimal(30, 8) // 积分股余额
  cashBalance     Decimal  @default(0) @db.Decimal(30, 8) // 现金余额
  frozenShares    Decimal  @default(0) @db.Decimal(30, 8) // 冻结积分股
  frozenCash      Decimal  @default(0) @db.Decimal(30, 8) // 冻结现金
  totalBought     Decimal  @default(0) @db.Decimal(30, 8) // 累计买入量
  totalSold       Decimal  @default(0) @db.Decimal(30, 8) // 累计卖出量
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt

  orders       Order[]
  transactions TradingTransaction[]

  @@map("trading_accounts")
}

// ==================== 订单 ====================

// 交易订单
model Order {
  id                String    @id @default(uuid())
  orderNo           String    @unique // 订单号
  accountSequence   String
  type              String // BUY, SELL
  status            String // PENDING, PARTIAL, FILLED, CANCELLED
  price             Decimal   @db.Decimal(30, 18) // 挂单价格
  quantity          Decimal   @db.Decimal(30, 8) // 订单数量
  filledQuantity    Decimal   @default(0) @db.Decimal(30, 8) // 已成交数量
  remainingQuantity Decimal   @db.Decimal(30, 8) // 剩余数量
  averagePrice      Decimal   @default(0) @db.Decimal(30, 18) // 平均成交价
  totalAmount       Decimal   @default(0) @db.Decimal(30, 8) // 总成交金额
  createdAt         DateTime  @default(now())
  updatedAt         DateTime  @updatedAt
  cancelledAt       DateTime?
  completedAt       DateTime?

  account TradingAccount @relation(fields: [accountSequence], references: [accountSequence])
  trades  Trade[]

  @@index([accountSequence, status])
  @@index([type, status, price])
  @@index([createdAt(sort: Desc)])
  @@map("orders")
}

// 成交记录
model Trade {
  id             String   @id @default(uuid())
  tradeNo        String   @unique
  buyOrderId     String
  sellOrderId    String
  buyerSequence  String
  sellerSequence String
  price          Decimal  @db.Decimal(30, 18)
  quantity       Decimal  @db.Decimal(30, 8)
  amount         Decimal  @db.Decimal(30, 8) // price * quantity
  createdAt      DateTime @default(now())

  buyOrder Order @relation(fields: [buyOrderId], references: [id])

  @@index([buyerSequence])
  @@index([sellerSequence])
  @@index([createdAt(sort: Desc)])
  @@map("trades")
}

// ==================== 交易流水 ====================

model TradingTransaction {
  id              String  @id @default(uuid())
  accountSequence String
  type            String // TRANSFER_IN, TRANSFER_OUT, BUY, SELL, FREEZE, UNFREEZE, DEPOSIT, WITHDRAW
  assetType       String // SHARE, CASH
  amount          Decimal @db.Decimal(30, 8)
  balanceBefore   Decimal @db.Decimal(30, 8)
  balanceAfter    Decimal @db.Decimal(30, 8)
  referenceId     String?
  referenceType   String?

  // 交易对手方信息（关键：用户ID和账户序列号）
  counterpartyType       String? @map("counterparty_type") // USER, POOL, SYSTEM
  counterpartyAccountSeq String? @map("counterparty_account_seq") // 对手方账户序列号
  counterpartyUserId     String? @map("counterparty_user_id") // 对手方用户ID

  // 详细备注（包含完整交易信息，格式: "卖出给用户[U123456], 价格0.5USDT"）
  memo        String?  @db.Text
  description String? // 保留兼容旧字段
  createdAt   DateTime @default(now())

  account TradingAccount @relation(fields: [accountSequence], references: [accountSequence])

  @@index([accountSequence, createdAt(sort: Desc)])
  @@index([counterpartyAccountSeq])
  @@index([counterpartyUserId])
  @@map("trading_transactions")
}

// ==================== 流通池 ====================

// 流通池（交易所流通池）
model CirculationPool {
  id           String   @id @default(uuid())
  totalShares  Decimal  @default(0) @db.Decimal(30, 8) // 流通池中的积分股
  totalCash    Decimal  @default(0) @db.Decimal(30, 8) // 流通池中的现金（股池）
  totalInflow  Decimal  @default(0) @db.Decimal(30, 8) // 累计流入
  totalOutflow Decimal  @default(0) @db.Decimal(30, 8) // 累计流出
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt

  transactions CirculationPoolTransaction[]

  @@map("circulation_pools")
}

// 流通池变动记录（包含交易对手方信息）
model CirculationPoolTransaction {
  id            String  @id @default(uuid())
  poolId        String  @map("pool_id")
  type          String // SHARE_IN, SHARE_OUT, CASH_IN, CASH_OUT, TRADE_BUY, TRADE_SELL
  assetType     String // SHARE, CASH
  amount        Decimal @db.Decimal(30, 8)
  balanceBefore Decimal @map("balance_before") @db.Decimal(30, 8)
  balanceAfter  Decimal @map("balance_after") @db.Decimal(30, 8)

  // 交易对手方信息（关键：用户ID和账户序列号）
  counterpartyType       String? @map("counterparty_type") // USER, POOL, SYSTEM, EXTERNAL
  counterpartyAccountSeq String? @map("counterparty_account_seq") // 对手方账户序列号
  counterpartyUserId     String? @map("counterparty_user_id") // 对手方用户ID

  // 关联信息
  referenceId   String? @map("reference_id") // 关联业务ID（如订单ID、交易ID）
  referenceType String? @map("reference_type") // 关联类型（ORDER, TRADE, TRANSFER）

  // 详细备注（包含完整交易信息）
  // 格式示例: "用户[U123456]买入100股, 订单号ORD20240110001"
  memo String? @db.Text

  // 扩展数据
  metadata Json?

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

  pool CirculationPool @relation(fields: [poolId], references: [id])

  @@index([poolId, createdAt(sort: Desc)])
  @@index([type, assetType])
  @@index([counterpartyAccountSeq])
  @@index([counterpartyUserId])
  @@index([referenceId])
  @@index([createdAt(sort: Desc)])
  @@map("circulation_pool_transactions")
}

// 保留旧的PoolTransaction以兼容（标记为废弃，后续迁移后删除）
// @deprecated 使用 CirculationPoolTransaction 替代
model PoolTransaction {
  id          String   @id @default(uuid())
  type        String // SHARE_IN, SHARE_OUT, CASH_IN, CASH_OUT
  amount      Decimal  @db.Decimal(30, 8)
  referenceId String?
  description String?
  createdAt   DateTime @default(now())

  @@index([createdAt(sort: Desc)])
  @@map("pool_transactions")
}

// ==================== K线数据 ====================

// 分钟K线
model MinuteKLine {
  id         String   @id @default(uuid())
  minute     DateTime @unique
  open       Decimal  @db.Decimal(30, 18)
  high       Decimal  @db.Decimal(30, 18)
  low        Decimal  @db.Decimal(30, 18)
  close      Decimal  @db.Decimal(30, 18)
  volume     Decimal  @db.Decimal(30, 8) // 成交量
  amount     Decimal  @db.Decimal(30, 8) // 成交额
  tradeCount Int      @default(0) // 成交笔数
  createdAt  DateTime @default(now())

  @@index([minute(sort: Desc)])
  @@map("minute_klines")
}

// 小时K线
model HourKLine {
  id         String   @id @default(uuid())
  hour       DateTime @unique
  open       Decimal  @db.Decimal(30, 18)
  high       Decimal  @db.Decimal(30, 18)
  low        Decimal  @db.Decimal(30, 18)
  close      Decimal  @db.Decimal(30, 18)
  volume     Decimal  @db.Decimal(30, 8)
  amount     Decimal  @db.Decimal(30, 8)
  tradeCount Int      @default(0)
  createdAt  DateTime @default(now())

  @@index([hour(sort: Desc)])
  @@map("hour_klines")
}

// 日K线
model DayKLine {
  id         String   @id @default(uuid())
  date       DateTime @unique @db.Date
  open       Decimal  @db.Decimal(30, 18)
  high       Decimal  @db.Decimal(30, 18)
  low        Decimal  @db.Decimal(30, 18)
  close      Decimal  @db.Decimal(30, 18)
  volume     Decimal  @db.Decimal(30, 8)
  amount     Decimal  @db.Decimal(30, 8)
  tradeCount Int      @default(0)
  createdAt  DateTime @default(now())

  @@index([date(sort: Desc)])
  @@map("day_klines")
}

// ==================== 划转记录 ====================

// 从挖矿账户划转记录
model TransferRecord {
  id              String    @id @default(uuid())
  transferNo      String    @unique
  accountSequence String
  direction       String // IN (从挖矿账户划入), OUT (划出到挖矿账户)
  amount          Decimal   @db.Decimal(30, 8)
  status          String // PENDING, COMPLETED, FAILED
  miningTxId      String? // 挖矿服务的交易ID
  errorMessage    String?
  createdAt       DateTime  @default(now())
  completedAt     DateTime?

  @@index([accountSequence])
  @@index([status])
  @@map("transfer_records")
}

// ==================== Outbox ====================

enum OutboxStatus {
  PENDING
  PUBLISHED
  FAILED
}

model OutboxEvent {
  id            String       @id @default(uuid())
  aggregateType String       @map("aggregate_type")
  aggregateId   String       @map("aggregate_id")
  eventType     String       @map("event_type")
  payload       Json
  topic         String       @default("trading.events")
  key           String?
  status        OutboxStatus @default(PENDING)
  retryCount    Int          @default(0) @map("retry_count")
  maxRetries    Int          @default(10) @map("max_retries")
  lastError     String?      @map("last_error")
  publishedAt   DateTime?    @map("published_at")
  nextRetryAt   DateTime?    @map("next_retry_at")
  createdAt     DateTime     @default(now()) @map("created_at")

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