// 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

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

  memberships               Membership[]
  phoneNumbers              PhoneNumber[]
  notificationSubscriptions NotificationSubscription[]
  messages                  Message[]
  phoneCalls                PhoneCall[]
  processingPhoneNumbers    ProcessingPhoneNumber[]
  subscriptions             Subscription[]

  @@unique([id, twilioAccountSid])
}

model Subscription {
  createdAt DateTime @default(now()) @db.Timestamptz
  updatedAt DateTime @updatedAt @db.Timestamptz

  paddleSubscriptionId      Int                @id @unique
  paddlePlanId              Int
  paddleCheckoutId          String
  status                    SubscriptionStatus
  updateUrl                 String
  cancelUrl                 String
  currency                  String
  unitPrice                 Int
  nextBillDate              DateTime           @db.Date
  lastEventTime             DateTime           @db.Timestamp
  cancellationEffectiveDate DateTime?          @db.Date

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

enum SubscriptionStatus {
  active
  trialing
  past_due
  paused
  deleted
}

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

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

  user   User?   @relation(fields: [userId], references: [id], onDelete: Cascade)
  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
  fullName       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], onDelete: Cascade)
  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], onDelete: Cascade)
  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], onDelete: Cascade)
  organizationId String
  phoneNumber    PhoneNumber  @relation(fields: [phoneNumberId], references: [id], onDelete: Cascade)
  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], onDelete: Cascade)
  organizationId String
  phoneNumber    PhoneNumber  @relation(fields: [phoneNumberId], references: [id], onDelete: Cascade)
  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[]

  processingPhoneNumber ProcessingPhoneNumber?
  organization          Organization           @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  organizationId        String

  @@unique([organizationId, id])
}

model ProcessingPhoneNumber {
  createdAt          DateTime     @default(now()) @db.Timestamptz
  hasFetchedMessages Boolean
  hasFetchedCalls    Boolean
  phoneNumber        PhoneNumber  @relation(fields: [phoneNumberId], references: [id], onDelete: Cascade)
  phoneNumberId      String
  organization       Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  organizationId     String

  @@id([organizationId, phoneNumberId])
}

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], onDelete: Cascade)
  organizationId String
  phoneNumber    PhoneNumber  @relation(fields: [phoneNumberId], references: [id], onDelete: Cascade)
  phoneNumberId  String
}
