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

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

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

model Snl {
  id   Int     @id @default(autoincrement())
  live Boolean @default(false)
}

model User {
  id              Int         @id @default(autoincrement())
  createdAt       DateTime    @default(now()) @map(name: "created_at")
  updatedAt       DateTime    @default(now()) @updatedAt @map(name: "updated_at")
  name            String?     @unique @db.Citext
  email           String?     @unique
  emailVerified   DateTime?   @map(name: "email_verified")
  image           String?
  items           Item[]      @relation("UserItems")
  fwdItems        Item[]      @relation("FwdItem")
  mentions        Mention[]
  messages        Message[]
  actions         ItemAct[]
  invoices        Invoice[]
  withdrawls      Withdrawl[]
  invites         Invite[]    @relation(name: "Invites")
  invite          Invite?     @relation(fields: [inviteId], references: [id])
  inviteId        String?
  bio             Item?       @relation(fields: [bioId], references: [id])
  bioId           Int?
  msats           BigInt      @default(0)
  stackedMsats    BigInt      @default(0)
  freeComments    Int         @default(5)
  freePosts       Int         @default(2)
  checkedNotesAt  DateTime?
  fiatCurrency    String      @default("USD")
  pubkey          String?     @unique
  slashtagId      String?     @unique
  trust           Float       @default(0)
  upvoteTrust     Float       @default(0)
  lastSeenAt      DateTime?
  lastCheckedJobs DateTime?
  photoId         Int?
  photo           Upload?     @relation(fields: [photoId], references: [id])
  subs            String[]

  // streak
  streak Int?

  // walkthrough
  upvotePopover Boolean @default(false)
  tipPopover    Boolean @default(false)

  // nostr
  nostrPubkey String?
  nostrRelays UserNostrRelay[]

  // referrals
  referrer   User?  @relation("referrals", fields: [referrerId], references: [id])
  referrerId Int?
  referrees  User[] @relation("referrals")

  // tip settings
  tipDefault   Int     @default(100)
  turboTipping Boolean @default(false)

  // notification settings
  noteItemSats       Boolean @default(true)
  noteEarning        Boolean @default(true)
  noteAllDescendants Boolean @default(true)
  noteMentions       Boolean @default(true)
  noteDeposits       Boolean @default(true)
  noteInvites        Boolean @default(true)
  noteJobIndicator   Boolean @default(true)
  noteCowboyHat      Boolean @default(true)

  // privacy settings
  hideInvoiceDesc  Boolean @default(false)
  hideFromTopUsers Boolean @default(false)
  hideCowboyHat    Boolean @default(false)

  // content settings
  wildWestMode Boolean @default(false)
  greeterMode  Boolean @default(false)

  Earn                Earn[]
  Upload              Upload[]             @relation(name: "Uploads")
  PollVote            PollVote[]
  Donation            Donation[]
  ReferralAct         ReferralAct[]
  Streak              Streak[]
  Bookmarks           Bookmark[]
  Subscriptions       Subscription[]
  ThreadSubscriptions ThreadSubscription[]
  PushSubscriptions   PushSubscription[]

  @@index([createdAt])
  @@index([inviteId])
  @@map(name: "users")
}

model Streak {
  id        Int       @id @default(autoincrement())
  createdAt DateTime  @default(now()) @map(name: "created_at")
  updatedAt DateTime  @default(now()) @updatedAt @map(name: "updated_at")
  startedAt DateTime  @db.Date
  endedAt   DateTime? @db.Date
  userId    Int
  user      User      @relation(fields: [userId], references: [id])

  @@unique([startedAt, userId])
  @@index([userId])
}

model NostrRelay {
  addr      String           @id
  createdAt DateTime         @default(now()) @map(name: "created_at")
  updatedAt DateTime         @default(now()) @updatedAt @map(name: "updated_at")
  users     UserNostrRelay[]
}

model UserNostrRelay {
  User           User       @relation(fields: [userId], references: [id])
  userId         Int
  NostrRelay     NostrRelay @relation(fields: [nostrRelayAddr], references: [addr])
  nostrRelayAddr String
  createdAt      DateTime   @default(now()) @map(name: "created_at")
  updatedAt      DateTime   @default(now()) @updatedAt @map(name: "updated_at")

  @@id([userId, nostrRelayAddr])
}

model Donation {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
  sats      Int
  userId    Int
  user      User     @relation(fields: [userId], references: [id])
}

model Upload {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
  type      String
  size      Int
  width     Int?
  height    Int?
  item      Item?    @relation(fields: [itemId], references: [id])
  itemId    Int?     @unique
  user      User     @relation(name: "Uploads", fields: [userId], references: [id])
  userId    Int

  User User[]

  @@index([createdAt])
  @@index([itemId])
  @@index([userId])
}

enum EarnType {
  POST
  COMMENT
  TIP_COMMENT
  TIP_POST
}

model Earn {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")

  msats  BigInt
  user   User   @relation(fields: [userId], references: [id])
  userId Int

  type   EarnType?
  typeId Int?
  rank   Int?

  @@index([createdAt])
  @@index([userId])
  @@index([createdAt, userId])
}

model LnAuth {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
  k1        String   @unique
  pubkey    String?
}

model LnWith {
  id           Int      @id @default(autoincrement())
  createdAt    DateTime @default(now()) @map(name: "created_at")
  updatedAt    DateTime @default(now()) @updatedAt @map(name: "updated_at")
  k1           String   @unique
  userId       Int
  withdrawalId Int?
}

model Invite {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
  user      User     @relation(name: "Invites", fields: [userId], references: [id])
  userId    Int
  gift      Int?
  limit     Int?
  revoked   Boolean  @default(false)
  invitees  User[]

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

model Message {
  id     Int    @id @default(autoincrement())
  text   String
  user   User   @relation(fields: [userId], references: [id])
  userId Int
}

enum Status {
  ACTIVE
  STOPPED
  NOSATS
}

model Item {
  id          Int                   @id @default(autoincrement())
  createdAt   DateTime              @default(now()) @map(name: "created_at")
  updatedAt   DateTime              @default(now()) @updatedAt @map(name: "updated_at")
  deletedAt   DateTime?
  title       String?
  text        String?
  url         String?
  user        User                  @relation("UserItems", fields: [userId], references: [id])
  userId      Int
  fwdUser     User?                 @relation(name: "FwdItem", fields: [fwdUserId], references: [id])
  fwdUserId   Int?
  parent      Item?                 @relation("ParentChildren", fields: [parentId], references: [id])
  parentId    Int?
  children    Item[]                @relation("ParentChildren")
  root        Item?                 @relation("RootDescendant", fields: [rootId], references: [id])
  rootId      Int?
  descendants Item[]                @relation("RootDescendant")
  actions     ItemAct[]
  mentions    Mention[]
  path        Unsupported("LTREE")?
  pin         Pin?                  @relation(fields: [pinId], references: [id])
  pinId       Int?
  uploadId    Int?
  upload      Upload?
  paidImgLink Boolean               @default(false)

  // open timestamps
  otsHash String?
  otsFile Bytes?

  // bounties
  bounty       Int?
  bountyPaidTo Int[]

  // is free post or bio
  freebie Boolean @default(false)
  bio     Boolean @default(false)

  // denormalized self stats
  weightedVotes     Float  @default(0)
  weightedDownVotes Float  @default(0)
  msats             BigInt @default(0)
  boost             Int    @default(0)
  upvotes           Int    @default(0)

  // denormalized comment stats
  ncomments        Int       @default(0)
  commentMsats     BigInt    @default(0)
  lastCommentAt    DateTime?
  weightedComments Float     @default(0)

  // if sub is null, this is the main sub
  sub     Sub?    @relation(fields: [subName], references: [name])
  subName String? @db.Citext

  // fields exclusively for job post types right now
  minSalary       Int?
  maxSalary       Int?
  maxBid          Int?
  status          Status    @default(ACTIVE)
  statusUpdatedAt DateTime?
  location        String?
  company         String?
  latitude        Float?
  longitude       Float?
  remote          Boolean?

  // fields for polls
  pollCost Int?

  User               User[]
  PollOption         PollOption[]
  PollVote           PollVote[]
  Bookmark           Bookmark[]
  ThreadSubscription ThreadSubscription[]

  @@index([weightedVotes])
  @@index([weightedDownVotes])
  @@index([bio])
  @@index([freebie])
  @@index([createdAt])
  @@index([userId])
  @@index([rootId])
  @@index([parentId])
  @@index([status])
  @@index([maxBid])
  @@index([statusUpdatedAt])
  @@index([subName])
  @@index([pinId])
  @@index([path])
}

model PollOption {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
  itemId    Int
  item      Item     @relation(fields: [itemId], references: [id])
  option    String

  PollVote PollVote[]

  @@index([itemId])
}

model PollVote {
  id           Int        @id @default(autoincrement())
  createdAt    DateTime   @default(now()) @map(name: "created_at")
  updatedAt    DateTime   @default(now()) @updatedAt @map(name: "updated_at")
  userId       Int
  user         User       @relation(fields: [userId], references: [id])
  itemId       Int
  item         Item       @relation(fields: [itemId], references: [id])
  pollOptionId Int
  pollOption   PollOption @relation(fields: [pollOptionId], references: [id])

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

enum PostType {
  LINK
  DISCUSSION
  JOB
  POLL
  BOUNTY
}

enum RankingType {
  WOT
  RECENT
  AUCTION
}

model Sub {
  name        String      @id @db.Citext
  createdAt   DateTime    @default(now()) @map(name: "created_at")
  updatedAt   DateTime    @default(now()) @updatedAt @map(name: "updated_at")
  postTypes   PostType[]
  rankingType RankingType
  baseCost    Int         @default(1)
  desc        String?

  Item         Item[]
  Subscription Subscription[]
}

model Subscription {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
  subName   String   @db.Citext
  sub       Sub      @relation(fields: [subName], references: [name])
  user      User     @relation(fields: [userId], references: [id])
  userId    Int
}

// the active pin is the latest one when it's a recurring cron
model Pin {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
  cron      String?
  timezone  String?
  position  Int
  Item      Item[]
}

model ReferralAct {
  id         Int      @id @default(autoincrement())
  createdAt  DateTime @default(now()) @map(name: "created_at")
  updatedAt  DateTime @default(now()) @updatedAt @map(name: "updated_at")
  referrerId Int
  referrer   User     @relation(fields: [referrerId], references: [id])
  itemActId  Int
  itemAct    ItemAct  @relation(fields: [itemActId], references: [id])
  msats      BigInt
}

enum ItemActType {
  VOTE
  BOOST
  TIP
  STREAM
  POLL
  DONT_LIKE_THIS
  FEE
}

model ItemAct {
  id          Int           @id @default(autoincrement())
  createdAt   DateTime      @default(now()) @map(name: "created_at")
  updatedAt   DateTime      @updatedAt @map(name: "updated_at")
  msats       BigInt
  act         ItemActType
  item        Item          @relation(fields: [itemId], references: [id])
  itemId      Int
  user        User          @relation(fields: [userId], references: [id])
  userId      Int
  ReferralAct ReferralAct[]

  @@index([itemId])
  @@index([userId])
  @@index([act])
  @@index([createdAt])
  // for getting a user's spending on an item, eg meSats
  @@index([itemId, userId, act])
  // for getting a user's spending over time, eg amount spent in a week
  @@index([userId, createdAt, act])
  // for checking if an item has been tipped recently, where the item number is small
  @@index([itemId, createdAt, act])
  // for checking if an item has been tipped recently, where the recent acts are small
  @@index([createdAt, itemId, act])
}

model Mention {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @updatedAt @map(name: "updated_at")
  item      Item     @relation(fields: [itemId], references: [id])
  itemId    Int
  user      User     @relation(fields: [userId], references: [id])
  userId    Int

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

model Invoice {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @updatedAt @map(name: "updated_at")
  user      User     @relation(fields: [userId], references: [id])
  userId    Int

  hash           String    @unique
  bolt11         String
  desc           String?
  expiresAt      DateTime
  confirmedAt    DateTime?
  msatsRequested BigInt
  msatsReceived  BigInt?
  cancelled      Boolean   @default(false)

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

enum WithdrawlStatus {
  CONFIRMED
  INSUFFICIENT_BALANCE
  INVALID_PAYMENT
  PATHFINDING_TIMEOUT
  ROUTE_NOT_FOUND
  UNKNOWN_FAILURE
}

model Withdrawl {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now()) @map(name: "created_at")
  updatedAt DateTime @updatedAt @map(name: "updated_at")
  user      User     @relation(fields: [userId], references: [id])
  userId    Int

  hash           String
  bolt11         String
  msatsPaying    BigInt
  msatsPaid      BigInt?
  msatsFeePaying BigInt
  msatsFeePaid   BigInt?

  status WithdrawlStatus?

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

model Account {
  id                 Int       @id @default(autoincrement())
  createdAt          DateTime  @default(now()) @map(name: "created_at")
  updatedAt          DateTime  @updatedAt @map(name: "updated_at")
  compoundId         String    @unique @map(name: "compound_id")
  userId             Int       @map(name: "user_id")
  providerType       String    @map(name: "provider_type")
  providerId         String    @map(name: "provider_id")
  providerAccountId  String    @map(name: "provider_account_id")
  refreshToken       String?   @map(name: "refresh_token")
  accessToken        String?   @map(name: "access_token")
  accessTokenExpires DateTime? @map(name: "access_token_expires")

  @@index([providerAccountId])
  @@index([providerId])
  @@index([userId])
  @@map(name: "accounts")
}

model Session {
  id           Int      @id @default(autoincrement())
  createdAt    DateTime @default(now()) @map(name: "created_at")
  updatedAt    DateTime @updatedAt @map(name: "updated_at")
  userId       Int      @map(name: "user_id")
  expires      DateTime
  sessionToken String   @unique @map(name: "session_token")
  accessToken  String   @unique @map(name: "access_token")

  @@map(name: "sessions")
}

model VerificationRequest {
  id         Int      @id @default(autoincrement())
  createdAt  DateTime @default(now()) @map(name: "created_at")
  updatedAt  DateTime @updatedAt @map(name: "updated_at")
  identifier String
  token      String   @unique
  expires    DateTime

  @@map(name: "verification_requests")
}

model Bookmark {
  user      User     @relation(fields: [userId], references: [id])
  userId    Int
  item      Item     @relation(fields: [itemId], references: [id])
  itemId    Int
  createdAt DateTime @default(now()) @map(name: "created_at")

  @@id([userId, itemId])
  @@index([createdAt])
}

model ThreadSubscription {
  user      User     @relation(fields: [userId], references: [id])
  userId    Int
  item      Item     @relation(fields: [itemId], references: [id])
  itemId    Int
  createdAt DateTime @default(now()) @map(name: "created_at")

  @@id([userId, itemId])
  @@index([createdAt])
}

model PushSubscription {
  id        Int       @id @default(autoincrement())
  user      User      @relation(fields: [userId], references: [id])
  userId    Int
  endpoint  String
  p256dh    String
  auth      String
  createdAt DateTime  @default(now()) @map(name: "created_at")

  @@index([userId])
}