<?php declare(strict_types=1);
/* ============================================================================
 * Assessments & Projects — Admin (Course first, dynamic Modules & Students)
 * ========================================================================== */

define('APP_ROOT', dirname(__DIR__, 2)); // .../elms

/* --- bootstrap / guards --- */
if (session_status() === PHP_SESSION_NONE) session_start();
require_once APP_ROOT . '/includes/auth.php';
require_once APP_ROOT . '/includes/db.php';
require_once APP_ROOT . '/includes/scope.php';
require_role(['super_admin','branch_admin']);

/* --- CSRF --- */
function csrf_token(): string { if (empty($_SESSION['csrf'])) $_SESSION['csrf']=bin2hex(random_bytes(16)); return $_SESSION['csrf']; }
function require_csrf(): void {
  if (!isset($_POST['csrf']) || !hash_equals($_SESSION['csrf'] ?? '', (string)$_POST['csrf'])) {
    http_response_code(403); exit('CSRF validation failed');
  }
}

/* --- helpers --- */
function esc($s){ return htmlspecialchars((string)$s, ENT_QUOTES|ENT_SUBSTITUTE,'UTF-8'); }
function base_url(): string {
  $dir = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? ''), '/'); $dir = preg_replace('#/admin/assessments$#','',$dir);
  return $dir === '' ? '/' : $dir;
}
function url_for(string $path): string { if ($path===''||$path[0]!=='/') $path='/'.$path; return rtrim(base_url(),'/').$path; }
function dt_or_null(?string $in): ?string { $in=trim((string)$in); if($in==='') return null; $in=str_replace('T',' ',$in); $ts=strtotime($in); return $ts?date('Y-m-d H:i:s',$ts):null; }
function dt_to_input(?string $db): string { return $db?str_replace(' ','T',substr($db,0,16)) : ''; }
function short_text(?string $s,int $n=90): string {
  $s=(string)($s??''); if($s==='') return ''; $len=function_exists('mb_strlen')?mb_strlen($s,'UTF-8'):strlen($s);
  return $len>$n ? ((function_exists('mb_substr')?mb_substr($s,0,$n,'UTF-8'):substr($s,0,$n)).'…') : $s;
}

/* --- schema helpers --- */
function table_exists(mysqli $db,string $t):bool{
  $t=$db->real_escape_string($t);
  $q=$db->query("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='$t' LIMIT 1");
  return (bool)($q && $q->num_rows);
}
function col_exists(mysqli $db,string $t,string $c):bool{
  $t=$db->real_escape_string($t); $c=$db->real_escape_string($c);
  $q=$db->query("SHOW COLUMNS FROM `$t` LIKE '$c'"); return (bool)($q && $q->num_rows);
}
function idx_exists(mysqli $db,string $t,string $i):bool{
  $t=$db->real_escape_string($t); $i=$db->real_escape_string($i);
  $q=$db->query("SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='$t' AND INDEX_NAME='$i' LIMIT 1");
  return (bool)($q && $q->num_rows);
}

/* --- ensure schema (safe adds) --- */
function ensure_schema(mysqli $db): void {
  if (!table_exists($db,'lms_assessments')) {
    $db->query("CREATE TABLE lms_assessments(
      id INT AUTO_INCREMENT PRIMARY KEY,
      title VARCHAR(255) NOT NULL,
      description TEXT NULL,
      type ENUM('assignment','project') NOT NULL DEFAULT 'assignment',
      course_id INT NULL,
      module_id INT NULL,
      available_from DATETIME NULL,
      available_to   DATETIME NULL,
      due_at         DATETIME NULL,
      release_at     DATETIME NULL,
      max_score INT NOT NULL DEFAULT 100,
      active TINYINT(1) NOT NULL DEFAULT 1,
      created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
  } else {
    if (!col_exists($db,'lms_assessments','description'))   $db->query("ALTER TABLE lms_assessments ADD description TEXT NULL AFTER title");
    if (!col_exists($db,'lms_assessments','type'))          $db->query("ALTER TABLE lms_assessments ADD type ENUM('assignment','project') NOT NULL DEFAULT 'assignment'");
    if (!col_exists($db,'lms_assessments','course_id'))     $db->query("ALTER TABLE lms_assessments ADD course_id INT NULL");
    if (!col_exists($db,'lms_assessments','module_id'))     $db->query("ALTER TABLE lms_assessments ADD module_id INT NULL");
    if (!col_exists($db,'lms_assessments','available_from'))$db->query("ALTER TABLE lms_assessments ADD available_from DATETIME NULL");
    if (!col_exists($db,'lms_assessments','available_to'))  $db->query("ALTER TABLE lms_assessments ADD available_to   DATETIME NULL");
    if (!col_exists($db,'lms_assessments','due_at'))        $db->query("ALTER TABLE lms_assessments ADD due_at         DATETIME NULL");
    if (!col_exists($db,'lms_assessments','release_at'))    $db->query("ALTER TABLE lms_assessments ADD release_at     DATETIME NULL");
    if (!col_exists($db,'lms_assessments','max_score'))     $db->query("ALTER TABLE lms_assessments ADD max_score      INT NOT NULL DEFAULT 100");
    if (!col_exists($db,'lms_assessments','active'))        $db->query("ALTER TABLE lms_assessments ADD active         TINYINT(1) NOT NULL DEFAULT 1");
  }
  if (!table_exists($db,'lms_assessment_batches'))  $db->query("CREATE TABLE lms_assessment_batches(assessment_id INT NOT NULL, batch_id INT NOT NULL, PRIMARY KEY(assessment_id,batch_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
  if (!table_exists($db,'lms_assessment_students')) $db->query("CREATE TABLE lms_assessment_students(assessment_id INT NOT NULL, student_id INT NOT NULL, PRIMARY KEY(assessment_id,student_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
  if (!idx_exists($db,'lms_assessments','idx_ass_course')) $db->query("CREATE INDEX idx_ass_course ON lms_assessments(course_id)");
  if (!idx_exists($db,'lms_assessments','idx_ass_active')) $db->query("CREATE INDEX idx_ass_active ON lms_assessments(active)");

  $db->query("CREATE TABLE IF NOT EXISTS lms_assessment_attachments(
    id INT AUTO_INCREMENT PRIMARY KEY,
    assessment_id INT NOT NULL,
    file_path VARCHAR(255) NOT NULL,
    uploaded_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    INDEX(assessment_id)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
}
ensure_schema($mysqli);

/* --- dynamic label helper --- */
function label_col(mysqli $db,string $table,array $candidates): string {
  $cols=[]; if ($res=$db->query("SHOW COLUMNS FROM `$table`")) while($r=$res->fetch_assoc()) $cols[]=$r['Field'];
  foreach($candidates as $c) if (in_array($c,$cols,true)) return $c; return 'id';
}

/* --- attachments helpers --- */
function save_assessment_attachment(mysqli $db, int $assessment_id, array $file): ?string {
  if (empty($file['name']) || !is_uploaded_file($file['tmp_name'])) return null;
  $dir = realpath(APP_ROOT).'/uploads/assessments'; if (!is_dir($dir)) @mkdir($dir,0775,true);
  $ext=strtolower(pathinfo($file['name'],PATHINFO_EXTENSION));
  $base=preg_replace('/[^A-Za-z0-9._-]+/','_', pathinfo($file['name'],PATHINFO_FILENAME));
  $name=date('Ymd_His')."_ass{$assessment_id}_{$base}".($ext?".$ext":''); $dest=$dir.'/'.$name;
  if(!move_uploaded_file($file['tmp_name'],$dest)) return null;
  $public='/uploads/assessments/'.$name;
  $st=$db->prepare("INSERT INTO lms_assessment_attachments(assessment_id,file_path) VALUES(?,?)"); $st->bind_param('is',$assessment_id,$public); $st->execute(); $st->close();
  return $public;
}
function get_latest_attachment(mysqli $db, int $assessment_id): ?string {
  $st=$db->prepare("SELECT file_path FROM lms_assessment_attachments WHERE assessment_id=? ORDER BY id DESC LIMIT 1");
  $st->bind_param('i',$assessment_id); $st->execute(); $st->bind_result($p); $ok=$st->fetch(); $st->close(); return $ok?$p:null;
}

/* --- data sources --- */
function courses_list(mysqli $db): array {
  $col=label_col($db,'courses',['course_name','name','title','label']);
  $rs=$db->query("SELECT id, COALESCE($col,'#') AS label FROM courses ORDER BY id DESC"); $out=[];
  while($r=$rs->fetch_assoc()) $out[(int)$r['id']]=$r['label']; return $out;
}
function course_modules_list(mysqli $db, ?int $courseId=null): array {
  if (!$db->query("SHOW TABLES LIKE 'course_modules'")->num_rows) return [];
  if ($courseId){ $st=$db->prepare("SELECT id,title FROM course_modules WHERE course_id=? ORDER BY sort_order ASC, id ASC"); $st->bind_param('i',$courseId); $st->execute(); $rs=$st->get_result(); }
  else { $rs=$db->query("SELECT id,title FROM course_modules ORDER BY sort_order ASC, id ASC"); }
  $out=[]; while($r=$rs->fetch_assoc()) $out[(int)$r['id']]=$r['title']; if(isset($st)) $st->close(); return $out;
}
function batches_list(mysqli $db, ?int $courseId=null): array {
  if (!$db->query("SHOW TABLES LIKE 'batches'")->num_rows) return [];
  $nm=label_col($db,'batches',['batch_name','name','title','label']);
  if ($courseId){ $st=$db->prepare("SELECT id,COALESCE($nm,'#') AS label FROM batches WHERE course_id=? ORDER BY id DESC"); $st->bind_param('i',$courseId); $st->execute(); $rs=$st->get_result(); }
  else { $rs=$db->query("SELECT id,COALESCE($nm,'#') AS label FROM batches ORDER BY id DESC"); }
  $out=[]; while($r=$rs->fetch_assoc()) $out[(int)$r['id']]=$r['label']; if(isset($st)) $st->close(); return $out;
}
function students_list(mysqli $db, ?int $courseId=null): array {
  if (!$db->query("SHOW TABLES LIKE 'studentss'")->num_rows) return [];
  $haveRef=$db->query("SHOW COLUMNS FROM studentss LIKE 'reference_no'")->num_rows>0;
  $haveCtr=$db->query("SHOW COLUMNS FROM studentss LIKE 'center_reg_no'")->num_rows>0;
  $sel="SELECT id, COALESCE(full_name,'#') AS nm".($haveRef?", reference_no AS ref":"").($haveCtr?", center_reg_no AS cen":"")." FROM studentss";
  if ($courseId){ $st=$db->prepare($sel." WHERE course_id=? ORDER BY id DESC"); $st->bind_param('i',$courseId); $st->execute(); $rs=$st->get_result(); }
  else { $rs=$db->query($sel." ORDER BY id DESC"); }
  $out=[]; while($r=$rs->fetch_assoc()){ $parts=[$r['nm']]; if($haveRef&&!empty($r['ref'])) $parts[]='Ref '.$r['ref']; if($haveCtr&&!empty($r['cen'])) $parts[]=$r['cen']; $out[(int)$r['id']]=implode(' • ',$parts); }
  if(isset($st)) $st->close(); return $out;
}

/* ---------- Students ↔ Batches mapping (auto-detect common table names) ---------- */
function find_batch_student_map(mysqli $db): ?array {
  $candidates=['batch_students','student_batches','batch_enrollments','batches_students','batch_student_map','enrollments'];
  foreach($candidates as $t){
    $r=$db->query("SHOW TABLES LIKE '".$db->real_escape_string($t)."'");
    if($r && $r->num_rows){
      $hasBatch=$db->query("SHOW COLUMNS FROM `$t` LIKE 'batch_id'")->num_rows>0;
      $hasStudent=$db->query("SHOW COLUMNS FROM `$t` LIKE 'student_id'")->num_rows>0;
      if($hasBatch && $hasStudent) return ['table'=>$t,'batch'=>'batch_id','student'=>'student_id'];
    }
  } return null;
}

/* --- POST ops --- */
$msg=null;
if ($_SERVER['REQUEST_METHOD']==='POST') {
  $op=$_POST['op'] ?? 'save';

  if ($op==='toggle') {
    require_csrf();
    $id=(int)($_POST['id'] ?? 0); $to=(int)($_POST['to'] ?? 0);
    $st=$mysqli->prepare("UPDATE lms_assessments SET active=? WHERE id=?"); $st->bind_param('ii',$to,$id); $st->execute(); $st->close();
    header('Location: '.url_for('/admin/assessments/index.php').'?msg='.urlencode("Assessment #$id set to ".($to?'ON':'OFF'))); exit;
  }

  if ($op==='delete') {
    require_csrf();
    $id=(int)($_POST['id'] ?? 0);
    $mysqli->begin_transaction();
    try{
      $mysqli->query("DELETE FROM lms_assessment_batches  WHERE assessment_id=$id");
      $mysqli->query("DELETE FROM lms_assessment_students WHERE assessment_id=$id");
      $mysqli->query("DELETE FROM lms_assessment_attachments WHERE assessment_id=$id");
      $mysqli->query("DELETE FROM lms_assessments        WHERE id=$id");
      $mysqli->commit(); $msg='Assessment deleted.';
    }catch(Throwable $e){ $mysqli->rollback(); $msg='Delete failed.'; }
    header('Location: '.url_for('/admin/assessments/index.php').'?msg='.urlencode($msg)); exit;
  }

  if ($op==='save') {
    require_csrf();
    $editId=(int)($_POST['edit_id'] ?? 0);
    $title=trim((string)($_POST['title'] ?? '')); if($title==='') $title='(untitled)';
    $description=trim((string)($_POST['description'] ?? ''));
    $type=(($_POST['type'] ?? 'assignment')==='project')?'project':'assignment';
    $course_id=(int)($_POST['course_id'] ?? 0);
    $module_id=(int)($_POST['module_id'] ?? 0);
    $max_score=(int)($_POST['max_score'] ?? 100);

    $available_from=dt_or_null($_POST['available_from'] ?? '');
    $available_to  =dt_or_null($_POST['available_to'] ?? '');
    $due_at        =dt_or_null($_POST['due_at'] ?? '');
    $release_at    =dt_or_null($_POST['release_at'] ?? '');

    $batch_ids   = array_values(array_unique(array_map('intval',(array)($_POST['batch_ids'] ?? []))));
    $student_ids = array_values(array_unique(array_map('intval',(array)($_POST['student_ids'] ?? []))));
    $batches_only = isset($_POST['batches_only']) ? 1 : 0;
    if ($batches_only || $batch_ids) $student_ids=[];

    if ($available_from && $available_to && strtotime($available_from) > strtotime($available_to)) {
      header('Location: '.url_for('/admin/assessments/index.php').'?msg='.urlencode('Available From must be before Available To.')); exit;
    }

    $mysqli->begin_transaction();
    try{
      if ($editId>0){
        $st=$mysqli->prepare("UPDATE lms_assessments
          SET title=?, description=?, type=?,
              course_id=NULLIF(?,0), module_id=NULLIF(?,0),
              available_from=?, available_to=?, due_at=?, release_at=?,
              max_score=? WHERE id=?");
        $st->bind_param('sssiissssii',$title,$description,$type,$course_id,$module_id,$available_from,$available_to,$due_at,$release_at,$max_score,$editId);
        $st->execute(); $st->close(); $id=$editId;
      }else{
        $st=$mysqli->prepare("INSERT INTO lms_assessments
          (title,description,type,course_id,module_id,available_from,available_to,due_at,release_at,max_score)
          VALUES (?,?,?,NULLIF(?,0),NULLIF(?,0),?,?,?,?,?)");
        $st->bind_param('sssiissssi',$title,$description,$type,$course_id,$module_id,$available_from,$available_to,$due_at,$release_at,$max_score);
        $st->execute(); $id=$st->insert_id; $st->close();
      }

      $mysqli->query("DELETE FROM lms_assessment_batches  WHERE assessment_id=$id");
      $mysqli->query("DELETE FROM lms_assessment_students WHERE assessment_id=$id");
      if ($batch_ids){ $st=$mysqli->prepare("INSERT INTO lms_assessment_batches(assessment_id,batch_id) VALUES (?,?)");
        foreach($batch_ids as $b){ $st->bind_param('ii',$id,$b); $st->execute(); } $st->close(); }
      if ($student_ids){ $st=$mysqli->prepare("INSERT INTO lms_assessment_students(assessment_id,student_id) VALUES (?,?)");
        foreach($student_ids as $s){ $st->bind_param('ii',$id,$s); $st->execute(); } $st->close(); }

      if (!empty($_FILES['brief']['name'])) save_assessment_attachment($mysqli,(int)$id,$_FILES['brief']);

      $mysqli->commit();
      header('Location: '.url_for('/admin/assessments/index.php').'?msg='.urlencode($editId>0?'Assessment updated.':'Assessment created.')); exit;
    }catch(Throwable $e){ $mysqli->rollback();
      header('Location: '.url_for('/admin/assessments/index.php').'?msg='.urlencode('Save failed.')); exit;
    }
  }
}

/* --- filters + lists --- */
$filterCourse = isset($_GET['course_id']) ? (int)$_GET['course_id'] : 0;
$courses  = courses_list($mysqli);
$batches  = batches_list($mysqli, $filterCourse ?: null);
$students = students_list($mysqli, $filterCourse ?: null);
$courseLabelCol = label_col($mysqli,'courses',['course_name','name','title','label']);

$where = $filterCourse ? " WHERE a.course_id=".$filterCourse : '';
$sql   = "SELECT a.*, COALESCE(c.$courseLabelCol,'#') AS course_label, cm.title AS module_label
          FROM lms_assessments a
          LEFT JOIN courses c         ON c.id=a.course_id
          LEFT JOIN course_modules cm ON cm.id=a.module_id
          $where ORDER BY a.id DESC LIMIT 100";
$list = ($rs=$mysqli->query($sql)) ? $rs->fetch_all(MYSQLI_ASSOC) : [];

/* --- edit prefill --- */
$editRow=null; $selB=$selS=[];
if (isset($_GET['edit'])) {
  $eid=(int)$_GET['edit'];
  $st=$mysqli->prepare("SELECT * FROM lms_assessments WHERE id=?"); $st->bind_param('i',$eid); $st->execute();
  $editRow=$st->get_result()->fetch_assoc(); $st->close();
  if ($editRow){
    $rs=$mysqli->query("SELECT batch_id FROM lms_assessment_batches WHERE assessment_id=".(int)$editRow['id']); while($r=$rs->fetch_assoc()) $selB[]=(int)$r['batch_id'];
    $rs=$mysqli->query("SELECT student_id FROM lms_assessment_students WHERE assessment_id=".(int)$editRow['id']); while($r=$rs->fetch_assoc()) $selS[]=(int)$r['student_id'];
  }
}

/* --- initial modules (course_modules) --- */
$formCourseId = (int)($editRow['course_id'] ?? $filterCourse ?? 0);
$modules = course_modules_list($mysqli, $formCourseId ?: null);
$midSel  = (int)($editRow['module_id'] ?? 0);

/* --- JS maps for dynamic Modules & Students --- */
$MODS_BY_COURSE = [];
if (table_exists($mysqli,'course_modules')) {
  $rs=$mysqli->query("SELECT id,course_id,COALESCE(title,CONCAT('Module #',id)) AS t FROM course_modules ORDER BY sort_order ASC, id ASC");
  while($r=$rs->fetch_assoc()) $MODS_BY_COURSE[(int)$r['course_id']][]=['id'=>(int)$r['id'],'t'=>$r['t']];
  if($rs) $rs->close();
}
$MODS_BY_BATCH = [];
if (table_exists($mysqli,'batch_modules') && table_exists($mysqli,'course_modules')) {
  $rs=$mysqli->query("SELECT bm.batch_id AS bid, cm.id AS id, COALESCE(cm.title,CONCAT('Module #',cm.id)) AS t
                      FROM batch_modules bm JOIN course_modules cm ON cm.id=bm.course_module_id
                      ORDER BY cm.title, cm.id");
  while($r=$rs->fetch_assoc()) $MODS_BY_BATCH[(int)$r['bid']][]=['id'=>(int)$r['id'],'t'=>$r['t']];
  if($rs) $rs->close();
}
/* Students by batch */
$STUDENTS_BY_ID    = $students; // id => label
$STUDENTS_BY_BATCH = [];
if ($map = find_batch_student_map($mysqli)) {
  $t=$map['table']; $bc=$map['batch']; $sc=$map['student'];
  $rs=$mysqli->query("SELECT `$bc` AS bid, `$sc` AS sid FROM `$t`");
  if ($rs){ while($r=$rs->fetch_assoc()){ $STUDENTS_BY_BATCH[(int)$r['bid']][]=(int)$r['sid']; } $rs->free(); }
}

$JS_MODS_BY_COURSE  = json_encode($MODS_BY_COURSE,  JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
$JS_MODS_BY_BATCH   = json_encode($MODS_BY_BATCH,   JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
$JS_STUDENTS_BY_ID  = json_encode($STUDENTS_BY_ID,  JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
$JS_STUDENTS_BY_BAT = json_encode($STUDENTS_BY_BATCH, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);

/* --- page header via shared layout --- */
$PAGE_TITLE='Assessments & Projects';
$PAGE_SUBTITLE='Create assignments, set windows, and publish to batches or students.';
$ACTIVE_MENU='assessments';
require APP_ROOT.'/includes/admin_layout_top.php';
?>

<?php if (isset($_GET['msg']) || $msg): ?>
  <div class="alert alert-info py-2"><?= esc($_GET['msg'] ?? $msg) ?></div>
<?php endif; ?>

<!-- Filters -->
<form class="row g-2 mb-3" method="get">
  <div class="col-auto">
    <select name="course_id" class="form-select form-select-sm" onchange="this.form.submit()">
      <option value="0">All Courses</option>
      <?php foreach($courses as $cid=>$cl): ?>
        <option value="<?= $cid ?>" <?= $filterCourse===$cid?'selected':'' ?>><?= esc($cl) ?></option>
      <?php endforeach; ?>
    </select>
  </div>
  <?php if ($filterCourse): ?>
    <div class="col-auto"><a class="btn btn-sm btn-outline-secondary" href="<?= url_for('/admin/assessments/index.php') ?>">Clear</a></div>
  <?php endif; ?>
</form>

<!-- Create / Edit -->
<div class="card mb-3">
  <div class="card-body">
    <form method="post" autocomplete="off" enctype="multipart/form-data">
      <input type="hidden" name="op" value="save">
      <input type="hidden" name="csrf" value="<?= esc(csrf_token()) ?>">
      <input type="hidden" name="edit_id" value="<?= isset($_GET['edit']) ? (int)$_GET['edit'] : 0 ?>">

      <div class="row g-3">
        <!-- COURSE -->
        <div class="col-md-6">
          <label class="form-label">Course</label>
          <select class="form-select" name="course_id" id="course-id"
                  onchange="location.href='<?= url_for('/admin/assessments/index.php') ?>?course_id='+this.value<?= isset($_GET['edit'])?"+'&edit=".((int)$_GET['edit'])."'" : '' ?>;">
            <option value="0">—</option>
            <?php $cid=(int)($editRow['course_id'] ?? $filterCourse);
              foreach($courses as $id=>$lab): ?>
              <option value="<?= $id ?>" <?= $cid===$id?'selected':'' ?>><?= esc($lab) ?></option>
            <?php endforeach; ?>
          </select>
          <div class="small text-muted mt-1">Lists below follow the selected course.</div>
        </div>

        <!-- MODULES -->
        <div class="col-md-6">
          <label class="form-label">Course module (optional)</label>
          <select class="form-select" name="module_id" id="module_id">
            <option value="0">—</option>
            <?php foreach($modules as $mid=>$mlab): ?>
              <option value="<?= (int)$mid ?>" <?= $midSel===$mid?'selected':'' ?>><?= esc($mlab) ?></option>
            <?php endforeach; ?>
          </select>
        </div>

        <!-- TITLE + TYPE -->
        <div class="col-md-6">
          <label class="form-label">Title</label>
          <input class="form-control" name="title" value="<?= esc($editRow['title'] ?? '') ?>">
        </div>
        <div class="col-md-6">
          <label class="form-label">Type</label>
          <?php $t=$editRow['type'] ?? 'assignment'; ?>
          <select class="form-select" name="type">
            <option value="assignment" <?= $t==='assignment'?'selected':'' ?>>Assignment</option>
            <option value="project"    <?= $t==='project'?'selected':'' ?>>Project</option>
          </select>
        </div>

        <div class="col-12">
          <label class="form-label">Description (optional)</label>
          <textarea class="form-control" name="description" id="desc" rows="3"><?= esc($editRow['description'] ?? '') ?></textarea>
          <div class="small text-muted" id="desc-count"></div>
        </div>

        <div class="col-md-6">
          <label class="form-label">Max score</label>
          <input class="form-control" type="number" name="max_score" value="<?= (int)($editRow['max_score'] ?? 100) ?>">
        </div>

        <div class="col-md-3">
          <label class="form-label">Available from</label>
          <input class="form-control" type="datetime-local" name="available_from" value="<?= esc(dt_to_input($editRow['available_from'] ?? null)) ?>">
        </div>
        <div class="col-md-3">
          <label class="form-label">Available to</label>
          <input class="form-control" type="datetime-local" name="available_to" value="<?= esc(dt_to_input($editRow['available_to'] ?? null)) ?>">
        </div>
        <div class="col-md-3">
          <label class="form-label">Due (deadline)</label>
          <input class="form-control" type="datetime-local" name="due_at" value="<?= esc(dt_to_input($editRow['due_at'] ?? null)) ?>">
        </div>
        <div class="col-md-3">
          <label class="form-label">Marks release at</label>
          <input class="form-control" type="datetime-local" name="release_at" value="<?= esc(dt_to_input($editRow['release_at'] ?? null)) ?>">
        </div>

        <!-- BATCHES (with picker) -->
        <div class="col-md-6">
          <label class="form-label">Publish to batches</label>
          <div class="d-flex gap-2 align-items-center mb-1">
            <input class="form-control form-control-sm" id="filter-batches" placeholder="Filter batches…">
            <button type="button" class="btn btn-sm btn-outline-secondary" id="btnBatchPicker">Filter</button>
            <button type="button" class="btn btn-sm btn-outline-secondary" id="btnBatchAll">Select all</button>
            <button type="button" class="btn btn-sm btn-outline-secondary" id="btnBatchNone">Clear</button>
          </div>
          <select class="form-select" id="select-batches" name="batch_ids[]" size="6" multiple>
            <?php foreach($batches as $id=>$lab): ?>
              <option value="<?= $id ?>" <?= in_array($id,$selB,true)?'selected':'' ?>><?= esc($lab) ?></option>
            <?php endforeach; ?>
          </select>
          <div class="small mt-1">
            <label class="form-check-label">
              <input type="checkbox" class="form-check-input me-1" name="batches_only" id="batches-only" <?= $selB && !$selS ? 'checked' : '' ?>>
              Publish only to the selected batches (ignore individual students)
            </label>
            <div id="batch-summary" class="mt-1"></div>
          </div>
        </div>

        <!-- STUDENTS (with picker) -->
        <div class="col-md-6">
          <label class="form-label">Publish to individual students</label>
          <div class="d-flex gap-2 align-items-center mb-1">
            <input class="form-control form-control-sm" id="filter-students" placeholder="Filter students…">
            <button type="button" class="btn btn-sm btn-outline-secondary" id="btnStudentPicker">Filter</button>
            <button type="button" class="btn btn-sm btn-outline-secondary" id="btnStuAll">Select all</button>
            <button type="button" class="btn btn-sm btn-outline-secondary" id="btnStuNone">Clear</button>
          </div>
          <select class="form-select" id="select-students" name="student_ids[]" size="6" multiple>
            <?php foreach($students as $id=>$lab): ?>
              <option value="<?= $id ?>" <?= in_array($id,$selS,true)?'selected':'' ?>><?= esc($lab) ?></option>
            <?php endforeach; ?>
          </select>
          <div class="small text-muted mt-1">If any batch is selected or “batches only” is ticked, students are ignored.</div>
          <div id="student-summary" class="mt-1"></div>
        </div>

        <!-- Attach -->
        <div class="col-12">
          <label class="form-label">Attach brief / project file (optional)</label>
          <input type="file" name="brief" class="form-control"
                 accept=".pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.zip,.rar,.7z,.txt,.jpg,.jpeg,.png,.mp4,.mov,.avi">
          <?php if (!empty($editRow['id'])):
            $___brief=get_latest_attachment($mysqli,(int)$editRow['id']);
            if($___brief): ?>
            <small class="form-text text-muted">Current: <a href="<?= esc($___brief) ?>" target="_blank"><?= esc(basename($___brief)) ?></a> (upload to replace)</small>
          <?php endif; endif; ?>
        </div>
      </div>

      <div class="mt-3 d-flex gap-2">
        <button class="btn btn-primary"><?= $editRow?'Update':'Create' ?></button>
        <?php if ($editRow): ?><a class="btn btn-outline-secondary" href="<?= url_for('/admin/assessments/index.php') ?>">Cancel edit</a><?php endif; ?>
      </div>
    </form>
  </div>
</div>

<!-- List -->
<div class="card">
  <div class="card-body">
    <div class="table-responsive">
      <table class="table table-sm align-middle">
        <thead class="table-light"><tr>
          <th style="width:28%">Title & Description</th><th>Course</th><th>Window</th><th>Due</th><th>Release</th><th>Active</th><th class="text-end">Action</th>
        </tr></thead>
        <tbody>
        <?php if(!$list): ?><tr><td colspan="7" class="text-muted">No assessments yet.</td></tr><?php endif; ?>
        <?php foreach($list as $r): $on=(int)$r['active']; ?>
          <tr>
            <td>
              <div class="fw-semibold"><?= esc($r['title']) ?></div>
              <div class="text-uppercase small text-muted mb-1"><?= esc($r['type']) ?></div>
              <?php if(!empty($r['module_label'])): ?><div class="small text-muted">Module: <?= esc($r['module_label']) ?></div><?php endif; ?>
              <?php if(!empty($r['description'])): ?><div class="small"><?= esc(short_text($r['description'],120)) ?></div><?php endif; ?>
            </td>
            <td><?= esc($r['course_label'] ?: '—') ?></td>
            <td class="small">
              <?= !empty($r['available_from']) ? '<span class="badge bg-light text-dark me-1">From: '.esc($r['available_from']).'</span>' : '<span class="badge bg-warning-subtle text-dark me-1">From: —</span>' ?>
              <?= !empty($r['available_to'])   ? '<span class="badge bg-light text-dark">To: '.esc($r['available_to']).'</span>'     : '<span class="badge bg-warning-subtle text-dark">To: —</span>' ?>
            </td>
            <td class="small">
              <?= !empty($r['due_at']) ? '<span class="badge bg-danger-subtle text-danger">Due: '.esc($r['due_at']).'</span>' : '<span class="badge bg-warning-subtle text-dark">Due: —</span>' ?>
            </td>
            <td class="small">
              <?= !empty($r['release_at']) ? '<span class="badge bg-light text-dark">Release: '.esc($r['release_at']).'</span>' : '<span class="badge bg-warning-subtle text-dark">Release: —</span>' ?>
            </td>
            <td>
              <form method="post" class="d-inline">
                <input type="hidden" name="op" value="toggle">
                <input type="hidden" name="csrf" value="<?= esc(csrf_token()) ?>">
                <input type="hidden" name="id" value="<?= (int)$r['id'] ?>">
                <input type="hidden" name="to" value="<?= $on?0:1 ?>">
                <button class="badge bg-<?= $on?'success':'secondary' ?> border-0" type="submit"><?= $on?'ON':'OFF' ?></button>
              </form>
            </td>
            <td class="text-end">
              <?php $brief=get_latest_attachment($mysqli,(int)$r['id']); if($brief): ?>
                <a class="btn btn-sm btn-outline-secondary" target="_blank" href="<?= esc($brief) ?>">Brief</a>
              <?php endif; ?>
              <a class="btn btn-sm btn-outline-secondary" href="<?= url_for('/admin/assessments/view.php').'?id='.(int)$r['id'] ?>">View</a>
              <a class="btn btn-sm btn-outline-primary" href="<?= url_for('/admin/assessments/index.php').'?edit='.(int)$r['id'].'&course_id='.(int)$r['course_id'] ?>">Edit</a>
              <form method="post" class="d-inline" onsubmit="return confirm('Delete this assessment?');">
                <input type="hidden" name="op" value="delete"><input type="hidden" name="csrf" value="<?= esc(csrf_token()) ?>"><input type="hidden" name="id" value="<?= (int)$r['id'] ?>">
                <button class="btn btn-sm btn-outline-danger" type="submit">Delete</button>
              </form>
            </td>
          </tr>
        <?php endforeach; ?>
        </tbody>
      </table>
    </div>
  </div>
</div>

<!-- Batch Picker Modal -->
<div class="modal fade" id="batchPickerModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg">
    <div class="modal-content">
      <div class="modal-header"><h5 class="modal-title">Select Batches</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
      <div class="modal-body">
        <input class="form-control mb-2" id="batch-modal-search" placeholder="Search batches…">
        <div id="batch-modal-list" class="list-group"></div>
      </div>
      <div class="modal-footer">
        <button type="button" id="batch-modal-all" class="btn btn-outline-secondary">Select all</button>
        <button type="button" id="batch-modal-none" class="btn btn-outline-secondary">Clear</button>
        <button type="button" class="btn btn-primary" data-bs-dismiss="modal">Apply</button>
      </div>
    </div>
  </div>
</div>

<!-- Student Picker Modal -->
<div class="modal fade" id="studentPickerModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg">
    <div class="modal-content">
      <div class="modal-header"><h5 class="modal-title">Select Students</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
      <div class="modal-body">
        <input class="form-control mb-2" id="student-modal-search" placeholder="Search students…">
        <div id="student-modal-list" class="list-group"></div>
      </div>
      <div class="modal-footer">
        <button type="button" id="student-modal-all" class="btn btn-outline-secondary">Select all</button>
        <button type="button" id="student-modal-none" class="btn btn-outline-secondary">Clear</button>
        <button type="button" class="btn btn-primary" data-bs-dismiss="modal">Apply</button>
      </div>
    </div>
  </div>
</div>

<script>
  // description counter
  (function(){const el=document.getElementById('desc'), out=document.getElementById('desc-count'); if(!el||!out) return;
    const upd=()=>out.textContent=el.value.length+' characters'; el.addEventListener('input',upd); upd();})();

  // simple inline filters
  function attachFilter(inp, sel){
    const box=document.getElementById(inp), s=document.getElementById(sel); if(!box||!s) return;
    const opts=[...s.options]; box.addEventListener('input',()=>{const q=box.value.trim().toLowerCase(); s.innerHTML='';
      opts.forEach(o=>{ if(!q || o.text.toLowerCase().includes(q)) s.appendChild(o); });});
  }
  attachFilter('filter-batches','select-batches');
  attachFilter('filter-students','select-students');

  // summaries & disable logic
  function summarize(selectId, outId, label){
    const sel=document.getElementById(selectId), out=document.getElementById(outId); if(!sel||!out) return;
    const chosen=[...sel.selectedOptions]; const chips=chosen.slice(0,6).map(o=>`<span class="badge bg-light text-dark me-1">${o.text}</span>`).join('');
    out.innerHTML = chosen.length ? `${chosen.length} ${label} selected · ${chips}` : '<span class="text-muted">None selected</span>';
  }
  function updateSummaries(){
    summarize('select-batches','batch-summary','batch(es)');
    summarize('select-students','student-summary','student(s)');
    const anyBatch = document.getElementById('select-batches')?.selectedOptions.length>0;
    const cb=document.getElementById('batches-only'); if (cb) cb.checked = cb.checked || anyBatch;
    const s=document.getElementById('select-students'); if (s && cb?.checked) s.setAttribute('disabled','disabled'); else s?.removeAttribute('disabled');
  }

  // ====== MAPS from PHP ======
  const MODS_BY_COURSE = <?= $JS_MODS_BY_COURSE ?? '{}' ?>;
  const MODS_BY_BATCH  = <?= $JS_MODS_BY_BATCH  ?? '{}' ?>;
  const STUDENTS_BY_ID = <?= $JS_STUDENTS_BY_ID ?? '{}' ?>;
  const STUDENTS_BY_BATCH = <?= $JS_STUDENTS_BY_BAT ?? '{}' ?>;

  // DOM refs
  const courseSel = document.getElementById('course-id');
  const batchSel  = document.getElementById('select-batches');
  const moduleSel = document.getElementById('module_id');
  const studentSel= document.getElementById('select-students');
  const onlyBatches=document.getElementById('batches-only');
  const PRESELECT = <?= (int)$midSel ?>;

  // helpers
  const selectedValues = (sel)=> Array.from(sel?.selectedOptions||[]).map(o=>o.value);
  const setSelected = (sel,vals)=>{ const S=new Set(vals.map(String)); Array.from(sel.options).forEach(o=>o.selected=S.has(o.value)); sel.dispatchEvent(new Event('change')); };
  const selectAll = (sel)=>{ Array.from(sel.options).forEach(o=>o.selected=true); sel.dispatchEvent(new Event('change')); };
  const clearAll  = (sel)=>{ Array.from(sel.options).forEach(o=>o.selected=false); sel.dispatchEvent(new Event('change')); };

  document.getElementById('btnBatchAll')?.addEventListener('click',()=>selectAll(batchSel));
  document.getElementById('btnBatchNone')?.addEventListener('click',()=>clearAll(batchSel));
  document.getElementById('btnStuAll')?.addEventListener('click',()=>selectAll(studentSel));
  document.getElementById('btnStuNone')?.addEventListener('click',()=>clearAll(studentSel));

  // modules builder
  function buildModuleOptions(items){
    const seen=new Set(), out=[]; (items||[]).forEach(x=>{ if(x && !seen.has(x.id)){ seen.add(x.id); out.push(x);} });
    out.sort((a,b)=>(a.t||'').localeCompare(b.t||'')); moduleSel.innerHTML='<option value="0">—</option>'+out.map(x=>`<option value="${x.id}">${x.t}</option>`).join('');
    if (PRESELECT && out.some(x=>x.id===PRESELECT)) moduleSel.value=String(PRESELECT);
  }
  function refillModules(){
    const cid=parseInt(courseSel?.value||'0',10); const bids=selectedValues(batchSel).map(v=>parseInt(v,10)).filter(Boolean);
    if (bids.length){ const all=[]; bids.forEach(b=> (MODS_BY_BATCH[String(b)]||[]).forEach(x=>all.push(x))); buildModuleOptions(all); return; }
    buildModuleOptions(MODS_BY_COURSE[String(cid)]||[]);
  }

  // students builder (union of selected batches)
  function refillStudentsByBatches(){
    if (!studentSel) return;
    const bids=selectedValues(batchSel).map(v=>parseInt(v,10)).filter(Boolean);
    if (bids.length && Object.keys(STUDENTS_BY_BATCH).length){
      const union=new Set(); bids.forEach(b=> (STUDENTS_BY_BATCH[String(b)]||[]).forEach(sid=>union.add(String(sid))));
      const keep=new Set(Array.from(studentSel.selectedOptions).map(o=>o.value).filter(v=>union.has(v)));
      const opts=[]; union.forEach(sid=>{ const label=STUDENTS_BY_ID[String(sid)]||('Student #'+sid); opts.push(new Option(label,String(sid),false,keep.has(String(sid)))); });
      opts.sort((a,b)=>a.text.localeCompare(b.text)); studentSel.innerHTML=''; opts.forEach(o=>studentSel.appendChild(o));
    } else {
      const prevSel=new Set(Array.from(studentSel.selectedOptions).map(o=>o.value));
      const opts=Object.entries(STUDENTS_BY_ID).map(([sid,label])=>new Option(label,String(sid),false,prevSel.has(String(sid))));
      opts.sort((a,b)=>a.text.localeCompare(b.text)); studentSel.innerHTML=''; opts.forEach(o=>studentSel.appendChild(o));
    }
    if (onlyBatches?.checked) studentSel.setAttribute('disabled','disabled'); else studentSel.removeAttribute('disabled');
    updateSummaries();
  }

  // wire changes
  batchSel?.addEventListener('change',()=>{ refillModules(); refillStudentsByBatches(); });
  courseSel?.addEventListener('change',refillModules);
  onlyBatches?.addEventListener('change',refillStudentsByBatches);

  // initial
  refillModules(); refillStudentsByBatches(); updateSummaries();

  // ======= Picker Modals (Bootstrap) =======
  const batchModal = new bootstrap.Modal(document.getElementById('batchPickerModal'));
  const studentModal=new bootstrap.Modal(document.getElementById('studentPickerModal'));

  document.getElementById('btnBatchPicker')?.addEventListener('click',()=>{
    const box=document.getElementById('batch-modal-list'); const q=document.getElementById('filter-batches').value.trim().toLowerCase();
    box.innerHTML=''; Array.from(batchSel.options).forEach(o=>{ if(!q||o.text.toLowerCase().includes(q)){ const id='bm_'+o.value;
      const row=document.createElement('label'); row.className='list-group-item d-flex align-items-center gap-2';
      row.innerHTML=`<input type="checkbox" class="form-check-input" ${o.selected?'checked':''} data-val="${o.value}" id="${id}"><span>${o.text}</span>`;
      box.appendChild(row); }});
    document.getElementById('batch-modal-search').value=q; batchModal.show();
  });
  document.getElementById('batch-modal-search')?.addEventListener('input',e=>{
    const q=e.target.value.trim().toLowerCase();
    Array.from(document.querySelectorAll('#batch-modal-list .list-group-item')).forEach(li=>{
      li.style.display = (!q||li.textContent.toLowerCase().includes(q)) ? '' : 'none';
    });
  });
  document.getElementById('batch-modal-all')?.addEventListener('click',()=>{ document.querySelectorAll('#batch-modal-list input[type=checkbox]').forEach(cb=>cb.checked=true); });
  document.getElementById('batch-modal-none')?.addEventListener('click',()=>{ document.querySelectorAll('#batch-modal-list input[type=checkbox]').forEach(cb=>cb.checked=false); });
  document.getElementById('batchPickerModal')?.addEventListener('hidden.bs.modal',()=>{
    const values=Array.from(document.querySelectorAll('#batch-modal-list input[type=checkbox]')).filter(cb=>cb.checked).map(cb=>cb.getAttribute('data-val'));
    setSelected(batchSel, values); refillModules(); refillStudentsByBatches();
  });

  document.getElementById('btnStudentPicker')?.addEventListener('click',()=>{
    const box=document.getElementById('student-modal-list'); box.innerHTML='';
    Array.from(studentSel.options).forEach(o=>{
      const id='sm_'+o.value; const row=document.createElement('label'); row.className='list-group-item d-flex align-items-center gap-2';
      row.innerHTML=`<input type="checkbox" class="form-check-input" ${o.selected?'checked':''} data-val="${o.value}" id="${id}"><span>${o.text}</span>`;
      box.appendChild(row);
    });
    document.getElementById('student-modal-search').value=''; studentModal.show();
  });
  document.getElementById('student-modal-search')?.addEventListener('input',e=>{
    const q=e.target.value.trim().toLowerCase();
    Array.from(document.querySelectorAll('#student-modal-list .list-group-item')).forEach(li=>{
      li.style.display = (!q||li.textContent.toLowerCase().includes(q)) ? '' : 'none';
    });
  });
  document.getElementById('student-modal-all')?.addEventListener('click',()=>{ document.querySelectorAll('#student-modal-list input[type=checkbox]').forEach(cb=>cb.checked=true); });
  document.getElementById('student-modal-none')?.addEventListener('click',()=>{ document.querySelectorAll('#student-modal-list input[type=checkbox]').forEach(cb=>cb.checked=false); });
  document.getElementById('studentPickerModal')?.addEventListener('hidden.bs.modal',()=>{
    const values=Array.from(document.querySelectorAll('#student-modal-list input[type=checkbox]')).filter(cb=>cb.checked).map(cb=>cb.getAttribute('data-val'));
    setSelected(studentSel, values); updateSummaries();
  });
</script>

<?php require APP_ROOT.'/includes/admin_layout_bottom.php'; ?>
