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

// // https://dev.to/connelevalsam/a-simple-crud-app-with-nextjs-prisma-sqlite-and-flutter-3oe1
// > npx prisma 

// // to update prisma DB/generate migration
// >npx prisma migrate dev

// //to generate schema
// > npx prisma 

// This is a Prisma database schema definition, which describes the structure and relationships between various entities in the database. Here's a brief overview of the different models:

// Publisher: Represents a publisher, with attributes such as first name, last name, email, phone, age, and availability. A publisher can have many availabilities and assignments, and can also have multiple user accounts and sessions.
// Availability: Represents the availability of a publisher on a specific day and time range. An availability belongs to a publisher and can have a name, day of the week, day of the month, start time, and end time.
// CartEvent: Represents a cart event, which is an event that requires a certain number of publishers to work. A cart event has a start and end time, a duration, and can have multiple shifts. It also has a location and an event type.
// Shift: Represents a shift, which is a specific time period during a cart event where one or more publishers are required to work. A shift belongs to a cart event and can have a name, start and end time, and can require transport.
// Assignment: Represents an assignment of a publisher to a specific shift. An assignment belongs to a shift and a publisher and can be tentative or final.
// Location: Represents a location where a cart event can take place. A location can have a name, address, and multiple cart events.
// Overall, this schema seems to represent a system for managing publishers and their assignments to cart events, including their availabilities and locations.

//$env:DATABASE="{connection string}"; npx prisma migrate deploy
datasource db {
  provider = "mysql"
  url      = env("DATABASE")
}

generator client {
  provider      = "prisma-client-js"
  binaryTargets = ["native", "debian-openssl-3.0.x"]
}

// graphql schema generator
// https://github.com/prisma-korea/graphql-schema-generator
// generator graphql {
//   provider = "graphql-schema-generator"
//   createCRUD = "true"
//   // # output = "./generated" This is default path.
// }

enum UserRole {
  ADMIN
  POWERUSER
  USER
  EXTERNAL
}

enum EventType {
  PW_Cart
  KH_Cleaning
}

//prisma type for day of week for sqlite db
enum DayOfWeek {
  Monday
  Tuesday
  Wednesday
  Thursday
  Friday
  Saturday
  Sunday
}

enum AvailabilityType {
  Weekly
  Monthly
  OneTime
  PreviousAssignment
  ReplacementOnly
}

// Вестител
// Бетелит
// Редовен Пионер
// Специален Пионер/Мисионер
enum PublisherType {
  Publisher
  Bethelite
  RegularPioneer
  SpecialPioneer_Missionary
}

enum ReportType {
  ServiceReport
  Experience
  Feedback_Problem
  Feedback_Suggestion
  Feedback
}

model Publisher {
  id             String         @id @default(cuid())
  firstName      String
  lastName       String
  email          String         @unique
  phone          String?
  isActive       Boolean        @default(true)
  isImported     Boolean        @default(false)
  isTrained      Boolean        @default(false)
  age            Int?
  availabilities Availability[]
  assignments    Assignment[]

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

  role                    UserRole      @default(USER)
  desiredShiftsPerMonth   Int           @default(4)
  isMale                  Boolean       @default(true)
  isNameForeign           Boolean       @default(false)
  isSubscribedToCoverMe   Boolean       @default(false)
  isSubscribedToReminders Boolean       @default(false)
  familyHeadId            String? // Optional familyHeadId for each family member
  familyHead              Publisher?    @relation("FamilyMember", fields: [familyHeadId], references: [id])
  familyMembers           Publisher[]   @relation("FamilyMember")
  alwaysAsFamily          Boolean?      @default(false) //NEW v1.0.1 // New field to indicate if the publisher always wants to be assigned with the family
  type                    PublisherType @default(Publisher)
  town                    String?
  comments                String?
  reports                 Report[]
  Message                 Message[]
  EventLog                EventLog[]
  lastLogin               DateTime?
  pushSubscription        Json?
  originalAssignments     Assignment[]  @relation("OriginalPublisher")
  congregation            Congregation? @relation(fields: [congregationId], references: [id])
  congregationId          Int?
  locale                  String?       @default("bg")
}

model Congregation {
  id         Int         @id @default(autoincrement())
  name       String
  address    String
  isActive   Boolean     @default(true)
  publishers Publisher[]
}

model Availability {
  id                       Int              @id @default(autoincrement())
  publisher                Publisher        @relation(fields: [publisherId], references: [id], onDelete: Cascade)
  publisherId              String
  name                     String
  dayofweek                DayOfWeek
  dayOfMonth               Int?
  weekOfMonth              Int?
  startTime                DateTime
  endTime                  DateTime
  isActive                 Boolean          @default(true)
  type                     AvailabilityType @default(Weekly)
  isWithTransportIn        Boolean          @default(false)
  isWithTransportOut       Boolean          @default(false)
  isFromPreviousAssignment Boolean          @default(false)
  isFromPreviousMonth      Boolean          @default(false)
  repeatWeekly             Boolean? // New field to indicate weekly repetition // until now dayofweek was used for repetition when dayOfMonth is null
  repeatFrequency          Int? // New field to indicate repetition frequency
  endDate                  DateTime? // New field for the end date of repetition
  dateOfEntry              DateTime? //NEW v1.0.1 
  parentAvailabilityId     Int?
  parentAvailability       Availability?    @relation("ParentAvailability", fields: [parentAvailabilityId], references: [id])
  ChildAvailabilities      Availability[]   @relation("ParentAvailability")
}

model CartEvent {
  id                 Int       @id @default(autoincrement())
  startTime          DateTime
  endTime            DateTime
  shiftDuration      Int
  shifts             Shift[]
  dayofweek          DayOfWeek
  isActive           Boolean   @default(true)
  location           Location  @relation(fields: [locationId], references: [id])
  locationId         Int
  eventType          EventType @default(PW_Cart)
  numberOfPublishers Int       @default(3)

  @@map("CartEvent")
}

model Shift {
  id                Int          @id @default(autoincrement())
  cartEvent         CartEvent    @relation(fields: [cartEventId], references: [id], onDelete: Cascade)
  cartEventId       Int
  assignments       Assignment[]
  name              String
  startTime         DateTime
  endTime           DateTime
  isActive          Boolean      @default(true)
  requiresTransport Boolean      @default(false)
  notes             String?
  //date              DateTime
  reportId          Int?         @unique
  Report            Report?      @relation(fields: [reportId], references: [id])
  isPublished       Boolean      @default(false)
  EventLog          EventLog[]

  @@map("Shift")
}

model Assignment {
  id                  Int        @id @default(autoincrement())
  shift               Shift      @relation(fields: [shiftId], references: [id], onDelete: Cascade)
  shiftId             Int
  publisher           Publisher  @relation(fields: [publisherId], references: [id], onDelete: Cascade)
  publisherId         String
  isBySystem          Boolean    @default(false) // if no availability for it, when importing previous schedules
  isConfirmed         Boolean    @default(false)
  isWithTransport     Boolean    @default(false)
  isMailSent          Boolean    @default(false)
  publicGuid          String?    @unique
  originalPublisherId String? // New field to store the original publisher id when the assignment is replaced
  originalPublisher   Publisher? @relation("OriginalPublisher", fields: [originalPublisherId], references: [id])

  @@map("Assignment")
}

model Location {
  id         Int         @id @default(autoincrement())
  name       String
  address    String
  isActive   Boolean     @default(true)
  content    String?     @db.LongText
  cartEvents CartEvent[]
  reports    Report[]
  picture1   String?
  picture2   String?
  picture3   String?

  backupLocationId   Int?
  backupLocation     Location?  @relation("BackupLocation", fields: [backupLocationId], references: [id])
  BackupForLocations Location[] @relation("BackupLocation")
  isOnMainMenu       Boolean    @default(false)

  @@map("Location")
}

model Report {
  id                   Int       @id @default(autoincrement())
  date                 DateTime
  publisherId          String
  publisher            Publisher @relation(fields: [publisherId], references: [id], onDelete: Cascade)
  locationId           Int?
  location             Location? @relation(fields: [locationId], references: [id])
  // shiftId              Int? # reference is in Shift model
  shift                Shift?
  placementCount       Int?
  videoCount           Int?
  returnVisitInfoCount Int?
  conversationCount    Int?

  experienceInfo String?    @db.LongText
  type           ReportType @default(ServiceReport)
  comments       String?

  @@map("Report")
}

//message types
enum MessageType {
  Email
  SMS
  Push
  InApp
}

model Survey {
  id          Int       @id @default(autoincrement())
  content     String    @db.Text
  answers     Json?
  messages    Message[]
  publicFrom  DateTime?
  publicUntil DateTime?
}

model Message {
  id          Int         @id @default(autoincrement())
  publisher   Publisher   @relation(fields: [publisherId], references: [id], onDelete: Cascade)
  publisherId String
  date        DateTime
  content     String      @db.Text
  isRead      Boolean     @default(false)
  isPublic    Boolean     @default(false)
  type        MessageType @default(Email)
  publicUntil DateTime?
  shownDate   DateTime?
  answer      String?
  answerDate  DateTime?

  Survey   Survey? @relation(fields: [surveyId], references: [id], onDelete: Cascade)
  surveyId Int?
}

enum EventLogType {
  AssignmentReplacementManual
  AssignmentReplacementRequested
  AssignmentReplacementAccepted
  SentEmail
  PasswordResetRequested
  PasswordResetEmailConfirmed
  PasswordResetCompleted
}

model EventLog {
  id          Int          @id @default(autoincrement())
  date        DateTime
  publisherId String?
  publisher   Publisher?   @relation(fields: [publisherId], references: [id], onDelete: SetNull)
  shiftId     Int?
  shift       Shift?       @relation(fields: [shiftId], references: [id])
  content     String       @db.VarChar(5000)
  type        EventLogType
}

//user auth and session management
model User {
  id                       String    @id @default(cuid())
  name                     String?
  email                    String?   @unique
  emailVerifyToken         String?
  emailVerified            DateTime?
  image                    String?
  accounts                 Account[]
  sessions                 Session[]
  passwordHashLocalAccount String? // New field to store the hashed password

  // Optional relation to Publisher
  publisherId String?    @unique
  publisher   Publisher? @relation
}

model Account {
  id                String  @id @default(cuid())
  userId            String
  type              String
  provider          String
  providerAccountId String
  refresh_token     String?
  access_token      String?
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String?
  session_state     String?

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

  @@unique([provider, providerAccountId])
}

model Session {
  id           String   @id @default(cuid())
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}

model Settings {
  key         String  @id
  value       String
  description String?
}
