// =============================================================================
// Admin Service - Prisma Schema
// =============================================================================

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

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

// =============================================================================
// App Version Management
// =============================================================================

model AppVersion {
  id            String    @id @default(uuid())
  platform      Platform
  versionCode   Int // Android: versionCode, iOS: CFBundleVersion
  versionName   String // 用户可见版本号，如 "1.2.3"
  buildNumber   String // 构建号
  downloadUrl   String // APK/IPA 下载地址
  fileSize      BigInt // 文件大小（字节）
  fileSha256    String // 文件 SHA-256 校验和
  minOsVersion  String? // 最低操作系统版本要求
  changelog     String // 更新日志
  isForceUpdate Boolean   @default(false) // 是否强制更新
  isEnabled     Boolean   @default(true) // 是否启用
  releaseDate   DateTime? // 发布日期
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
  createdBy     String // 创建人ID
  updatedBy     String? // 更新人ID

  @@index([platform, isEnabled])
  @@index([platform, versionCode])
  @@map("app_versions")
}

enum Platform {
  ANDROID
  IOS
}

// =============================================================================
// Notification System (通知系统)
// =============================================================================

/// 系统通知 - 管理员发布的公告/通知
model Notification {
  id          String               @id @default(uuid())
  title       String // 通知标题
  content     String // 通知内容
  type        NotificationType // 通知类型
  priority    NotificationPriority @default(NORMAL) // 优先级
  targetType  TargetType           @default(ALL) // 目标用户类型
  targetLogic TargetLogic          @default(ANY) @map("target_logic") // 多标签匹配逻辑
  imageUrl    String? // 可选的图片URL
  linkUrl     String? // 可选的跳转链接
  isEnabled        Boolean              @default(true) // 是否启用
  requiresForceRead Boolean             @default(false) // 是否需要强制弹窗阅读（管理员可配置）
  publishedAt DateTime? // 发布时间（null表示草稿）
  expiresAt   DateTime? // 过期时间（null表示永不过期）
  createdAt   DateTime             @default(now())
  updatedAt   DateTime             @updatedAt
  createdBy   String // 创建人ID

  // 关联
  readRecords NotificationRead[]
  targetTags  NotificationTagTarget[] // BY_TAG 时使用
  targetUsers NotificationUserTarget[] // SPECIFIC 时使用

  @@index([isEnabled, publishedAt])
  @@index([type])
  @@index([targetType])
  @@map("notifications")
}

/// 用户已读记录
model NotificationRead {
  id             String   @id @default(uuid())
  notificationId String
  userSerialNum  String // 用户序列号
  readAt         DateTime @default(now())

  notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade)

  @@unique([notificationId, userSerialNum])
  @@index([userSerialNum])
  @@map("notification_reads")
}

/// 通知类型
enum NotificationType {
  SYSTEM // 系统通知
  ACTIVITY // 活动通知
  REWARD // 收益通知
  UPGRADE // 升级通知
  ANNOUNCEMENT // 公告
}

/// 通知优先级
enum NotificationPriority {
  LOW
  NORMAL
  HIGH
  URGENT
}

/// 目标用户类型
enum TargetType {
  ALL // 所有用户
  BY_TAG // 按标签匹配
  SPECIFIC // 指定用户列表
}

/// 多标签匹配逻辑
enum TargetLogic {
  ANY // 匹配任一标签
  ALL // 匹配所有标签
}

/// 通知-标签关联
model NotificationTagTarget {
  id             String @id @default(uuid())
  notificationId String @map("notification_id")
  tagId          String @map("tag_id")

  notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade)
  tag          UserTag      @relation(fields: [tagId], references: [id], onDelete: Cascade)

  @@unique([notificationId, tagId])
  @@index([tagId])
  @@map("notification_tag_targets")
}

/// 通知-用户关联 (指定用户)
model NotificationUserTarget {
  id              String @id @default(uuid())
  notificationId  String @map("notification_id")
  accountSequence String @map("account_sequence") @db.VarChar(12)

  notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade)

  @@unique([notificationId, accountSequence])
  @@index([accountSequence])
  @@map("notification_user_targets")
}

// =============================================================================
// User Profile System (用户画像系统) - 面向通知 + 广告
// =============================================================================

// -----------------------------------------------------------------------------
// 标签分类 (Tag Category) - 标签的分组管理
// -----------------------------------------------------------------------------

/// 标签分类
model TagCategory {
  id          String   @id @default(uuid())
  code        String   @unique @db.VarChar(50) // "lifecycle", "value", "behavior"
  name        String   @db.VarChar(100) // "生命周期", "价值分层", "行为特征"
  description String?  @db.Text
  sortOrder   Int      @default(0) @map("sort_order")
  isEnabled   Boolean  @default(true) @map("is_enabled")
  createdAt   DateTime @default(now()) @map("created_at")
  updatedAt   DateTime @updatedAt @map("updated_at")

  tags UserTag[]

  @@index([code])
  @@index([isEnabled])
  @@map("tag_categories")
}

// -----------------------------------------------------------------------------
// 用户标签 (User Tag) - 增强版
// -----------------------------------------------------------------------------

/// 标签类型
enum TagType {
  MANUAL // 手动打标 (管理员操作)
  AUTO // 自动打标 (规则驱动)
  COMPUTED // 计算型 (实时计算，不存储关联)
  SYSTEM // 系统内置 (不可删除)
}

/// 标签值类型
enum TagValueType {
  BOOLEAN // 布尔型: 有/无
  ENUM // 枚举型: 高/中/低
  NUMBER // 数值型: 0-100分
  STRING // 字符串型
}

/// 用户标签定义
model UserTag {
  id          String  @id @default(uuid())
  categoryId  String? @map("category_id")
  code        String  @unique @db.VarChar(50) // "vip", "new_user", "whale"
  name        String  @db.VarChar(100) // "VIP用户", "新用户", "大客户"
  description String? @db.Text
  color       String? @db.VarChar(20) // "#FF5722"

  type      TagType      @default(MANUAL) // 标签类型
  valueType TagValueType @default(BOOLEAN) @map("value_type") // 标签值类型

  // 枚举型标签的可选值
  // 例如: ["高", "中", "低"] 或 ["活跃", "沉默", "流失"]
  enumValues Json? @map("enum_values")

  // 关联的自动规则 (type=AUTO 时使用)
  ruleId String?                 @unique @map("rule_id")
  rule   UserClassificationRule? @relation(fields: [ruleId], references: [id], onDelete: SetNull)

  // 广告相关
  isAdvertisable Boolean @default(true) @map("is_advertisable") // 是否可用于广告定向
  estimatedUsers Int?    @map("estimated_users") // 预估覆盖用户数

  isEnabled Boolean  @default(true) @map("is_enabled")
  sortOrder Int      @default(0) @map("sort_order")
  createdAt DateTime @default(now()) @map("created_at")
  updatedAt DateTime @updatedAt @map("updated_at")

  // 关联
  category      TagCategory?            @relation(fields: [categoryId], references: [id], onDelete: SetNull)
  assignments   UserTagAssignment[]
  notifications NotificationTagTarget[]

  @@index([categoryId])
  @@index([code])
  @@index([type])
  @@index([isEnabled])
  @@index([isAdvertisable])
  @@map("user_tags")
}

// -----------------------------------------------------------------------------
// 用户-标签关联 - 支持标签值
// -----------------------------------------------------------------------------

/// 用户-标签关联
model UserTagAssignment {
  id              String @id @default(uuid())
  accountSequence String @map("account_sequence") @db.VarChar(12)
  tagId           String @map("tag_id")

  // 标签值 (根据 valueType)
  // BOOLEAN: null (存在即为true)
  // ENUM: "高" / "中" / "低"
  // NUMBER: "85" (字符串存储)
  // STRING: 任意字符串
  value String? @db.VarChar(100)

  assignedAt DateTime  @default(now()) @map("assigned_at")
  assignedBy String?   @map("assigned_by") // null=系统自动, 否则为管理员ID
  expiresAt  DateTime? @map("expires_at") // 可选过期时间
  source     String?   @db.VarChar(50) // 来源: "rule:xxx", "import", "manual", "kafka"

  tag UserTag @relation(fields: [tagId], references: [id], onDelete: Cascade)

  @@unique([accountSequence, tagId])
  @@index([accountSequence])
  @@index([tagId])
  @@index([value])
  @@index([expiresAt])
  @@map("user_tag_assignments")
}

// -----------------------------------------------------------------------------
// 用户分类规则 (Classification Rule)
// -----------------------------------------------------------------------------

/// 用户分类规则
model UserClassificationRule {
  id          String  @id @default(uuid())
  name        String  @db.VarChar(100) // "30天内新用户"
  description String? @db.Text

  // 规则条件 (JSON)
  // 示例:
  // {
  //   "type": "AND",
  //   "rules": [
  //     { "field": "registeredAt", "operator": "within_days", "value": 30 },
  //     { "field": "kycStatus", "operator": "eq", "value": "VERIFIED" }
  //   ]
  // }
  conditions Json

  isEnabled Boolean  @default(true) @map("is_enabled")
  createdAt DateTime @default(now()) @map("created_at")
  updatedAt DateTime @updatedAt @map("updated_at")

  // 关联的自动标签
  tag UserTag?

  @@map("user_classification_rules")
}

// -----------------------------------------------------------------------------
// 用户特征 (User Features) - 数值型指标
// -----------------------------------------------------------------------------

/// 用户特征 - 计算后的用户画像指标
model UserFeature {
  id              String @id @default(uuid())
  accountSequence String @unique @map("account_sequence") @db.VarChar(12)

  // RFM 模型
  rfmRecency   Int?     @map("rfm_recency") // 最近一次活跃距今天数
  rfmFrequency Int?     @map("rfm_frequency") // 过去30天活跃天数
  rfmMonetary  Decimal? @map("rfm_monetary") @db.Decimal(18, 2) // 累计消费金额
  rfmScore     Int?     @map("rfm_score") // RFM综合分 (0-100)

  // 活跃度
  activeLevel  String?   @map("active_level") @db.VarChar(20) // "高活跃", "中活跃", "低活跃", "沉默"
  lastActiveAt DateTime? @map("last_active_at")

  // 价值分层
  valueLevel    String?  @map("value_level") @db.VarChar(20) // "高价值", "中价值", "低价值", "潜力"
  lifetimeValue Decimal? @map("lifetime_value") @db.Decimal(18, 2) // 用户生命周期价值 LTV

  // 生命周期
  lifecycleStage String? @map("lifecycle_stage") @db.VarChar(20) // "新用户", "成长期", "成熟期", "衰退期", "流失"

  // 自定义特征 (JSON扩展)
  customFeatures Json? @map("custom_features")

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

  @@index([rfmScore])
  @@index([activeLevel])
  @@index([valueLevel])
  @@index([lifecycleStage])
  @@map("user_features")
}

// -----------------------------------------------------------------------------
// 人群包 (Audience Segment) - 复杂定向
// -----------------------------------------------------------------------------

/// 人群包用途
enum SegmentUsageType {
  GENERAL // 通用
  NOTIFICATION // 通知定向
  ADVERTISING // 广告定向
  ANALYTICS // 数据分析
}

/// 人群包 - 多条件组合的用户群
model AudienceSegment {
  id          String  @id @default(uuid())
  name        String  @db.VarChar(100) // "高价值活跃用户"
  description String? @db.Text

  // 定向条件 (JSON)
  // {
  //   "type": "AND",
  //   "conditions": [
  //     { "type": "tag", "tagCode": "vip", "operator": "eq", "value": true },
  //     { "type": "feature", "field": "rfmScore", "operator": "gte", "value": 80 },
  //     { "type": "profile", "field": "province", "operator": "in", "value": ["广东", "浙江"] }
  //   ]
  // }
  conditions Json

  // 预估数据
  estimatedUsers Int?      @map("estimated_users")
  lastCalculated DateTime? @map("last_calculated")

  // 用途
  usageType SegmentUsageType @default(GENERAL) @map("usage_type")

  isEnabled Boolean  @default(true) @map("is_enabled")
  createdAt DateTime @default(now()) @map("created_at")
  updatedAt DateTime @updatedAt @map("updated_at")
  createdBy String   @map("created_by")

  @@index([usageType])
  @@index([isEnabled])
  @@map("audience_segments")
}

// -----------------------------------------------------------------------------
// 标签变更日志 (审计追踪)
// -----------------------------------------------------------------------------

/// 标签变更操作
enum TagAction {
  ASSIGN // 打标签
  UPDATE // 更新标签值
  REMOVE // 移除标签
  EXPIRE // 过期移除
}

/// 标签变更日志
model UserTagLog {
  id              String @id @default(uuid())
  accountSequence String @map("account_sequence") @db.VarChar(12)
  tagCode         String @map("tag_code") @db.VarChar(50)

  action   TagAction
  oldValue String?   @map("old_value") @db.VarChar(100)
  newValue String?   @map("new_value") @db.VarChar(100)

  reason     String? @db.VarChar(200) // "规则触发", "管理员操作", "导入", "过期清理"
  operatorId String? @map("operator_id")

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

  @@index([accountSequence, createdAt])
  @@index([tagCode])
  @@index([action])
  @@index([createdAt])
  @@map("user_tag_logs")
}

// =============================================================================
// User Query View (用户查询视图 - 通过 Kafka 事件同步)
// =============================================================================

/// 用户查询视图 - 本地物化视图，通过消费 Kafka 事件同步维护
/// 用于 admin-web 用户管理页面的查询，避免跨服务 HTTP 调用
model UserQueryView {
  userId          BigInt @id @map("user_id")
  accountSequence String @unique @map("account_sequence") @db.VarChar(12)

  // 基本信息 (来自 identity-service 事件)
  nickname          String? @db.VarChar(100)
  avatarUrl         String? @map("avatar_url") @db.Text
  phoneNumberMasked String? @map("phone_number_masked") @db.VarChar(20) // 脱敏: 138****8888

  // 推荐关系
  inviterSequence String? @map("inviter_sequence") @db.VarChar(12)

  // KYC 状态
  kycStatus String @default("NOT_VERIFIED") @map("kyc_status") @db.VarChar(20)

  // 认种统计 (来自 planting-service 事件)
  personalAdoptionCount Int @default(0) @map("personal_adoption_count")
  teamAddressCount      Int @default(0) @map("team_address_count")
  teamAdoptionCount     Int @default(0) @map("team_adoption_count")

  // 授权统计 (来自 authorization-service 事件)
  provinceAdoptionCount Int @default(0) @map("province_adoption_count")
  cityAdoptionCount     Int @default(0) @map("city_adoption_count")

  // 排名
  leaderboardRank Int? @map("leaderboard_rank")

  // 状态
  status   String  @default("ACTIVE") @db.VarChar(20)
  isOnline Boolean @default(false) @map("is_online")

  // 时间戳
  registeredAt DateTime  @map("registered_at")
  lastActiveAt DateTime? @map("last_active_at")
  syncedAt     DateTime  @default(now()) @map("synced_at")

  @@index([accountSequence])
  @@index([nickname])
  @@index([status])
  @@index([registeredAt])
  @@index([personalAdoptionCount])
  @@index([inviterSequence])
  @@map("user_query_view")
}

// =============================================================================
// Referral Query View (推荐关系查询视图 - 通过 CDC 同步)
// =============================================================================

/// 推荐关系查询视图 - 通过 Debezium CDC 从 referral-service 同步
/// 用于 admin-web 查看用户推荐关系，避免跨服务调用
model ReferralQueryView {
  id              BigInt @id @map("relationship_id")
  userId          BigInt @unique @map("user_id")
  accountSequence String @unique @map("account_sequence") @db.VarChar(12)

  // 推荐人信息
  referrerId BigInt? @map("referrer_id")
  rootUserId BigInt? @map("root_user_id")

  // 推荐码
  myReferralCode   String  @unique @map("my_referral_code") @db.VarChar(20)
  usedReferralCode String? @map("used_referral_code") @db.VarChar(20)

  // 推荐链信息
  ancestorPath BigInt[] @map("ancestor_path")
  depth        Int      @default(0) @map("depth")

  // 直推统计
  directReferralCount Int @default(0) @map("direct_referral_count")
  activeDirectCount   Int @default(0) @map("active_direct_count")

  // 时间戳
  createdAt DateTime @map("created_at")
  syncedAt  DateTime @default(now()) @map("synced_at")

  @@index([referrerId])
  @@index([accountSequence])
  @@index([myReferralCode])
  @@index([usedReferralCode])
  @@index([rootUserId])
  @@index([depth])
  @@map("referral_query_view")
}

// =============================================================================
// Wallet Query Views (钱包查询视图 - 通过 CDC 同步)
// =============================================================================

/// 钱包账户查询视图 - 通过 Debezium CDC 从 wallet-service 同步
model WalletAccountQueryView {
  id              BigInt @id @map("wallet_id")
  accountSequence String @unique @map("account_sequence") @db.VarChar(20)
  userId          BigInt @unique @map("user_id")

  // USDT 余额
  usdtAvailable Decimal @default(0) @map("usdt_available") @db.Decimal(20, 8)
  usdtFrozen    Decimal @default(0) @map("usdt_frozen") @db.Decimal(20, 8)

  // DST 余额
  dstAvailable Decimal @default(0) @map("dst_available") @db.Decimal(20, 8)
  dstFrozen    Decimal @default(0) @map("dst_frozen") @db.Decimal(20, 8)

  // BNB 余额
  bnbAvailable Decimal @default(0) @map("bnb_available") @db.Decimal(20, 8)
  bnbFrozen    Decimal @default(0) @map("bnb_frozen") @db.Decimal(20, 8)

  // OG 余额
  ogAvailable Decimal @default(0) @map("og_available") @db.Decimal(20, 8)
  ogFrozen    Decimal @default(0) @map("og_frozen") @db.Decimal(20, 8)

  // RWAD 余额
  rwadAvailable Decimal @default(0) @map("rwad_available") @db.Decimal(20, 8)
  rwadFrozen    Decimal @default(0) @map("rwad_frozen") @db.Decimal(20, 8)

  // 算力
  hashpower Decimal @default(0) @map("hashpower") @db.Decimal(20, 8)

  // 待领取/可结算/已结算收益
  pendingUsdt           Decimal @default(0) @map("pending_usdt") @db.Decimal(20, 8)
  pendingHashpower      Decimal @default(0) @map("pending_hashpower") @db.Decimal(20, 8)
  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)

  // 状态
  status     String  @default("ACTIVE") @map("status") @db.VarChar(20)
  hasPlanted Boolean @default(false) @map("has_planted")

  // 时间戳
  createdAt DateTime @map("created_at")
  syncedAt  DateTime @default(now()) @map("synced_at")

  @@index([accountSequence])
  @@index([usdtAvailable(sort: Desc)])
  @@index([hashpower(sort: Desc)])
  @@index([status])
  @@map("wallet_account_query_view")
}

/// 提现订单查询视图 - 通过 Debezium CDC 从 wallet-service 同步
model WithdrawalOrderQueryView {
  id              BigInt @id @map("order_id")
  orderNo         String @unique @map("order_no") @db.VarChar(50)
  accountSequence String @map("account_sequence") @db.VarChar(20)
  userId          BigInt @map("user_id")

  // 提现信息
  amount    Decimal @map("amount") @db.Decimal(20, 8)
  fee       Decimal @map("fee") @db.Decimal(20, 8)
  chainType String  @map("chain_type") @db.VarChar(20)
  toAddress String  @map("to_address") @db.VarChar(100)

  // 交易信息
  txHash String? @map("tx_hash") @db.VarChar(100)

  // 内部转账标识
  isInternalTransfer Boolean @default(false) @map("is_internal_transfer")
  toAccountSequence  String? @map("to_account_sequence") @db.VarChar(20)
  toUserId           BigInt? @map("to_user_id")

  // 状态
  status       String  @default("PENDING") @map("status") @db.VarChar(20)
  errorMessage String? @map("error_message") @db.VarChar(500)

  // 时间戳
  frozenAt      DateTime? @map("frozen_at")
  broadcastedAt DateTime? @map("broadcasted_at")
  confirmedAt   DateTime? @map("confirmed_at")
  createdAt     DateTime  @map("created_at")
  syncedAt      DateTime  @default(now()) @map("synced_at")

  @@index([accountSequence])
  @@index([userId])
  @@index([status])
  @@index([chainType])
  @@index([txHash])
  @@index([createdAt])
  @@map("withdrawal_order_query_view")
}

/// 法币提现订单查询视图 - 通过 Debezium CDC 从 wallet-service 同步
model FiatWithdrawalOrderQueryView {
  id              BigInt @id @map("order_id")
  orderNo         String @unique @map("order_no") @db.VarChar(50)
  accountSequence String @map("account_sequence") @db.VarChar(20)
  userId          BigInt @map("user_id")

  // 金额
  amount Decimal @map("amount") @db.Decimal(20, 8)
  fee    Decimal @map("fee") @db.Decimal(20, 8)

  // 收款方式
  paymentMethod String @map("payment_method") @db.VarChar(20)

  // 银行卡信息 (脱敏)
  bankName         String? @map("bank_name") @db.VarChar(100)
  bankCardNoMasked String? @map("bank_card_no_masked") @db.VarChar(50)
  cardHolderName   String? @map("card_holder_name") @db.VarChar(100)

  // 支付宝/微信 (脱敏)
  alipayAccountMasked String? @map("alipay_account_masked") @db.VarChar(100)
  wechatAccountMasked String? @map("wechat_account_masked") @db.VarChar(100)

  // 状态
  status       String  @default("PENDING") @map("status") @db.VarChar(20)
  errorMessage String? @map("error_message") @db.VarChar(500)

  // 审核信息
  reviewedBy   String?   @map("reviewed_by") @db.VarChar(100)
  reviewedAt   DateTime? @map("reviewed_at")
  reviewRemark String?   @map("review_remark") @db.VarChar(500)

  // 打款信息
  paidBy String?   @map("paid_by") @db.VarChar(100)
  paidAt DateTime? @map("paid_at")

  // 时间戳
  frozenAt    DateTime? @map("frozen_at")
  completedAt DateTime? @map("completed_at")
  createdAt   DateTime  @map("created_at")
  syncedAt    DateTime  @default(now()) @map("synced_at")

  @@index([accountSequence])
  @@index([userId])
  @@index([status])
  @@index([paymentMethod])
  @@index([reviewedBy])
  @@index([createdAt])
  @@map("fiat_withdrawal_order_query_view")
}

// =============================================================================
// Planting Query Views (认种查询视图 - 通过 CDC 同步)
// =============================================================================

/// 认种订单查询视图 - 通过 Debezium CDC 从 planting-service 同步
model PlantingOrderQueryView {
  id              BigInt @id @map("order_id")
  orderNo         String @unique @map("order_no") @db.VarChar(50)
  userId          BigInt @map("user_id")
  accountSequence String @map("account_sequence") @db.VarChar(20)

  // 认种信息
  treeCount   Int     @map("tree_count")
  totalAmount Decimal @map("total_amount") @db.Decimal(20, 8)

  // 省市选择
  selectedProvince String? @map("selected_province") @db.VarChar(10)
  selectedCity     String? @map("selected_city") @db.VarChar(10)

  // 订单状态
  status String @default("CREATED") @map("status") @db.VarChar(30)

  // 底池信息
  poolInjectionBatchId BigInt? @map("pool_injection_batch_id")

  // 时间戳
  createdAt       DateTime  @map("created_at")
  paidAt          DateTime? @map("paid_at")
  fundAllocatedAt DateTime? @map("fund_allocated_at")
  miningEnabledAt DateTime? @map("mining_enabled_at")
  syncedAt        DateTime  @default(now()) @map("synced_at")

  @@index([userId])
  @@index([accountSequence])
  @@index([status])
  @@index([selectedProvince, selectedCity])
  @@index([createdAt])
  @@index([paidAt])
  @@map("planting_order_query_view")
}

/// 用户持仓查询视图 - 通过 Debezium CDC 从 planting-service 同步
model PlantingPositionQueryView {
  id     BigInt @id @map("position_id")
  userId BigInt @unique @map("user_id")

  // 持仓统计
  totalTreeCount     Int @default(0) @map("total_tree_count")
  effectiveTreeCount Int @default(0) @map("effective_tree_count")
  pendingTreeCount   Int @default(0) @map("pending_tree_count")

  // 挖矿状态
  firstMiningStartAt DateTime? @map("first_mining_start_at")

  // 时间戳
  createdAt DateTime @map("created_at")
  syncedAt  DateTime @default(now()) @map("synced_at")

  @@index([totalTreeCount])
  @@map("planting_position_query_view")
}

/// 合同签署任务查询视图 - 通过 Debezium CDC 从 planting-service 同步
model ContractSigningTaskQueryView {
  id BigInt @id @map("task_id")

  // 关联信息
  orderNo         String @unique @map("order_no") @db.VarChar(50)
  contractNo      String @unique @map("contract_no") @db.VarChar(30)
  userId          BigInt @map("user_id")
  accountSequence String @map("account_sequence") @db.VarChar(20)

  // 合同信息
  contractVersion String @map("contract_version") @db.VarChar(20)

  // 订单信息快照
  treeCount    Int     @map("tree_count")
  totalAmount  Decimal @map("total_amount") @db.Decimal(20, 8)
  provinceCode String  @map("province_code") @db.VarChar(10)
  provinceName String  @map("province_name") @db.VarChar(50)
  cityCode     String  @map("city_code") @db.VarChar(10)
  cityName     String  @map("city_name") @db.VarChar(50)

  // 签署状态
  status    String   @default("PENDING") @map("status") @db.VarChar(30)
  expiresAt DateTime @map("expires_at")

  // 签署时间戳
  signedAt DateTime? @map("signed_at")

  // 时间戳
  createdAt DateTime @map("created_at")
  syncedAt  DateTime @default(now()) @map("synced_at")

  @@index([userId])
  @@index([status])
  @@index([expiresAt])
  @@map("contract_signing_task_query_view")
}

// =============================================================================
// Authorization Query Views (授权查询视图 - 通过 CDC 同步)
// =============================================================================

/// 授权角色查询视图 - 通过 Debezium CDC 从 authorization-service 同步
model AuthorizationRoleQueryView {
  id              String @id
  userId          String @map("user_id")
  accountSequence String @map("account_sequence")
  roleType        String @map("role_type") @db.VarChar(30)
  regionCode      String @map("region_code")
  regionName      String @map("region_name")
  status          String @default("PENDING") @db.VarChar(20)
  displayTitle    String @map("display_title")

  // 授权信息
  authorizedAt DateTime? @map("authorized_at")
  authorizedBy String?   @map("authorized_by")
  revokedAt    DateTime? @map("revoked_at")
  revokedBy    String?   @map("revoked_by")

  // 软删除
  deletedAt DateTime? @map("deleted_at")

  // 考核配置
  initialTargetTreeCount Int    @map("initial_target_tree_count")
  monthlyTargetType      String @map("monthly_target_type") @db.VarChar(20)

  // 权益状态
  benefitActive      Boolean   @default(false) @map("benefit_active")
  benefitActivatedAt DateTime? @map("benefit_activated_at")

  // 月度考核追踪
  lastAssessmentMonth String? @map("last_assessment_month")
  monthlyTreesAdded   Int     @default(0) @map("monthly_trees_added")

  // 申请时提供的办公室照片（MinIO URL）
  officePhotoUrls String[] @default([]) @map("office_photo_urls")

  // 时间戳
  createdAt DateTime @map("created_at")
  syncedAt  DateTime @default(now()) @map("synced_at")

  @@index([accountSequence])
  @@index([userId])
  @@index([roleType, regionCode])
  @@index([status])
  @@index([deletedAt])
  @@map("authorization_role_query_view")
}

/// 月度考核查询视图 - 通过 Debezium CDC 从 authorization-service 同步
model MonthlyAssessmentQueryView {
  id              String @id
  authorizationId String @map("authorization_id")
  userId          String @map("user_id")
  accountSequence String @map("account_sequence")
  roleType        String @map("role_type") @db.VarChar(30)
  regionCode      String @map("region_code")

  // 考核月份
  assessmentMonth String @map("assessment_month")
  monthIndex      Int    @map("month_index")

  // 考核目标
  monthlyTarget    Int @map("monthly_target")
  cumulativeTarget Int @map("cumulative_target")

  // 完成情况
  monthlyCompleted    Int       @default(0) @map("monthly_completed")
  cumulativeCompleted Int       @default(0) @map("cumulative_completed")
  completedAt         DateTime? @map("completed_at")

  // 考核结果
  result String @default("NOT_ASSESSED") @db.VarChar(20)

  // 排名
  rankingInRegion Int?    @map("ranking_in_region")
  isFirstPlace    Boolean @default(false) @map("is_first_place")

  // 豁免
  isBypassed Boolean @default(false) @map("is_bypassed")

  // 时间戳
  assessedAt DateTime? @map("assessed_at")
  createdAt  DateTime  @map("created_at")
  syncedAt   DateTime  @default(now()) @map("synced_at")

  @@index([accountSequence, assessmentMonth])
  @@index([userId, assessmentMonth])
  @@index([roleType, regionCode, assessmentMonth])
  @@index([assessmentMonth, result])
  @@map("monthly_assessment_query_view")
}

/// 权益考核记录查询视图 - 通过 Debezium CDC 从 authorization-service 同步
/// 独立于火柴人排名（MonthlyAssessment），专门记录权益有效性考核历史
model BenefitAssessmentQueryView {
  id              String @id
  authorizationId String @map("authorization_id")
  userId          String @map("user_id")
  accountSequence String @map("account_sequence")
  roleType        String @map("role_type") @db.VarChar(30)
  regionCode      String @map("region_code")
  regionName      String @map("region_name")

  // 考核月份
  assessmentMonth String @map("assessment_month")
  monthIndex      Int    @map("month_index")

  // 考核目标
  monthlyTarget    Int @map("monthly_target")
  cumulativeTarget Int @map("cumulative_target")

  // 完成情况
  treesCompleted Int @map("trees_completed")
  treesRequired  Int @map("trees_required")

  // 权益状态变化
  benefitActionTaken    String   @map("benefit_action_taken") @db.VarChar(20)
  previousBenefitStatus Boolean  @map("previous_benefit_status")
  newBenefitStatus      Boolean  @map("new_benefit_status")
  newValidUntil         DateTime? @map("new_valid_until")

  // 考核结果
  result String @default("NOT_ASSESSED") @db.VarChar(20)

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

  // 时间戳
  assessedAt DateTime @map("assessed_at")
  createdAt  DateTime @map("created_at")
  syncedAt   DateTime @default(now()) @map("synced_at")

  @@unique([authorizationId, assessmentMonth])
  @@index([accountSequence, assessmentMonth])
  @@index([userId, assessmentMonth])
  @@index([roleType, regionCode, assessmentMonth])
  @@index([assessmentMonth, result])
  @@map("benefit_assessment_query_view")
}

/// 系统账户查询视图 - 通过 Debezium CDC 从 authorization-service 同步
model SystemAccountQueryView {
  id          BigInt @id @map("account_id")
  accountType String @map("account_type") @db.VarChar(30)

  // 区域信息
  regionCode String? @map("region_code") @db.VarChar(10)
  regionName String? @map("region_name") @db.VarChar(50)

  // 钱包地址
  walletAddress String? @map("wallet_address") @db.VarChar(42)

  // 余额
  usdtBalance Decimal @default(0) @map("usdt_balance") @db.Decimal(20, 8)
  hashpower   Decimal @default(0) @map("hashpower") @db.Decimal(20, 8)

  // 累计统计
  totalReceived    Decimal @default(0) @map("total_received") @db.Decimal(20, 8)
  totalTransferred Decimal @default(0) @map("total_transferred") @db.Decimal(20, 8)

  // 状态
  status String @default("ACTIVE") @map("status") @db.VarChar(20)

  // 时间戳
  createdAt DateTime @map("created_at")
  syncedAt  DateTime @default(now()) @map("synced_at")

  @@index([accountType])
  @@index([walletAddress])
  @@map("system_account_query_view")
}

// =============================================================================
// Ledger Views (分类账视图 - 通过 CDC 同步)
// =============================================================================

/// 钱包流水分类账 - 通过 Debezium CDC 从 wallet-service 同步
/// 记录所有用户钱包的资金变动（充值/提现/收益/扣款等）
model WalletLedgerEntryView {
  id              BigInt @id @map("entry_id")
  accountSequence String @map("account_sequence") @db.VarChar(20)
  userId          BigInt @map("user_id")

  // 流水类型
  entryType String @map("entry_type") @db.VarChar(50)

  // 金额变动 (正数入账, 负数支出)
  amount    Decimal @map("amount") @db.Decimal(20, 8)
  assetType String  @map("asset_type") @db.VarChar(20)

  // 余额快照 (操作后余额)
  balanceAfter Decimal? @map("balance_after") @db.Decimal(20, 8)

  // 关联引用
  refOrderId String? @map("ref_order_id") @db.VarChar(100)
  refTxHash  String? @map("ref_tx_hash") @db.VarChar(100)

  // 备注
  memo String? @map("memo") @db.Text

  // 时间戳
  createdAt DateTime @map("created_at")
  syncedAt  DateTime @default(now()) @map("synced_at")

  @@index([accountSequence, createdAt(sort: Desc)])
  @@index([userId, createdAt(sort: Desc)])
  @@index([entryType])
  @@index([assetType])
  @@index([refOrderId])
  @@index([refTxHash])
  @@index([createdAt])
  @@map("wallet_ledger_entry_view")
}

/// 认种资金分配分类账 - 通过 Debezium CDC 从 planting-service 同步
/// 记录每笔认种订单的资金分配明细
model FundAllocationView {
  id      BigInt @id @map("allocation_id")
  orderId BigInt @map("order_id")

  // 分配信息
  targetType      String  @map("target_type") @db.VarChar(50)
  amount          Decimal @map("amount") @db.Decimal(20, 8)
  targetAccountId String? @map("target_account_id") @db.VarChar(100)

  // 时间戳
  createdAt DateTime @map("created_at")
  syncedAt  DateTime @default(now()) @map("synced_at")

  @@index([orderId])
  @@index([targetType, targetAccountId])
  @@index([createdAt])
  @@map("fund_allocation_view")
}

/// 系统账户流水分类账 - 通过 Debezium CDC 从 authorization-service 同步
/// 记录系统账户（成本账户、运营账户、区域账户）的资金变动
model SystemAccountLedgerView {
  id        BigInt @id @map("ledger_id")
  accountId BigInt @map("account_id")

  // 流水类型
  entryType String @map("entry_type") @db.VarChar(30)

  // 金额
  amount       Decimal @map("amount") @db.Decimal(20, 8)
  balanceAfter Decimal @map("balance_after") @db.Decimal(20, 8)

  // 关联信息
  sourceOrderId  BigInt? @map("source_order_id")
  sourceRewardId BigInt? @map("source_reward_id")
  txHash         String? @map("tx_hash") @db.VarChar(66)

  memo String? @map("memo") @db.VarChar(500)

  // 时间戳
  createdAt DateTime @map("created_at")
  syncedAt  DateTime @default(now()) @map("synced_at")

  @@index([accountId, createdAt(sort: Desc)])
  @@index([sourceOrderId])
  @@index([txHash])
  @@index([createdAt])
  @@map("system_account_ledger_view")
}

// =============================================================================
// Kafka Event Tracking (事件消费追踪)
// =============================================================================

/// 事件消费位置追踪 - 用于幂等性和断点续传
model EventConsumerOffset {
  id            BigInt   @id @default(autoincrement())
  consumerGroup String   @map("consumer_group") @db.VarChar(100)
  topic         String   @db.VarChar(100)
  partition     Int
  offset        BigInt
  updatedAt     DateTime @default(now()) @map("updated_at")

  @@unique([consumerGroup, topic, partition])
  @@map("event_consumer_offsets")
}

/// 已处理事件记录 - 用于幂等性检查
model ProcessedEvent {
  id          BigInt   @id @default(autoincrement())
  eventId     String   @unique @map("event_id") @db.VarChar(100)
  eventType   String   @map("event_type") @db.VarChar(50)
  processedAt DateTime @default(now()) @map("processed_at")

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

// =============================================================================
// System Config (系统配置)
// =============================================================================

/// 系统配置 - 键值对存储，用于存储各种系统设置
model SystemConfig {
  id          String   @id @default(uuid())
  key         String   @unique @db.VarChar(100) // 配置键
  value       String   @db.Text // 配置值 (JSON 格式)
  description String?  @db.VarChar(255) // 配置描述
  createdAt   DateTime @default(now()) @map("created_at")
  updatedAt   DateTime @updatedAt @map("updated_at")
  updatedBy   String?  @map("updated_by") // 更新人ID

  @@index([key])
  @@map("system_configs")
}

// =============================================================================
// System Maintenance (系统维护公告)
// =============================================================================

/// 系统维护公告 - 用于系统升级/维护期间阻断用户操作
model SystemMaintenance {
  id        String   @id @default(uuid())
  title     String   @db.VarChar(100) // 标题：如"系统升级中"
  message   String   @db.Text // 说明：如"预计10:00恢复，请稍候"
  startTime DateTime @map("start_time") // 维护开始时间
  endTime   DateTime @map("end_time") // 维护结束时间
  isActive  Boolean  @default(false) @map("is_active") // 是否激活
  createdAt DateTime @default(now()) @map("created_at")
  updatedAt DateTime @updatedAt @map("updated_at")
  createdBy String   @map("created_by") // 创建人ID
  updatedBy String?  @map("updated_by") // 更新人ID

  @@index([isActive])
  @@index([startTime, endTime])
  @@map("system_maintenances")
}

// =============================================================================
// Co-Managed Wallet System (共管钱包系统)
// =============================================================================

/// 共管钱包会话状态
enum WalletSessionStatus {
  WAITING // 等待参与方加入
  READY // 所有参与方已就绪
  PROCESSING // 密钥生成中
  COMPLETED // 创建完成
  FAILED // 创建失败
  CANCELLED // 已取消
}

/// 共管钱包会话 - 钱包创建过程的会话记录
model CoManagedWalletSession {
  id           String              @id @default(uuid())
  walletName   String              @map("wallet_name") @db.VarChar(100) // 钱包名称
  thresholdT   Int                 @map("threshold_t") // 签名阈值 T
  thresholdN   Int                 @map("threshold_n") // 参与方总数 N
  inviteCode   String              @unique @map("invite_code") @db.VarChar(20) // 邀请码
  status       WalletSessionStatus @default(WAITING) // 会话状态
  participants String              @db.Text // 参与方列表 (JSON)
  currentRound Int                 @default(0) @map("current_round") // 当前密钥生成轮次
  totalRounds  Int                 @default(3) @map("total_rounds") // 总轮次
  publicKey    String?             @map("public_key") @db.VarChar(200) // 生成的公钥
  error        String?             @db.Text // 错误信息
  createdAt    DateTime            @default(now()) @map("created_at")
  updatedAt    DateTime            @updatedAt @map("updated_at")
  createdBy    String              @map("created_by") @db.VarChar(100) // 创建者

  @@index([inviteCode])
  @@index([status])
  @@index([createdBy])
  @@index([createdAt])
  @@map("co_managed_wallet_sessions")
}

/// 共管钱包 - 创建成功后的钱包记录
model CoManagedWallet {
  id           String   @id @default(uuid())
  sessionId    String   @unique @map("session_id") // 关联的会话 ID
  name         String   @db.VarChar(100) // 钱包名称
  publicKey    String   @map("public_key") @db.VarChar(200) // 钱包公钥
  thresholdT   Int      @map("threshold_t") // 签名阈值 T
  thresholdN   Int      @map("threshold_n") // 参与方总数 N
  participants String   @db.Text // 参与方列表 (JSON)
  createdAt    DateTime @default(now()) @map("created_at")
  createdBy    String   @map("created_by") @db.VarChar(100) // 创建者

  @@index([sessionId])
  @@index([publicKey])
  @@index([createdBy])
  @@index([createdAt])
  @@map("co_managed_wallets")
}

// =============================================================================
// App Assets (应用资源 - 开屏图/引导图)
// =============================================================================

/// 应用资源类型
enum AppAssetType {
  SPLASH // 开屏图
  GUIDE  // 引导图
}

/// 应用资源 - 管理开屏图和引导图
model AppAsset {
  id        String       @id @default(uuid())
  type      AppAssetType
  sortOrder Int          @map("sort_order")
  imageUrl  String       @map("image_url") @db.Text
  title     String?      @db.VarChar(100)
  subtitle  String?      @db.VarChar(200)
  isEnabled Boolean      @default(true) @map("is_enabled")
  createdAt DateTime     @default(now()) @map("created_at")
  updatedAt DateTime     @updatedAt @map("updated_at")

  @@unique([type, sortOrder])
  @@index([type, isEnabled])
  @@map("app_assets")
}

// =============================================================================
// Contract Batch Download Tasks (合同批量下载任务)
// [2026-02-05] 新增：支持管理后台合同批量下载
// 回滚方式：删除此 model 并运行 prisma migrate
// =============================================================================

/// 批量下载任务状态
enum BatchDownloadStatus {
  PENDING    // 待处理
  PROCESSING // 处理中
  COMPLETED  // 已完成
  FAILED     // 失败
  CANCELLED  // 已取消
}

/// 合同批量下载任务 - 记录批量下载请求的执行状态
model ContractBatchDownloadTask {
  id                   BigInt              @id @default(autoincrement())
  taskNo               String              @unique @map("task_no") @db.VarChar(50)
  status               BatchDownloadStatus @default(PENDING)

  // 下载统计
  totalContracts       Int                 @default(0) @map("total_contracts")
  downloadedCount      Int                 @default(0) @map("downloaded_count")
  failedCount          Int                 @default(0) @map("failed_count")
  progress             Int                 @default(0) // 0-100

  // 断点续传支持
  lastProcessedOrderNo String?             @map("last_processed_order_no") @db.VarChar(50)

  // 结果文件
  resultFileUrl        String?             @map("result_file_url") @db.VarChar(500)
  resultFileSize       BigInt?             @map("result_file_size")

  // 错误信息
  errors               Json?               // 失败的合同列表

  // 操作者
  operatorId           String              @map("operator_id") @db.VarChar(50)

  // 筛选条件
  filters              Json?               // { signedAfter, signedBefore, provinceCode, cityCode }

  // 时间戳
  createdAt            DateTime            @default(now()) @map("created_at")
  startedAt            DateTime?           @map("started_at")
  completedAt          DateTime?           @map("completed_at")
  expiresAt            DateTime?           @map("expires_at") // 结果文件过期时间

  @@index([status])
  @@index([operatorId])
  @@index([createdAt])
  @@map("contract_batch_download_tasks")
}

// =============================================================================
// Customer Service Contacts (客服联系方式)
// =============================================================================

/// 客服联系方式类型
enum ContactType {
  WECHAT // 微信
  QQ     // QQ
}

/// 客服联系方式 - 管理员配置的客服联系信息
model CustomerServiceContact {
  id        String      @id @default(uuid())
  type      ContactType
  label     String      @db.VarChar(100)
  value     String      @db.VarChar(200)
  sortOrder Int         @map("sort_order")
  isEnabled Boolean     @default(true) @map("is_enabled")
  createdAt DateTime    @default(now()) @map("created_at")
  updatedAt DateTime    @updatedAt @map("updated_at")

  @@index([type, isEnabled])
  @@index([sortOrder])
  @@map("customer_service_contacts")
}

// =============================================================================
// 预种计划开关配置
// 控制预种功能的开启/关闭，不影响已完成的业务流程
// =============================================================================
model PrePlantingConfig {
  id          String    @id @default(uuid())
  isActive    Boolean   @default(false) @map("is_active")
  activatedAt DateTime? @map("activated_at")
  updatedAt   DateTime  @updatedAt @map("updated_at")
  updatedBy   String?   @map("updated_by") @db.VarChar(50)

  @@map("pre_planting_configs")
}

// =============================================================================
// 认种树定价配置 (Tree Pricing Supplement)
// 基础价 15831 USDT 不变，supplement 作为加价全额归总部 (S0000000001)
// 正式认种总价 = 15831 + currentSupplement
// 预种总价 = (15831 + currentSupplement) / 5
// =============================================================================
model TreePricingConfig {
  id                       String    @id @default(uuid())
  currentSupplement        Int       @default(0) @map("current_supplement")
  autoIncreaseEnabled      Boolean   @default(false) @map("auto_increase_enabled")
  autoIncreaseAmount       Int       @default(0) @map("auto_increase_amount")
  autoIncreaseIntervalDays Int       @default(0) @map("auto_increase_interval_days")
  lastAutoIncreaseAt       DateTime? @map("last_auto_increase_at")
  nextAutoIncreaseAt       DateTime? @map("next_auto_increase_at")
  updatedAt                DateTime  @updatedAt @map("updated_at")
  updatedBy                String?   @map("updated_by") @db.VarChar(50)

  @@map("tree_pricing_configs")
}

// =============================================================================
// 认种树价格变更审计日志 (Tree Price Change Audit Log)
// 每次价格变更（手动或自动）都会记录一条不可修改的日志
// =============================================================================
model TreePriceChangeLog {
  id                 String          @id @default(uuid())
  changeType         PriceChangeType @map("change_type")
  previousSupplement Int             @map("previous_supplement")
  newSupplement      Int             @map("new_supplement")
  changeAmount       Int             @map("change_amount")
  reason             String?         @db.VarChar(500)
  operatorId         String?         @map("operator_id") @db.VarChar(50)
  createdAt          DateTime        @default(now()) @map("created_at")

  @@index([createdAt])
  @@index([changeType])
  @@map("tree_price_change_logs")
}

enum PriceChangeType {
  MANUAL // 管理员手动调整
  AUTO   // 自动涨价任务
}
