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

// Get a free hosted Postgres database in seconds: `npx create-db`

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

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

enum UserRole {
  ADMIN
  FAMILY
}

enum GameStatus {
  OPEN
  CLOSED
}

enum PredictionCardType {
  LEGACY
  CUSTOM
}

enum PredictionValueType {
  NUMBER
  TEXT
  SELECT
  MULTI_TEXT
  DATE
}

enum PredictionActivityType {
  CARD_CREATED
  CARD_UPDATED
  CARD_DELETED
  PREDICTION_CREATED
  PREDICTION_UPDATED
  OUTCOME_SET
  SCORE_SUGGESTED
  SCORE_VALIDATED
  GAME_CLOSED
  GAME_OPENED
}

enum ParentType {
  PAPA
  MAMAN
}

enum Trimester {
  T1
  T2
  T3
  DATATION
}

enum ProjectStatus {
  DRAFT
  OPEN
  CLOSED
  FINALIZED
}

model User {
  id           String   @id @default(cuid())
  username     String   @unique
  displayName  String?
  profileImageUrl String?
  profileBgColor  String?
  passwordHash String
  refreshTokenHash String?
  workspaceId  String?
  workspace    Workspace? @relation("WorkspaceUsers", fields: [workspaceId], references: [id], onDelete: SetNull)
  role         UserRole @default(FAMILY)
  createdAt    DateTime @default(now())

  ownedWorkspace          Workspace?          @relation("WorkspaceOwner")
  createdProjects         Project[]           @relation("ProjectsCreatedBy")
  projectMembership       ProjectMembership?
  assignedMemberships     ProjectMembership[] @relation("ProjectMembershipAssignedBy")

  predictionCardsCreated   PredictionCard[]      @relation("PredictionCardsCreatedBy")
  predictionEntries        PredictionEntry[]     @relation("PredictionEntriesByUser")
  predictionHistoryEvents  PredictionEntryHistory[] @relation("PredictionHistoryByUser")
  predictionOutcomesSet    PredictionOutcome[]   @relation("PredictionOutcomesSetBy")
  predictionScoresValidated PredictionFieldScore[] @relation("PredictionScoresValidatedBy")
  predictionActivities     PredictionActivity[]  @relation("PredictionActivitiesByUser")

  @@index([workspaceId])
}

model Workspace {
  id         String   @id @default(cuid())
  slug       String   @unique
  name       String
  ownerUserId String  @unique
  ownerUser  User     @relation("WorkspaceOwner", fields: [ownerUserId], references: [id], onDelete: Restrict)
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt

  users      User[]   @relation("WorkspaceUsers")
  projects   Project[]
}

model Project {
  id                 String       @id @default(cuid())
  workspaceId        String
  workspace          Workspace    @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
  createdById        String
  createdBy          User         @relation("ProjectsCreatedBy", fields: [createdById], references: [id], onDelete: Restrict)
  clonedFromProjectId String?
  clonedFromProject  Project?     @relation("ProjectCloneSource", fields: [clonedFromProjectId], references: [id], onDelete: SetNull)
  clonedProjects     Project[]    @relation("ProjectCloneSource")
  name               String
  description        String?
  projectImageUrl    String?
  projectBgColor     String?
  status             ProjectStatus @default(DRAFT)
  babyCount          Int          @default(1)
  createdAt          DateTime     @default(now())
  updatedAt          DateTime     @updatedAt

  babies             ProjectBaby[]
  memberships        ProjectMembership[]
  games              PredictionGame[]
  cards              PredictionCard[]
  entries            PredictionEntry[]
  outcomes           PredictionOutcome[]
  fieldScores        PredictionFieldScore[]
  activities         PredictionActivity[]
  parentIndices      ParentIndices[]
  babyIndices        BabyIndices[]

  @@index([workspaceId, createdAt])
  @@index([createdById, createdAt])
}

model ProjectBaby {
  id        String   @id @default(cuid())
  projectId String
  project   Project  @relation(fields: [projectId], references: [id], onDelete: Cascade)
  babyIndex Int
  label     String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@unique([projectId, babyIndex])
  @@index([projectId])
}

model ProjectMembership {
  id           String   @id @default(cuid())
  projectId    String
  project      Project  @relation(fields: [projectId], references: [id], onDelete: Cascade)
  userId       String   @unique
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  assignedById String?
  assignedBy   User?    @relation("ProjectMembershipAssignedBy", fields: [assignedById], references: [id], onDelete: SetNull)
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt

  @@unique([projectId, userId])
  @@index([projectId])
}

model PredictionGame {
  id         String     @id @default(cuid())
  projectId  String?
  project    Project?   @relation(fields: [projectId], references: [id], onDelete: SetNull)
  title      String     @default("Pronostics bebe")
  status     GameStatus @default(OPEN)
  closedAt   DateTime?
  reopenedAt DateTime?
  createdAt  DateTime   @default(now())
  updatedAt  DateTime   @updatedAt

  cards      PredictionCard[]
  entries    PredictionEntry[]
  activities PredictionActivity[]

  @@index([projectId])
}

model PredictionCard {
  id          String             @id @default(cuid())
  gameId      String             @default("singleton")
  game        PredictionGame     @relation(fields: [gameId], references: [id], onDelete: Cascade)
  projectId   String?
  project     Project?           @relation(fields: [projectId], references: [id], onDelete: SetNull)
  code        String?
  title       String
  description String?
  type        PredictionCardType @default(CUSTOM)
  valueType   PredictionValueType
  styleId     Int                @default(0)
  unit        String?
  isActive    Boolean            @default(true)
  isDeletable Boolean            @default(true)
  sortOrder   Int                @default(0)
  basePoints  Int                @default(0)
  createdById String
  createdBy   User               @relation("PredictionCardsCreatedBy", fields: [createdById], references: [id], onDelete: Restrict)
  createdAt   DateTime           @default(now())
  updatedAt   DateTime           @updatedAt

  fields      PredictionCardField[]
  options     PredictionCardOption[]
  entries     PredictionEntry[]
  outcomes    PredictionOutcome[]
  activities  PredictionActivity[]

  @@unique([projectId, code])
  @@index([gameId, isActive, sortOrder])
  @@index([projectId, isActive, sortOrder])
}

model PredictionCardField {
  id          String   @id @default(cuid())
  cardId      String
  card        PredictionCard @relation(fields: [cardId], references: [id], onDelete: Cascade)
  label       String
  sortOrder   Int      @default(0)
  points      Int      @default(0)
  isPrimary   Boolean  @default(false)
  isRequired  Boolean  @default(false)
  minNumber   Float?
  maxNumber   Float?
  stepNumber  Float?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  values      PredictionEntryValue[]
  outcomes    PredictionOutcome[]
  scores      PredictionFieldScore[]

  @@unique([cardId, label])
  @@index([cardId, sortOrder])
}

model PredictionCardOption {
  id         String   @id @default(cuid())
  cardId     String
  card       PredictionCard @relation(fields: [cardId], references: [id], onDelete: Cascade)
  label      String
  value      String
  sortOrder  Int      @default(0)

  @@unique([cardId, value])
  @@index([cardId, sortOrder])
}

model PredictionEntry {
  id         String   @id @default(cuid())
  gameId     String   @default("singleton")
  game       PredictionGame @relation(fields: [gameId], references: [id], onDelete: Cascade)
  projectId  String?
  project    Project? @relation(fields: [projectId], references: [id], onDelete: SetNull)
  userId     String
  user       User     @relation("PredictionEntriesByUser", fields: [userId], references: [id], onDelete: Cascade)
  cardId     String
  card       PredictionCard @relation(fields: [cardId], references: [id], onDelete: Cascade)
  selectedBabyIndex Int?
  totalPoints Int     @default(0)
  isScored   Boolean  @default(false)
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt

  values     PredictionEntryValue[]
  history    PredictionEntryHistory[]
  scores     PredictionFieldScore[]
  activities PredictionActivity[]

  @@unique([userId, cardId, selectedBabyIndex])
  @@index([cardId])
  @@index([userId])
  @@index([projectId, userId])
}

model PredictionEntryValue {
  id          String   @id @default(cuid())
  entryId     String
  entry       PredictionEntry @relation(fields: [entryId], references: [id], onDelete: Cascade)
  fieldId     String
  field       PredictionCardField @relation(fields: [fieldId], references: [id], onDelete: Cascade)
  valueText   String?
  valueNumber Float?
  valueDate   DateTime?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  @@unique([entryId, fieldId])
  @@index([fieldId])
}

model PredictionEntryHistory {
  id         String   @id @default(cuid())
  entryId    String
  entry      PredictionEntry @relation(fields: [entryId], references: [id], onDelete: Cascade)
  userId     String
  user       User     @relation("PredictionHistoryByUser", fields: [userId], references: [id], onDelete: Cascade)
  snapshot   Json
  message    String?
  createdAt  DateTime @default(now())

  @@index([entryId, createdAt])
}

model PredictionOutcome {
  id          String   @id @default(cuid())
  cardId      String
  card        PredictionCard @relation(fields: [cardId], references: [id], onDelete: Cascade)
  projectId   String?
  project     Project? @relation(fields: [projectId], references: [id], onDelete: SetNull)
  fieldId     String
  field       PredictionCardField @relation(fields: [fieldId], references: [id], onDelete: Cascade)
  selectedBabyIndex Int?
  valueText   String?
  valueNumber Float?
  valueDate   DateTime?
  setById     String
  setBy       User     @relation("PredictionOutcomesSetBy", fields: [setById], references: [id], onDelete: Restrict)
  setAt       DateTime @default(now())

  @@unique([cardId, fieldId, selectedBabyIndex])
  @@index([projectId])
  @@index([projectId, selectedBabyIndex])
}

model PredictionFieldScore {
  id             String   @id @default(cuid())
  entryId        String
  entry          PredictionEntry @relation(fields: [entryId], references: [id], onDelete: Cascade)
  projectId      String?
  project        Project? @relation(fields: [projectId], references: [id], onDelete: SetNull)
  fieldId        String
  field          PredictionCardField @relation(fields: [fieldId], references: [id], onDelete: Cascade)
  suggestedPoints Int    @default(0)
  awardedPoints  Int?
  isValidated    Boolean  @default(false)
  note           String?
  validatedById  String?
  validatedBy    User?    @relation("PredictionScoresValidatedBy", fields: [validatedById], references: [id], onDelete: SetNull)
  validatedAt    DateTime?
  updatedAt      DateTime @updatedAt

  @@unique([entryId, fieldId])
  @@index([projectId])
}

model PredictionActivity {
  id         String   @id @default(cuid())
  gameId     String   @default("singleton")
  game       PredictionGame @relation(fields: [gameId], references: [id], onDelete: Cascade)
  projectId  String?
  project    Project? @relation(fields: [projectId], references: [id], onDelete: SetNull)
  type       PredictionActivityType
  userId     String?
  user       User?    @relation("PredictionActivitiesByUser", fields: [userId], references: [id], onDelete: SetNull)
  cardId     String?
  card       PredictionCard? @relation(fields: [cardId], references: [id], onDelete: SetNull)
  entryId    String?
  entry      PredictionEntry? @relation(fields: [entryId], references: [id], onDelete: SetNull)
  message    String
  createdAt  DateTime @default(now())

  @@index([createdAt])
  @@index([projectId, createdAt])
}

// ===== INDICES =====

model ParentIndices {
  id             String     @id @default(cuid())
  projectId      String
  project        Project    @relation(fields: [projectId], references: [id], onDelete: Cascade)
  parentType     ParentType
  poids          Float?
  taille         Float?
  perimCranien   Float?
  dateNaissance  DateTime?
  updatedAt      DateTime   @updatedAt

  photos         ParentIndexPhoto[]

  @@unique([projectId, parentType])
  @@index([projectId])
}

model ParentIndexPhoto {
  id              String        @id @default(cuid())
  parentIndicesId String
  parentIndices   ParentIndices @relation(fields: [parentIndicesId], references: [id], onDelete: Cascade)
  url             String
  sortOrder       Int           @default(0)
  createdAt       DateTime      @default(now())

  @@index([parentIndicesId])
}

model BabyIndices {
  id        String    @id @default(cuid())
  projectId String
  project   Project   @relation(fields: [projectId], references: [id], onDelete: Cascade)
  babyIndex Int
  dpa       DateTime?
  updatedAt DateTime  @updatedAt

  trimesters BabyTrimesterEntry[]

  @@unique([projectId, babyIndex])
  @@index([projectId])
}

model BabyTrimesterEntry {
  id            String      @id @default(cuid())
  babyIndicesId String
  babyIndices   BabyIndices @relation(fields: [babyIndicesId], references: [id], onDelete: Cascade)
  trimester     Trimester
  date          DateTime?
  note          String?
  poids         Float?
  taille        Float?
  perimCranien  Float?
  updatedAt     DateTime    @updatedAt

  photos        BabyTrimesterPhoto[]

  @@unique([babyIndicesId, trimester])
  @@index([babyIndicesId])
}

model BabyTrimesterPhoto {
  id               String             @id @default(cuid())
  trimesterEntryId String
  trimesterEntry   BabyTrimesterEntry @relation(fields: [trimesterEntryId], references: [id], onDelete: Cascade)
  url              String
  sortOrder        Int                @default(0)
  createdAt        DateTime           @default(now())

  @@index([trimesterEntryId])
}
