<?php
// /elms/student/assessments/index.php — Student assessments (UI refreshed; logic unchanged)
declare(strict_types=1);
if (session_status() === PHP_SESSION_NONE) session_start();

require_once __DIR__.'/../../includes/app.php';
require_once __DIR__.'/../../includes/db.php';

// Optional: timezone bootstrap if you have it
$tz_boot = __DIR__ . '/../../includes/time_boot.php';
if (is_file($tz_boot)) require_once $tz_boot;

/* ---------- auth ---------- */
$authStudent = __DIR__.'/../../includes/student_auth.php';
if (is_file($authStudent)) {
  require_once $authStudent;
  if (!function_exists('require_student')) {
    function require_student(): void {
      $next = $_SERVER['REQUEST_URI'] ?? '/';
      header('Location: '.app_url('/student/login.php?next='.rawurlencode($next)));
      exit;
    }
  }
  require_student();
} else {
  // fallback to generic role gate if student_auth is not present
  $auth2 = __DIR__.'/../../includes/auth.php';
  if (is_file($auth2)) {
    require_once $auth2;
    if (function_exists('require_role')) require_role(['student','super_admin','branch_admin']);
  }
}

/* ---------- helpers ---------- */
if (!function_exists('esc')) {
  function esc($s){ return htmlspecialchars((string)$s, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8'); }
}
if (!function_exists('safe_lower')) {
  function safe_lower(string $s): string {
    return function_exists('mb_strtolower') ? mb_strtolower($s, 'UTF-8') : strtolower($s);
  }
}
function t_exists(string $t): bool { global $mysqli;
  try{
    $st=$mysqli->prepare("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? LIMIT 1");
    $st->bind_param('s',$t); $st->execute();
    $res=$st->get_result(); $ok=$res?(bool)$res->fetch_row():false;
    if($res) $res->free(); $st->close(); return $ok;
  }catch(Throwable){ return false; }
}
function c_exists(string $t,string $c): bool { global $mysqli;
  try{
    $st=$mysqli->prepare("SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? AND COLUMN_NAME=? LIMIT 1");
    $st->bind_param('ss',$t,$c); $st->execute();
    $res=$st->get_result(); $ok=$res?(bool)$res->fetch_row():false;
    if($res) $res->free(); $st->close(); return $ok;
  }catch(Throwable){ return false; }
}

/* ---------- student + enrollment context ---------- */
$student_id = (int)($_SESSION['student_id'] ?? 0);
$FORCE_SHOWALL = isset($_GET['showall']) && ($_GET['showall']==='1' || $_GET['showall']==='true');

/* collect course ids from many possible schemas */
function student_course_ids(mysqli $db, int $sid): array {
  if ($sid<=0) return [];
  $ids = [];
  $grab = function(string $sql) use($db,$sid,&$ids){
    if ($st=$db->prepare($sql)) {
      $st->bind_param('i',$sid); $st->execute();
      if($res=$st->get_result()){
        while($r=$res->fetch_row()) $ids[(int)$r[0]]=1;
        $res->free();
      }
      $st->close();
    }
  };
  // 1) direct tables
  $direct = [
    'enrollments'            => 'course_id',
    'lms_enrollments'        => 'course_id',
    'student_courses'        => 'course_id',
    'student_selected_plans' => 'course_id',
  ];
  foreach ($direct as $tbl=>$col)
    if (t_exists($tbl) && c_exists($tbl,$col) && c_exists($tbl,'student_id'))
      $grab("SELECT DISTINCT `$col` FROM `$tbl` WHERE student_id=?");

  // 2) via batches
  $batchMaps = [
    'enrollments'      => 'batch_id',
    'lms_enrollments'  => 'batch_id',
    'batch_students'   => 'batch_id',
    'student_batches'  => 'batch_id',
    'students_batches' => 'batch_id',
    'batches_students' => 'batch_id',
  ];
  $batchIds = [];
  foreach ($batchMaps as $tbl=>$bcol) {
    if (t_exists($tbl) && c_exists($tbl,$bcol) && c_exists($tbl,'student_id')) {
      if ($st=$db->prepare("SELECT DISTINCT `$bcol` FROM `$tbl` WHERE student_id=?")) {
        $st->bind_param('i',$sid); $st->execute();
        if($res=$st->get_result()){
          while($r=$res->fetch_row()) $batchIds[(int)$r[0]]=1;
          $res->free();
        }
        $st->close();
      }
    }
  }
  if ($batchIds && t_exists('batches') && c_exists('batches','course_id')) {
    $list = implode(',', array_map('intval', array_keys($batchIds)));
    if ($res=$db->query("SELECT DISTINCT course_id FROM batches WHERE id IN ($list)")) {
      while($r=$res->fetch_row()) $ids[(int)$r[0]]=1;
      $res->free();
    }
  }
  return array_keys($ids);
}

$courseIds = student_course_ids($mysqli, $student_id);
$cidList   = $courseIds ? implode(',', array_map('intval',$courseIds)) : '0';

/* ---------- detect assessments table ---------- */
$ATBL=null;
foreach (['lms_assessments','assessments','assignments','course_assessments'] as $try) {
  if (t_exists($try)) { $ATBL=$try; break; }
}

$assess=[]; $usedFallback=false;
$stats=['total'=>0,'due'=>0,'overdue'=>0,'submitted'=>0];

if ($ATBL && $student_id>0) {
  $A_ID     = c_exists($ATBL,'id') ? 'id' : (c_exists($ATBL,'assessment_id') ? 'assessment_id' : 'id');
  $A_TITLE  = c_exists($ATBL,'title') ? 'title' : (c_exists($ATBL,'name') ? 'name' : $A_ID);
  $A_TYPE   = c_exists($ATBL,'type') ? 'type' : (c_exists($ATBL,'category') ? 'category' : "'assessment'");
  $A_MAX    = c_exists($ATBL,'max_score') ? 'max_score' : (c_exists($ATBL,'total_marks')?'total_marks':'NULL');
  $A_DUE    = c_exists($ATBL,'due_at') ? 'due_at' : (c_exists($ATBL,'due_date')?'due_date':(c_exists($ATBL,'due')?'due':null));
  $A_OPEN   = c_exists($ATBL,'available_from') ? 'available_from' :
              (c_exists($ATBL,'release_at')?'release_at' :
              (c_exists($ATBL,'release_date')?'release_date' :
              (c_exists($ATBL,'open_from')?'open_from' : null)));
  $A_CLOSE  = c_exists($ATBL,'available_to') ? 'available_to' :
              (c_exists($ATBL,'close_at')?'close_at' :
              (c_exists($ATBL,'close_date')?'close_date' :
              (c_exists($ATBL,'end_at')?'end_at' : null)));
  $A_ACTIVE = c_exists($ATBL,'active') ? 'active' :
              (c_exists($ATBL,'is_active')?'is_active':(c_exists($ATBL,'status')?'status':null));
  $A_COURSE = c_exists($ATBL,'course_id') ? 'course_id' : null;
  $A_MODULE = c_exists($ATBL,'module_id') ? 'module_id' : null;

  // mappings (optional)
  $MAP_COURSE=null; $MAP_AID=null; $MAP_CID=null;
  foreach (['lms_assessment_courses','assessment_courses','assessments_courses','assessment_course','assessment_to_course'] as $mt) {
    if (t_exists($mt)) {
      foreach (['assessment_id','assess_id','aid','assessment'] as $ac) {
        foreach (['course_id','cid','course'] as $cc) {
          if (c_exists($mt,$ac) && c_exists($mt,$cc)) { $MAP_COURSE=$mt; $MAP_AID=$ac; $MAP_CID=$cc; break 2; }
        }
      }
    }
  }
  $MAP_BATCH=null; $MAP_BAID=null; $MAP_BID=null;
  foreach (['lms_assessment_batches','assessment_batches','assessments_batches','assessment_to_batch'] as $mt) {
    if (t_exists($mt)) {
      foreach (['assessment_id','assess_id','aid','assessment'] as $ac) {
        foreach (['batch_id','bid','batch'] as $bc) {
          if (c_exists($mt,$ac) && c_exists($mt,$bc)) { $MAP_BATCH=$mt; $MAP_BAID=$ac; $MAP_BID=$bc; break 2; }
        }
      }
    }
  }

  /* ---------- WHERE ---------- */
  $where = [];
  if ($A_ACTIVE) $where[] = "(a.`$A_ACTIVE` IS NULL OR a.`$A_ACTIVE` IN (1,'1','Y','YES','true','TRUE','ACTIVE','Active','active'))";
  $window=[];
  if ($A_OPEN)  $window[]="(a.`$A_OPEN`  IS NULL OR a.`$A_OPEN`  <= CURRENT_TIMESTAMP())";
  if ($A_CLOSE) $window[]="(a.`$A_CLOSE` IS NULL OR a.`$A_CLOSE` >= CURRENT_TIMESTAMP())";
  if ($window) $where[]='('.implode(' AND ',$window).')';

  $owns=[];
  if ($A_COURSE && $courseIds) $owns[] = "a.`$A_COURSE` IN ($cidList)";
  if ($A_MODULE && t_exists('lms_modules') && c_exists('lms_modules','course_id') && $courseIds)
    $owns[] = "EXISTS(SELECT 1 FROM lms_modules m WHERE m.id=a.`$A_MODULE` AND m.course_id IN ($cidList))";
  if ($MAP_COURSE && $courseIds)
    $owns[] = "EXISTS(SELECT 1 FROM `$MAP_COURSE` ac WHERE ac.`$MAP_AID`=a.`$A_ID` AND ac.`$MAP_CID` IN ($cidList))";
  if ($MAP_BATCH) {
    $batchOwn=[];
    foreach (['enrollments','lms_enrollments','batch_students','student_batches','students_batches','batches_students'] as $bt) {
      if (t_exists($bt) && c_exists($bt,'student_id') && c_exists($bt,'batch_id')) {
        $batchOwn[]="EXISTS(SELECT 1 FROM `$bt` bs WHERE bs.batch_id=ab.`$MAP_BID` AND bs.student_id={$student_id})";
      }
    }
    if ($batchOwn) $owns[]="EXISTS(SELECT 1 FROM `$MAP_BATCH` ab WHERE ab.`$MAP_BAID`=a.`$A_ID` AND (".implode(' OR ',$batchOwn)."))";
  }
  $bundle=[];
  foreach (['scope','audience','assign_to','visibility','target'] as $col) if (c_exists($ATBL,$col)) $bundle[]="LOWER(a.`$col`) IN ('all','bundle','global','everyone')";
  foreach (['is_bundle','is_global','for_all'] as $col)            if (c_exists($ATBL,$col)) $bundle[]="a.`$col` IN (1,'1','Y','YES','true','TRUE')";
  if ($bundle) $owns[]='('.implode(' OR ',$bundle).')';

  if ($owns) $where[]='('.implode(' OR ',$owns).')';
  $order = $A_DUE ? "a.`$A_DUE` IS NULL, a.`$A_DUE`" : "a.`$A_ID` DESC";

  $selectCoursePieces=[];
  if ($A_COURSE) $selectCoursePieces[]="a.`$A_COURSE`";
  if ($A_MODULE && t_exists('lms_modules') && c_exists('lms_modules','course_id'))
    $selectCoursePieces[]="(SELECT m.course_id FROM lms_modules m WHERE m.id=a.`$A_MODULE` LIMIT 1)";
  if ($MAP_COURSE)
    $selectCoursePieces[]="(SELECT ac.`$MAP_CID` FROM `$MAP_COURSE` ac WHERE ac.`$MAP_AID`=a.`$A_ID` LIMIT 1)";
  $selectCourse = $selectCoursePieces ? ", COALESCE(".implode(',',$selectCoursePieces).") AS course_id" : ", NULL AS course_id";

  $sel="a.`$A_ID` AS id, a.`$A_TITLE` AS title, $A_TYPE AS type".
       ($A_DUE?   ", a.`$A_DUE`   AS due_at"   : "").
       ($A_OPEN?  ", a.`$A_OPEN`  AS open_at"  : "").
       ($A_CLOSE? ", a.`$A_CLOSE` AS close_at" : "").
       ($A_MAX?   ", a.`$A_MAX`   AS max_score": "").
       $selectCourse;

  // MAIN query (strict)
  $sqlMain = "SELECT $sel FROM `$ATBL` a ".($where?('WHERE '.implode(' AND ',$where)):'')." ORDER BY $order";
  if (!$FORCE_SHOWALL) {
    if ($rs=$mysqli->query($sqlMain)) {
      while($a=$rs->fetch_assoc()){
        $submitted=false;
        if (t_exists('lms_submissions') && c_exists('lms_submissions','assessment_id') && c_exists('lms_submissions','student_id')){
          if($q=$mysqli->prepare("SELECT 1 FROM lms_submissions WHERE assessment_id=? AND student_id=? LIMIT 1")){
            $aid=(int)$a['id']; $q->bind_param('ii',$aid,$student_id);
            $q->execute(); $q->bind_result($x); $submitted=(bool)$q->fetch(); $q->close();
          }
        }
        $a['_submitted']=$submitted;
        $stats['total']++;
        if (!empty($a['due_at'])) {
          $dueTs=strtotime((string)$a['due_at']);
          if ($dueTs) { if ($dueTs<time()) $stats['overdue']++; else $stats['due']++; }
        }
        if ($submitted) $stats['submitted']++;
        $assess[]=$a;
      }
      $rs->free();
    }
  }

  // FALLBACK: nothing found → show all active+open (limit 50)
  if ($FORCE_SHOWALL || !$assess) {
    $usedFallback=true;
    $fallbackWhere=[];
    if ($A_ACTIVE) $fallbackWhere[]="(a.`$A_ACTIVE` IS NULL OR a.`$A_ACTIVE` IN (1,'1','Y','YES','true','TRUE','ACTIVE','Active','active'))";
    $win=[];
    if ($A_OPEN)  $win[]="(a.`$A_OPEN`  IS NULL OR a.`$A_OPEN`  <= CURRENT_TIMESTAMP())";
    if ($A_CLOSE) $win[]="(a.`$A_CLOSE` IS NULL OR a.`$A_CLOSE` >= CURRENT_TIMESTAMP())";
    if ($win) $fallbackWhere[]='('.implode(' AND ',$win).')';
    $sqlFb = "SELECT $sel FROM `$ATBL` a ".($fallbackWhere?('WHERE '.implode(' AND ',$fallbackWhere)):'')." ORDER BY $order LIMIT 50";
    if ($rs=$mysqli->query($sqlFb)) {
      $assess=[]; $stats=['total'=>0,'due'=>0,'overdue'=>0,'submitted'=>0];
      while($a=$rs->fetch_assoc()){
        $submitted=false;
        if (t_exists('lms_submissions') && c_exists('lms_submissions','assessment_id') && c_exists('lms_submissions','student_id')){
          if($q=$mysqli->prepare("SELECT 1 FROM lms_submissions WHERE assessment_id=? AND student_id=? LIMIT 1")){
            $aid=(int)$a['id']; $q->bind_param('ii',$aid,$student_id);
            $q->execute(); $q->bind_result($x); $submitted=(bool)$q->fetch(); $q->close();
          }
        }
        $a['_submitted']=$submitted;
        $stats['total']++;
        if (!empty($a['due_at'])) {
          $dueTs=strtotime((string)$a['due_at']);
          if ($dueTs) { if ($dueTs<time()) $stats['overdue']++; else $stats['due']++; }
        }
        if ($submitted) $stats['submitted']++;
        $assess[]=$a;
      }
      $rs->free();
    }
  }
}

/* ---------- page ---------- */
$PAGE_TITLE  = 'Assessments';
$ACTIVE_MENU = 'ass';

/* Layout include */
$__top1 = __DIR__.'/../studentlayout_top.php';
$__top2 = __DIR__.'/../layout_top.php';
require is_file($__top1) ? $__top1 : $__top2;
?>
<style>
  /* ======= BRAND + THEME (change to your colors) ======= */
  :root{
    /* Primary brand colors */
    --accent:#0d47a1;   /* Eden primary deep blue */
    --accent-2:#1976d2; /* Eden light blue */

    /* Base/UI tokens */
    --font: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", Arial, "Helvetica Neue", sans-serif;
    --ink:#0f172a;
    --muted:#64748b;
    --border:#e6eaf3;
    --surface:#ffffff;
    --surface-2:#f8fafc;
    --shadow:0 10px 26px rgba(2,6,23,.06);

    /* Status tokens */
    --ok-bg:#eafcf0;      --ok-fg:#14532d;    --ok-br:#bbf7d0;
    --due-bg:#e1f5ff;     --due-fg:#013a63;   --due-br:#c9e8ff;
    --over-bg:#fee2e2;    --over-fg:#7f1d1d;  --over-br:#fecaca;
    --soft-bg:#eef2ff;    --soft-fg:#1e3a8a;  --soft-br:#dbe4ff;
  }

  /* stretch main content on big screens while keeping your left sidebar */
  .app-content, .page, .page-body, .container, .container-fluid { max-width: 1480px !important; }
  @media (min-width:1680px){ .app-content, .page, .page-body, .container, .container-fluid { max-width: 1600px !important; } }

  .ass-root{ font-family:var(--font); color:var(--ink); }

  /* Toolbar card */
  .ass-toolbar{
    display:grid; grid-template-columns: 1fr 320px; gap:12px; align-items:center;
    background:var(--surface); border:1px solid var(--border);
    border-radius:16px; box-shadow:var(--shadow); padding:12px 14px; margin-bottom:14px
  }
  .ass-toolbar .left{
    display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  }
  .ass-toolbar .title{ font-weight:800; font-size:1.05rem; }
  .ass-toolbar .stat{
    font-size:.85rem; border:1px solid var(--border); border-radius:999px;
    padding:4px 10px; background:var(--surface-2); white-space:nowrap
  }
  .ass-toolbar .search{ height: 38px; }

  /* Filter pills row (full width) */
  .filters{
    grid-column:1/-1; display:flex; flex-wrap:wrap; gap:8px;
    margin-top:2px;
  }
  .filters .pill{
    border:1px solid var(--border); border-radius:999px; padding:6px 12px;
    background:#fff; cursor:pointer; font-size:.9rem; transition:all .15s ease;
  }
  .filters .pill:hover{ background:#f3f6ff; border-color:#d7e4ff; }
  .filters .pill.active{ background:linear-gradient(90deg,var(--accent),var(--accent-2)); color:#fff; border-color:transparent; }

  /* List (always one column) */
  .ass-grid{ display:grid; grid-template-columns: 1fr; gap:12px; margin-top:10px; }

  .ass-card{
    display:flex; align-items:center; justify-content:space-between; gap:14px;
    background:#fff; border:1px solid var(--border); border-radius:16px;
    box-shadow:var(--shadow); padding:14px;
  }
  .ass-title{ font-weight:800; font-size:1.02rem; }

  .badge{
    display:inline-block; font-size:.78rem; padding:4px 8px; border-radius:999px;
    border:1px solid var(--border); margin-right:6px;
  }
  .badge.soft{ background:var(--soft-bg); color:var(--soft-fg); border-color:var(--soft-br); }
  .badge.due{  background:var(--due-bg);  color:var(--due-fg);  border-color:var(--due-br); }
  .badge.over{ background:var(--over-bg); color:var(--over-fg); border-color:var(--over-br); }
  .badge.ok{   background:var(--ok-bg);   color:var(--ok-fg);   border-color:var(--ok-br); }

  .ass-actions .btn{ padding:.42rem .66rem }
</style>

<div class="ass-root">
  <!-- Toolbar -->
  <div class="ass-toolbar">
    <div class="left">
      <div class="title">Assessments</div>
      <span class="stat">Total <?= (int)$stats['total'] ?></span>
      <span class="stat">Due soon <?= (int)$stats['due'] ?></span>
      <span class="stat">Overdue <?= (int)$stats['overdue'] ?></span>
      <span class="stat">Submitted <?= (int)$stats['submitted'] ?></span>
    </div>
    <input id="assSearch" class="form-control form-control-sm search" placeholder="Search title…">
    <div class="filters">
      <span class="pill active" data-filter="all">All</span>
      <span class="pill" data-filter="due">Due soon</span>
      <span class="pill" data-filter="overdue">Overdue</span>
      <span class="pill" data-filter="notsub">Not submitted</span>
      <span class="pill" data-filter="submitted">Submitted</span>
    </div>
  </div>

  <?php if ($usedFallback): ?>
    <div class="alert alert-info py-2">Showing active & open assessments (fallback view). Add <code>?showall=1</code> to force this view.</div>
  <?php endif; ?>

  <!-- List -->
  <div class="ass-grid" id="assList">
    <?php if (!$assess): ?>
      <div class="text-muted p-3">No assessments found.</div>
    <?php else: foreach($assess as $a):
      $id   = (int)$a['id'];
      $title= trim((string)$a['title']); if($title==='') $title='Assessment #'.$id;
      $due  = !empty($a['due_at']) ? date('Y-m-d H:i', strtotime((string)$a['due_at'])) : '';
      $isOver    = ($due && strtotime((string)$a['due_at'])<time());
      $isDueSoon = ($due && strtotime((string)$a['due_at'])>=time());
      $submitted = !empty($a['_submitted']);
      $max = isset($a['max_score']) && $a['max_score']!==null ? (int)$a['max_score'] : null;
      $cid = isset($a['course_id']) ? (int)$a['course_id'] : 0;

      $classes = [];
      if($submitted)   $classes[]='submitted';
      if($isOver)      $classes[]='overdue';
      if(!$submitted)  $classes[]='notsub';
      if($isDueSoon)   $classes[]='due';

      $briefUrl  = app_url('/student/assessments/brief.php?assessment_id='.$id);
      $submitUrl = app_url('/student/assessments/submit.php?assessment_id='.$id . ($cid>0 ? '&course_id='.$cid : ''));
    ?>
      <div class="ass-card" data-title="<?= esc(safe_lower($title)) ?>" data-tags="<?= esc(implode(' ',$classes)) ?>">
        <div class="d-flex align-items-center gap-3 flex-wrap">
          <div class="ass-title"><?= esc($title) ?></div>
          <div class="small">
            <?php if($max!==null): ?><span class="badge soft">Max <?= (int)$max ?></span><?php endif; ?>
            <span class="badge <?= $submitted?'ok':'soft' ?>"><?= $submitted?'Submitted':'Not submitted' ?></span>
            <?php if($due): ?><span class="badge <?= $isOver?'over':'due' ?>">Due <?= esc($due) ?></span><?php endif; ?>
          </div>
        </div>
        <div class="ass-actions d-flex gap-2">
          <a class="btn btn-sm btn-outline-secondary" href="<?= esc($briefUrl) ?>" target="_blank" rel="noopener">Brief</a>
          <a class="btn btn-sm btn-primary" href="<?= esc($submitUrl) ?>">Submit</a>
        </div>
      </div>
    <?php endforeach; endif; ?>
  </div>
</div>

<script>
  // search + filter (UI only)
  const q = document.getElementById('assSearch');
  const pills = document.querySelectorAll('.filters .pill');
  let current = 'all';
  function apply(){
    const term = (q.value||'').trim().toLowerCase();
    document.querySelectorAll('#assList .ass-card').forEach(it=>{
      const t = it.getAttribute('data-title')||'';
      const tags = it.getAttribute('data-tags')||'';
      const matchTerm = !term || t.includes(term);
      const matchTag = (current==='all') || tags.includes(current);
      it.style.display = (matchTerm && matchTag) ? '' : 'none';
    });
  }
  q.addEventListener('input', apply);
  pills.forEach(p=>p.addEventListener('click', ()=>{
    pills.forEach(x=>x.classList.remove('active'));
    p.classList.add('active');
    current = p.getAttribute('data-filter');
    apply();
  }));
</script>

<?php
$__bot1 = __DIR__.'/../studentlayout_bottom.php';
$__bot2 = __DIR__.'/../layout_bottom.php';
require is_file($__bot1) ? $__bot1 : $__bot2;
