datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

enum Role {
  SUPER_ADMIN
  ADMIN
  USER
}

model User {
  id                String             @id @default(cuid())
  name              String
  email             String             @unique
  passwordHash      String
  role              Role               @default(USER)
  isActive          Boolean            @default(true)
  lastLoginAt       DateTime?
  createdAt         DateTime           @default(now())
  updatedAt         DateTime           @updatedAt
  profile           Profile?
  auraResults       AuraResult[]
  baziResults       BaziResult[]
  numerologyResults NumerologyResult[]
  /// Reports that belong to this person.
  reports           Report[]           @relation("ReportOwner")
  /// Reports this user ran the scan for (themselves, or participants in a session).
  scannedReports    Report[]           @relation("ReportCreator")
  events            Event[]
  /// Affiliate code that brought this user in (from a shared link), if any.
  referredByCode    String?
  orders            Order[]
  affiliate         Affiliate?
}

enum EventKind {
  MALL
  KANTOR
  SEKOLAH
  KOMUNITAS
  LAINNYA
}

enum EventStatus {
  AKTIF
  SELESAI
}

/// A group scanning session run by an admin — e.g. a mall booth or an office wellness day.
model Event {
  id          String      @id @default(cuid())
  name        String
  kind        EventKind   @default(LAINNYA)
  location    String?
  date        DateTime?
  status      EventStatus @default(AKTIF)
  createdById String
  createdAt   DateTime    @default(now())
  updatedAt   DateTime    @updatedAt
  createdBy   User        @relation(fields: [createdById], references: [id], onDelete: Restrict)
  reports     Report[]

  @@index([createdById])
}

/// One aura photo scan and everything derived from it — the "Laporan Lengkap".
model Report {
  id           String    @id @default(cuid())
  /// Unguessable token for the participant's QR / share link (/r/<token>).
  shareToken   String    @unique
  /// The person this report belongs to. Null for session participants who haven't claimed it yet.
  ownerId      String?
  createdById  String
  eventId      String?
  subjectName  String
  subjectEmail String?
  subjectPhone String?
  consentAt    DateTime?
  photo        String?   @db.MediumText
  /// Services this report covers, comma-separated: any of aura, bazi, numerology.
  services     String    @default("aura,bazi,numerology")
  /// Null when the report doesn't include the aura photo service.
  aura         Json?
  scan         Json?
  bazi         Json?
  numerology   Json?
  createdAt    DateTime  @default(now())
  updatedAt    DateTime  @updatedAt
  owner        User?     @relation("ReportOwner", fields: [ownerId], references: [id], onDelete: SetNull)
  createdBy    User      @relation("ReportCreator", fields: [createdById], references: [id], onDelete: Restrict)
  event        Event?    @relation(fields: [eventId], references: [id], onDelete: SetNull)

  @@index([ownerId, createdAt])
  @@index([eventId, createdAt])
}

model Profile {
  id           String    @id @default(cuid())
  userId       String    @unique
  gender       String?
  birthDate    DateTime?
  birthTime    String?
  birthCity    String?
  birthCountry String?
  timezone     String?
  user         User      @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model AuraQuestion {
  id        String       @id @default(cuid())
  question  String       @db.Text
  category  String?
  order     Int
  active    Boolean      @default(true)
  answers   AuraAnswer[]
}

model AuraAnswer {
  id             String       @id @default(cuid())
  questionId     String
  text           String       @db.Text
  rootScore      Float        @default(0)
  sacralScore    Float        @default(0)
  solarScore     Float        @default(0)
  heartScore     Float        @default(0)
  throatScore    Float        @default(0)
  thirdEyeScore  Float        @default(0)
  crownScore     Float        @default(0)
  question       AuraQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade)
}

model AuraResult {
  id                 String   @id @default(cuid())
  userId             String?
  createdAt          DateTime @default(now())
  rootScore          Float
  sacralScore        Float
  solarScore         Float
  heartScore         Float
  throatScore        Float
  thirdEyeScore      Float
  crownScore         Float
  dominantChakra     String
  secondaryChakra    String?
  growthChakra       String?
  auraProfile        String
  calculationVersion String   @default("1.0")
  interpretation     Json?
  user               User?    @relation(fields: [userId], references: [id], onDelete: SetNull)
}

model BaziResult {
  id                 String   @id @default(cuid())
  userId             String?
  createdAt          DateTime @default(now())
  yearStem           String
  yearBranch         String
  monthStem          String
  monthBranch        String
  dayStem            String
  dayBranch          String
  hourStem           String
  hourBranch         String
  dayMaster          String
  dayMasterType      String?
  elements           Json
  calculationVersion String   @default("1.0")
  interpretation     Json?
  user               User?    @relation(fields: [userId], references: [id], onDelete: SetNull)
}

model NumerologyResult {
  id                 String   @id @default(cuid())
  userId             String?
  createdAt          DateTime @default(now())
  system             String   @default("pythagorean")
  lifePath           Int
  destiny            Int
  soulUrge           Int
  personality        Int
  birthday           Int
  maturity           Int
  calculationVersion String   @default("1.0")
  interpretation     Json?
  user               User?    @relation(fields: [userId], references: [id], onDelete: SetNull)
}

model AiInterpretation {
  id            String   @id @default(cuid())
  type          String
  entityId      String
  model         String
  promptVersion String
  inputHash     String?  @unique
  content       Json
  createdAt     DateTime @default(now())
}

enum OrderStatus {
  PENDING
  PAID
  FAILED
  EXPIRED
}

/// A purchase of the premium package, paid through Midtrans.
model Order {
  id            String      @id @default(cuid())
  /// Order id sent to Midtrans (unique per attempt).
  providerRef   String      @unique
  userId        String
  amount        Int
  status        OrderStatus @default(PENDING)
  /// Affiliate code credited for this sale, resolved when the order is created.
  referralCode  String?
  paymentType   String?
  redirectUrl   String?     @db.Text
  paidAt        DateTime?
  createdAt     DateTime    @default(now())
  updatedAt     DateTime    @updatedAt
  user          User        @relation(fields: [userId], references: [id], onDelete: Cascade)
  commission    Commission?

  @@index([userId, createdAt])
  @@index([referralCode])
}

/// A buyer who can share their aura photo and earn commission on referred sales.
model Affiliate {
  id            String       @id @default(cuid())
  userId        String       @unique
  code          String       @unique
  /// Where commission is paid out, e.g. "BCA 1234567890 a.n. Najib" or an e-wallet number.
  payoutAccount String?      @db.Text
  createdAt     DateTime     @default(now())
  user          User         @relation(fields: [userId], references: [id], onDelete: Cascade)
  commissions   Commission[]
}

enum CommissionStatus {
  PENDING
  PAID
  CANCELLED
}

model Commission {
  id          String           @id @default(cuid())
  affiliateId String
  orderId     String           @unique
  amount      Int
  /// Rate applied, in percent.
  ratePercent Int
  status      CommissionStatus @default(PENDING)
  paidAt      DateTime?
  createdAt   DateTime         @default(now())
  affiliate   Affiliate        @relation(fields: [affiliateId], references: [id], onDelete: Cascade)
  order       Order            @relation(fields: [orderId], references: [id], onDelete: Cascade)

  @@index([affiliateId, status])
}
