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

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

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

// --------------------------------------

model Organization {
  id                   String   @id @default(uuid())
  createdAt            DateTime @default(now()) @db.Timestamptz
  updatedAt            DateTime @updatedAt @db.Timestamptz
  encryptionKey        String
  paddleCustomerId     String?
  paddleSubscriptionId String?

  twilioAccountSid String?
  twilioAuthToken  String? // TODO: encrypt it with encryptionKey
  twimlAppSid      String?

  memberships               Membership[]
  phoneNumbers              PhoneNumber[]
  notificationSubscriptions NotificationSubscription[]
  messages                  Message[]
  phoneCalls                PhoneCall[]

  @@unique([id, twilioAccountSid])
}

model Membership {
  id   String         @id @default(uuid())
  role MembershipRole

  organization   Organization @relation(fields: [organizationId], references: [id])
  organizationId String

  user   User?   @relation(fields: [userId], references: [id])
  userId String?

  // When the user joins, we will clear out the name and email and set the user.
  invitedName  String?
  invitedEmail String?

  @@unique([organizationId, invitedEmail])
}

enum MembershipRole {
  OWNER
  ADMIN
  USER
}

// The owners of the SaaS (you) can have a SUPERADMIN role to access all data
enum GlobalRole {
  SUPERADMIN
  CUSTOMER
}

model User {
  id             String     @id @default(uuid())
  createdAt      DateTime   @default(now()) @db.Timestamptz
  updatedAt      DateTime   @updatedAt @db.Timestamptz
  name           String?
  email          String     @unique
  hashedPassword String?
  role           GlobalRole @default(CUSTOMER)

  memberships Membership[]
  tokens      Token[]
  sessions    Session[]
}

enum Role {
  USER
  ADMIN
}

model Session {
  id                 String    @id @default(uuid())
  createdAt          DateTime  @default(now()) @db.Timestamptz
  updatedAt          DateTime  @updatedAt @db.Timestamptz
  expiresAt          DateTime? @db.Timestamptz
  handle             String    @unique
  hashedSessionToken String?
  antiCSRFToken      String?
  publicData         String?
  privateData        String?

  user   User?   @relation(fields: [userId], references: [id])
  userId String?
}

model Token {
  id          String    @id @default(uuid())
  createdAt   DateTime  @default(now()) @db.Timestamptz
  updatedAt   DateTime  @updatedAt @db.Timestamptz
  hashedToken String
  type        TokenType
  expiresAt   DateTime  @db.Timestamptz
  sentTo      String

  user   User   @relation(fields: [userId], references: [id])
  userId String

  @@unique([hashedToken, type])
}

enum TokenType {
  RESET_PASSWORD
}

model Message {
  id        String        @id @default(uuid())
  sentAt    DateTime      @db.Timestamptz
  content   String
  from      String
  to        String
  direction Direction
  status    MessageStatus

  organization   Organization @relation(fields: [organizationId], references: [id])
  organizationId String
  phoneNumber    PhoneNumber  @relation(fields: [phoneNumberId], references: [id])
  phoneNumberId  String

  @@unique([organizationId, phoneNumberId, id])
}

enum Direction {
  Inbound
  Outbound
}

enum MessageStatus {
  Queued
  Sending
  Sent
  Failed
  Delivered
  Undelivered
  Receiving
  Received
  Accepted
  Scheduled
  Read
  PartiallyDelivered
  Canceled

  Error
}

model PhoneCall {
  id        String     @id
  createdAt DateTime   @default(now()) @db.Timestamptz
  from      String
  to        String
  status    CallStatus
  direction Direction
  duration  String

  organization   Organization @relation(fields: [organizationId], references: [id])
  organizationId String
  phoneNumber    PhoneNumber  @relation(fields: [phoneNumberId], references: [id])
  phoneNumberId  String

  @@unique([organizationId, phoneNumberId, id])
}

enum CallStatus {
  Queued
  Ringing
  InProgress
  Completed
  Busy
  Failed
  NoAnswer
  Canceled
}

model PhoneNumber {
  id        String   @id
  createdAt DateTime @default(now()) @db.Timestamptz
  number    String

  messages                  Message[]
  phoneCalls                PhoneCall[]
  notificationSubscriptions NotificationSubscription[]

  organization   Organization @relation(fields: [organizationId], references: [id])
  organizationId String

  @@unique([organizationId, id])
}

model NotificationSubscription {
  id             String   @id @default(uuid())
  createdAt      DateTime @default(now()) @db.Timestamptz
  updatedAt      DateTime @updatedAt @db.Timestamptz
  endpoint       String   @unique
  expirationTime Int?
  keys_p256dh    String
  keys_auth      String

  organization   Organization @relation(fields: [organizationId], references: [id])
  organizationId String
  phoneNumber    PhoneNumber  @relation(fields: [phoneNumberId], references: [id])
  phoneNumberId  String
}