<?php
// student/quiz.php — Standalone quiz runner (with embed mode).
// UX: Prev / Next / Submit, radio auto-advance, checkbox needs Continue/Submit.
// AJAX updates; degrades gracefully without JS.

declare(strict_types=1);
if (session_status() === PHP_SESSION_NONE) session_start();

require_once __DIR__.'/../includes/app.php';
require_once __DIR__.'/../includes/db.php';
if (is_file(__DIR__.'/../includes/helpers.php')) require_once __DIR__.'/../includes/helpers.php';

header('Content-Type: text/html; charset=utf-8');

/* ---------- helpers ---------- */
if (!function_exists('esc')) { function esc($s){ return htmlspecialchars((string)$s, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8'); } }
if (!function_exists('str_contains')) { function str_contains($h,$n){ return $n==='' || strpos((string)$h,(string)$n)!==false; } }

function ensure_quiz_schema_if_any(){ if(function_exists('ensure_quiz_schema')){ global $mysqli; ensure_quiz_schema($mysqli); } }
function load_quiz(int $id){ global $mysqli; $q=$mysqli->prepare("SELECT * FROM lms_quizzes WHERE id=?"); $q->bind_param('i',$id); $q->execute(); $r=$q->get_result()->fetch_assoc(); $q->close(); return $r?:[]; }
function load_q_and_opts(int $quiz_id): array {
  global $mysqli; $Q=[]; $O=[];
  $q=$mysqli->prepare("SELECT * FROM lms_quiz_questions WHERE quiz_id=? ORDER BY sort_order,id");
  $q->bind_param('i',$quiz_id); $q->execute(); $rs=$q->get_result(); while($x=$rs->fetch_assoc()) $Q[]=$x; $q->close();
  if ($Q){
    $ids=implode(',',array_map('intval',array_column($Q,'id')));
    $res=$mysqli->query("SELECT * FROM lms_quiz_options WHERE question_id IN ($ids) ORDER BY question_id, sort_order, id");
    while($o=$res->fetch_assoc()) $O[(int)$o['question_id']][]=$o;
  }
  return [$Q,$O];
}

/* ---------- inputs ---------- */
$quiz_id = (int)($_GET['quiz_id'] ?? 0);
$EMBED   = isset($_GET['embed']) && (string)$_GET['embed'] === '1';
if ($quiz_id <= 0){ echo '<div class="p-4 text-danger">quiz_id is required.</div>'; exit; }

/* ---------- load ---------- */
ensure_quiz_schema_if_any();
$QUIZ = load_quiz($quiz_id);
if (!$QUIZ){ echo '<div class="p-4 text-danger">Quiz not found.</div>'; exit; }
[$QUEST,$OPTS] = load_q_and_opts($quiz_id);
if (!$QUEST){ echo '<div class="p-4 text-warning">No questions configured for this quiz.</div>'; exit; }

/* ---------- randomization (stable per session) ---------- */
$rand = !empty($QUIZ['randomized']);
if ($rand){
  if (empty($_SESSION['standalone_quiz_order'][$quiz_id]['q'])) {
    $_SESSION['standalone_quiz_order'][$quiz_id]['q'] = array_map(fn($r)=>(int)$r['id'], $QUEST);
    shuffle($_SESSION['standalone_quiz_order'][$quiz_id]['q']);
  }
  $qOrder = $_SESSION['standalone_quiz_order'][$quiz_id]['q'];
  usort($QUEST, fn($a,$b)=> array_search((int)$a['id'],$qOrder) <=> array_search((int)$b['id'],$qOrder));

  if (empty($_SESSION['standalone_quiz_order'][$quiz_id]['o'])) {
    $_SESSION['standalone_quiz_order'][$quiz_id]['o'] = [];
    foreach ($OPTS as $qid=>$opts){
      $ids = array_map(fn($o)=>(int)$o['id'],$opts);
      shuffle($ids);
      $_SESSION['standalone_quiz_order'][$quiz_id]['o'][(int)$qid] = $ids;
    }
  }
}

/* ---------- session state ---------- */
$S =& $_SESSION['standalone_quiz'][$quiz_id];   // ['idx'=>0,'answers'=>[qid=>[oid,...]]]
if (!is_array($S)) $S = ['idx'=>0,'answers'=>[]];
$total = count($QUEST);

/* ---------- AJAX detection ---------- */
$AJAX = ($_SERVER['REQUEST_METHOD']==='POST') && (
  isset($_POST['ajax']) ||
  (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower((string)$_SERVER['HTTP_X_REQUESTED_WITH'])==='xmlhttprequest')
);

/* ---------- handle step/submit ---------- */
if ($_SERVER['REQUEST_METHOD']==='POST'){
  $act = (string)($_POST['action'] ?? '');
  $idx = max(0, min((int)($S['idx'] ?? 0), $total-1));
  $qid = (int)$QUEST[$idx]['id'];

  // save picks (if any)
  $pickedArr = [];
  if (isset($_POST['answer']) && is_array($_POST['answer'])){
    foreach ($_POST['answer'] as $v) { $pickedArr[] = (int)$v; }
    $pickedArr = array_values(array_unique(array_filter($pickedArr, fn($x)=>$x>0)));
  }
  if ($pickedArr) $S['answers'][$qid] = $pickedArr;

  if ($act==='prev'){
    $S['idx'] = max(0, $idx-1);

  } elseif ($act==='next'){
    $S['idx'] = min($total-1, $idx+1);

  } elseif ($act==='submit'){
    $score=0; $max=0;
    foreach ($QUEST as $qrow){
      $max += (int)($qrow['points'] ?? 1);
      $qid2    = (int)$qrow['id'];
      $chosen  = array_map('intval', $S['answers'][$qid2] ?? []);
      sort($chosen);
      $correct = [];
      foreach (($OPTS[$qid2] ?? []) as $op){ if (!empty($op['is_correct'])) $correct[] = (int)$op['id']; }
      sort($correct);
      if ($correct && $chosen === $correct) $score += (int)($qrow['points'] ?? 1);
    }
    unset($_SESSION['standalone_quiz'][$quiz_id], $_SESSION['standalone_quiz_order'][$quiz_id]);

    ob_start();
    echo '<div class="p-3">';
    echo '<div class="h5 mb-2">'.esc($QUIZ['title'] ?? ('Quiz #'.$quiz_id)).' — Result</div>';
    echo '<div class="alert alert-info">Score: <strong>'.(int)$score.'</strong> / '.(int)$max.'</div>';
    echo '<a class="btn btn-secondary" href="quiz.php?quiz_id='.(int)$quiz_id.($EMBED?'&embed=1':'').'">Retake</a>';
    echo '</div>';
    $inner = ob_get_clean();
    if ($AJAX){ echo $inner; exit; }
    echo '<div id="quiz-box">'.$inner.'</div>'; exit;
  }
}

/* ---------- render current question ---------- */
$idx = max(0, min((int)($S['idx'] ?? 0), $total-1));
$q   = $QUEST[$idx];
$qid = (int)$q['id'];
$opts = $OPTS[$qid] ?? [];
if ($rand && !empty($_SESSION['standalone_quiz_order'][$quiz_id]['o'][$qid])) {
  $order = $_SESSION['standalone_quiz_order'][$quiz_id]['o'][$qid];
  usort($opts, fn($a,$b)=> array_search((int)$a['id'],$order) <=> array_search((int)$b['id'],$order));
}
$selected = array_map('intval', $S['answers'][$qid] ?? []);
$correctCount = 0; foreach ($opts as $op) if (!empty($op['is_correct'])) $correctCount++;
$multi  = $correctCount > 1;
$isLast = ($idx >= $total-1);
$isFirst= ($idx === 0);
$pct    = (int)floor(($idx)/max(1,$total)*100);
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title><?php echo esc($QUIZ['title'] ?? ('Quiz #'.$quiz_id)); ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
  :root{--border:#e7ecf5;--muted:#6b7280}
  body{
    font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,"Helvetica Neue",Arial,sans-serif;
    <?php if ($EMBED): ?>margin:0;background:transparent;<?php endif; ?>
  }
  .wrap{
    max-width:920px;margin:0 auto;padding:18px;
    <?php if ($EMBED): ?>max-width:100%;padding:12px;<?php endif; ?>
  }
  .h5{font-weight:700;font-size:18px}
  .q-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}
  .q-prog{height:6px;background:#eef2ff;border-radius:999px;overflow:hidden;box-shadow:inset 0 1px 2px rgba(2,6,23,.05)}
  .q-prog>span{display:block;height:100%;background:linear-gradient(90deg,#2563eb,#0ea5e9)}
  .opt{display:flex;gap:10px;align-items:flex-start;padding:12px;border:1px solid var(--border);border-radius:12px;background:#fff;
       cursor:pointer;transition:border-color .15s, box-shadow .15s;margin-bottom:8px}
  .opt:hover{border-color:#cfe0ff;box-shadow:0 4px 12px rgba(37,99,235,.08)}
  .opt input{margin-top:4px}
  .opt.active{border-color:#2563eb; box-shadow:0 0 0 3px rgba(37,99,235,.12)}
  .q-footer{position:sticky;bottom:0;background:#fff;padding-top:8px}
  .q-cta{display:flex;justify-content:space-between;gap:8px;padding:8px;border-top:1px solid var(--border)}
  .q-cta .right{display:flex;gap:8px}
  .btn{display:inline-block;padding:.5rem .75rem;border-radius:.5rem;border:1px solid #d0d7e2;background:#fff;cursor:pointer}
  .btn-primary{background:#2563eb;border-color:#2563eb;color:#fff}
  .btn-success{background:#16a34a;border-color:#16a34a;color:#fff}
  .btn-outline-secondary{background:#fff;border-color:#c9d2e3;color:#334155}
  .btn:disabled{opacity:.5;cursor:not-allowed}
  .alert{padding:.75rem 1rem;border-radius:.5rem;border:1px solid #cbd5e1;background:#f8fafc}
  .alert-info{border-color:#93c5fd;background:#eff6ff}
  .small{font-size:12px;color:var(--muted)}
</style>
</head>
<body>
<div class="wrap">
  <?php if (!$EMBED): ?>
    <div class="h5" style="margin:0 0 10px 0;"><?php echo esc($QUIZ['title'] ?? ('Quiz #'.$quiz_id)); ?></div>
  <?php endif; ?>

  <?php
  // inner (works with and without JS)
  ob_start();
  echo '<div id="quiz-box">';
  echo '<form id="quiz-form" method="post" action="quiz.php?quiz_id='.(int)$quiz_id.($EMBED?'&embed=1':'').'" target="_self" data-last="'.($isLast?'1':'0').'" data-multi="'.($multi?'1':'0').'" data-first="'.($isFirst?'1':'0').'">';
  echo '<div class="q-head"><div class="small">Question '.($idx+1).' of '.$total.'</div><div style="min-width:160px"></div></div>';
  echo '<div class="q-prog"><span style="width:'.$pct.'%"></span></div>';

  echo '<div class="mt-3 mb-2" style="font-weight:600;margin-top:12px;margin-bottom:6px">Q'.($idx+1).'. '.esc($q['question_text']).' <span class="small">('.(int)($q['points'] ?? 1).' pt)</span></div>';
  echo '<div class="small" style="margin-bottom:8px">'.($multi ? 'Select all that apply.' : 'Select the best answer.').'</div>';

  if ($opts){
    foreach($opts as $op){
      $oid=(int)$op['id'];
      $checked = in_array($oid, $selected, true);
      $type = $multi ? 'checkbox' : 'radio';
      echo '<label class="opt'.($checked?' active':'').'" data-oid="'.$oid.'">';
      echo   '<input type="'.$type.'" name="answer[]" value="'.$oid.'" '.($checked?'checked':'').'>';
      echo   '<span>'.esc($op['option_text']).'</span>';
      echo '</label>';
    }
  } else {
    echo '<div class="small">No options.</div>';
  }

  echo '<div class="q-footer"><div class="q-cta" id="qCta">';
    echo '<div class="left">';
      if (!$isFirst){
        echo '<button type="button" class="btn btn-outline-secondary js-act" data-act="prev">← Previous</button>';
      } else {
        echo '<button type="button" class="btn btn-outline-secondary" disabled>← Previous</button>';
      }
    echo '</div>';
    echo '<div class="right">';
      if ($isLast){
        echo '<button type="button" class="btn btn-success js-act" id="btnSubmit" data-act="submit" '.($multi?'disabled':'').'>Submit</button>';
      } else {
        echo '<button type="button" class="btn btn-primary js-act" id="btnNext" data-act="next" '.($multi?'disabled':'').'>Next →</button>';
      }
    echo '</div>';
  echo '</div></div>';

  echo '</form></div>';
  $inner = ob_get_clean();

  if ($AJAX){ echo $inner; exit; }

  echo $inner;
  ?>
</div>

<script>
(function initQuiz(){
  function replaceBox(oldBox, html){
    var tmp = document.createElement('div');
    tmp.innerHTML = html;
    var next = tmp.querySelector('#quiz-box') || tmp.firstElementChild;
    if (next) oldBox.replaceWith(next); else oldBox.innerHTML = html;
  }
  function wire(){
    var box  = document.getElementById('quiz-box');
    if (!box) return;
    var form = box.querySelector('#quiz-form');
    if (!form) return;

    var isMulti = form.dataset.multi === '1';
    var isLast  = form.dataset.last === '1';

    function anyChecked(){
      var boxes = form.querySelectorAll('input[name="answer[]"]');
      for (var i=0;i<boxes.length;i++){ if (boxes[i].checked) return true; }
      return false;
    }
    function markActive(){
      var opts = box.querySelectorAll('.opt');
      for (var i=0;i<opts.length;i++){
        var inp = opts[i].querySelector('input');
        opts[i].classList.toggle('active', !!inp && inp.checked);
      }
    }
    function updateButtons(){
      var on = anyChecked();
      var nextBtn   = box.querySelector('#btnNext');
      var submitBtn = box.querySelector('#btnSubmit');
      if (nextBtn)   nextBtn.disabled   = !on;
      if (submitBtn) submitBtn.disabled = !on;
    }
    function send(act){
      var fd = new FormData(form);
      fd.set('ajax','1');
      if (act) fd.set('action', act);
      fetch(form.action, { method:'POST', body:fd, headers:{'X-Requested-With':'XMLHttpRequest'} })
        .then(function(r){ return r.text(); })
        .then(function(html){ replaceBox(box, html); wire(); })
        .catch(console.error);
    }

    // Auto-advance for radio
    form.addEventListener('change', function(e){
      var t = e.target;
      if (!t || t.name !== 'answer[]') return;
      markActive();
      updateButtons();
      if (!isMulti){
        send(isLast ? 'submit' : 'next');
      }
    });

    // Buttons
    box.querySelectorAll('.js-act').forEach(function(btn){
      btn.addEventListener('click', function(e){
        e.preventDefault();
        var act = btn.getAttribute('data-act') || '';
        var need = (act==='next' || act==='submit') && isMulti;
        if (need && !anyChecked()) return;
        send(act);
      });
    });

    // init
    markActive();
    updateButtons();
  }
  wire();
})();
</script>
</body>
</html>
