generator client {
  provider = "prisma-client"
  output   = "../src/generated/prisma"
}

datasource db {
  provider = "postgresql"
}

// ─── Auth.js tables ──────────────────────────────────────────

model User {
  id             String    @id @default(cuid())
  email          String    @unique
  emailVerified  DateTime?
  hashedPassword String?
  username       String?
  displayName    String?
  avatarUrl      String    @default("")
  jobTitle       String    @default("")
  company        String    @default("")
  bio            String    @default("")
  role           String    @default("viewer")
  activeOrgId    String?
  createdAt      DateTime  @default(now())
  updatedAt      DateTime  @updatedAt

  accounts    Account[]
  sessions    Session[]
  memberships OrgMember[]

  assignedCards  ResponseCard[] @relation("AssignedCards")
  assignorCards  ResponseCard[] @relation("AssignorCards")
  reviewedCards  ResponseCard[] @relation("ReviewedCards")
  activityLogs   ActivityLog[]
  notifications  Notification[]

  authentikUid String? @unique
}

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])
}

// ─── Organization / Multi-tenancy ────────────────────────────

model Organization {
  id                 String   @id @default(cuid())
  name               String
  slug               String   @unique
  type               String   @default("church")
  timezone           String   @default("America/Chicago")
  settings           Json?
  allowedDomains     String[] @default([])
  onboardingComplete Boolean  @default(false)
  onboardingStep     Int      @default(0)
  createdAt          DateTime @default(now())
  updatedAt          DateTime @updatedAt

  locations     Location[]
  members       OrgMember[]
  invitations   Invitation[]
  apiKeys       ApiKey[]
  cards         ResponseCard[]
  jobs          ProcessingJob[]
  integrations  Integration[]
  formTemplates FormTemplate[]
  persons       Person[]
}

model OrgMember {
  id             String       @id @default(cuid())
  userId         String
  organizationId String
  role           String       @default("viewer")
  dismissedHints Json?
  user           User         @relation(fields: [userId], references: [id], onDelete: Cascade)
  organization   Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  createdAt      DateTime     @default(now())

  @@unique([userId, organizationId])
}

model Location {
  id             String          @id @default(cuid())
  organizationId String
  name           String
  address        String?
  timezone       String?
  organization   Organization    @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  collectionDays CollectionDay[]
  cards          ResponseCard[]
  createdAt      DateTime        @default(now())
  updatedAt      DateTime        @updatedAt
}

model CollectionDay {
  id          String         @id @default(cuid())
  locationId  String
  name        String
  description String?
  rrule       String?
  dayOfWeek   Int?
  timeStart   String?
  timeEnd     String?
  isRecurring Boolean        @default(true)
  date        DateTime?
  isActive    Boolean        @default(true)
  location    Location       @relation(fields: [locationId], references: [id], onDelete: Cascade)
  cards       ResponseCard[]
  createdAt   DateTime       @default(now())
  updatedAt   DateTime       @updatedAt
}

// ─── Form Templates (Dynamic Fields) ────────────────────────

model FormTemplate {
  id             String   @id @default(cuid())
  organizationId String
  name           String
  slug           String
  description    String?
  isDefault      Boolean  @default(false)
  isActive       Boolean  @default(true)
  version        Int      @default(1)
  branding       Json?
  settings       Json?
  createdAt      DateTime @default(now())
  updatedAt      DateTime @updatedAt

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

  @@unique([organizationId, slug])
  @@index([organizationId])
}

model FormField {
  id              String   @id @default(cuid())
  formTemplateId  String
  key             String
  label           String
  type            String
  section         String   @default("personal")
  required        Boolean  @default(false)
  removable       Boolean  @default(true)
  sortOrder       Int      @default(0)
  options         Json?
  placeholder     String?
  helpText        String?
  validation      Json?
  visibleOnCard   Boolean  @default(true)
  visibleOnSurvey Boolean  @default(true)
  isCore          Boolean  @default(false)
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt

  formTemplate FormTemplate @relation(fields: [formTemplateId], references: [id], onDelete: Cascade)

  @@unique([formTemplateId, key])
  @@index([formTemplateId, sortOrder])
}

// ─── People (Contact Directory) ─────────────────────────────

model Person {
  id             String   @id @default(cuid())
  organizationId String
  firstName      String
  lastName       String
  email          String?
  cellPhone      String?
  fieldData      Json?
  mergedIntoId   String?
  createdAt      DateTime @default(now())
  updatedAt      DateTime @updatedAt

  organization Organization  @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  cards        ResponseCard[]
  mergedInto   Person?        @relation("PersonMerge", fields: [mergedIntoId], references: [id])
  mergedFrom   Person[]       @relation("PersonMerge")

  @@index([organizationId])
  @@index([email])
  @@index([organizationId, firstName, lastName])
  @@index([mergedIntoId])
}

// ─── Integrations ────────────────────────────────────────────

model Integration {
  id             String       @id @default(cuid())
  organizationId String
  provider       String
  name           String
  enabled        Boolean      @default(false)
  config         Json
  fieldMapping   Json?
  syncDirection  String       @default("push")
  triggerEvents  Json?
  lastSyncAt     DateTime?
  lastSyncStatus String?
  createdAt      DateTime     @default(now())
  updatedAt      DateTime     @updatedAt
  organization   Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)

  @@unique([organizationId, provider, name])
  @@index([organizationId, provider])
}

// ─── Invitations ─────────────────────────────────────────────

model Invitation {
  id             String       @id @default(cuid())
  email          String
  role           String       @default("viewer")
  organizationId String
  invitedById    String
  token          String       @unique @default(cuid())
  expiresAt      DateTime
  acceptedAt     DateTime?
  createdAt      DateTime     @default(now())
  organization   Organization @relation(fields: [organizationId], references: [id])
}

// ─── Password Reset ─────────────────────────────────────────

model PasswordResetToken {
  id        String   @id @default(cuid())
  email     String
  token     String   @unique
  expiresAt DateTime
  createdAt DateTime @default(now())

  @@index([email])
}

// ─── System config ───────────────────────────────────────────

model SystemConfig {
  id              String   @id @default("singleton")
  isSetupComplete Boolean  @default(false)
  setupStep       Int      @default(0)
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt
}

// ─── Core application models ─────────────────────────────────

model ResponseCard {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  firstName          String?
  lastName           String?
  name               String?
  gender             String?
  dateOfBirth        String?
  maritalStatus      String?
  maritalStatusOther String?
  visitType          String?
  cellPhone          String?
  homePhone          String?
  email              String?
  address            String?
  aptNumber          String?
  city               String?
  state              String?
  zip                String?
  prayerRequests     String?
  prayerForTeam      Boolean @default(false)
  prayerConfidential Boolean @default(false)

  messageTopics         Json?
  messageTopicsOther    String?
  nextStep              Json?
  attendanceDuration    String?
  campusPreference      Json?
  campusPreferenceOther String?
  howHeard              Json?
  howHeardOther         String?
  serviceAttended       String?

  followUp           String?
  notes              String?
  serviceTime        String?
  planningCenter     String?
  iSaidYesBookSent   Boolean   @default(false)
  ftGuestLetterSent  Boolean   @default(false)
  firstTimeGuestDate DateTime?
  salvationDate      DateTime?

  assignedToId String?
  assignedById String?
  assignedAt   DateTime?
  reviewedById String?
  reviewedAt   DateTime?
  reviewNotes  String?

  assignedTo User? @relation("AssignedCards", fields: [assignedToId], references: [id])
  assignedBy User? @relation("AssignorCards", fields: [assignedById], references: [id])
  reviewedBy User? @relation("ReviewedCards", fields: [reviewedById], references: [id])

  sourceFile     String?
  frontImagePath String?
  backImagePath  String?
  ocrStatus      String  @default("pending")
  reviewStatus   String  @default("unreviewed")
  ocrConfidence  Float?
  ocrError       String?
  rawOcrResponse Json?

  mondayItemId String?

  fieldData        Json?
  formTemplateId   String?
  personId         String?
  submissionSource String?

  organizationId  String?
  locationId      String?
  collectionDayId String?
  collectionDate  DateTime?

  organization  Organization?  @relation(fields: [organizationId], references: [id])
  location      Location?      @relation(fields: [locationId], references: [id])
  collectionDay CollectionDay? @relation(fields: [collectionDayId], references: [id])
  formTemplate  FormTemplate?  @relation(fields: [formTemplateId], references: [id])
  person        Person?        @relation(fields: [personId], references: [id])

  @@index([ocrStatus])
  @@index([reviewStatus])
  @@index([name])
  @@index([firstName, lastName])
  @@index([createdAt])
  @@index([mondayItemId])
  @@index([assignedToId])
  @@index([reviewedById])
  @@index([organizationId])
  @@index([locationId])
  @@index([collectionDayId])
  @@index([formTemplateId])
  @@index([personId])
}

model ProcessingJob {
  id             String   @id @default(cuid())
  createdAt      DateTime @default(now())
  updatedAt      DateTime @updatedAt
  fileName       String
  filePath       String
  status         String   @default("queued")
  totalPages     Int      @default(0)
  processed      Int      @default(0)
  error          String?
  cardIds        Json?
  organizationId String?

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

  @@index([status])
}

model AppSettings {
  id        String @id @default("singleton")
  ollamaUrl String @default("http://192.168.68.108:11434")
  model     String @default("llava:7b")
  watchDir  String @default("")
  watching  Boolean @default(false)

  sourceRetentionDays Int @default(30)
  imageRetentionDays  Int @default(180)

  aiProvider String @default("gateway")
  aiModel    String @default("")

  mondayApiToken    String  @default("")
  mondayBoardId     String  @default("")
  mondayEnabled     Boolean @default(false)
  mondayColumnMap   Json?
  mondayWebhookId   String  @default("")
  mondayWebhookUrl  String  @default("")

  webhookUrl        String  @default("")
  webhookSecret     String  @default("")
  webhookEnabled    Boolean @default(false)
  webhookEvents     Json?

  emailImapHost        String  @default("imap.dreamhost.com")
  emailImapPort        Int     @default(993)
  emailImapUser        String  @default("echo-ocr@stillwell.cloud")
  emailImapPass        String  @default("")
  emailImapTls         Boolean @default(true)
  emailFolder          String  @default("INBOX")
  emailWatching        Boolean @default(false)
  emailProcessed       String  @default("mark_read")
  emailProcessedFolder String  @default("Processed")

  ftpEnabled        Boolean @default(false)
  ftpHost           String  @default("")
  ftpPort           Int     @default(22)
  ftpUser           String  @default("")
  ftpPass           String  @default("")
  ftpProtocol       String  @default("sftp")  // "sftp" | "ftp" | "ftps"
  ftpIncomingDir    String  @default("/incoming")
  ftpProcessedDir   String  @default("/processed")
}

model ActivityLog {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now())
  cardId    String?
  action    String
  source    String
  summary   String
  changes   Json?
  userId    String?

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

  @@index([cardId, createdAt])
}

model Notification {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now())
  read      Boolean  @default(false)
  dismissed Boolean  @default(false)
  type      String
  title     String
  message   String
  cardId    String?
  actionUrl String?
  meta      Json?
  userId    String?

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

  @@index([read, dismissed, createdAt])
  @@index([cardId])
  @@index([userId])
}

model ApiKey {
  id             String       @id @default(cuid())
  name           String
  hashedKey      String       @unique
  prefix         String
  organizationId String
  permissions    Json
  lastUsedAt     DateTime?
  expiresAt      DateTime?
  createdAt      DateTime     @default(now())
  organization   Organization @relation(fields: [organizationId], references: [id])
}
