// 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")
}

// ============================================
// User Management
// ============================================

model Role {
  id          Int      @id @default(autoincrement())
  code        String   @unique @db.VarChar(50)
  name        Json // { th: "", en: "" }
  description Json?
  created_at  DateTime @default(now())

  users User[]

  @@index([code])
  @@map("roles")
}

model User {
  id                Int       @id @default(autoincrement())
  username          String    @unique @db.VarChar(50)
  email             String    @unique @db.VarChar(255)
  password          String    @db.VarChar(255)
  role_id           Int
  email_verified_at DateTime?
  is_deactivated    Boolean   @default(false)
  created_at        DateTime  @default(now())
  updated_at        DateTime? @updatedAt

  role    Role         @relation(fields: [role_id], references: [id], onDelete: Restrict)
  profile UserProfile?

  // Relations
  created_courses       Course[]            @relation("CourseCreator")
  approved_courses      Course[]            @relation("CourseApprover")
  instructor_courses    CourseInstructor[]
  enrollments           Enrollment[]
  lesson_progress       LessonProgress[]
  quiz_attempts         QuizAttempt[]
  certificates          Certificate[]
  created_categories    Category[]          @relation("CategoryCreator")
  updated_categories    Category[]          @relation("CategoryUpdater")
  updated_profiles      UserProfile[]       @relation("ProfileUpdater")
  created_quizzes       Quiz[]              @relation("QuizCreator")
  updated_quizzes       Quiz[]              @relation("QuizUpdater")
  created_announcements Announcement[]      @relation("AnnouncementCreator")
  updated_announcements Announcement[]      @relation("AnnouncementUpdater")
  updated_courses       Course[]            @relation("CourseUpdater")
  orders                Order[]
  instructor_balance    InstructorBalance?
  withdrawal_requests   WithdrawalRequest[] @relation("WithdrawalInstructor")
  approved_withdrawals  WithdrawalRequest[] @relation("WithdrawalApprover")
  updated_withdrawals   WithdrawalRequest[] @relation("WithdrawalUpdater")
  submitted_approvals   CourseApproval[]    @relation("ApprovalSubmitter")
  reviewed_approvals    CourseApproval[]    @relation("ApprovalReviewer")
  audit_logs            AuditLog[]

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

model UserProfile {
  id         Int       @id @default(autoincrement())
  user_id    Int       @unique
  prefix     Json? // { th: "นาย", en: "Mr." }
  first_name String    @db.VarChar(100)
  last_name  String    @db.VarChar(100)
  phone      String?   @db.VarChar(20)
  avatar_url String?   @db.VarChar(500)
  birth_date DateTime?
  created_at DateTime  @default(now())
  updated_at DateTime? @updatedAt
  updated_by Int?

  user    User  @relation(fields: [user_id], references: [id], onDelete: Cascade)
  updater User? @relation("ProfileUpdater", fields: [updated_by], references: [id])

  @@index([user_id])
  @@map("user_profiles")
}

model Category {
  id          Int       @id @default(autoincrement())
  name        Json // { th: "", en: "" }
  slug        String    @unique @db.VarChar(100)
  description Json?
  icon        String?   @db.VarChar(100)
  sort_order  Int       @default(0)
  is_active   Boolean   @default(true)
  created_at  DateTime  @default(now())
  created_by  Int
  updated_at  DateTime? @updatedAt
  updated_by  Int?

  courses Course[]
  creator User     @relation("CategoryCreator", fields: [created_by], references: [id], onDelete: Restrict)
  updater User?    @relation("CategoryUpdater", fields: [updated_by], references: [id])

  @@index([slug])
  @@index([is_active])
  @@index([sort_order])
  @@map("categories")
}

// ============================================
// Course Structure
// ============================================

enum CourseStatus {
  DRAFT
  PENDING
  APPROVED
  REJECTED
  ARCHIVED
}

model Course {
  id               Int          @id @default(autoincrement())
  category_id      Int?
  title            Json // { th: "", en: "" }
  slug             String       @unique @db.VarChar(200)
  description      Json
  thumbnail_url    String?      @db.VarChar(500)
  price            Decimal      @default(0) @db.Decimal(10, 2)
  is_free          Boolean      @default(false)
  have_certificate Boolean      @default(false)
  status           CourseStatus @default(DRAFT)
  approved_by      Int?
  approved_at      DateTime?
  rejection_reason String?      @db.Text
  created_at       DateTime     @default(now())
  created_by       Int
  updated_at       DateTime?    @updatedAt
  updated_by       Int?

  category        Category?          @relation(fields: [category_id], references: [id], onDelete: SetNull)
  creator         User               @relation("CourseCreator", fields: [created_by], references: [id], onDelete: Restrict)
  approver        User?              @relation("CourseApprover", fields: [approved_by], references: [id])
  updater         User?              @relation("CourseUpdater", fields: [updated_by], references: [id])
  chapters        Chapter[]
  instructors     CourseInstructor[]
  enrollments     Enrollment[]
  announcements   Announcement[]
  courseApprovals CourseApproval[]

  @@index([category_id])
  @@index([slug])
  @@index([status])
  @@index([created_by])
  @@index([status, is_free])
  @@index([category_id, status])
  @@map("courses")
}

model CourseInstructor {
  id         Int      @id @default(autoincrement())
  course_id  Int
  user_id    Int
  is_primary Boolean  @default(false)
  joined_at  DateTime @default(now())

  course Course @relation(fields: [course_id], references: [id], onDelete: Cascade)
  user   User   @relation(fields: [user_id], references: [id], onDelete: Cascade)

  @@unique([course_id, user_id])
  @@index([course_id])
  @@index([user_id])
  @@index([is_primary])
  @@map("course_instructors")
}

enum ApprovalAction {
  SUBMITTED
  APPROVED
  REJECTED
}

model CourseApproval {
  id              Int            @id @default(autoincrement())
  course_id       Int
  submitted_by    Int
  reviewed_by     Int?
  action          ApprovalAction @default(SUBMITTED)
  previous_status CourseStatus?
  new_status      CourseStatus?
  comment         String?        @db.Text
  created_at      DateTime       @default(now())

  course    Course @relation(fields: [course_id], references: [id], onDelete: Cascade)
  submitter User   @relation("ApprovalSubmitter", fields: [submitted_by], references: [id], onDelete: Restrict)
  reviewer  User?  @relation("ApprovalReviewer", fields: [reviewed_by], references: [id])

  @@index([course_id])
  @@index([submitted_by])
  @@index([reviewed_by])
  @@index([action])
  @@index([created_at])
  @@index([course_id, created_at])
  @@map("course_approvals")
}

model Chapter {
  id           Int       @id @default(autoincrement())
  course_id    Int
  title        Json // { th: "", en: "" }
  description  Json?
  sort_order   Int       @default(0)
  is_published Boolean   @default(true)
  created_at   DateTime  @default(now())
  updated_at   DateTime? @updatedAt

  course  Course   @relation(fields: [course_id], references: [id], onDelete: Cascade)
  lessons Lesson[]

  @@index([course_id])
  @@index([course_id, sort_order])
  @@map("chapters")
}

// ============================================
// Lessons
// ============================================

enum LessonType {
  VIDEO
  QUIZ
}

model Lesson {
  id                      Int        @id @default(autoincrement())
  chapter_id              Int
  title                   Json // { th: "", en: "" }
  content                 Json? // multi-language lesson content
  type                    LessonType
  duration_minutes        Int?
  sort_order              Int        @default(0)
  is_sequential           Boolean    @default(true)
  prerequisite_lesson_ids Json? // array of lesson IDs
  require_pass_quiz       Boolean    @default(false)
  is_published            Boolean    @default(true)
  created_at              DateTime   @default(now())
  updated_at              DateTime?  @updatedAt

  chapter     Chapter            @relation(fields: [chapter_id], references: [id], onDelete: Cascade)
  attachments LessonAttachment[]
  quiz        Quiz?
  progress    LessonProgress[]

  @@index([chapter_id])
  @@index([chapter_id, sort_order])
  @@index([type])
  @@map("lessons")
}

model LessonAttachment {
  id          Int      @id @default(autoincrement())
  lesson_id   Int
  file_name   String   @db.VarChar(255)
  file_path   String   @db.VarChar(500)
  file_size   Int
  mime_type   String   @db.VarChar(100)
  description Json?
  sort_order  Int      @default(0)
  created_at  DateTime @default(now())

  lesson Lesson @relation(fields: [lesson_id], references: [id], onDelete: Cascade)

  @@index([lesson_id])
  @@index([lesson_id, sort_order])
  @@map("lesson_attachments")
}

// ============================================
// Quiz System
// ============================================

enum QuestionType {
  MULTIPLE_CHOICE
  TRUE_FALSE
  SHORT_ANSWER
}

model Quiz {
  id                            Int       @id @default(autoincrement())
  lesson_id                     Int       @unique
  title                         Json // { th: "", en: "" }
  description                   Json?
  passing_score                 Int       @default(60)
  time_limit                    Int? // in minutes
  shuffle_questions             Boolean   @default(false)
  shuffle_choices               Boolean   @default(false)
  show_answers_after_completion Boolean   @default(true)
  is_skippable                  Boolean   @default(true)
  created_at                    DateTime  @default(now())
  created_by                    Int
  updated_at                    DateTime? @updatedAt
  updated_by                    Int?

  lesson    Lesson        @relation(fields: [lesson_id], references: [id], onDelete: Cascade)
  creator   User          @relation("QuizCreator", fields: [created_by], references: [id], onDelete: Restrict)
  updater   User?         @relation("QuizUpdater", fields: [updated_by], references: [id])
  questions Question[]
  attempts  QuizAttempt[]

  @@index([lesson_id])
  @@map("quizzes")
}

model Question {
  id            Int          @id @default(autoincrement())
  quiz_id       Int
  question      Json // { th: "", en: "" }
  explanation   Json? // answer explanation
  question_type QuestionType @default(MULTIPLE_CHOICE)
  score         Int          @default(1)
  sort_order    Int          @default(0)
  created_at    DateTime     @default(now())
  updated_at    DateTime?    @updatedAt

  quiz    Quiz     @relation(fields: [quiz_id], references: [id], onDelete: Cascade)
  choices Choice[]

  @@index([quiz_id])
  @@index([quiz_id, sort_order])
  @@map("questions")
}

model Choice {
  id          Int     @id @default(autoincrement())
  question_id Int
  text        Json // { th: "", en: "" }
  is_correct  Boolean @default(false)
  sort_order  Int     @default(0)

  question Question @relation(fields: [question_id], references: [id], onDelete: Cascade)

  @@index([question_id])
  @@map("choices")
}

// ============================================
// Student Progress
// ============================================

enum EnrollmentStatus {
  ENROLLED
  IN_PROGRESS
  COMPLETED
  DROPPED
}

model Enrollment {
  id                  Int              @id @default(autoincrement())
  user_id             Int
  course_id           Int
  status              EnrollmentStatus @default(ENROLLED)
  progress_percentage Int              @default(0)
  enrolled_at         DateTime         @default(now())
  started_at          DateTime?
  completed_at        DateTime?
  last_accessed_at    DateTime?

  user         User          @relation(fields: [user_id], references: [id], onDelete: Cascade)
  course       Course        @relation(fields: [course_id], references: [id], onDelete: Cascade)
  certificates Certificate[]

  @@unique([user_id, course_id], name: "unique_enrollment")
  @@index([user_id])
  @@index([course_id])
  @@index([status])
  @@index([last_accessed_at])
  @@map("enrollments")
}

model Certificate {
  id            Int      @id @default(autoincrement())
  user_id       Int
  course_id     Int
  enrollment_id Int      @unique
  file_path     String   @db.VarChar(500)
  issued_at     DateTime @default(now())

  user       User       @relation(fields: [user_id], references: [id], onDelete: Cascade)
  enrollment Enrollment @relation(fields: [enrollment_id], references: [id], onDelete: Cascade)

  @@index([user_id])
  @@index([course_id])
  @@index([enrollment_id])
  @@index([user_id, course_id])
  @@map("certificates")
}

model LessonProgress {
  id                        Int       @id @default(autoincrement())
  user_id                   Int
  lesson_id                 Int
  is_completed              Boolean   @default(false)
  completed_at              DateTime?
  video_progress_seconds    Int       @default(0)
  video_duration_seconds    Int?
  video_progress_percentage Decimal?  @db.Decimal(5, 2)
  last_watched_at           DateTime?
  created_at                DateTime  @default(now())
  updated_at                DateTime? @updatedAt

  user   User   @relation(fields: [user_id], references: [id], onDelete: Cascade)
  lesson Lesson @relation(fields: [lesson_id], references: [id], onDelete: Cascade)

  @@unique([user_id, lesson_id])
  @@index([user_id])
  @@index([lesson_id])
  @@index([last_watched_at])
  @@map("lesson_progress")
}

model QuizAttempt {
  id              Int       @id @default(autoincrement())
  user_id         Int
  quiz_id         Int
  score           Int       @default(0)
  total_questions Int
  correct_answers Int       @default(0)
  is_passed       Boolean   @default(false)
  attempt_number  Int       @default(1)
  answers         Json? // student answers for review
  started_at      DateTime  @default(now())
  completed_at    DateTime?

  quiz Quiz @relation(fields: [quiz_id], references: [id], onDelete: Cascade)
  user User @relation(fields: [user_id], references: [id], onDelete: Cascade)

  @@index([user_id])
  @@index([quiz_id])
  @@index([user_id, quiz_id])
  @@index([user_id, quiz_id, attempt_number])
  @@map("quiz_attempts")
}

// ============================================
// Communication
// ============================================

enum AnnouncementStatus {
  DRAFT
  PUBLISHED
  ARCHIVED
}

model Announcement {
  id           Int                @id @default(autoincrement())
  course_id    Int
  title        Json // { th: "", en: "" }
  content      Json // { th: "", en: "" }
  status       AnnouncementStatus @default(DRAFT)
  is_pinned    Boolean            @default(false)
  published_at DateTime?
  created_at   DateTime           @default(now())
  created_by   Int
  updated_at   DateTime?          @updatedAt
  updated_by   Int?

  course      Course                   @relation(fields: [course_id], references: [id], onDelete: Cascade)
  creator     User                     @relation("AnnouncementCreator", fields: [created_by], references: [id], onDelete: Restrict)
  updater     User?                    @relation("AnnouncementUpdater", fields: [updated_by], references: [id])
  attachments AnnouncementAttachment[]

  @@index([course_id])
  @@index([created_by])
  @@index([status])
  @@index([course_id, status, is_pinned, published_at])
  @@map("announcements")
}

model AnnouncementAttachment {
  id              Int      @id @default(autoincrement())
  announcement_id Int
  file_name       String   @db.VarChar(255)
  file_path       String   @db.VarChar(500)
  file_size       Int
  mime_type       String   @db.VarChar(100)
  created_at      DateTime @default(now())

  announcement Announcement @relation(fields: [announcement_id], references: [id], onDelete: Cascade)

  @@index([announcement_id])
  @@map("announcement_attachments")
}

// ============================================
// Payment System
// ============================================

enum OrderStatus {
  PENDING
  PAID
  CANCELLED
  REFUNDED
}

enum PaymentStatus {
  PENDING
  SUCCESS
  FAILED
}

enum WithdrawalStatus {
  PENDING
  APPROVED
  REJECTED
  PAID
}

model Order {
  id           Int         @id @default(autoincrement())
  user_id      Int
  total_amount Decimal     @default(0) @db.Decimal(10, 2)
  status       OrderStatus @default(PENDING)
  created_at   DateTime    @default(now())
  updated_at   DateTime?   @updatedAt

  user     User        @relation(fields: [user_id], references: [id], onDelete: Cascade)
  items    OrderItem[]
  payments Payment[]

  @@index([user_id])
  @@index([status])
  @@index([user_id, status])
  @@map("orders")
}

model OrderItem {
  id         Int      @id @default(autoincrement())
  order_id   Int
  course_id  Int
  price      Decimal  @db.Decimal(10, 2)
  created_at DateTime @default(now())

  order Order @relation(fields: [order_id], references: [id], onDelete: Cascade)

  @@index([order_id])
  @@index([course_id])
  @@map("order_items")
}

model Payment {
  id             Int           @id @default(autoincrement())
  order_id       Int
  provider       String        @db.VarChar(50)
  transaction_id String?       @unique @db.VarChar(255)
  amount         Decimal       @db.Decimal(10, 2)
  status         PaymentStatus @default(PENDING)
  paid_at        DateTime?
  created_at     DateTime      @default(now())
  updated_at     DateTime?     @updatedAt

  order Order @relation(fields: [order_id], references: [id], onDelete: Cascade)

  @@index([order_id])
  @@index([transaction_id])
  @@index([status])
  @@map("payments")
}

model InstructorBalance {
  id               Int       @id @default(autoincrement())
  instructor_id    Int       @unique
  available_amount Decimal   @default(0) @db.Decimal(10, 2)
  withdrawn_amount Decimal   @default(0) @db.Decimal(10, 2)
  created_at       DateTime  @default(now())
  updated_at       DateTime? @updatedAt

  instructor User @relation(fields: [instructor_id], references: [id], onDelete: Cascade)

  @@index([instructor_id])
  @@map("instructor_balances")
}

model WithdrawalRequest {
  id              Int              @id @default(autoincrement())
  instructor_id   Int
  amount          Decimal          @db.Decimal(10, 2)
  status          WithdrawalStatus @default(PENDING)
  approved_by     Int?
  approved_at     DateTime?
  rejected_reason String?          @db.Text
  created_at      DateTime         @default(now())
  updated_at      DateTime?        @updatedAt
  updated_by      Int?

  instructor User  @relation("WithdrawalInstructor", fields: [instructor_id], references: [id], onDelete: Cascade)
  approver   User? @relation("WithdrawalApprover", fields: [approved_by], references: [id])
  updater    User? @relation("WithdrawalUpdater", fields: [updated_by], references: [id])

  @@index([instructor_id])
  @@index([status])
  @@index([instructor_id, status])
  @@map("withdrawal_requests")
}

// ============================================
// Audit Log System
// ============================================

enum AuditAction {
  CREATE
  UPDATE
  DELETE
  LOGIN
  LOGOUT
  ENROLL
  UNENROLL
  SUBMIT_QUIZ
  APPROVE_COURSE
  REJECT_COURSE
  UPLOAD_FILE
  DELETE_FILE
  CHANGE_PASSWORD
  RESET_PASSWORD
  VERIFY_EMAIL
  DEACTIVATE_USER
  ACTIVATE_USER
}

model AuditLog {
  id          Int         @id @default(autoincrement())
  user_id     Int?
  action      AuditAction
  entity_type String      @db.VarChar(100) // Course, User, Lesson, Quiz, etc.
  entity_id   Int?
  old_value   Json?       // ค่าเดิม (สำหรับ UPDATE/DELETE)
  new_value   Json?       // ค่าใหม่ (สำหรับ CREATE/UPDATE)
  ip_address  String?     @db.VarChar(45) // รองรับ IPv6
  user_agent  String?     @db.Text
  metadata    Json?       // ข้อมูลเพิ่มเติม เช่น request_id, session_id
  created_at  DateTime    @default(now())

  user User? @relation(fields: [user_id], references: [id], onDelete: SetNull)

  @@index([user_id])
  @@index([action])
  @@index([entity_type])
  @@index([entity_type, entity_id])
  @@index([created_at])
  @@index([user_id, created_at])
  @@index([action, created_at])
  @@map("audit_logs")
}
