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

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

model Guild {
  id        String         @id
  createdAt DateTime       @default(now())
  updatedAt DateTime       @updatedAt
  settings  GuildSettings?
  cases     Case[]
  escalationRules EscalationRule[]
  autoModConfig AutoModConfig?
  autoModRules AutoModRule[]
  loggingConfig LoggingConfig?
  logChannels LogChannel[]
  welcomeConfig WelcomeConfig?
  verificationConfig VerificationConfig?
  levelingConfig LevelingConfig?
  memberLevels MemberLevel[]
  levelRewards LevelReward[]
  economyConfig EconomyConfig?
  memberEconomies MemberEconomy[]
  shopItems ShopItem[]
  inventoryItems InventoryItem[]
  polls Poll[]
  reminders Reminder[]
  afkStatuses AfkStatus[]
  giveaways Giveaway[]
  ticketConfig TicketConfig?
  ticketCategories TicketCategory[]
  tickets Ticket[]
  selfRolePanels SelfRolePanel[]
  tags Tag[]
  starboardConfig StarboardConfig?
  starboardEntries StarboardEntry[]
  suggestionConfig SuggestionConfig?
  suggestions Suggestion[]
  birthdays Birthday[]
  birthdayConfig BirthdayConfig?
  tempVoiceConfig TempVoiceConfig?
  tempVoiceChannels TempVoiceChannel[]
  statsConfig StatsConfig?
  inviteStats InviteStat[]
  inviteJoins InviteJoin[]
  activityStats ActivityStat[]
  socialFeeds SocialFeed[]
  scheduledMessages ScheduledMessage[]
  guildBackups GuildBackup[]
  dashboardAccessRules DashboardAccessRule[]
  dashboardAuditLogs DashboardAuditLog[]
  commandOverrides CommandOverride[]
}

model GuildSettings {
  id                String   @id @default(cuid())
  guildId           String   @unique
  locale            String   @default("de")
  timezone          String   @default("Europe/Berlin")
  moderationEnabled Boolean  @default(true)
  /// Snipe/editsnipe storage and commands (SPEC: default off for privacy).
  snipeEnabled      Boolean  @default(false)
  /// Global command channel whitelist (empty = all channels unless denied).
  commandAllowedChannelIds String[] @default([])
  /// Global command channel blacklist.
  commandDeniedChannelIds  String[] @default([])
  guild             Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model DashboardAccessRule {
  id        String   @id @default(cuid())
  guildId   String
  roleId    String
  modules   Json
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  guild     Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, roleId])
  @@index([guildId])
}

model DashboardAuditLog {
  id          String   @id @default(cuid())
  guildId     String?
  actorUserId String
  action      String
  path        String?
  before      Json?
  after       Json?
  createdAt   DateTime @default(now())
  guild       Guild?   @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@index([guildId, createdAt])
  @@index([actorUserId, createdAt])
}

model User {
  id        String    @id
  createdAt DateTime  @default(now())
  warnings  Warning[]
  notes     ModNote[]
}

model Case {
  id             String    @id @default(cuid())
  caseNumber     Int
  guildId        String
  targetUserId   String
  moderatorId    String
  action         String
  reason         String?
  metadata       Json?
  deletedAt      DateTime?
  createdAt      DateTime  @default(now())
  updatedAt      DateTime  @updatedAt
  guild          Guild     @relation(fields: [guildId], references: [id], onDelete: Cascade)
  warnings       Warning[]
  moderationNote ModNote[]

  @@unique([guildId, caseNumber])
  @@index([guildId, targetUserId])
}

model Warning {
  id         String   @id @default(cuid())
  guildId    String
  userId     String
  moderatorId String
  reason     String?
  caseId     String?
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
  user       User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  case       Case?    @relation(fields: [caseId], references: [id], onDelete: SetNull)

  @@index([guildId, userId])
}

model ModNote {
  id         String   @id @default(cuid())
  guildId    String
  userId     String
  moderatorId String
  note       String
  caseId     String?
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
  user       User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  case       Case?    @relation(fields: [caseId], references: [id], onDelete: SetNull)

  @@index([guildId, userId])
}

model EscalationRule {
  id         String   @id @default(cuid())
  guildId    String
  warnCount  Int
  action     String
  durationMs Int?
  reason     String?
  enabled    Boolean  @default(true)
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
  guild      Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, warnCount])
  @@index([guildId, enabled])
}

model AutoModConfig {
  id                        String   @id @default(cuid())
  guildId                   String   @unique
  enabled                   Boolean  @default(true)
  antiRaidEnabled           Boolean  @default(false)
  antiRaidJoinThreshold     Int      @default(10)
  antiRaidWindowSeconds     Int      @default(10)
  antiRaidAction            String   @default("LOCKDOWN")
  antiNukeEnabled           Boolean  @default(false)
  antiNukeBanThreshold      Int      @default(5)
  antiNukeChannelThreshold  Int      @default(3)
  antiNukeWindowSeconds     Int      @default(60)
  lockdownActive            Boolean  @default(false)
  createdAt                 DateTime @default(now())
  updatedAt                 DateTime @updatedAt
  guild                     Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model AutoModRule {
  id          String   @id @default(cuid())
  guildId     String
  ruleType    String
  enabled     Boolean  @default(true)
  action      String   @default("DELETE")
  threshold   Json?
  exceptions  Json?
  wordList    Json?
  durationMs  Int?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  guild       Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, ruleType])
  @@index([guildId, enabled])
}

model LoggingConfig {
  id                 String   @id @default(cuid())
  guildId            String   @unique
  enabled            Boolean  @default(true)
  ignoreBots         Boolean  @default(true)
  ignoredChannelIds  String[] @default([])
  ignoredRoleIds     String[] @default([])
  /// Days to keep Case / dashboard audit rows; 0 = keep forever.
  retentionDays      Int      @default(90)
  createdAt          DateTime @default(now())
  updatedAt          DateTime @updatedAt
  guild              Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model LogChannel {
  id        String   @id @default(cuid())
  guildId   String
  eventType String
  channelId String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  guild     Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, eventType])
  @@index([guildId])
}

model WelcomeConfig {
  id               String   @id @default(cuid())
  guildId          String   @unique
  welcomeEnabled   Boolean  @default(false)
  leaveEnabled     Boolean  @default(false)
  welcomeChannelId String?
  leaveChannelId   String?
  welcomeType      String   @default("TEXT")
  welcomeContent   String?
  welcomeEmbed     Json?
  leaveContent     String?
  leaveEmbed       Json?
  welcomeDmEnabled Boolean  @default(false)
  welcomeDmContent String?
  userAutoroleIds  String[] @default([])
  botAutoroleIds   String[] @default([])
  imageTitle       String?
  imageSubtitle    String?
  createdAt        DateTime @default(now())
  updatedAt        DateTime @updatedAt
  guild            Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model VerificationConfig {
  id               String   @id @default(cuid())
  guildId          String   @unique
  enabled          Boolean  @default(false)
  channelId        String?
  verifiedRoleId   String?
  unverifiedRoleId String?
  mode             String   @default("BUTTON")
  minAccountAgeDays Int     @default(0)
  failAction       String   @default("KICK")
  panelChannelId   String?
  panelMessageId   String?
  createdAt        DateTime @default(now())
  updatedAt        DateTime @updatedAt
  guild            Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model LevelingConfig {
  id                    String   @id @default(cuid())
  guildId               String   @unique
  enabled               Boolean  @default(true)
  textXpMin             Int      @default(15)
  textXpMax             Int      @default(25)
  textCooldownSeconds   Int      @default(60)
  voiceXpPerMinute      Int      @default(10)
  noXpChannelIds        String[] @default([])
  noXpRoleIds           String[] @default([])
  roleMultipliers       Json?
  channelMultipliers    Json?
  levelUpMode           String   @default("CHANNEL")
  levelUpChannelId      String?
  levelUpMessage        String?
  stackRewards          Boolean  @default(true)
  cardAccentColor       String   @default("#6366F1")
  cardBackgroundColor   String   @default("#111827")
  createdAt             DateTime @default(now())
  updatedAt             DateTime @updatedAt
  guild                 Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model MemberLevel {
  id        String   @id @default(cuid())
  guildId   String
  userId    String
  xp        Int      @default(0)
  level     Int      @default(0)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  guild     Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, userId])
  @@index([guildId, xp])
}

model LevelReward {
  id        String   @id @default(cuid())
  guildId   String
  level     Int
  roleId    String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  guild     Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, level])
  @@index([guildId])
}

model EconomyConfig {
  id              String   @id @default(cuid())
  guildId         String   @unique
  enabled         Boolean  @default(true)
  currencyName    String   @default("Coins")
  currencySymbol  String   @default("🪙")
  dailyAmount     Int      @default(200)
  weeklyAmount    Int      @default(1000)
  workMin         Int      @default(50)
  workMax         Int      @default(150)
  workCooldownSeconds Int  @default(3600)
  startingBalance Int      @default(0)
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt
  guild           Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model MemberEconomy {
  id           String    @id @default(cuid())
  guildId      String
  userId       String
  balance      Int       @default(0)
  lastDailyAt  DateTime?
  lastWeeklyAt DateTime?
  lastWorkAt   DateTime?
  createdAt    DateTime  @default(now())
  updatedAt    DateTime  @updatedAt
  guild        Guild     @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, userId])
  @@index([guildId, balance])
}

model ShopItem {
  id          String   @id @default(cuid())
  guildId     String
  name        String
  description String?
  price       Int
  roleId      String?
  stock       Int?
  enabled     Boolean  @default(true)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  guild       Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
  inventory   InventoryItem[]

  @@index([guildId, enabled])
}

model InventoryItem {
  id        String   @id @default(cuid())
  guildId   String
  userId    String
  itemId    String
  quantity  Int      @default(1)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  guild     Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
  item      ShopItem @relation(fields: [itemId], references: [id], onDelete: Cascade)

  @@unique([guildId, userId, itemId])
  @@index([guildId, userId])
}

model Poll {
  id            String     @id @default(cuid())
  guildId       String
  channelId     String
  messageId     String?
  creatorId     String
  question      String
  options       Json
  multiSelect   Boolean    @default(false)
  anonymous     Boolean    @default(false)
  endsAt        DateTime?
  closedAt      DateTime?
  createdAt     DateTime   @default(now())
  updatedAt     DateTime   @updatedAt
  guild         Guild      @relation(fields: [guildId], references: [id], onDelete: Cascade)
  votes         PollVote[]

  @@index([guildId])
}

model PollVote {
  id        String   @id @default(cuid())
  pollId    String
  userId    String
  optionIndex Int
  createdAt DateTime @default(now())
  poll      Poll     @relation(fields: [pollId], references: [id], onDelete: Cascade)

  @@unique([pollId, userId, optionIndex])
  @@index([pollId])
}

model Reminder {
  id          String    @id @default(cuid())
  guildId     String?
  userId      String
  channelId   String
  content     String
  remindAt    DateTime
  recurringCron String?
  jobId       String?
  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt
  guild       Guild?    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@index([userId])
  @@index([remindAt])
}

model AfkStatus {
  id        String   @id @default(cuid())
  guildId   String
  userId    String
  reason    String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  guild     Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, userId])
}

model Giveaway {
  id              String    @id @default(cuid())
  guildId         String
  channelId       String
  messageId       String?
  prize           String
  winnerCount     Int       @default(1)
  endsAt          DateTime
  requiredRoleId  String?
  requiredLevel   Int?
  requiredMemberDays Int?
  paused          Boolean   @default(false)
  endedAt         DateTime?
  winners         String[]  @default([])
  entrants        String[]  @default([])
  hostId          String
  createdAt       DateTime  @default(now())
  updatedAt       DateTime  @updatedAt
  guild           Guild     @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@index([guildId, endsAt])
}

model TicketConfig {
  id                 String   @id @default(cuid())
  guildId            String   @unique
  enabled            Boolean  @default(true)
  mode               String   @default("CHANNEL")
  categoryId         String?
  logChannelId       String?
  transcriptDm       Boolean  @default(false)
  inactivityHours    Int      @default(72)
  ratingEnabled      Boolean  @default(true)
  createdAt          DateTime @default(now())
  updatedAt          DateTime @updatedAt
  guild              Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model TicketCategory {
  id              String   @id @default(cuid())
  guildId         String
  name            String
  description     String?
  emoji           String?
  supportRoleIds  String[] @default([])
  formFields      Json?
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt
  guild           Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
  tickets         Ticket[]

  @@unique([guildId, name])
  @@index([guildId])
}

model Ticket {
  id            String    @id @default(cuid())
  guildId       String
  categoryId    String?
  openerId      String
  claimedById   String?
  channelId     String?
  threadId      String?
  status        String    @default("OPEN")
  priority      String    @default("NORMAL")
  subject       String?
  formAnswers   Json?
  transcriptHtml String?
  rating        Int?
  closedAt      DateTime?
  lastActivityAt DateTime @default(now())
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
  guild         Guild     @relation(fields: [guildId], references: [id], onDelete: Cascade)
  category      TicketCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull)

  @@index([guildId, status])
  @@index([channelId])
}

model SelfRolePanel {
  id          String   @id @default(cuid())
  guildId     String
  channelId   String
  messageId   String?
  title       String
  description String?
  mode        String   @default("BUTTONS")
  behavior    String   @default("NORMAL")
  roles       Json
  expiresAt   DateTime?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  guild       Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@index([guildId])
}

model Tag {
  id              String   @id @default(cuid())
  guildId         String
  name            String
  content         String?
  embed           Json?
  responseType    String   @default("TEXT")
  triggerWord     String?
  allowedRoleIds  String[] @default([])
  allowedChannelIds String[] @default([])
  createdById     String
  useCount        Int      @default(0)
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt
  guild           Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, name])
  @@index([guildId])
}

model StarboardConfig {
  id               String   @id @default(cuid())
  guildId          String   @unique
  enabled          Boolean  @default(false)
  channelId        String?
  emoji            String   @default("⭐")
  threshold        Int      @default(3)
  allowSelfStar    Boolean  @default(false)
  ignoredChannelIds String[] @default([])
  createdAt        DateTime @default(now())
  updatedAt        DateTime @updatedAt
  guild            Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model StarboardEntry {
  id               String   @id @default(cuid())
  guildId          String
  sourceChannelId  String
  sourceMessageId  String
  starboardMessageId String
  starCount        Int      @default(0)
  createdAt        DateTime @default(now())
  updatedAt        DateTime @updatedAt
  guild            Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, sourceMessageId])
  @@index([guildId])
}

model SuggestionConfig {
  id                String   @id @default(cuid())
  guildId           String   @unique
  enabled           Boolean  @default(true)
  openChannelId     String?
  approvedChannelId String?
  deniedChannelId   String?
  createThread      Boolean  @default(true)
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt
  guild             Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model Suggestion {
  id              String   @id @default(cuid())
  guildId         String
  authorId        String
  content         String
  status          String   @default("OPEN")
  messageId       String?
  channelId       String?
  threadId        String?
  upvotes          Int      @default(0)
  downvotes        Int      @default(0)
  voterUpIds      String[] @default([])
  voterDownIds    String[] @default([])
  staffReason     String?
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt
  guild           Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@index([guildId, status])
}

model BirthdayConfig {
  id              String   @id @default(cuid())
  guildId         String   @unique
  enabled         Boolean  @default(true)
  channelId       String?
  roleId          String?
  message         String?
  timezone        String   @default("Europe/Berlin")
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt
  guild           Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model Birthday {
  id        String   @id @default(cuid())
  guildId   String
  userId    String
  month     Int
  day       Int
  year      Int?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  guild     Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, userId])
  @@index([guildId, month, day])
}

model TempVoiceConfig {
  id          String   @id @default(cuid())
  guildId     String   @unique
  enabled     Boolean  @default(false)
  hubChannelId String?
  categoryId  String?
  defaultName String   @default("{user}'s Channel")
  defaultLimit Int     @default(0)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  guild       Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model TempVoiceChannel {
  id          String   @id @default(cuid())
  guildId     String
  channelId   String   @unique
  ownerId     String
  controlMessageId String?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  guild       Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@index([guildId, ownerId])
}

model StatsConfig {
  id                String   @id @default(cuid())
  guildId           String   @unique
  enabled           Boolean  @default(false)
  membersChannelId  String?
  onlineChannelId   String?
  boostsChannelId   String?
  membersTemplate   String   @default("Members: {count}")
  onlineTemplate    String   @default("Online: {count}")
  boostsTemplate    String   @default("Boosts: {count}")
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt
  guild             Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)
}

model InviteStat {
  id          String   @id @default(cuid())
  guildId     String
  inviterId   String
  code        String?
  joins       Int      @default(0)
  leaves      Int      @default(0)
  fakes       Int      @default(0)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  guild       Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, inviterId])
  @@index([guildId, joins])
}

model InviteJoin {
  id          String    @id @default(cuid())
  guildId     String
  userId      String
  inviterId   String?
  code        String?
  isFake      Boolean   @default(false)
  leftAt      DateTime?
  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt
  guild       Guild     @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, userId])
  @@index([guildId, inviterId])
}

model ActivityStat {
  id           String   @id @default(cuid())
  guildId      String
  userId       String
  channelId    String?
  messageCount Int      @default(0)
  voiceMinutes Int      @default(0)
  day          DateTime
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt
  guild        Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, userId, channelId, day])
  @@index([guildId, day])
}

model SocialFeed {
  id            String    @id @default(cuid())
  guildId       String
  type          String
  sourceId      String
  channelId     String
  rolePingId    String?
  template      String?
  lastItemId    String?
  enabled       Boolean   @default(true)
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
  guild         Guild     @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@index([guildId, type])
  @@index([enabled])
}

model ScheduledMessage {
  id            String    @id @default(cuid())
  guildId       String
  channelId     String
  creatorId     String
  content       String?
  embed         Json?
  rolePingId    String?
  cron          String?
  runAt         DateTime?
  jobId         String?
  enabled       Boolean   @default(true)
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
  guild         Guild     @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@index([guildId, enabled])
}

model GuildBackup {
  id          String   @id @default(cuid())
  guildId     String
  name        String
  createdById String
  payload     Json
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  guild       Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@index([guildId, createdAt])
}

model CommandOverride {
  id                String   @id @default(cuid())
  guildId           String
  commandName       String
  enabled           Boolean  @default(true)
  allowedRoleIds    String[] @default([])
  deniedRoleIds     String[] @default([])
  allowedChannelIds String[] @default([])
  deniedChannelIds  String[] @default([])
  cooldownSeconds   Int?
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt
  guild             Guild    @relation(fields: [guildId], references: [id], onDelete: Cascade)

  @@unique([guildId, commandName])
  @@index([guildId])
}

model OwnerTeamMember {
  id        String   @id @default(cuid())
  userId    String   @unique
  role      String
  note      String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model GlobalUserBlacklist {
  id          String   @id @default(cuid())
  userId      String   @unique
  reason      String?
  note        String?
  createdById String
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

model GuildBlacklist {
  id          String   @id @default(cuid())
  guildId     String   @unique
  reason      String?
  createdById String
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

model FeatureFlag {
  id                String   @id @default(cuid())
  key               String   @unique
  enabled           Boolean  @default(false)
  rolloutPercent    Int      @default(0)
  whitelistGuildIds String[] @default([])
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt
}

model BotPresenceConfig {
  id                 String   @id @default("singleton")
  status             String   @default("online")
  activityType       String   @default("Watching")
  activityText       String   @default("nexumi.de")
  rotatingMessages   Json?
  maintenanceMode    Boolean  @default(false)
  maintenanceMessage String?
  updatedAt          DateTime @updatedAt
}

model ChangelogEntry {
  id          String   @id @default(cuid())
  version     String
  title       String
  body        String
  publishedAt DateTime @default(now())
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

model OwnerAuditLog {
  id          String   @id @default(cuid())
  actorUserId String
  action      String
  targetType  String?
  targetId    String?
  before      Json?
  after       Json?
  createdAt   DateTime @default(now())

  @@index([createdAt])
}

/// Per-tier limits and feature gates (FREE / PREMIUM). Seeded on first use.
model PremiumTierConfig {
  tier         String   @id
  maxTags      Int
  maxFeeds     Int
  maxBackups   Int
  /// JSON object of feature key → boolean (tags, feeds, guildbackup, …).
  features     Json
  updatedAt    DateTime @updatedAt
}

model GuildPremiumAssignment {
  id           String    @id @default(cuid())
  guildId      String    @unique
  tier         String
  note         String?
  assignedById String
  expiresAt    DateTime?
  createdAt    DateTime  @default(now())
  updatedAt    DateTime  @updatedAt

  @@index([tier])
}

model UserPremiumAssignment {
  id           String    @id @default(cuid())
  userId       String    @unique
  tier         String
  note         String?
  assignedById String
  expiresAt    DateTime?
  createdAt    DateTime  @default(now())
  updatedAt    DateTime  @updatedAt

  @@index([tier])
}

model GdprDeletionLog {
  id        String   @id @default(cuid())
  userId    String
  guildId   String?
  summary   Json?
  createdAt DateTime @default(now())

  @@index([userId, createdAt])
}

