<?php
// /elms/student/assessments/brief.php — open/download assessment brief
// - Mirrors student index visibility (course/module/batch + bundle/global + time window)
// - Falls back to "active & open" like the list page when mapping is unknown
// - Finds brief via attachments tables OR fields on the assessment row
// - Opens URL directly; opens local files from /elms/uploads/...
declare(strict_types=1);
if (session_status() === PHP_SESSION_NONE) session_start();

$DEBUG = isset($_GET['debug']) && $_GET['debug'] === '1';
$FORCE_DOWNLOAD = isset($_GET['download']) && $_GET['download'] == '1';

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

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

/* ---------- helpers ---------- */
function esc($s){ return htmlspecialchars((string)$s, ENT_QUOTES|ENT_SUBSTITUTE,'UTF-8'); }
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 $e){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 $e){return false;}
}
function app_base_from_script(): string {
  $script = $_SERVER['SCRIPT_NAME'] ?? '/elms/student/assessments/brief.php';
  if (preg_match('~^(.*/elms)(?:/|$)~',$script,$m)) return rtrim($m[1],'/'); return '/elms';
}
function public_href(?string $p): string {
  if(!$p) return '';
  $p=str_replace('\\','/',$p);
  if (preg_match('#^https?://#i',$p)) return $p;
  $base = app_base_from_script();
  if ($p[0] === '/') {
    // already absolute – if it's under /uploads use app base
    if (stripos($p, '/uploads/') === 0) return $base.$p;
    return $p;
  }
  if (preg_match('#^(uploads/|assess|files/|docs/|content/)#i',$p)) return $base.'/'.ltrim($p,'/');
  return $base.'/uploads/'.ltrim($p,'/');
}
function student_course_ids(mysqli $db,int $sid): array {
  if($sid<=0) return [];
  $ids=[]; $run=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();
    }
  };
  if(t_exists('enrollments')&&c_exists('enrollments','course_id')) $run("SELECT DISTINCT e.course_id FROM enrollments e WHERE e.student_id=?");
  if(t_exists('enrollments')&&t_exists('batches')&&c_exists('batches','course_id')) $run("SELECT DISTINCT b.course_id FROM enrollments e JOIN batches b ON b.id=e.batch_id WHERE e.student_id=?");
  if(t_exists('lms_enrollments')&&c_exists('lms_enrollments','course_id')) $run("SELECT DISTINCT e.course_id FROM lms_enrollments e WHERE e.student_id=?");
  if(t_exists('student_selected_plans')&&c_exists('student_selected_plans','course_id')) $run("SELECT DISTINCT s.course_id FROM student_selected_plans s WHERE s.student_id=?");
  if(t_exists('student_courses')&&c_exists('student_courses','course_id')) $run("SELECT DISTINCT sc.course_id FROM student_courses sc WHERE sc.student_id=?");
  return array_keys($ids);
}
function student_batch_ids(mysqli $db,int $sid): array {
  if($sid<=0) return [];
  $ids=[]; $run=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();
    }
  };
  if(t_exists('enrollments')&&c_exists('enrollments','batch_id')) $run("SELECT DISTINCT e.batch_id FROM enrollments e WHERE e.student_id=?");
  if(t_exists('lms_enrollments')&&c_exists('lms_enrollments','batch_id')) $run("SELECT DISTINCT e.batch_id FROM lms_enrollments e WHERE e.student_id=?");
  return array_keys($ids);
}

/* ---------- input ---------- */
$student_id    = (int)($_SESSION['student_id'] ?? 0);
$assessment_id = (int)($_GET['assessment_id'] ?? 0);
if ($assessment_id<=0 || $student_id<=0) { http_response_code(403); exit('Access denied.'); }

/* ---------- detect assessment table/columns ---------- */
$ATBL=null;
foreach(['lms_assessments','assessments','assignments','course_assessments'] as $t){ if(t_exists($t)){ $ATBL=$t; break; } }
if(!$ATBL){ http_response_code(404); exit('Assessments table not found'); }

$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_ACTIVE = c_exists($ATBL,'active')?'active':(c_exists($ATBL,'is_active')?'is_active':null);
$A_OPEN   = c_exists($ATBL,'available_from')?'available_from':(c_exists($ATBL,'release_at')?'release_at':(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,'end_at')?'end_at':null));
$A_COURSE = c_exists($ATBL,'course_id')?'course_id':null;
$A_MODULE = c_exists($ATBL,'module_id')?'module_id':null;

/* mapping tables (optional) */
$MAP_COURSE=$MAP_AID=$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=$MAP_BAID=$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; }
  }
}

/* columns that might carry a brief */
$urlCols  = ['brief_url','url','link'];
$fileCols = ['brief_file','brief_path','brief_document','brief_pdf','file_path','attachment','attach_file','file','document','instructions_file','assignment_file'];
$textCols = ['brief','instructions','description','details'];

/* ---------- build a SELECT that pulls possible brief columns ---------- */
$sel="a.`$A_ID` AS id, a.`$A_TITLE` AS title";
foreach($urlCols as $c)  if(c_exists($ATBL,$c))  $sel.=", a.`$c` AS `$c`";
foreach($fileCols as $c) if(c_exists($ATBL,$c)) $sel.=", a.`$c` AS `$c`";
foreach($textCols as $c) if(c_exists($ATBL,$c)) $sel.=", a.`$c` AS `$c`";

/* ---------- strict visibility (same as list page) ---------- */
$cidList = student_course_ids($mysqli,$student_id);
$bidList = student_batch_ids($mysqli,$student_id);

$where = ["a.`$A_ID`=?"]; $types='i'; $params=[$assessment_id];
if($A_ACTIVE) $where[]="(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`<=NOW())"; if($A_CLOSE) $win[]="(a.`$A_CLOSE` IS NULL OR a.`$A_CLOSE`>=NOW())";
if($win) $where[]='('.implode(' AND ',$win).')';

$own=[];
if($A_COURSE && $cidList) $own[]="a.`$A_COURSE` IN (".implode(',',array_map('intval',$cidList)).")";
if($A_MODULE && t_exists('lms_modules') && c_exists('lms_modules','course_id') && $cidList)
  $own[]="EXISTS(SELECT 1 FROM lms_modules m WHERE m.id=a.`$A_MODULE` AND m.course_id IN (".implode(',',array_map('intval',$cidList))."))";
if($MAP_COURSE && $cidList)
  $own[]="EXISTS(SELECT 1 FROM `$MAP_COURSE` ac WHERE ac.`$MAP_AID`=a.`$A_ID` AND ac.`$MAP_CID` IN (".implode(',',array_map('intval',$cidList))."))";
if($MAP_BATCH && $bidList)
  $own[]="EXISTS(SELECT 1 FROM `$MAP_BATCH` ab WHERE ab.`$MAP_BAID`=a.`$A_ID` AND ab.`$MAP_BID` IN (".implode(',',array_map('intval',$bidList))."))";
/* bundle/global flags seen in some schemas */
$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) $own[]='('.implode(' OR ',$bundle).')';

if($own) $where[]='('.implode(' OR ',$own).')';

/* run strict first */
$sqlStrict="SELECT $sel FROM `$ATBL` a WHERE ".implode(' AND ',$where)." LIMIT 1";
$st=$mysqli->prepare($sqlStrict); $st->bind_param($types,...$params); $st->execute();
$res=$st->get_result(); $A=$res?$res->fetch_assoc():null; if($res)$res->free(); $st->close();

/* ---------- fallback (like the list page says) ---------- */
if(!$A){
  $whereFallback = ["a.`$A_ID`=?"]; $types='i'; $params=[$assessment_id];
  if($A_ACTIVE) $whereFallback[]="(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`<=NOW())"; if($A_CLOSE) $win[]="(a.`$A_CLOSE` IS NULL OR a.`$A_CLOSE`>=NOW())";
  if($win) $whereFallback[]='('.implode(' AND ',$win).')';
  $sqlFallback="SELECT $sel FROM `$ATBL` a WHERE ".implode(' AND ',$whereFallback)." LIMIT 1";
  $st=$mysqli->prepare($sqlFallback); $st->bind_param($types,...$params); $st->execute();
  $res=$st->get_result(); $A=$res?$res->fetch_assoc():null; if($res)$res->free(); $st->close();
}

/* ---------- not visible at all ---------- */
if(!$A){
  if($DEBUG){
    header('Content-Type:text/plain; charset=utf-8');
    echo "Access denied or assessment not found.\n";
    echo "cidList=".json_encode($cidList)."\n";
    echo "bidList=".json_encode($bidList)."\n";
    echo "SQL(strict): $sqlStrict\n";
  }
  http_response_code(403); exit('Access denied.');
}

/* ---------- locate the brief ---------- */
/* 1) attachments tables (most reliable) */
$open = '';
$attachTables = [
  ['lms_assessment_attachments','assessment_id',['url','file_path','path','file']],
  ['assessment_attachments','assessment_id',['url','file_path','path','file']],
  ['attachments','assessment_id',['url','file_path','path','file']],
];
foreach($attachTables as [$tbl,$aidCol,$cols]){
  if(!t_exists($tbl) || !c_exists($tbl,$aidCol)) continue;
  $pick=null; foreach($cols as $cc){ if(c_exists($tbl,$cc)){ $pick=$cc; break; } }
  if(!$pick) continue;
  $q=$mysqli->prepare("SELECT `$pick` FROM `$tbl` WHERE `$aidCol`=? ORDER BY id DESC LIMIT 1");
  $q->bind_param('i',$assessment_id); $q->execute(); $q->bind_result($val);
  if($q->fetch() && $val){ $open = (string)$val; $q->close(); break; }
  $q->close();
}

/* 2) direct fields on the assessment row */
if(!$open){
  foreach($urlCols as $c)  if(!empty($A[$c])){ $open=(string)$A[$c]; break; }
  if(!$open){
    foreach($fileCols as $c) if(!empty($A[$c])){ $open = (string)$A[$c]; break; }
  }
}

/* 3) render instructions text if no file/url */
if(!$open){
  $title = $A['title'] ?? ('Assessment #'.$assessment_id);
  $body = ''; foreach($textCols as $c) if(!empty($A[$c])){ $body=(string)$A[$c]; break; }
  ?><!doctype html>
  <meta charset="utf-8"><title><?= esc($title) ?> — Brief</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <div class="container py-4">
    <h1 class="h4 mb-3"><?= esc($title) ?> — Brief</h1>
    <?php if($body): ?>
      <div class="card"><div class="card-body"><?= $body ?></div></div>
    <?php else: ?>
      <div class="alert alert-info">No brief file or URL was attached to this assessment.</div>
    <?php endif; ?>
    <a class="btn btn-secondary mt-3" href="/elms/student/assessments/index.php">← Back</a>
  </div>
  <?php
  exit;
}

/* ---------- open the brief ---------- */
$href = public_href($open);
if (preg_match('#^https?://#i',$href)) {
  // external or absolute URL
  header('Location: '.$href, true, 302); exit;
}

/* local path under /elms/uploads/... */
$APP_ROOT = dirname(__DIR__, 2);                // .../elms
$fs = realpath($APP_ROOT.'/'.ltrim($href,'/')); // map to filesystem

if ($FORCE_DOWNLOAD && $fs && is_file($fs) && is_readable($fs)) {
  // stream with download headers
  $name = basename($fs);
  $size = filesize($fs);
  $mime = function_exists('mime_content_type') ? (mime_content_type($fs) ?: 'application/octet-stream') : 'application/octet-stream';
  header('Content-Type: application/octet-stream');
  header('Content-Length: '.$size);
  header('X-Content-Type-Options: nosniff');
  header('Content-Disposition: attachment; filename="'.rawurlencode($name).'"');
  readfile($fs); exit;
} else {
  // just redirect to web path for inline preview
  header('Location: '.$href, true, 302); exit;
}
