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

generator json {
  provider = "prisma-json-types-generator"
}

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

model CodeMigration {
  id        String   @id @default(dbgenerated("gen_random_uuid()"))
  name      String   @unique
  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt

  @@map("__code_migrations")
}

enum ProjectType {
  website
  app
  backend
}

model Organization {
  id              String          @id @default(dbgenerated("gen_random_uuid()"))
  name            String
  projects        Project[]
  members         Member[]
  createdByUserId String?
  createdBy       User?           @relation(name: "organizationCreatedBy", fields: [createdByUserId], references: [id])
  ProjectAccess   ProjectAccess[]
  Client          Client[]
  Dashboard       Dashboard[]
  ShareOverview   ShareOverview[]
  integrations    Integration[]
  invites         Invite[]

  // Subscription
  subscriptionId                          String?
  subscriptionCustomerId                  String?
  subscriptionPriceId                     String?
  subscriptionProductId                   String?
  /// [IPrismaSubscriptionStatus]
  subscriptionStatus                      String?
  subscriptionStartsAt                    DateTime?
  subscriptionEndsAt                      DateTime?
  subscriptionCanceledAt                  DateTime?
  subscriptionCreatedByUserId             String?
  subscriptionCreatedBy                   User?     @relation(name: "subscriptionCreatedBy", fields: [subscriptionCreatedByUserId], references: [id])
  subscriptionPeriodEventsCount           Int       @default(0)
  subscriptionPeriodEventsCountExceededAt DateTime?
  subscriptionPeriodEventsLimit           Int       @default(0)
  subscriptionInterval                    String?

  // When deleteAt > now(), the organization will be deleted
  deleteAt DateTime?

  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt

  @@map("organizations")
}

model User {
  id                   String          @id @default(dbgenerated("gen_random_uuid()"))
  email                String          @unique
  firstName            String?
  lastName             String?
  createdOrganizations Organization[]  @relation("organizationCreatedBy")
  subscriptions        Organization[]  @relation("subscriptionCreatedBy")
  membership           Member[]
  sentInvites          Member[]        @relation("invitedBy")
  createdAt            DateTime        @default(now())
  updatedAt            DateTime        @default(now()) @updatedAt
  deletedAt            DateTime?
  ProjectAccess        ProjectAccess[]
  sessions             Session[]
  accounts             Account[]
  invites              Invite[]

  @@map("users")
}

model Account {
  id                    String          @id @default(dbgenerated("gen_random_uuid()"))
  userId                String
  user                  User            @relation(fields: [userId], references: [id], onDelete: Cascade)
  email                 String?
  provider              String
  providerId            String?
  accessToken           String?
  refreshToken          String?
  accessTokenExpiresAt  DateTime?
  refreshTokenExpiresAt DateTime?
  scope                 String?
  password              String?
  createdAt             DateTime        @default(now())
  updatedAt             DateTime        @default(now()) @updatedAt
  resetPasswords        ResetPassword[]

  @@map("accounts")
}

model Session {
  id        String   @id
  userId    String
  expiresAt DateTime
  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt
  user      User     @relation(references: [id], fields: [userId], onDelete: Cascade)

  @@map("sessions")
}

model Member {
  id             String       @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  role           String
  email          String
  // userId is nullable because we want to allow invites to be sent to emails that are not registered
  userId         String?
  user           User?        @relation(fields: [userId], references: [id], onDelete: Cascade)
  invitedById    String?
  invitedBy      User?        @relation("invitedBy", fields: [invitedById], references: [id])
  organizationId String
  organization   Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  meta           Json?
  createdAt      DateTime     @default(now())
  updatedAt      DateTime     @default(now()) @updatedAt

  @@map("members")
}

model Invite {
  id             String       @id
  email          String
  createdBy      User         @relation(fields: [createdById], references: [id])
  createdById    String
  organizationId String
  organization   Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  projectAccess  String[]
  expiresAt      DateTime
  createdAt      DateTime     @default(now())
  updatedAt      DateTime     @default(now()) @updatedAt
  role           String

  @@map("invites")
}

model Project {
  id             String        @id @default(dbgenerated("gen_random_uuid()"))
  name           String
  organization   Organization  @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  organizationId String
  eventsCount    Int           @default(0)
  types          ProjectType[] @default([])
  domain         String?
  cors           String[]      @default([])
  crossDomain    Boolean       @default(false)
  /// [IPrismaProjectFilters]
  filters        Json          @default("[]")

  clients    Client[]
  reports    Report[]
  dashboards Dashboard[]
  share      ShareOverview?
  meta       EventMeta[]
  references Reference[]
  access     ProjectAccess[]

  notificationRules NotificationRule[]
  notifications     Notification[]

  // When deleteAt > now(), the project will be deleted
  deleteAt DateTime?

  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt

  @@map("projects")
}

enum AccessLevel {
  read
  write
  admin
}

model ProjectAccess {
  id             String       @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  projectId      String
  project        Project      @relation(fields: [projectId], references: [id], onDelete: Cascade)
  organization   Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  organizationId String
  userId         String
  user           User         @relation(fields: [userId], references: [id], onDelete: Cascade)
  level          AccessLevel
  createdAt      DateTime     @default(now())
  updatedAt      DateTime     @default(now()) @updatedAt

  @@map("project_access")
}

model Salt {
  salt      String   @id
  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt

  @@map("salts")
}

enum ClientType {
  read
  write
  root
}

model Client {
  id             String       @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  name           String
  secret         String?
  type           ClientType   @default(write)
  projectId      String?
  project        Project?     @relation(fields: [projectId], references: [id], onDelete: Cascade)
  organization   Organization @relation(fields: [organizationId], references: [id])
  organizationId String

  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt

  @@map("clients")
}

enum Interval {
  hour
  day
  month
  minute
  week
}

enum ChartType {
  linear
  bar
  histogram
  pie
  metric
  area
  map
  funnel
  retention
}

model Dashboard {
  id             String       @id @default(dbgenerated("gen_random_uuid()"))
  name           String
  organization   Organization @relation(fields: [organizationId], references: [id])
  organizationId String
  projectId      String
  project        Project      @relation(fields: [projectId], references: [id], onDelete: Cascade)
  reports        Report[]

  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt

  @@map("dashboards")
}

enum Metric {
  sum
  average
  min
  max
}

model Report {
  id           String    @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  name         String
  interval     Interval
  range        String    @default("30d")
  chartType    ChartType
  lineType     String    @default("monotone")
  breakdowns   Json
  events       Json
  formula      String?
  unit         String?
  metric       Metric    @default(sum)
  projectId    String
  project      Project   @relation(fields: [projectId], references: [id], onDelete: Cascade)
  previous     Boolean   @default(false)
  criteria     String?
  funnelGroup  String?
  funnelWindow Float?

  dashboardId String
  dashboard   Dashboard @relation(fields: [dashboardId], references: [id])

  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt

  @@map("reports")
}

model ShareOverview {
  id             String       @unique
  projectId      String       @unique
  project        Project      @relation(fields: [projectId], references: [id], onDelete: Cascade)
  organization   Organization @relation(fields: [organizationId], references: [id])
  organizationId String
  public         Boolean      @default(false)
  password       String?
  createdAt      DateTime     @default(now())
  updatedAt      DateTime     @default(now()) @updatedAt

  @@map("shares")
}

model EventMeta {
  id         String   @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  name       String
  conversion Boolean?
  color      String?
  icon       String?
  projectId  String
  project    Project  @relation(fields: [projectId], references: [id], onDelete: Cascade)

  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt

  @@unique([name, projectId])
  @@map("event_meta")
}

model Reference {
  id          String   @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  title       String
  description String?
  date        DateTime @default(now())
  projectId   String
  project     Project  @relation(fields: [projectId], references: [id], onDelete: Cascade)

  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt

  @@map("references")
}

enum IntegrationType {
  app
  mail
  custom
}

model NotificationRule {
  id            String         @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  name          String
  projectId     String
  project       Project        @relation(fields: [projectId], references: [id], onDelete: Cascade)
  integrations  Integration[]
  sendToApp     Boolean        @default(false)
  sendToEmail   Boolean        @default(false)
  /// [IPrismaNotificationRuleConfig]
  config        Json
  template      String?
  createdAt     DateTime       @default(now())
  updatedAt     DateTime       @default(now()) @updatedAt
  notifications Notification[]

  @@map("notification_rules")
}

model Notification {
  id                 String            @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  projectId          String
  project            Project           @relation(fields: [projectId], references: [id], onDelete: Cascade)
  title              String
  message            String
  isReadAt           DateTime?
  createdAt          DateTime          @default(now())
  updatedAt          DateTime          @default(now()) @updatedAt
  sendToApp          Boolean           @default(false)
  sendToEmail        Boolean           @default(false)
  integration        Integration?      @relation(fields: [integrationId], references: [id])
  integrationId      String?           @db.Uuid
  notificationRuleId String?           @db.Uuid
  notificationRule   NotificationRule? @relation(fields: [notificationRuleId], references: [id])
  /// [IPrismaNotificationPayload]
  payload            Json?

  @@map("notifications")
}

model Integration {
  id                String             @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  name              String
  /// [IPrismaIntegrationConfig]
  config            Json
  organization      Organization       @relation(fields: [organizationId], references: [id])
  organizationId    String
  notificationRules NotificationRule[]
  notifications     Notification[]
  createdAt         DateTime           @default(now())
  updatedAt         DateTime           @default(now()) @updatedAt

  @@map("integrations")
}

model ResetPassword {
  id        String   @id
  accountId String
  account   Account  @relation(fields: [accountId], references: [id])
  expiresAt DateTime
  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt

  @@map("reset_password")
}
