// 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 AuthorizationRole {
  id                        String   @id @default(uuid())
  userId                    String   @map("user_id")
  accountSequence           String   @map("account_sequence")
  roleType                  RoleType @map("role_type")
  regionCode                String   @map("region_code")
  regionName                String   @map("region_name")
  status                    AuthorizationStatus @default(PENDING)
  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")
  revokeReason              String?   @map("revoke_reason")

  // 软删除 (大厂通用做法: deleted_at 为 NULL 表示未删除)
  deletedAt                 DateTime? @map("deleted_at")

  // 考核配置
  initialTargetTreeCount    Int      @map("initial_target_tree_count")
  monthlyTargetType         MonthlyTargetType @map("monthly_target_type")

  // 自有团队占比
  requireLocalPercentage    Decimal  @default(5.0) @map("require_local_percentage") @db.Decimal(5, 2)
  exemptFromPercentageCheck Boolean  @default(false) @map("exempt_from_percentage_check")

  // 权益状态
  benefitActive             Boolean  @default(false) @map("benefit_active")
  benefitActivatedAt        DateTime? @map("benefit_activated_at")
  benefitDeactivatedAt      DateTime? @map("benefit_deactivated_at")
  benefitValidUntil         DateTime? @map("benefit_valid_until")  // 权益有效期截止日期（当前月+下月末）

  // 月度考核追踪
  lastAssessmentMonth       String?  @map("last_assessment_month")  // 上次考核月份 YYYY-MM
  monthlyTreesAdded         Int      @default(0) @map("monthly_trees_added")  // 当月新增树数
  lastMonthTreesAdded       Int      @default(0) @map("last_month_trees_added")  // 上月新增树数（考核用存档）

  // 当前考核月份索引
  currentMonthIndex         Int      @default(0) @map("current_month_index")

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

  // 时间戳
  createdAt                 DateTime @default(now()) @map("created_at")
  updatedAt                 DateTime @updatedAt @map("updated_at")

  // 关联
  assessments               MonthlyAssessment[]
  bypassRecords             MonthlyBypass[]

  // 注意: 唯一约束通过数据库层的部分索引实现，只对 deleted_at IS NULL 的记录生效
  // 需要手动执行迁移 SQL 创建部分唯一索引
  // @@unique([accountSequence, roleType, regionCode]) -- 已移除，改用部分索引
  @@index([accountSequence])
  @@index([userId])
  @@index([roleType, regionCode])
  @@index([status])
  @@index([roleType, status])
  @@index([deletedAt])
  @@map("authorization_roles")
}

// ============ 月度考核表 ============
model MonthlyAssessment {
  id                    String   @id @default(uuid())
  authorizationId       String   @map("authorization_id")
  userId                String   @map("user_id")
  accountSequence       String   @map("account_sequence")
  roleType              RoleType @map("role_type")
  regionCode            String   @map("region_code")

  // 考核月份
  assessmentMonth       String   @map("assessment_month") // YYYY-MM
  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") // 达标时间（用于排名）

  // 自有团队占比
  localTeamCount        Int      @default(0) @map("local_team_count")
  totalTeamCount        Int      @default(0) @map("total_team_count")
  localPercentage       Decimal  @default(0) @map("local_percentage") @db.Decimal(10, 2)
  localPercentagePass   Boolean  @default(false) @map("local_percentage_pass")

  // 超越目标占比
  exceedRatio           Decimal  @default(0) @map("exceed_ratio") @db.Decimal(10, 4)

  // 考核结果
  result                AssessmentResult @default(NOT_ASSESSED)

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

  // 豁免
  isBypassed            Boolean  @default(false) @map("is_bypassed")
  bypassedBy            String?  @map("bypassed_by")
  bypassedAt            DateTime? @map("bypassed_at")

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

  // 关联
  authorization         AuthorizationRole @relation(fields: [authorizationId], references: [id])

  @@unique([authorizationId, assessmentMonth])
  @@index([accountSequence, assessmentMonth])
  @@index([userId, assessmentMonth])
  @@index([roleType, regionCode, assessmentMonth])
  @@index([assessmentMonth, result])
  @@index([assessmentMonth, roleType, exceedRatio(sort: Desc)])
  @@map("monthly_assessments")
}

// ============ 单月豁免记录表 ============
model MonthlyBypass {
  id                String   @id @default(uuid())
  authorizationId   String   @map("authorization_id")
  userId            String   @map("user_id")
  accountSequence   String   @map("account_sequence")
  roleType          RoleType @map("role_type")
  bypassMonth       String   @map("bypass_month") // YYYY-MM

  // 授权信息
  grantedBy         String   @map("granted_by")
  grantedAt         DateTime @map("granted_at")
  reason            String?

  // 审批信息（三人授权）
  approver1Id       String   @map("approver1_id")
  approver1At       DateTime @map("approver1_at")
  approver2Id       String?  @map("approver2_id")
  approver2At       DateTime? @map("approver2_at")
  approver3Id       String?  @map("approver3_id")
  approver3At       DateTime? @map("approver3_at")
  approvalStatus    ApprovalStatus @default(PENDING) @map("approval_status")

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

  authorization     AuthorizationRole @relation(fields: [authorizationId], references: [id])

  @@unique([authorizationId, bypassMonth])
  @@index([accountSequence, bypassMonth])
  @@index([userId, bypassMonth])
  @@map("monthly_bypasses")
}

// ============ 阶梯考核目标配置表 ============
model LadderTargetConfig {
  id               String   @id @default(uuid())
  roleType         RoleType @map("role_type")
  monthIndex       Int      @map("month_index")
  monthlyTarget    Int      @map("monthly_target")
  cumulativeTarget Int      @map("cumulative_target")
  isActive         Boolean  @default(true) @map("is_active")

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

  @@unique([roleType, monthIndex])
  @@map("ladder_target_configs")
}

// ============ 认种限制配置表 ============
model PlantingRestriction {
  id                  String   @id @default(uuid())
  restrictionType     RestrictionType @map("restriction_type")

  // 账户限制配置
  accountLimitDays    Int?     @map("account_limit_days")
  accountLimitCount   Int?     @map("account_limit_count")

  // 总量限制配置
  totalLimitDays      Int?     @map("total_limit_days")
  totalLimitCount     Int?     @map("total_limit_count")
  currentTotalCount   Int      @default(0) @map("current_total_count")

  // 生效时间
  startAt             DateTime @map("start_at")
  endAt               DateTime @map("end_at")

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

  @@map("planting_restrictions")
}

// ============ 管理员授权审批表 ============
model AdminApproval {
  id              String   @id @default(uuid())
  operationType   OperationType @map("operation_type")
  targetId        String   @map("target_id")
  targetType      String   @map("target_type")
  requestData     Json     @map("request_data")

  // 审批状态
  status          ApprovalStatus @default(PENDING)

  // 审批人
  requesterId     String   @map("requester_id")
  approver1Id     String?  @map("approver1_id")
  approver1At     DateTime? @map("approver1_at")
  approver2Id     String?  @map("approver2_id")
  approver2At     DateTime? @map("approver2_at")
  approver3Id     String?  @map("approver3_id")
  approver3At     DateTime? @map("approver3_at")

  // 完成信息
  completedAt     DateTime? @map("completed_at")
  rejectedBy      String?   @map("rejected_by")
  rejectedAt      DateTime? @map("rejected_at")
  rejectReason    String?   @map("reject_reason")

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

  @@index([status])
  @@index([targetId, targetType])
  @@map("admin_approvals")
}

// ============ 授权操作日志表 ============
model AuthorizationAuditLog {
  id              String   @id @default(uuid())
  operationType   String   @map("operation_type")
  targetUserId    String   @map("target_user_id")
  targetRoleType  RoleType? @map("target_role_type")
  targetRegionCode String? @map("target_region_code")

  operatorId      String   @map("operator_id")
  operatorRole    String   @map("operator_role")

  beforeState     Json?    @map("before_state")
  afterState      Json?    @map("after_state")

  ipAddress       String?  @map("ip_address")
  userAgent       String?  @map("user_agent")

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

  @@index([targetUserId])
  @@index([operatorId])
  @@index([createdAt])
  @@map("authorization_audit_logs")
}

// ============ 省市热度统计表 ============
model RegionHeatMap {
  id              String   @id @default(uuid())
  regionCode      String   @map("region_code")
  regionName      String   @map("region_name")
  regionType      RegionType @map("region_type")

  totalPlantings  Int      @default(0) @map("total_plantings")
  monthlyPlantings Int     @default(0) @map("monthly_plantings")
  weeklyPlantings Int      @default(0) @map("weekly_plantings")
  dailyPlantings  Int      @default(0) @map("daily_plantings")

  activeUsers     Int      @default(0) @map("active_users")
  authCompanyCount Int     @default(0) @map("auth_company_count")

  heatScore       Decimal  @default(0) @map("heat_score") @db.Decimal(10, 2)

  updatedAt       DateTime @updatedAt @map("updated_at")

  @@unique([regionCode, regionType])
  @@map("region_heat_maps")
}

// ============ 火柴人排名视图数据表 ============
model StickmanRanking {
  id                  String   @id @default(uuid())
  userId              String   @map("user_id")
  accountSequence     String   @map("account_sequence")
  authorizationId     String   @map("authorization_id")
  roleType            RoleType @map("role_type")
  regionCode          String   @map("region_code")
  regionName          String   @map("region_name")

  // 用户信息
  nickname            String
  avatarUrl           String?  @map("avatar_url")

  // 进度信息
  currentMonth        String   @map("current_month")
  cumulativeCompleted Int      @map("cumulative_completed")
  cumulativeTarget    Int      @map("cumulative_target")
  progressPercentage  Decimal  @map("progress_percentage") @db.Decimal(10, 2)
  exceedRatio         Decimal  @map("exceed_ratio") @db.Decimal(10, 4)

  // 排名
  ranking             Int
  isFirstPlace        Boolean  @map("is_first_place")

  // 本月收益
  monthlyRewardUsdt   Decimal  @map("monthly_reward_usdt") @db.Decimal(18, 2)
  monthlyRewardRwad   Decimal  @map("monthly_reward_rwad") @db.Decimal(18, 8)

  updatedAt           DateTime @updatedAt @map("updated_at")

  @@unique([authorizationId, currentMonth])
  @@index([accountSequence, currentMonth])
  @@index([roleType, regionCode, currentMonth])
  @@map("stickman_rankings")
}

// ============ 系统配置表 ============
model AuthorizationConfig {
  id          String   @id @default(uuid())
  configKey   String   @unique @map("config_key")
  configValue String   @map("config_value")
  description String?
  isActive    Boolean  @default(true) @map("is_active")

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

  @@map("authorization_configs")
}

// ============ 枚举定义 ============
enum RoleType {
  COMMUNITY              // 社区
  AUTH_PROVINCE_COMPANY  // 授权省公司（团队权益20U）
  PROVINCE_COMPANY       // 正式省公司（区域权益15U+1%算力）
  AUTH_CITY_COMPANY      // 授权市公司（团队权益40U）
  CITY_COMPANY           // 正式市公司（区域权益35U+2%算力）
}

enum AuthorizationStatus {
  PENDING     // 待授权/待考核
  AUTHORIZED  // 已授权
  REVOKED     // 已撤销
}

enum AssessmentResult {
  NOT_ASSESSED  // 未考核
  PASS          // 达标
  FAIL          // 未达标
  BYPASSED      // 豁免
}

enum MonthlyTargetType {
  NONE    // 无月度考核（正式省市公司）
  FIXED   // 固定目标（社区：10棵/月）
  LADDER  // 阶梯目标（授权省市公司）
}

enum RestrictionType {
  ACCOUNT_LIMIT  // 账户限时限量
  TOTAL_LIMIT    // 总量限制
}

enum ApprovalStatus {
  PENDING   // 待审批
  APPROVED  // 已通过
  REJECTED  // 已拒绝
}

enum OperationType {
  GRANT_AUTHORIZATION    // 授予授权
  REVOKE_AUTHORIZATION   // 撤销授权
  GRANT_BYPASS           // 授予豁免
  EXEMPT_PERCENTAGE      // 豁免占比考核
  MODIFY_CONFIG          // 修改配置
}

enum RegionType {
  PROVINCE  // 省
  CITY      // 市
}

// ============ 系统账户类型枚举 ============
enum SystemAccountType {
  COST_ACCOUNT       // 成本账户
  OPERATION_ACCOUNT  // 运营账户
  HQ_COMMUNITY       // 总部社区账户
  RWAD_POOL_PENDING  // RWAD矿池待注入
  SYSTEM_PROVINCE    // 系统省账户（无授权时）
  SYSTEM_CITY        // 系统市账户（无授权时）
}

// ============ 系统账户流水类型枚举 ============
enum SystemLedgerEntryType {
  PLANTING_ALLOCATION    // 认种分配收入
  REWARD_EXPIRED         // 过期奖励收入
  TRANSFER_OUT           // 转出
  TRANSFER_IN            // 转入
  WITHDRAWAL             // 提现
  ADJUSTMENT             // 调整
}

// ============ 系统账户表 ============
// 管理成本、运营、总部社区、矿池等系统级账户
model SystemAccount {
  id              BigInt   @id @default(autoincrement()) @map("account_id")

  // 账户类型
  accountType     SystemAccountType @map("account_type")

  // 区域信息（仅 SYSTEM_PROVINCE/SYSTEM_CITY 需要）
  regionCode      String?  @map("region_code") @db.VarChar(10)
  regionName      String?  @map("region_name") @db.VarChar(50)

  // MPC 生成的钱包地址（按需生成）
  walletAddress   String?  @map("wallet_address") @db.VarChar(42)
  mpcPublicKey    String?  @map("mpc_public_key") @db.VarChar(130)

  // 余额（USDT）
  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 @default(now()) @map("created_at")
  updatedAt       DateTime @updatedAt @map("updated_at")

  ledgerEntries   SystemAccountLedger[]

  @@unique([accountType, regionCode], name: "uk_account_region")
  @@index([accountType], name: "idx_system_account_type")
  @@index([walletAddress], name: "idx_system_wallet_address")
  @@map("system_accounts")
}

// ============ 系统账户流水表 ============
// 记录系统账户的所有资金变动（Append-only）
model SystemAccountLedger {
  id              BigInt   @id @default(autoincrement()) @map("ledger_id")
  accountId       BigInt   @map("account_id")

  // 流水类型
  entryType       SystemLedgerEntryType @map("entry_type")

  // 金额
  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 @default(now()) @map("created_at")

  account         SystemAccount @relation(fields: [accountId], references: [id])

  @@index([accountId, createdAt(sort: Desc)], name: "idx_system_ledger_account_created")
  @@index([sourceOrderId], name: "idx_system_ledger_source_order")
  @@index([txHash], name: "idx_system_ledger_tx_hash")
  @@map("system_account_ledgers")
}

// ============ 权益有效性考核记录表 ============
// 专门记录权益激活/续期/失效的考核历史
// 与 MonthlyAssessment (火柴人排名) 分离，避免职责混淆
model BenefitAssessmentRecord {
  id                    String   @id @default(uuid())
  authorizationId       String   @map("authorization_id")
  userId                String   @map("user_id")
  accountSequence       String   @map("account_sequence")
  roleType              RoleType @map("role_type")
  regionCode            String   @map("region_code")
  regionName            String   @map("region_name")

  // 考核月份
  assessmentMonth       String   @map("assessment_month") // YYYY-MM
  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    BenefitActionType @map("benefit_action_taken")  // RENEWED / DEACTIVATED / ACTIVATED
  previousBenefitStatus Boolean  @map("previous_benefit_status")        // 考核前权益状态
  newBenefitStatus      Boolean  @map("new_benefit_status")             // 考核后权益状态
  newValidUntil         DateTime? @map("new_valid_until")               // 新的有效期截止日

  // 考核结果
  result                AssessmentResult @default(NOT_ASSESSED)

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

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

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

// ============ 权益操作类型枚举 ============
enum BenefitActionType {
  ACTIVATED     // 首次激活
  RENEWED       // 续期
  DEACTIVATED   // 失效
  NO_CHANGE     // 无变化（未到考核时间）
}

// ============================================
// Outbox 事件表 - 保证事件可靠发送
// 使用 Outbox Pattern 确保领域事件100%送达
// ============================================
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)

  // 发布状态: PENDING, SENT, CONFIRMED, FAILED
  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")

  @@index([status, createdAt])
  @@index([status, nextRetryAt])
  @@index([aggregateType, aggregateId])
  @@index([topic])
  @@map("outbox_events")
}
