<?php
// /elms/student/quiz.php
// ESOFT-style student quiz player: instructions, timer, sidebar navigation, prev/next, review & finish.
declare(strict_types=1);

if (session_status() === PHP_SESSION_NONE) session_start();
require_once __DIR__ . '/../includes/db.php';
if (is_file(__DIR__ . '/../includes/student_auth.php')) require_once __DIR__ . '/../includes/student_auth.php';
if (is_file(__DIR__ . '/../includes/helpers.php')) require_once __DIR__ . '/../includes/helpers.php';

$mysqli = $mysqli ?? ($conn ?? null);
if (!$mysqli instanceof mysqli) { http_response_code(500); exit('DB connection missing'); }
$mysqli->set_charset('utf8mb4');

if (!function_exists('esc')) {
    function esc($s): string { return htmlspecialchars((string)$s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
}
function sq_table_exists(string $table): bool { global $mysqli; $st=$mysqli->prepare("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? LIMIT 1"); $st->bind_param('s',$table); $st->execute(); $ok=(bool)$st->get_result()->fetch_row(); $st->close(); return $ok; }
function sq_col_exists(string $table,string $col): bool { global $mysqli; $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',$table,$col); $st->execute(); $ok=(bool)$st->get_result()->fetch_row(); $st->close(); return $ok; }

function sq_ensure_attempt_table(): void {
    global $mysqli;

    $mysqli->query("CREATE TABLE IF NOT EXISTS `lms_quiz_attempts` (
        `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
        `quiz_id` INT UNSIGNED NOT NULL,
        `student_id` INT UNSIGNED NULL,
        `score` INT NOT NULL DEFAULT 0,
        `max_score` INT NOT NULL DEFAULT 0,
        `percentage` DECIMAL(6,2) NOT NULL DEFAULT 0,
        `answers_json` LONGTEXT NULL,
        `started_at` DATETIME NULL,
        `submitted_at` DATETIME NULL,
        PRIMARY KEY (`id`),
        KEY `idx_quiz_student` (`quiz_id`,`student_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $cols = [
        'quiz_id'      => "INT UNSIGNED NOT NULL DEFAULT 0",
        'student_id'   => "INT UNSIGNED NULL",
        'score'        => "INT NOT NULL DEFAULT 0",
        'max_score'    => "INT NOT NULL DEFAULT 0",
        'percentage'   => "DECIMAL(6,2) NOT NULL DEFAULT 0",
        'answers_json' => "LONGTEXT NULL",
        'started_at'   => "DATETIME NULL",
        'submitted_at' => "DATETIME NULL",
    ];

    foreach ($cols as $col => $def) {
        if (!sq_col_exists('lms_quiz_attempts', $col)) {
            $mysqli->query("ALTER TABLE `lms_quiz_attempts` ADD COLUMN `$col` $def");
        }
    }
}
function sq_student_id(): int {
    foreach (['student_id','elms_student_id','user_id','id'] as $k) if (!empty($_SESSION[$k])) return (int)$_SESSION[$k];
    return 0;
}
function sq_load_quiz(int $quiz_id): array { global $mysqli; $st=$mysqli->prepare("SELECT * FROM lms_quizzes WHERE id=? AND active=1 LIMIT 1"); $st->bind_param('i',$quiz_id); $st->execute(); $r=$st->get_result()->fetch_assoc(); $st->close(); return $r ?: []; }
function sq_load_questions(int $quiz_id): array {
    global $mysqli;
    $Q=[]; $O=[];
    $st=$mysqli->prepare("SELECT * FROM lms_quiz_questions WHERE quiz_id=? ORDER BY sort_order,id");
    $st->bind_param('i',$quiz_id); $st->execute(); $rs=$st->get_result(); while($q=$rs->fetch_assoc()) $Q[]=$q; $st->close();
    if ($Q) {
        $ids=implode(',',array_map('intval',array_column($Q,'id')));
        $rs=$mysqli->query("SELECT * FROM lms_quiz_options WHERE question_id IN ($ids) ORDER BY question_id,sort_order,id");
        while($o=$rs->fetch_assoc()) $O[(int)$o['question_id']][]=$o;
    }
    return [$Q,$O];
}
function sq_save_attempt(array $quiz, array $questions, array $opts, array $answers, int $startedAt): array {
    global $mysqli;
    $score=0; $max=0;
    foreach($questions as $q){
        $qid=(int)$q['id']; $pts=(int)($q['points']??1); $max += $pts;
        $chosen=array_map('intval',$answers[$qid]??[]); sort($chosen);
        $correct=[]; foreach($opts[$qid]??[] as $op) if(!empty($op['is_correct'])) $correct[]=(int)$op['id']; sort($correct);
        if ($correct && $chosen === $correct) $score += $pts;
    }
    $pct = $max > 0 ? round(($score/$max)*100,2) : 0;
    $studentId=sq_student_id(); $json=json_encode($answers, JSON_UNESCAPED_UNICODE);
    sq_ensure_attempt_table();
    $started = date('Y-m-d H:i:s',$startedAt ?: time()); $submitted=date('Y-m-d H:i:s'); $quizId=(int)$quiz['id'];
    $st=$mysqli->prepare("INSERT INTO lms_quiz_attempts(quiz_id,student_id,score,max_score,percentage,answers_json,started_at,submitted_at) VALUES (?,?,?,?,?,?,?,?)");
    $st->bind_param('iiiiisss',$quizId,$studentId,$score,$max,$pct,$json,$started,$submitted); $st->execute(); $attemptId=(int)$st->insert_id; $st->close();
    return ['attempt_id'=>$attemptId,'score'=>$score,'max'=>$max,'pct'=>$pct];
}

$quiz_id=(int)($_GET['quiz_id'] ?? 0);
if($quiz_id<=0){ echo 'quiz_id required'; exit; }
$QUIZ=sq_load_quiz($quiz_id);
if(!$QUIZ){ echo 'Quiz not found or inactive.'; exit; }
[$QUEST,$OPTS]=sq_load_questions($quiz_id);
if(!$QUEST){ echo 'No questions configured.'; exit; }

/* apply max_questions/randomize once per session */
$key='student_quiz_'.$quiz_id;
if (empty($_SESSION[$key]) || ($_GET['restart'] ?? '') === '1') {
    $ids=array_map(fn($q)=>(int)$q['id'],$QUEST);
    if(!empty($QUIZ['randomized'])) shuffle($ids);
    $maxQ=(int)($QUIZ['max_questions']??0);
    if($maxQ>0 && $maxQ<count($ids)) $ids=array_slice($ids,0,$maxQ);
    $_SESSION[$key]=['started'=>false,'started_at'=>time(),'qids'=>$ids,'answers'=>[],'done'=>false,'result'=>null];
}
$S =& $_SESSION[$key];
$qMap=[]; foreach($QUEST as $q) $qMap[(int)$q['id']]=$q;
$QUEST=array_values(array_filter(array_map(fn($id)=>$qMap[$id]??null,$S['qids'])));
$total=count($QUEST);

if($_SERVER['REQUEST_METHOD']==='POST'){
    $action=$_POST['action']??'';
    if($action==='start'){
        $S['started']=true; $S['started_at']=time();
        header('Location: quiz.php?quiz_id='.$quiz_id); exit;
    }
    if($action==='save_answer'){
        $qid=(int)($_POST['qid']??0); $ans=$_POST['answer']??[]; if(!is_array($ans)) $ans=[];
        $S['answers'][$qid]=array_values(array_unique(array_map('intval',$ans)));
        header('Content-Type: application/json'); echo json_encode(['ok'=>true]); exit;
    }
    if($action==='submit'){
        $S['done']=true; $S['result']=sq_save_attempt($QUIZ,$QUEST,$OPTS,$S['answers']??[],$S['started_at']??time());
        header('Location: quiz.php?quiz_id='.$quiz_id.'&result=1'); exit;
    }
}

if(!empty($S['done'])){
    $r=$S['result'] ?? ['score'=>0,'max'=>0,'pct'=>0];
    ?>
    <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Quiz Result</title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"></head><body class="bg-light d-flex align-items-center justify-content-center" style="min-height:100vh;">
    <div class="container py-5"><div class="card shadow-sm mx-auto" style="max-width:560px"><div class="card-body text-center p-5"><h3 class="mb-2"><?= esc($QUIZ['title']) ?></h3><div class="display-5 fw-bold text-primary"><?= (int)$r['score'] ?> / <?= (int)$r['max'] ?></div><p class="text-muted">Percentage: <?= esc($r['pct']) ?>%</p><a class="btn btn-primary" href="quiz.php?quiz_id=<?= (int)$quiz_id ?>&restart=1">Retake Quiz</a></div></div></div></body></html>
    <?php exit;
}

if(empty($S['started'])){
    ?>
<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title><?= esc($QUIZ['title']) ?></title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"><style>body{background:#fff;font-family:Arial,sans-serif}.start-wrap{min-height:100vh;display:flex;align-items:center;justify-content:center}.logo-box{font-size:46px;font-weight:900;color:#174ea6}.card{width:500px;max-width:94vw;box-shadow:0 4px 18px rgba(0,0,0,.12);border:0}.btn-main{background:#3498db;color:#fff;font-weight:700}.btn-main:hover{background:#2383c4;color:#fff}</style></head><body>
<div class="start-wrap"><div class="text-center">
<div class="logo-box">
    <img src="/elms/assets/119.jpg" alt="EDEN CAMPUS" style="max-height:90px;">
</div>
<h1 class="h2 fw-bold text-secondary mb-4">Online Examination</h1>
<div class="card text-start"><div class="card-body p-4">
<h6 class="fw-bold text-secondary">Instructions</h6>
<form method="post"><input type="hidden" name="action" value="start"><label class="form-check mb-3"><input class="form-check-input" type="checkbox" required> I have read the exam instructions</label><button class="btn btn-main w-100">Begin Examination</button></form></div></div><div class="text-muted small mt-3">© <?= date('Y') ?> Powered by EDEN CAMPUS</div></div></div>
</body></html>
<?php exit; }

$timeLimit=(int)($QUIZ['time_limit_sec']??0);
$remaining=$timeLimit>0 ? max(0, ($S['started_at']+$timeLimit)-time()) : 0;
if($timeLimit>0 && $remaining<=0){ $S['done']=true; $S['result']=sq_save_attempt($QUIZ,$QUEST,$OPTS,$S['answers']??[],$S['started_at']??time()); header('Location: quiz.php?quiz_id='.$quiz_id.'&result=1'); exit; }

$courseLabel='';
if(sq_table_exists('courses') && !empty($QUIZ['course_id'])){ $col=sq_col_exists('courses','course_name')?'course_name':(sq_col_exists('courses','name')?'name':'id'); $cid=(int)$QUIZ['course_id']; $st=$mysqli->prepare("SELECT `$col` AS label FROM courses WHERE id=? LIMIT 1"); $st->bind_param('i',$cid); $st->execute(); if($row=$st->get_result()->fetch_assoc()) $courseLabel=(string)$row['label']; $st->close(); }
$refNo = $_SESSION['center_reg_no'] ?? $_SESSION['student_ref'] ?? $_SESSION['student_id'] ?? '—';
?>
<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title><?= esc($QUIZ['title']) ?></title><style>
*{box-sizing:border-box}body{margin:0;background:#fff;font-family:Arial,sans-serif;color:#111827}.top-logo{height:54px;display:flex;align-items:center;justify-content:center;border-bottom:1px solid #ddd;box-shadow:0 1px 6px rgba(0,0,0,.1);font-weight:800}.top-logo span{color:#174ea6;margin-right:14px;font-size:28px}.meta{height:58px;display:flex;align-items:center;justify-content:center;gap:28px;border-bottom:1px solid #e5e7eb;box-shadow:0 2px 8px rgba(0,0,0,.08);color:#94a3b8}.meta b{color:#334155}.side{position:fixed;top:112px;left:0;bottom:48px;width:52px;background:#f8fafc;border-right:1px solid #e5e7eb}.qnav{height:52px;display:flex;align-items:center;justify-content:center;border-bottom:1px solid #e5e7eb;cursor:pointer}.qnav.active{background:#fff;font-weight:800;border-left:4px solid #2563eb}.qnav.done{color:#16a34a}.exam{margin-left:52px;padding:150px 80px 100px}.question{max-width:900px;margin:0 auto}.qtext{font-size:21px;margin-bottom:44px}.opt{display:block;margin:20px 0;color:#64748b;font-size:18px;cursor:pointer}.opt input{margin-right:14px;transform:scale(1.1)}.bottom{position:fixed;left:52px;right:0;bottom:0;height:48px;background:#f8fafc;border-top:1px solid #e5e7eb;display:flex;justify-content:space-between}.btn{border:0;padding:0 26px;font-weight:800;font-size:16px;cursor:pointer}.btn-muted{background:#dbe3ea;color:#374151}.btn-primary{background:#2f8fd3;color:white}.btn-submit{background:#2f8fd3;color:white;margin-right:210px}.hidden{display:none}@media(max-width:900px){.meta{gap:10px;font-size:12px}.exam{padding:80px 20px 90px}.qtext{font-size:18px}.btn-submit{margin-right:0}}
</style></head><body>
<div class="top-logo">
    <img src="/elms/assets/119.jpg" alt="EDEN CAMPUS" style="height:34px;margin-right:10px;">
    <strong>EDEN CAMPUS</strong>
</div>
<div class="meta"><div>Attempt Type: <b>Online</b></div><div>Question Count: <b><?= (int)$total ?></b></div><div>Time: <b id="timer"><?= $timeLimit>0 ? '' : 'No limit' ?></b></div><div>Reference Number: <b><?= esc($refNo) ?></b></div><div>Course: <b><?= esc($courseLabel ?: ($QUIZ['title'] ?? 'Quiz')) ?></b></div></div>
<div class="side" id="sideNav"><?php foreach($QUEST as $i=>$q): $qid=(int)$q['id']; ?><div class="qnav <?= $i===0?'active':'' ?> <?= !empty($S['answers'][$qid])?'done':'' ?>" data-i="<?= $i ?>"><?= $i+1 ?></div><?php endforeach; ?></div>
<form method="post" id="submitForm"><input type="hidden" name="action" value="submit"></form>
<div class="exam">
<?php foreach($QUEST as $i=>$q): $qid=(int)$q['id']; $selected=array_map('intval',$S['answers'][$qid]??[]); $opts=$OPTS[$qid]??[]; ?>
<section class="question <?= $i===0?'':'hidden' ?>" data-i="<?= $i ?>" data-qid="<?= $qid ?>">
  <div class="qtext"><span style="color:#c4cad4;margin-right:12px"><?= $i+1 ?></span><?= esc($q['question_text']) ?></div>
  <?php foreach($opts as $op): $oid=(int)$op['id']; ?>
  <label class="opt"><input type="radio" name="ans_<?= $qid ?>" value="<?= $oid ?>" <?= in_array($oid,$selected,true)?'checked':'' ?>><?= esc($op['option_text']) ?></label>
  <?php endforeach; ?>
</section>
<?php endforeach; ?>
</div>
<div class="bottom"><div><button type="button" class="btn btn-muted" id="prevBtn">← Prev</button><button type="button" class="btn btn-muted" id="nextBtn">Next →</button></div><button type="button" class="btn btn-submit" id="finishBtn">Review and Finish</button></div>
<script>
const total=<?= (int)$total ?>; let cur=0; const quizId=<?= (int)$quiz_id ?>; let remaining=<?= (int)$remaining ?>; const hasTimer=<?= $timeLimit>0?'true':'false' ?>;
const qs=[...document.querySelectorAll('.question')], nav=[...document.querySelectorAll('.qnav')];
function show(i){cur=Math.max(0,Math.min(total-1,i));qs.forEach((q,k)=>q.classList.toggle('hidden',k!==cur));nav.forEach((n,k)=>n.classList.toggle('active',k===cur));}
function save(qid,val){const fd=new FormData();fd.append('action','save_answer');fd.append('qid',qid);fd.append('answer[]',val);fetch('quiz.php?quiz_id='+quizId,{method:'POST',body:fd}).then(()=>{const n=nav.find(x=>+x.dataset.i===cur); if(n)n.classList.add('done');});}
document.addEventListener('change',e=>{if(e.target.matches('.opt input')){const sec=e.target.closest('.question');save(sec.dataset.qid,e.target.value);}});
nav.forEach(n=>n.onclick=()=>show(+n.dataset.i));document.getElementById('prevBtn').onclick=()=>show(cur-1);document.getElementById('nextBtn').onclick=()=>show(cur+1);document.getElementById('finishBtn').onclick=()=>{if(confirm('Submit your answers now?'))document.getElementById('submitForm').submit();};
function fmt(s){const h=Math.floor(s/3600),m=Math.floor((s%3600)/60),x=s%60;return String(h).padStart(2,'0')+' hours '+String(m).padStart(2,'0')+' minutes '+String(x).padStart(2,'0')+' seconds remaining';}
if(hasTimer){const t=document.getElementById('timer');setInterval(()=>{remaining--;t.textContent=fmt(Math.max(0,remaining));if(remaining<=0)document.getElementById('submitForm').submit();},1000);t.textContent=fmt(remaining);}show(0);
</script>
</body></html>
