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

datasource db {
  provider = "postgresql"
}

model Organization {
  id              String   @id @default(cuid())
  name            String
  slug            String   @unique
  orgType         String   @default("charity") // charity | fundraiser
  country         String   @default("UK")
  timezone        String   @default("Europe/London")
  bankName        String?
  bankSortCode    String?
  bankAccountNo   String?
  bankAccountName String?
  refPrefix       String   @default("PNPL")
  logo            String?
  primaryColor    String   @default("#1e40af")
  gcAccessToken   String?
  gcEnvironment   String   @default("sandbox")
  whatsappConnected Boolean @default(false)
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt

  users    User[]
  events   Event[]
  pledges  Pledge[]
  imports  Import[]

  @@index([slug])
}

model User {
  id             String   @id @default(cuid())
  email          String   @unique
  name           String?
  hashedPassword String?
  role           String   @default("staff") // super_admin, org_admin, staff, volunteer
  organizationId String
  organization   Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  createdAt      DateTime @default(now())
  updatedAt      DateTime @updatedAt

  @@index([organizationId])
}

model Event {
  id               String   @id @default(cuid())
  name             String
  slug             String
  description      String?
  eventDate        DateTime?
  location         String?
  goalAmount       Int?     // in pence
  currency         String   @default("GBP")
  status           String   @default("active") // draft, active, closed, archived
  paymentMode      String   @default("self") // self = we show bank details, external = redirect to URL
  externalUrl      String?  // e.g. https://launchgood.com/my-campaign
  externalPlatform String?  // launchgood, enthuse, justgiving, gofundme, other
  zakatEligible    Boolean  @default(false) // is this campaign Zakat-eligible?
  organizationId   String
  organization     Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  createdAt      DateTime @default(now())
  updatedAt      DateTime @updatedAt

  qrSources QrSource[]
  pledges   Pledge[]

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

model QrSource {
  id            String   @id @default(cuid())
  label         String   // "Table 5", "Volunteer: Ahmed"
  code          String   @unique // short token for URL
  volunteerName String?
  tableName     String?
  eventId       String
  event         Event    @relation(fields: [eventId], references: [id], onDelete: Cascade)
  scanCount     Int      @default(0)
  createdAt     DateTime @default(now())

  pledges Pledge[]

  @@index([eventId])
  @@index([code])
}

model Pledge {
  id             String   @id @default(cuid())
  reference      String   @unique // human-safe bank ref e.g. "PNPL-7K4P-50"
  amountPence    Int
  currency       String   @default("GBP")
  rail           String   // bank, gocardless, card
  status         String   @default("new") // new, initiated, paid, overdue, cancelled
  donorName      String?
  donorEmail     String?
  donorPhone     String?

  // --- Home address (required by HMRC for Gift Aid claims) ---
  donorAddressLine1 String?
  donorPostcode     String?

  // --- Gift Aid (HMRC) ---
  giftAid        Boolean   @default(false)
  giftAidAt      DateTime? // when the declaration was made
  isZakat        Boolean   @default(false) // donor marked this as Zakat

  // --- Communication consent (GDPR / PECR) ---
  emailOptIn     Boolean   @default(false)
  whatsappOptIn  Boolean   @default(false)

  // --- Consent audit trail (immutable evidence) ---
  // Stores exact text shown, timestamps, IP, user agent per consent type
  consentMeta    Json?

  iPaidClickedAt DateTime?
  notes          String?

  // Payment scheduling — the core of "pledge now, pay later"
  dueDate              DateTime? // null = pay now, set = promise to pay on this date
  planId               String?   // groups installments together
  installmentNumber    Int?      // e.g. 1 (of 4)
  installmentTotal     Int?      // e.g. 4
  reminderSentForDueDate Boolean @default(false)

  eventId        String
  event          Event    @relation(fields: [eventId], references: [id])
  qrSourceId     String?
  qrSource       QrSource? @relation(fields: [qrSourceId], references: [id])
  organizationId String
  organization   Organization @relation(fields: [organizationId], references: [id])

  paymentInstruction PaymentInstruction?
  payments           Payment[]
  reminders          Reminder[]

  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt
  paidAt      DateTime?
  cancelledAt DateTime?

  @@index([organizationId, status])
  @@index([reference])
  @@index([eventId, status])
  @@index([donorEmail])
  @@index([donorPhone])
  @@index([dueDate, status])
  @@index([planId])
}

model PaymentInstruction {
  id            String   @id @default(cuid())
  pledgeId      String   @unique
  pledge        Pledge   @relation(fields: [pledgeId], references: [id], onDelete: Cascade)
  bankReference String   // the unique ref to use
  bankDetails   Json     // {sortCode, accountNo, accountName, bankName}
  gcMandateId   String?
  gcMandateUrl  String?
  sentAt        DateTime?
  createdAt     DateTime @default(now())

  @@index([bankReference])
}

model Payment {
  id          String   @id @default(cuid())
  pledgeId    String
  pledge      Pledge   @relation(fields: [pledgeId], references: [id], onDelete: Cascade)
  provider    String   // bank, gocardless, stripe
  providerRef String?  // external ID
  amountPence Int
  status      String   @default("pending") // pending, confirmed, failed
  matchedBy   String?  // auto, manual
  receivedAt  DateTime?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  importId    String?
  import      Import?  @relation(fields: [importId], references: [id])

  @@index([pledgeId])
  @@index([providerRef])
}

model Reminder {
  id          String   @id @default(cuid())
  pledgeId    String
  pledge      Pledge   @relation(fields: [pledgeId], references: [id], onDelete: Cascade)
  step        Int      // 0=instructions, 1=nudge, 2=urgency, 3=final
  channel     String   @default("email") // email, sms, whatsapp
  scheduledAt DateTime
  sentAt      DateTime?
  status      String   @default("pending") // pending, sent, skipped, failed
  payload     Json?
  createdAt   DateTime @default(now())

  @@index([pledgeId])
  @@index([scheduledAt, status])
}

model Import {
  id             String   @id @default(cuid())
  organizationId String
  organization   Organization @relation(fields: [organizationId], references: [id])
  kind           String   // bank_statement, gocardless_export, crm_export
  fileName       String?
  rowCount       Int      @default(0)
  matchedCount   Int      @default(0)
  unmatchedCount Int      @default(0)
  mappingConfig  Json?
  stats          Json?
  status         String   @default("pending") // pending, processing, completed, failed
  uploadedAt     DateTime @default(now())

  payments Payment[]

  @@index([organizationId])
}

model AnalyticsEvent {
  id        String   @id @default(cuid())
  eventType String   // pledge_start, amount_selected, rail_selected, identity_submitted, pledge_completed, instruction_copy_clicked, i_paid_clicked, payment_matched
  pledgeId  String?
  eventId   String?
  qrSourceId String?
  metadata  Json?
  createdAt DateTime @default(now())

  @@index([eventType])
  @@index([pledgeId])
  @@index([eventId])
  @@index([createdAt])
}
