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

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

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

// ============================================================================
// ENUMS
// ============================================================================

enum UserRole {
  USER
  ADMIN
  MODERATOR
}

enum CharacterDisplay {
  SIMPLIFIED
  TRADITIONAL
  BOTH
}

enum Difficulty {
  EASY
  MEDIUM
  HARD
  SUSPENDED
}

// ============================================================================
// LANGUAGE & HANZI MODELS
// ============================================================================

model Language {
  id          String   @id @default(cuid())
  code        String   @unique // ISO 639-1 code (e.g., "en", "zh", "es")
  name        String   // English name (e.g., "English", "Chinese")
  nativeName  String   // Native name (e.g., "English", "中文")
  isActive    Boolean  @default(true)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  meanings        HanziMeaning[]
  userPreferences UserPreference[]

  @@map("languages")
}

model Hanzi {
  id         String   @id @default(cuid())
  simplified String   @unique // The simplified Chinese character
  radical    String? // Radical/base component
  frequency  Int? // Frequency ranking (lower = more common)
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt

  forms           HanziForm[]
  hskLevels       HanziHSKLevel[]
  partsOfSpeech   HanziPOS[]
  userProgress    UserHanziProgress[]
  collectionItems CollectionItem[]
  sessionReviews  SessionReview[]

  @@index([simplified])
  @@map("hanzi")
}

model HanziForm {
  id          String   @id @default(cuid())
  hanziId     String
  traditional String // Traditional variant
  isDefault   Boolean  @default(false) // Primary traditional form
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  hanzi          Hanzi               @relation(fields: [hanziId], references: [id], onDelete: Cascade)
  transcriptions HanziTranscription[]
  meanings       HanziMeaning[]
  classifiers    HanziClassifier[]

  @@index([hanziId])
  @@index([traditional])
  @@map("hanzi_forms")
}

model HanziTranscription {
  id        String   @id @default(cuid())
  formId    String
  type      String // "pinyin", "numeric", "wadegiles", etc.
  value     String // The actual transcription
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  form HanziForm @relation(fields: [formId], references: [id], onDelete: Cascade)

  @@index([formId])
  @@index([type, value])
  @@map("hanzi_transcriptions")
}

model HanziMeaning {
  id         String   @id @default(cuid())
  formId     String
  languageId String
  meaning    String   @db.Text // Translation/definition
  orderIndex Int      @default(0) // Order of meanings
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt

  form     HanziForm @relation(fields: [formId], references: [id], onDelete: Cascade)
  language Language  @relation(fields: [languageId], references: [id])

  @@index([formId])
  @@index([languageId])
  @@map("hanzi_meanings")
}

model HanziHSKLevel {
  id        String   @id @default(cuid())
  hanziId   String
  level     String // "new-1", "old-3", etc.
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  hanzi Hanzi @relation(fields: [hanziId], references: [id], onDelete: Cascade)

  @@index([hanziId])
  @@index([level])
  @@map("hanzi_hsk_levels")
}

model HanziPOS {
  id        String   @id @default(cuid())
  hanziId   String
  pos       String // "n", "v", "adj", "adv", etc.
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  hanzi Hanzi @relation(fields: [hanziId], references: [id], onDelete: Cascade)

  @@index([hanziId])
  @@map("hanzi_pos")
}

model HanziClassifier {
  id         String   @id @default(cuid())
  formId     String
  classifier String // Measure word
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt

  form HanziForm @relation(fields: [formId], references: [id], onDelete: Cascade)

  @@index([formId])
  @@map("hanzi_classifiers")
}

// ============================================================================
// USER & AUTH MODELS
// ============================================================================

model User {
  id            String    @id @default(cuid())
  email         String    @unique
  password      String // Hashed with bcrypt
  name          String?
  role          UserRole  @default(USER)
  isActive      Boolean   @default(true)
  emailVerified DateTime?
  image         String?
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt

  collections      Collection[]
  hanziProgress    UserHanziProgress[]
  preference       UserPreference?
  learningSessions LearningSession[]
  accounts         Account[]
  sessions         Session[]

  @@index([email])
  @@map("users")
}

model UserPreference {
  id                    String           @id @default(cuid())
  userId                String           @unique
  preferredLanguageId   String
  characterDisplay      CharacterDisplay @default(SIMPLIFIED)
  transcriptionType     String           @default("pinyin") // "pinyin", "numeric", etc.
  cardsPerSession       Int              @default(20)
  dailyGoal             Int              @default(50) // Cards per day
  removalThreshold      Int              @default(10) // Consecutive correct before suggesting removal
  allowManualDifficulty Boolean          @default(true)
  createdAt             DateTime         @default(now())
  updatedAt             DateTime         @updatedAt

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

  @@map("user_preferences")
}

// NextAuth.js models
model Account {
  id                String  @id @default(cuid())
  userId            String
  type              String
  provider          String
  providerAccountId String
  refresh_token     String? @db.Text
  access_token      String? @db.Text
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String? @db.Text
  session_state     String?

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

  @@unique([provider, providerAccountId])
  @@map("accounts")
}

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

  @@map("sessions")
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
  @@map("verification_tokens")
}

// ============================================================================
// LEARNING MODELS
// ============================================================================

model Collection {
  id          String   @id @default(cuid())
  name        String
  description String?  @db.Text
  isGlobal    Boolean  @default(false) // Global collections (HSK levels) vs user collections
  createdBy   String?
  isPublic    Boolean  @default(false) // User collections can be public
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  creator          User?             @relation(fields: [createdBy], references: [id], onDelete: SetNull)
  items            CollectionItem[]
  learningSessions LearningSession[]

  @@index([createdBy])
  @@index([isGlobal])
  @@map("collections")
}

model CollectionItem {
  id           String   @id @default(cuid())
  collectionId String
  hanziId      String
  orderIndex   Int      @default(0)
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt

  collection Collection @relation(fields: [collectionId], references: [id], onDelete: Cascade)
  hanzi      Hanzi      @relation(fields: [hanziId], references: [id], onDelete: Cascade)

  @@unique([collectionId, hanziId])
  @@index([collectionId])
  @@index([hanziId])
  @@map("collection_items")
}

model UserHanziProgress {
  id                String      @id @default(cuid())
  userId            String
  hanziId           String
  correctCount      Int         @default(0)
  incorrectCount    Int         @default(0)
  consecutiveCorrect Int        @default(0)
  easeFactor        Float       @default(2.5) // SM-2 algorithm
  interval          Int         @default(1) // Days between reviews
  nextReviewDate    DateTime    @default(now())
  manualDifficulty  Difficulty? // Optional manual override
  createdAt         DateTime    @default(now())
  updatedAt         DateTime    @updatedAt

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

  @@unique([userId, hanziId])
  @@index([userId, nextReviewDate])
  @@index([hanziId])
  @@map("user_hanzi_progress")
}

model LearningSession {
  id               String    @id @default(cuid())
  userId           String
  collectionId     String?
  startedAt        DateTime  @default(now())
  endedAt          DateTime?
  cardsReviewed    Int       @default(0)
  correctAnswers   Int       @default(0)
  incorrectAnswers Int       @default(0)
  createdAt        DateTime  @default(now())
  updatedAt        DateTime  @updatedAt

  user       User            @relation(fields: [userId], references: [id], onDelete: Cascade)
  collection Collection?     @relation(fields: [collectionId], references: [id], onDelete: SetNull)
  reviews    SessionReview[]

  @@index([userId])
  @@index([startedAt])
  @@map("learning_sessions")
}

model SessionReview {
  id           String   @id @default(cuid())
  sessionId    String
  hanziId      String
  isCorrect    Boolean
  responseTime Int? // Milliseconds
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt

  session LearningSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
  hanzi   Hanzi           @relation(fields: [hanziId], references: [id], onDelete: Cascade)

  @@index([sessionId])
  @@index([hanziId])
  @@map("session_reviews")
}
