<?php
require_once __DIR__ . "/auth.php";
require_role(['super','admin','staff']);
require_once __DIR__ . "/../includes/db.php";


mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn->set_charset('utf8mb4');

function h($v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }

function make_password(int $len = 10): string {
  $alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789@#$%&*!?';
  $out = '';
  for ($i=0; $i<$len; $i++) $out .= $alphabet[random_int(0, strlen($alphabet)-1)];
  return $out;
}

/* =========================================================
   INLINE AJAX ENDPOINTS (MUST BE BEFORE ANY HTML OUTPUT)
   ========================================================= */
if (isset($_GET['action'])) {
  $action = (string)$_GET['action'];

  /* ---- 1) Course -> Batches ---- */
  if ($action === 'batches') {
    $course_id = (int)($_GET['course_id'] ?? 0);
    $branch_id = (int)($_GET['branch_id'] ?? 0);

    header('Content-Type: text/html; charset=utf-8');
    echo '<option value="">Select an Opti...</option>';
    if ($course_id <= 0) exit;

    if ($branch_id > 0) {
      $st = $conn->prepare("
        SELECT id, batch_code, batch_name
        FROM batches
        WHERE status='Active' AND course_id=? AND branch_id=?
        ORDER BY batch_name
      ");
      $st->bind_param("ii", $course_id, $branch_id);
    } else {
      $st = $conn->prepare("
        SELECT id, batch_code, batch_name
        FROM batches
        WHERE status='Active' AND course_id=?
        ORDER BY batch_name
      ");
      $st->bind_param("i", $course_id);
    }

    $st->execute();
    $rs = $st->get_result();
    while ($b = $rs->fetch_assoc()) {
      $label = trim(($b['batch_code'] ?? '') . ' ' . ($b['batch_name'] ?? ''));
      echo '<option value="'.(int)$b['id'].'">'.h($label).'</option>';
    }
    exit;
  }

  /* ---- 2) Course -> Exams ---- */
  if ($action === 'exams') {
    $course_id = (int)($_GET['course_id'] ?? 0);

    header('Content-Type: text/html; charset=utf-8');
    echo '<option value="">Select an Opti...</option>';
    if ($course_id <= 0) exit;

    $st = $conn->prepare("SELECT id, title FROM exams WHERE course_id=? ORDER BY title");
    $st->bind_param("i", $course_id);
    $st->execute();
    $rs = $st->get_result();

    while ($e = $rs->fetch_assoc()) {
      echo '<option value="'.(int)$e['id'].'">'.h($e['title']).'</option>';
    }
    exit;
  }

  /* ---- 3) Filter -> Students list (JSON) ---- */
  if ($action === 'students') {
    header('Content-Type: application/json; charset=utf-8');
    if (ob_get_length()) @ob_clean();

    $course_id = (int)($_GET['course_id'] ?? 0);
    $batch_id  = (int)($_GET['batch_id'] ?? 0);
    $branch_id = (int)($_GET['branch_id'] ?? 0);

    if ($course_id <= 0 || $batch_id <= 0) {
      echo json_encode(['ok'=>false,'error'=>'Missing course_id or batch_id']);
      exit;
    }

    $chk = $conn->prepare("SELECT course_id, branch_id FROM batches WHERE id=? LIMIT 1");
    $chk->bind_param("i", $batch_id);
    $chk->execute();
    $bi = $chk->get_result()->fetch_assoc() ?: [];

    if ((int)($bi['course_id'] ?? 0) !== $course_id) {
      echo json_encode(['ok'=>false,'error'=>'Batch does not belong to selected course']);
      exit;
    }

    if ($branch_id > 0 && (int)($bi['branch_id'] ?? 0) > 0 && (int)$bi['branch_id'] !== $branch_id) {
      echo json_encode(['ok'=>false,'error'=>'Batch does not belong to selected branch']);
      exit;
    }

    $st = $conn->prepare("
      SELECT
        s.id AS student_id,
        COALESCE(sn.center_reg_no, s.center_reg_no, sn.reference_no, s.reference_no) AS reg_no,
        s.full_name,
        s.nic_passport
      FROM enrollments e
      JOIN studentss s ON s.id = e.student_id
      LEFT JOIN student_numbers sn
        ON sn.student_id = s.id AND sn.course_id = ?
      WHERE e.batch_id = ?
      ORDER BY s.full_name ASC
    ");
    $st->bind_param("ii", $course_id, $batch_id);
    $st->execute();

    echo json_encode([
      'ok' => true,
      'students' => $st->get_result()->fetch_all(MYSQLI_ASSOC)
    ]);
    exit;
  }

  /* ---- 4) Bulk Insert -> SAVE INTO `students` table (JSON) ---- */
  if ($action === 'bulk_insert') {
    header('Content-Type: application/json; charset=utf-8');
    if (ob_get_length()) @ob_clean();

    $course_id = (int)($_POST['course_id'] ?? 0);
    $exam_id   = (int)($_POST['exam_id'] ?? 0);
    $exam_date = trim($_POST['exam_date'] ?? date('Y-m-d'));
    $ids       = $_POST['student_ids'] ?? [];

    if ($course_id <= 0 || $exam_id <= 0) {
      echo json_encode(['ok'=>false,'error'=>'Missing course_id or exam_id']);
      exit;
    }

    if (!is_array($ids) || count($ids) === 0) {
      echo json_encode(['ok'=>false,'error'=>'No students selected']);
      exit;
    }

    $course_name = '';
    $cst = $conn->prepare("SELECT course_name FROM courses WHERE id=? LIMIT 1");
    $cst->bind_param("i", $course_id);
    $cst->execute();
    $course_name = (string)(($cst->get_result()->fetch_assoc()['course_name'] ?? ''));

    $unit_exam = '';
    $est = $conn->prepare("SELECT title FROM exams WHERE id=? LIMIT 1");
    $est->bind_param("i", $exam_id);
    $est->execute();
    $unit_exam = (string)(($est->get_result()->fetch_assoc()['title'] ?? ''));

    if ($course_name === '' || $unit_exam === '') {
      echo json_encode(['ok'=>false,'error'=>'Course name or exam title missing']);
      exit;
    }

    $findByReg = $conn->prepare("SELECT id FROM students WHERE course_reg_no=? LIMIT 1");
    $findByNic = $conn->prepare("SELECT id FROM students WHERE nic_number=? LIMIT 1");

    $upd = $conn->prepare("
      UPDATE students
      SET name=?, nic_number=?, password=?, password_plain=?, password_valid_date=?, course_name=?, unit_exam=?
      WHERE id=?
      LIMIT 1
    ");

    $ins = $conn->prepare("
      INSERT INTO students
      (course_reg_no, name, nic_number, password, password_plain, password_valid_date, course_name, unit_exam, created_at)
      VALUES (?,?,?,?,?,?,?,?,NOW())
    ");

    $findStudentExam = $conn->prepare("
      SELECT id
      FROM student_exams
      WHERE student_id=? AND exam_id=? AND DATE(created_at)=?
      LIMIT 1
    ");

    $nextAttempt = $conn->prepare("
      SELECT COALESCE(MAX(attempt_no), 0) + 1 AS next_attempt
      FROM student_exams
      WHERE student_id=? AND exam_id=?
    ");

    $insertStudentExam = $conn->prepare("
      INSERT INTO student_exams
      (student_id, exam_id, attempt_no, created_at)
      VALUES (?,?,?,?)
    ");

    $conn->begin_transaction();

    try {
      $created = 0;
      $updated = 0;
      $skipped = 0;
      $assigned = 0;

      foreach ($ids as $sid_raw) {
        $sid = (int)$sid_raw;
        if ($sid <= 0) continue;

        $st = $conn->prepare("
          SELECT
            s.full_name,
            s.nic_passport,
            COALESCE(sn.center_reg_no, s.center_reg_no, sn.reference_no, s.reference_no) AS reg_no
          FROM studentss s
          LEFT JOIN student_numbers sn
            ON sn.student_id=s.id AND sn.course_id=?
          WHERE s.id=? LIMIT 1
        ");
        $st->bind_param("ii", $course_id, $sid);
        $st->execute();
        $r = $st->get_result()->fetch_assoc() ?: [];

        $reg_no = trim((string)($r['reg_no'] ?? ''));
        $name   = trim((string)($r['full_name'] ?? ''));
        $nic    = trim((string)($r['nic_passport'] ?? ''));

        if ($reg_no === '' || $name === '') {
          $skipped++;
          continue;
        }

        $nic2 = $nic !== '' ? $nic : $reg_no;

        $plain = make_password(10);
        $hash  = password_hash($plain, PASSWORD_DEFAULT);

        $examStudentId = 0;

        $findByReg->bind_param("s", $reg_no);
        $findByReg->execute();
        $row = $findByReg->get_result()->fetch_assoc();
        if ($row) $examStudentId = (int)$row['id'];

        if ($examStudentId <= 0) {
          $findByNic->bind_param("s", $nic2);
          $findByNic->execute();
          $row2 = $findByNic->get_result()->fetch_assoc();
          if ($row2) $examStudentId = (int)$row2['id'];
        }

        if ($examStudentId > 0) {
          $upd->bind_param("sssssssi", $name, $nic2, $hash, $plain, $exam_date, $course_name, $unit_exam, $examStudentId);
          $upd->execute();
          $updated++;
        } else {
          $ins->bind_param("ssssssss", $reg_no, $name, $nic2, $hash, $plain, $exam_date, $course_name, $unit_exam);
          $ins->execute();
          $examStudentId = (int)$conn->insert_id;
          $created++;
        }

        $findStudentExam->bind_param("iis", $examStudentId, $exam_id, $exam_date);
        $findStudentExam->execute();
        $existingAttempt = $findStudentExam->get_result()->fetch_assoc();

        if (!$existingAttempt) {
          $nextAttempt->bind_param("ii", $examStudentId, $exam_id);
          $nextAttempt->execute();
          $attemptRow = $nextAttempt->get_result()->fetch_assoc();
          $attemptNo = (int)($attemptRow['next_attempt'] ?? 1);
          if ($attemptNo <= 0) $attemptNo = 1;

          $createdAt = $exam_date . ' ' . date('H:i:s');
          $insertStudentExam->bind_param("iiis", $examStudentId, $exam_id, $attemptNo, $createdAt);
          $insertStudentExam->execute();
          $assigned++;
        }
      }

      $conn->commit();

      echo json_encode([
        'ok'       => true,
        'created'  => $created,
        'updated'  => $updated,
        'assigned' => $assigned,
        'skipped'  => $skipped
      ]);
      exit;

    } catch (Throwable $e) {
      $conn->rollback();
      echo json_encode(['ok'=>false,'error'=>$e->getMessage()]);
      exit;
    }
  }

  header('Content-Type: application/json; charset=utf-8');
  echo json_encode(['ok'=>false,'error'=>'Unknown action']);
  exit;
}

/* =========================================================
   PAGE UI
   ========================================================= */
$courses  = $conn->query("SELECT id, course_name, code FROM courses WHERE status='Active' ORDER BY course_name");
$branches = $conn->query("SELECT id, name FROM branches ORDER BY name");
?>
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Bulk Exam Student Assignment</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet"/>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet"/>

  <style>
    :root{
      --brand:#4f2db8;
      --brand-dark:#3b228d;
      --brand-soft:#efeaff;
      --accent:#ff5a1f;
      --bg:#f4f7fb;
      --text:#172033;
      --muted:#6b7280;
      --line:#e8ecf4;
      --white:#ffffff;
      --success:#16a34a;
      --danger:#dc2626;
      --shadow:0 18px 40px rgba(20, 29, 58, .08);
      --radius:18px;
    }

    *{box-sizing:border-box}

    body{
      background:
        radial-gradient(circle at top right, rgba(79,45,184,.08), transparent 22%),
        linear-gradient(180deg, #f8fbff 0%, #f1f5fb 100%);
      color:var(--text);
      font-family:system-ui,-apple-system,"Segoe UI",Roboto,Ubuntu,"Helvetica Neue",Arial,sans-serif;
    }

    .bulk-page-wrap{
      max-width:1320px;
    }

    .topbar{
      position:relative;
      padding:18px 24px;
      margin:0 0 16px 0;
      min-height:auto;
      border-radius:18px;
      background:linear-gradient(135deg,#102a68 0%, #4f2db8 100%);
      box-shadow:0 12px 28px rgba(16,42,104,.16);
      border:1px solid rgba(255,255,255,.10);
    }

    .page-title{
      font-size:1.85rem;
      font-weight:800;
      text-align:right;
      margin:0;
      color:#fff;
      letter-spacing:.2px;
    }

    .filters{
      margin:0 0 14px 0;
      padding:16px;
      background:rgba(255,255,255,.92);
      border:1px solid rgba(221,228,240,.85);
      border-radius:18px;
      box-shadow:var(--shadow);
      backdrop-filter:blur(8px);
    }

    .filters .form-label{
      font-weight:700;
      color:#24304a;
      margin-bottom:9px;
      font-size:.96rem;
    }

    .form-control,
    .form-select{
      height:50px;
      border:1px solid #dce3ef;
      border-radius:14px;
      background:#fff;
      color:#1f2937;
      font-weight:500;
      box-shadow:none !important;
      transition:border-color .18s ease, box-shadow .18s ease, transform .18s ease;
    }

    .form-control:focus,
    .form-select:focus{
      border-color:#7c5cff;
      box-shadow:0 0 0 4px rgba(124,92,255,.10) !important;
    }

    .select2-container{ width:100% !important; }

    .select2-container .select2-selection--single{
      height:50px !important;
      border:1px solid #dce3ef !important;
      border-radius:14px !important;
      display:flex !important;
      align-items:center !important;
      padding:0 12px !important;
      background:#fff !important;
    }

    .select2-container--default .select2-selection--single .select2-selection__rendered{
      line-height:48px !important;
      padding-left:0 !important;
      color:#1f2937 !important;
      font-weight:500;
    }

    .select2-container--default .select2-selection--single .select2-selection__arrow{
      height:48px !important;
    }

    .select2-dropdown{
      border:1px solid #dce3ef !important;
      border-radius:14px !important;
      overflow:hidden;
      box-shadow:0 16px 36px rgba(15,23,42,.12);
    }

    .select2-search__field{
      border-radius:10px !important;
      border:1px solid #dce3ef !important;
    }

    .actions{
      display:flex;
      gap:12px;
      justify-content:flex-end;
      align-items:flex-end;
      padding-top:30px;
    }

    .btn-purple{
      height:50px;
      min-width:150px;
      border:none;
      border-radius:14px;
      font-weight:800;
      color:#fff;
      background:linear-gradient(135deg,var(--brand) 0%, var(--brand-dark) 100%);
      box-shadow:0 14px 28px rgba(79,45,184,.24);
      transition:.18s ease;
    }

    .btn-purple:hover{
      color:#fff;
      transform:translateY(-1px);
      box-shadow:0 18px 30px rgba(79,45,184,.30);
    }

    .btn-filter{
      background:linear-gradient(135deg,#4f2db8 0%, #3b228d 100%);
    }

    .btn-insert{
      background:linear-gradient(135deg,#ff6a2b 0%, #f04d23 100%);
      box-shadow:0 14px 28px rgba(240,77,35,.24);
    }

    .btn-insert:hover{
      box-shadow:0 18px 30px rgba(240,77,35,.30);
    }

    .headcount{
      margin:0;
      padding:14px 18px;
      font-weight:800;
      font-size:1rem;
      color:#172033;
      background:#fff;
      border:1px solid var(--line);
      border-radius:18px 18px 0 0;
      box-shadow:var(--shadow);
      border-bottom:none;
    }

    .headcount #headCount{
      display:inline-flex;
      align-items:center;
      justify-content:center;
      min-width:34px;
      height:34px;
      padding:0 10px;
      margin-left:8px;
      border-radius:999px;
      background:var(--brand-soft);
      color:var(--brand-dark);
      font-weight:800;
    }

    .table-wrap{
      margin:0 0 24px 0;
      padding:0;
      background:#fff;
      border:1px solid var(--line);
      border-top:none;
      border-radius:0 0 18px 18px;
      box-shadow:var(--shadow);
      overflow:hidden;
    }

    .table{
      margin:0;
    }

    .table thead th{
      border-bottom:1px solid #e9edf5;
      color:#24304a;
      font-weight:800;
      background:linear-gradient(180deg,#fbfcff 0%, #f6f8fc 100%);
      padding:16px 16px;
      white-space:nowrap;
    }

    .table tbody td{
      border-top:1px solid #f0f3f8;
      padding:15px 16px;
      color:#1f2937;
      vertical-align:middle;
    }

    .table tbody tr:hover{
      background:#fafbff;
    }

    .cb-green{
      width:18px;
      height:18px;
      accent-color:#4f46e5;
    }

    .empty-state{
      text-align:center;
      color:var(--muted);
      padding:30px 12px !important;
    }

    .toast-area{
      position:fixed;
      right:18px;
      bottom:18px;
      z-index:9999;
      min-width:320px;
    }

    @media (max-width: 991px){
      .page-title{
        text-align:left;
        padding-left:0;
        font-size:1.55rem;
        line-height:1.2;
      }

      .actions{
        justify-content:stretch;
        padding-top:10px;
      }

      .btn-purple{
        width:100%;
        min-width:unset;
      }
    }

    @media (max-width: 767px){
      .filters{
        padding:16px;
      }

      .page-title{
        font-size:1.35rem;
      }

      .table-wrap{
        overflow-x:auto;
      }

      .table{
        min-width:760px;
      }
    }
  </style>
</head>
<body>


<main class="container py-4 bulk-page-wrap">
  <div class="topbar">
    <h1 class="page-title">Bulk Exam Student Assignment</h1>
  </div>

<div class="filters">
  <div class="row g-3 align-items-end">
    <div class="col-lg col-md-6">
      <label class="form-label">Course</label>
      <select id="course_id" class="form-select">
        <option value="">Select an Opti...</option>
        <?php while($c=$courses->fetch_assoc()): ?>
          <option value="<?= (int)$c['id'] ?>"><?= h(($c['code'] ? $c['code']." - " : "") . $c['course_name']) ?></option>
        <?php endwhile; ?>
      </select>
    </div>

    <div class="col-lg col-md-6">
      <label class="form-label">Batch Number</label>
      <select id="batch_id" class="form-select">
        <option value="">Select an Opti...</option>
      </select>
    </div>

    <div class="col-lg col-md-6">
      <label class="form-label">Exam Title</label>
      <select id="exam_id" class="form-select">
        <option value="">Select an Opti...</option>
      </select>
    </div>

    <div class="col-lg col-md-6">
      <label class="form-label">Branch</label>
      <select id="branch_id" class="form-select">
        <option value="">Select an Opti...</option>
        <?php while($b=$branches->fetch_assoc()): ?>
          <option value="<?= (int)$b['id'] ?>"><?= h($b['name']) ?></option>
        <?php endwhile; ?>
      </select>
    </div>

    <div class="col-lg col-md-6">
      <label class="form-label">Exam Date</label>
      <input id="exam_date" type="date" class="form-control" value="<?= date('Y-m-d') ?>">
    </div>

    <div class="col-lg-auto col-md-6">
      <div class="actions">
        <button id="btnFilter" class="btn btn-purple btn-filter">
          <i class="bi bi-search me-2"></i>Filter
        </button>
        <button id="btnBulkInsert" class="btn btn-purple btn-insert">
          <i class="bi bi-people-fill me-2"></i>Bulk Insert
        </button>
      </div>
    </div>
  </div>
</div>

  <div class="headcount">Selected Students <span id="headCount">0</span></div>

  <div class="table-wrap">
    <table class="table">
      <thead>
        <tr>
          <th style="width:60px;"><input id="checkAll" type="checkbox" class="cb-green"></th>
          <th>Registration Number</th>
          <th>Name</th>
          <th>NIC/Passport Number</th>
        </tr>
      </thead>
      <tbody id="studentsBody">
        <tr><td colspan="4" class="empty-state">Please select Course, Batch, and Exam Title, then click Filter.</td></tr>
      </tbody>
    </table>
  </div>
</main>

<div class="toast-area" id="toastArea"></div>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>

<script>
function toast(msg, type="success"){
  const id = "t" + Math.random().toString(16).slice(2);
  const bg = type==="success" ? "bg-success" : (type==="warning" ? "bg-warning text-dark" : "bg-danger");
  const html = `
    <div id="${id}" class="toast align-items-center text-white ${bg} border-0 mb-2" role="alert">
      <div class="d-flex">
        <div class="toast-body">${msg}</div>
        <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
      </div>
    </div>`;
  $("#toastArea").append(html);
  const el = document.getElementById(id);
  const t = new bootstrap.Toast(el, { delay: 3000 });
  t.show();
  el.addEventListener('hidden.bs.toast', () => el.remove());
}

function initSelect2(){
  $("#course_id,#batch_id,#exam_id,#branch_id").select2({
    width:"100%",
    allowClear:true,
    placeholder:"Select an Opti..."
  });
}

function loadBatches(){
  const course_id = $("#course_id").val();
  const branch_id = $("#branch_id").val() || "";

  $("#batch_id").html('<option value="">Select an Opti...</option>').trigger("change");
  if(!course_id) return;

  $.get(window.location.pathname, {action:"batches", course_id, branch_id}, function(html){
    $("#batch_id").html(html).trigger("change");
  });
}

function loadExams(){
  const course_id = $("#course_id").val();

  $("#exam_id").html('<option value="">Select an Opti...</option>').trigger("change");
  if(!course_id) return;

  $.get(window.location.pathname, {action:"exams", course_id}, function(html){
    $("#exam_id").html(html).trigger("change");
  });
}

function renderStudents(rows){
  const $body = $("#studentsBody");
  $body.empty();

  if(!rows || rows.length === 0){
    $body.append('<tr><td colspan="4" class="empty-state">No students found for the selected filters.</td></tr>');
    $("#headCount").text("0");
    return;
  }

  $("#headCount").text(rows.length);

  rows.forEach(function(r){
    $body.append(`
      <tr>
        <td><input type="checkbox" class="cb-green cbStudent" value="${r.student_id}"></td>
        <td>${r.reg_no || "-"}</td>
        <td>${r.full_name || "-"}</td>
        <td>${r.nic_passport || "-"}</td>
      </tr>
    `);
  });
}

function filterStudents(){
  const course_id = $("#course_id").val();
  const batch_id  = $("#batch_id").val();
  const exam_id   = $("#exam_id").val();
  const branch_id = $("#branch_id").val();

  if(!course_id || !batch_id || !exam_id){
    toast("Please select Course, Batch Number, and Exam Title.", "warning");
    return;
  }

  $.getJSON(window.location.pathname, {action:"students", course_id, batch_id, branch_id}, function(res){
    if(!res.ok){
      toast(res.error || "Failed", "danger");
      return;
    }
    renderStudents(res.students);
  });
}

function bulkInsert(){
  const course_id = $("#course_id").val();
  const exam_id   = $("#exam_id").val();
  const exam_date = $("#exam_date").val();

  if(!course_id || !exam_id){
    toast("Please select Course and Exam Title.", "warning");
    return;
  }

  const ids = $(".cbStudent:checked").map(function(){ return this.value; }).get();

  if(ids.length === 0){
    toast("Please select students.", "warning");
    return;
  }

  $.ajax({
    url: window.location.pathname + "?action=bulk_insert",
    method: "POST",
    dataType: "json",
    data: { course_id, exam_id, exam_date, student_ids: ids },
    success: function(res){
      if(!res.ok){
        toast(res.error || "Failed", "danger");
        return;
      }
      toast(`Created: ${res.created} | Updated: ${res.updated} | Assigned: ${res.assigned} | Skipped: ${res.skipped}`, "success");
    },
    error: function(xhr){
      toast("Server error. Check console.", "danger");
      console.log(xhr.responseText);
    }
  });
}

$(function(){
  initSelect2();

  $("#course_id").on("change", function(){
    loadBatches();
    loadExams();
  });

  $("#branch_id").on("change", function(){
    loadBatches();
  });

  $("#btnFilter").on("click", function(e){
    e.preventDefault();
    filterStudents();
  });

  $("#btnBulkInsert").on("click", function(e){
    e.preventDefault();
    bulkInsert();
  });

  $("#checkAll").on("click", function(){
    $(".cbStudent").prop("checked", this.checked);
  });
});
</script>
</body>
</html>