// E-Learning Platform - Enhanced ERD with Constraints
// Version 2.0 - Improved with NOT NULL, CHECK, DEFAULT, and UNIQUE constraints

Table users {
  id int [pk, increment]
  name varchar [not null]
  email varchar [unique, not null]
  password varchar [not null]
  role varchar [not null, default: 'student', note: 'admin | instructor | student']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    email [unique]
    role
  }
}

Table courses {
  id int [pk, increment]
  categories_id int [ref: > categories.id]
  title jsonb [not null, note: '{ "th": "...", "en": "..." }']
  description jsonb [note: '{ "th": "...", "en": "..." }']
  price decimal [not null, default: 0, note: 'must be >= 0']
  is_free boolean [not null, default: false]
  status varchar [not null, default: 'draft', note: 'draft | pending | approved | rejected']
  instructor_id int [not null, ref: > users.id]
  approved_by int [ref: > users.id, note: 'admin user id']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    instructor_id
    categories_id
    status
    (instructor_id, status)
  }
}

Table categories {
  id int [pk, increment]
  name jsonb [not null, note: 'multi-language category name']
  description jsonb [note: 'optional']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
}

Table chapters {
  id int [pk, increment]
  course_id int [not null, ref: > courses.id]
  title jsonb [not null, note: 'multi-language']
  sort_order int [not null, default: 0, note: 'must be >= 0']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    course_id
    (course_id, sort_order)
  }
}

Table lessons {
  id int [pk, increment]
  chapter_id int [not null, ref: > chapters.id]
  title jsonb [not null, note: 'multi-language']
  content jsonb [note: 'multi-language lesson content']
  type varchar [not null, note: 'video | pdf | text | quiz']
  sort_order int [not null, default: 0, note: 'must be >= 0']
  is_sequential boolean [not null, default: true, note: 'require previous lessons to be completed']
  prerequisite_lesson_ids jsonb [note: 'array of lesson IDs that must be completed first, e.g. [1, 2, 3]']
  require_pass_quiz boolean [default: false, note: 'require passing quiz to unlock next lessons']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    chapter_id
    (chapter_id, sort_order)
    type
  }
}

Table quizzes {
  id int [pk, increment]
  lesson_id int [not null, ref: > lessons.id]
  title jsonb [not null, note: 'multi-language']
  passing_score int [not null, default: 60, note: 'must be 0-100']
  time_limit int [note: 'in minutes, must be > 0 if set']
  max_attempts int [note: 'null = unlimited']
  cooldown_minutes int [note: 'waiting time between attempts']
  score_policy varchar [default: 'highest', note: 'highest | latest | first | average']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    lesson_id
  }
}

Table questions {
  id int [pk, increment]
  quiz_id int [not null, ref: > quizzes.id]
  question jsonb [not null, note: 'multi-language']
  question_type varchar [not null, default: 'multiple_choice', note: 'multiple_choice | true_false']
  score int [not null, default: 1, note: 'must be > 0']
  sort_order int [not null, default: 0]
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    quiz_id
    (quiz_id, sort_order)
  }
}

Table choices {
  id int [pk, increment]
  question_id int [not null, ref: > questions.id]
  text jsonb [not null, note: 'multi-language']
  is_correct boolean [not null, default: false]
  sort_order int [not null, default: 0]
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    question_id
  }
}

Table enrollments {
  id int [pk, increment]
  user_id int [not null, ref: > users.id]
  course_id int [not null, ref: > courses.id]
  status varchar [not null, default: 'enrolled', note: 'enrolled | completed']
  progress_percentage int [not null, default: 0, note: '0-100']
  certificate_issued boolean [not null, default: false]
  certificate_id varchar [unique, note: 'unique certificate identifier']
  enrolled_at datetime [not null, default: `now()`]
  completed_at datetime [note: 'when status changed to completed']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    (user_id, course_id) [unique, name: 'unique_enrollment']
    user_id
    course_id
    status
  }
}

Table lesson_progress {
  id int [pk, increment]
  user_id int [not null, ref: > users.id]
  lesson_id int [not null, ref: > lessons.id]
  is_completed boolean [not null, default: false]
  completed_at datetime
  video_progress_seconds int [default: 0, note: 'current playback position in seconds']
  video_duration_seconds int [note: 'total video duration in seconds']
  video_progress_percentage decimal(5,2) [note: 'calculated: (progress/duration)*100']
  last_watched_at datetime [note: 'last time user watched this video']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    (user_id, lesson_id) [unique]
    user_id
    lesson_id
    last_watched_at
  }
}

Table quiz_attempts {
  id int [pk, increment]
  user_id int [not null, ref: > users.id]
  quiz_id int [not null, ref: > quizzes.id]
  score int [not null, default: 0, note: '0-100']
  total_questions int [not null]
  correct_answers int [not null, default: 0]
  is_passed boolean [not null, default: false]
  attempt_number int [not null, default: 1]
  started_at datetime [not null, default: `now()`]
  completed_at datetime
  created_at datetime [not null, default: `now()`]
  
  indexes {
    user_id
    quiz_id
    (user_id, quiz_id)
    (user_id, quiz_id, attempt_number)
  }
}

Table announcements {
  id int [pk, increment]
  course_id int [not null, ref: > courses.id]
  instructor_id int [not null, ref: > users.id]
  title jsonb [not null, note: 'multi-language']
  content jsonb [not null, note: 'multi-language']
  is_pinned boolean [not null, default: false, note: 'pin important announcements to top']
  published_at datetime [note: 'scheduled publish date, null = publish immediately']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    course_id
    instructor_id
    (course_id, is_pinned, published_at)
    (course_id, published_at)
  }
}

Table announcement_attachments {
  id int [pk, increment]
  announcement_id int [not null, ref: > announcements.id]
  file_name varchar [not null]
  file_path varchar [not null, note: 'S3 key or file path']
  file_size int [not null, note: 'in bytes']
  mime_type varchar [not null]
  created_at datetime [not null, default: `now()`]
  
  indexes {
    announcement_id
  }
}

Table lesson_attachments {
  id int [pk, increment]
  lesson_id int [not null, ref: > lessons.id]
  file_name varchar [not null]
  file_path varchar [not null, note: 'S3 key or file path']
  file_size int [not null, note: 'in bytes']
  mime_type varchar [not null]
  description jsonb [note: 'multi-language description']
  sort_order int [not null, default: 0]
  created_at datetime [not null, default: `now()`]
  
  indexes {
    lesson_id
    (lesson_id, sort_order)
  }
}

Table orders {
  id int [pk, increment]
  user_id int [not null, ref: > users.id]
  total_amount decimal [not null, default: 0, note: 'must be >= 0']
  status varchar [not null, default: 'pending', note: 'pending | paid | cancelled']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    user_id
    status
    (user_id, status)
  }
}

Table order_items {
  id int [pk, increment]
  order_id int [not null, ref: > orders.id]
  course_id int [not null, ref: > courses.id]
  price decimal [not null, note: 'must be >= 0']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    order_id
    course_id
  }
}

Table payments {
  id int [pk, increment]
  order_id int [not null, ref: > orders.id]
  provider varchar [not null, note: 'stripe | paypal | promptpay etc.']
  transaction_id varchar [unique, note: 'unique transaction ID from payment provider']
  amount decimal [not null, note: 'must be > 0']
  status varchar [not null, default: 'pending', note: 'pending | success | failed']
  paid_at datetime
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    order_id
    transaction_id [unique]
    status
  }
}

Table instructor_balances {
  id int [pk, increment]
  instructor_id int [not null, unique, ref: > users.id, note: 'one balance record per instructor']
  available_amount decimal [not null, default: 0, note: 'must be >= 0']
  withdrawn_amount decimal [not null, default: 0, note: 'must be >= 0']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    instructor_id [unique]
  }
}

Table withdrawal_requests {
  id int [pk, increment]
  instructor_id int [not null, ref: > users.id]
  amount decimal [not null, note: 'must be > 0']
  status varchar [not null, default: 'pending', note: 'pending | approved | rejected | paid']
  approved_by int [ref: > users.id, note: 'admin user id']
  rejected_reason varchar [note: 'reason if rejected']
  created_at datetime [not null, default: `now()`]
  updated_at datetime [not null, default: `now()`]
  
  indexes {
    instructor_id
    status
    (instructor_id, status)
  }
}

// Additional helpful notes:
// 1. All foreign keys should have ON DELETE actions defined during implementation
// 2. Suggested ON DELETE actions:
//    - courses.instructor_id: RESTRICT (prevent deleting instructor with courses)
//    - enrollments: CASCADE (delete enrollments when user/course deleted)
//    - announcements: CASCADE (delete announcements when course deleted)
//    - quiz_attempts: CASCADE (delete attempts when user deleted)
// 3. All jsonb fields support multi-language: { "th": "...", "en": "..." }
// 4. Indexes are suggested for common query patterns
// 5. Consider adding soft delete (deleted_at) for important tables
