<?php
require_once __DIR__ . '/header.php';
require_login();

$user       = current_user();
$isSuper    = is_super_admin();
$facilityId = $user['facility_id'];

function get_bands(PDO $pdo, int $formId): array {
    $s = $pdo->prepare('SELECT * FROM grade_bands WHERE form_id = ? ORDER BY sort_order');
    $s->execute([$formId]);
    return $s->fetchAll();
}
function pick_grade(array $bands, float $percent): string {
    foreach ($bands as $b) {
        if ($percent >= $b['min_percent'] && $percent <= $b['max_percent']) return $b['label'];
    }
    return 'Uncategorised';
}

// ---------------- Available forms (with facility scoping) ----------------
$params = [];
$sql = 'SELECT * FROM forms WHERE deleted_at IS NULL';
if (!$isSuper && $facilityId) {
    $sql .= ' AND (facility_id IS NULL OR facility_id = ?)';
    $params[] = $facilityId;
}
$sql .= ' ORDER BY name';
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$forms = $stmt->fetchAll();

$lockedFormId = v_int($_GET['form_id'] ?? 0, 0);
$lockedForm   = null;
if ($lockedFormId > 0) {
    $s = $pdo->prepare('SELECT * FROM forms WHERE id = ? AND deleted_at IS NULL');
    $s->execute([$lockedFormId]);
    $lockedForm = $s->fetch();
    if (!$lockedForm) $lockedFormId = 0;
}

$candidate    = null;
$form         = null;
$items        = [];
$result       = false;
$lastAttempt  = null;     // for "Undo" within 10 minutes
$err          = '';
$timerData    = null;
$draftPayload = null;

// ---------------- STEP 1: scan barcode + open station ----------------
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['load_for_grading'])) {
    csrf_require();

    $barcode = v_clean_string($_POST['barcode'] ?? '', 50);
    $formId  = $lockedFormId ?: v_int($_POST['form_id'] ?? 0, 1);

    if ($barcode === '' || $formId <= 0) {
        $err = 'Barcode and station are required.';
    } elseif (!v_barcode($barcode)) {
        $err = 'Invalid barcode format.';
    } else {
        $s = $pdo->prepare('
            SELECT c.*, f.name AS facility_name
            FROM candidates c JOIN facilities f ON c.facility_id = f.id
            WHERE c.barcode = ? AND c.deleted_at IS NULL');
        $s->execute([$barcode]);
        $candidate = $s->fetch();

        if (!$candidate) {
            $err = 'Candidate not found.';
        } elseif (!$isSuper && $facilityId && (int)$candidate['facility_id'] !== (int)$facilityId) {
            $err = 'Access denied for this facility.';
            $candidate = null;
        } else {
            $s = $pdo->prepare('SELECT * FROM forms WHERE id = ? AND deleted_at IS NULL');
            $s->execute([$formId]);
            $form = $s->fetch();

            if (!$form) {
                $err = 'Form not found.';
                $candidate = null;
            } else {
                // Per-form auto-duration (admin override via ?duration=N still works)
                $durationOverride = isset($_GET['duration']) ? v_int($_GET['duration'], 0, 60, -1) : -1;
                $durationMinutes  = $durationOverride >= 0 ? $durationOverride : (int)($form['default_duration_minutes'] ?? 8);

                $stationName = $form['name'];
                $startTime   = date('Y-m-d H:i:s');

                $q = $pdo->prepare("SELECT id FROM osce_sessions WHERE candidate_id = ? AND station = ?");
                $q->execute([$candidate['id'], $stationName]);
                $existing = $q->fetch();

                if ($existing) {
                    $pdo->prepare("
                        UPDATE osce_sessions
                        SET status            = 'checked_in',
                            examiner_id       = ?,
                            duration_minutes  = ?,
                            start_time        = ?,
                            grading_started_at= NULL,
                            submitted_at      = NULL,
                            last_action       = 'Candidate checked in'
                        WHERE id = ?
                    ")->execute([$user['id'], $durationMinutes, $startTime, $existing['id']]);
                } else {
                    $pdo->prepare("
                        INSERT INTO osce_sessions
                        (candidate_id, station, examiner_id, status, start_time, duration_minutes, last_action)
                        VALUES (?, ?, ?, 'checked_in', ?, ?, 'Candidate checked in')
                    ")->execute([$candidate['id'], $stationName, $user['id'], $startTime, $durationMinutes]);
                }

                audit_log($pdo, 'station_check_in', [
                    'candidate_id' => (int)$candidate['id'],
                    'form_id'      => (int)$formId,
                    'duration_min' => $durationMinutes,
                ]);

                if ($durationMinutes > 0) {
                    $startEpoch = strtotime($startTime);
                    $timerData = [
                        'end_ms'        => ($startEpoch + ($durationMinutes * 60)) * 1000,
                        'server_now_ms' => time() * 1000,
                        'duration_min'  => $durationMinutes,
                    ];
                }

                $s = $pdo->prepare('SELECT * FROM form_items WHERE form_id = ? ORDER BY sort_order');
                $s->execute([$formId]);
                $items = $s->fetchAll();

                $d = $pdo->prepare('SELECT payload FROM grade_drafts WHERE examiner_id = ? AND candidate_id = ? AND form_id = ?');
                $d->execute([$user['id'], $candidate['id'], $formId]);
                $drow = $d->fetch();
                if ($drow) {
                    $draftPayload = json_decode($drow['payload'], true) ?: null;
                }
            }
        }
    }
}

// ---------------- STEP 2: save attempt ----------------
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_attempt'])) {
    csrf_require();

    $candidateId   = v_int($_POST['candidate_id'] ?? 0, 1);
    $formId        = v_int($_POST['form_id']      ?? 0, 1);
    $stationName   = v_clean_string($_POST['station_name'] ?? '', 100);
    $globalComment = v_clean_string($_POST['global_comment'] ?? '', 2000);

    $cs = $pdo->prepare('
        SELECT c.*, f.name AS facility_name
        FROM candidates c JOIN facilities f ON c.facility_id = f.id
        WHERE c.id = ? AND c.deleted_at IS NULL');
    $cs->execute([$candidateId]);
    $candidate = $cs->fetch();

    $fs = $pdo->prepare('SELECT * FROM forms WHERE id = ? AND deleted_at IS NULL');
    $fs->execute([$formId]);
    $form = $fs->fetch();

    if (!$candidate || !$form) {
        $err = 'Invalid submission.';
    } elseif (!$isSuper && $facilityId && (int)$candidate['facility_id'] !== (int)$facilityId) {
        $err = 'Access denied.';
    } else {
        $is = $pdo->prepare("SELECT * FROM form_items WHERE form_id = ? ORDER BY sort_order");
        $is->execute([$formId]);
        $items = $is->fetchAll();

        $scores   = $_POST['score']        ?? [];
        $comments = $_POST['item_comment'] ?? [];

        $total = 0; $maxTotal = 0;
        foreach ($items as $it) {
            $max = (int)$it['max_score'];
            $maxTotal += $max;
            $val = v_int($scores[$it['id']] ?? 0, 0, $max, 0);
            $total += $val;
        }
        $percent = $maxTotal > 0 ? round(($total / $maxTotal) * 100, 2) : 0;
        $grade   = pick_grade(get_bands($pdo, $formId), $percent);

        try {
            $pdo->beginTransaction();
            $pdo->prepare("
                INSERT INTO attempts
                    (candidate_id, form_id, examiner_id, station_name,
                     total_score, max_score, percentage, final_grade, global_comment)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
            ")->execute([$candidateId, $formId, $user['id'], $stationName, $total, $maxTotal, $percent, $grade, $globalComment]);

            $attemptId = (int)$pdo->lastInsertId();

            $ins = $pdo->prepare("INSERT INTO attempt_items (attempt_id, form_item_id, score, comment) VALUES (?, ?, ?, ?)");
            foreach ($items as $it) {
                $max = (int)$it['max_score'];
                $val = v_int($scores[$it['id']] ?? 0, 0, $max, 0);
                $cmt = v_clean_string($comments[$it['id']] ?? '', 1000);
                $ins->execute([$attemptId, $it['id'], $val, $cmt]);
            }

            $pdo->prepare("
                UPDATE osce_sessions
                SET status='submitted', submitted_at=NOW(), last_action='Form submitted'
                WHERE candidate_id = ? AND station = ?
            ")->execute([$candidateId, $stationName]);

            $pdo->prepare("DELETE FROM grade_drafts WHERE examiner_id = ? AND candidate_id = ? AND form_id = ?")
                ->execute([$user['id'], $candidateId, $formId]);

            $pdo->commit();

            audit_log($pdo, 'grade_save', [
                'attempt_id'   => $attemptId,
                'candidate_id' => $candidateId,
                'form_id'      => $formId,
                'total'        => $total,
                'percentage'   => $percent,
                'grade'        => $grade,
            ]);

            $result      = true;
            $lastAttempt = [
                'id'           => $attemptId,
                'percent'      => $percent,
                'grade'        => $grade,
                'total'        => $total,
                'max'          => $maxTotal,
                'candidate_id' => $candidateId,
                'form_id'      => $formId,
                'station'      => $stationName,
                'created_at'   => date('Y-m-d H:i:s'),
            ];
        } catch (Throwable $e) {
            $pdo->rollBack();
            $err = 'Could not save attempt; please try again.';
            error_log('grade_save: ' . $e->getMessage());
        }
    }
}

// Surface previous submission if just landed back here after submit (for inline undo)
if ($result && $lastAttempt) {
    $_SESSION['osce_last_attempt'] = $lastAttempt;
}
?>

<h2>Grade Candidate</h2>

<?php if ($err): ?><div class="alert alert-danger"><?php echo h($err); ?></div><?php endif; ?>

<!-- Centralised round banner (visible whenever a round is active; overrides per-session timer) -->
<div id="round-banner" class="timer-box" style="display:none; background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%); color:#f1f5f9;">
    <div style="font-size:13px; opacity:.7; text-transform:uppercase; letter-spacing:.05em;" id="round-banner-label">Round</div>
    <div id="round-banner-time" style="font-size:48px; font-weight:800;">--:--</div>
    <div style="font-size:12px; opacity:.7;">Synchronised with the central exam clock</div>
</div>

<?php if ($timerData): ?>
<div id="osce-timer-box" class="timer-box">
    ⏱ Time Remaining: <span id="osce-timer">--:--</span>
</div>
<?php endif; ?>

<?php if ($candidate && $form && !$result): ?>
    <!-- ===== CANDIDATE IDENTITY CARD ===== -->
    <div style="background:linear-gradient(135deg,#1e293b 0%,#334155 100%); color:#fff; padding:18px 22px; border-radius:10px; margin-bottom:18px; box-shadow:var(--shadow-lg);">
        <div style="display:flex; gap:18px; align-items:center; flex-wrap:wrap;">
            <div style="width:64px; height:64px; border-radius:50%; background:#475569; display:flex; align-items:center; justify-content:center; font-size:28px; font-weight:700;">
                <?php echo strtoupper(h(substr($candidate['name'], 0, 1))); ?>
            </div>
            <div style="flex:1; min-width:200px;">
                <div style="font-size:13px; opacity:.7; text-transform:uppercase; letter-spacing:.05em;">Candidate</div>
                <div style="font-size:22px; font-weight:700; line-height:1.2;"><?php echo h($candidate['name']); ?></div>
                <div style="opacity:.85; margin-top:2px;">
                    <strong><?php echo h($candidate['candidate_number']); ?></strong>
                    · Barcode: <code style="background:rgba(255,255,255,.1); padding:2px 6px; border-radius:4px;"><?php echo h($candidate['barcode']); ?></code>
                    · <?php echo h($candidate['facility_name']); ?>
                </div>
            </div>
            <div style="text-align:right; min-width:160px;">
                <div style="font-size:13px; opacity:.7; text-transform:uppercase; letter-spacing:.05em;">Station</div>
                <div style="font-size:18px; font-weight:600;"><?php echo h($form['name']); ?></div>
                <?php if (($form['default_duration_minutes'] ?? 0) > 0): ?>
                    <div style="opacity:.85; font-size:13px;"><?php echo (int)$form['default_duration_minutes']; ?>-minute station</div>
                <?php endif; ?>
            </div>
        </div>
    </div>
<?php endif; ?>

<!-- ===== Step 1: scan ===== -->
<?php if (!$result && !$candidate): ?>
<form method="post" class="mb-2">
    <?php echo csrf_field(); ?>
    <input type="hidden" name="load_for_grading" value="1">
    <div class="form-row">
        <div class="field">
            <label>Scan / Type Barcode</label>
            <input type="text" name="barcode" autofocus required autocomplete="off" placeholder="Scan with USB reader or type C000001">
        </div>
        <?php if (!$lockedFormId): ?>
        <div class="field">
            <label>Station (Form)</label>
            <select name="form_id" required>
                <option value="">-- choose --</option>
                <?php foreach ($forms as $f): ?>
                    <option value="<?php echo (int)$f['id']; ?>" data-duration="<?php echo (int)($f['default_duration_minutes'] ?? 8); ?>">
                        <?php echo h($f['name']); ?>
                        (<?php echo (int)($f['default_duration_minutes'] ?? 8); ?> min)
                    </option>
                <?php endforeach; ?>
            </select>
            <small class="muted">Duration is auto-loaded from the form's configured default.</small>
        </div>
        <?php else: ?>
            <input type="hidden" name="form_id" value="<?php echo (int)$lockedFormId; ?>">
            <div class="field">
                <label>Station</label>
                <input type="text" value="<?php echo h($lockedForm['name']); ?> (<?php echo (int)($lockedForm['default_duration_minutes'] ?? 8); ?> min)" disabled>
            </div>
        <?php endif; ?>
    </div>
    <button type="submit" class="btn btn-primary btn-lg">Load Candidate</button>
</form>
<?php endif; ?>

<?php if ($candidate && $form && !$result): ?>
    <?php if ($draftPayload): ?>
        <div class="alert alert-warning">
            A previous draft was found and restored. You can continue from where you left off.
        </div>
    <?php endif; ?>

    <form method="post" id="grade-form" data-candidate="<?php echo (int)$candidate['id']; ?>" data-form="<?php echo (int)$form['id']; ?>">
        <?php echo csrf_field(); ?>
        <input type="hidden" name="save_attempt" value="1">
        <input type="hidden" name="candidate_id" value="<?php echo (int)$candidate['id']; ?>">
        <input type="hidden" name="form_id" value="<?php echo (int)$form['id']; ?>">
        <input type="hidden" name="station_name" value="<?php echo h($form['name']); ?>">

        <p><span class="autosave-status" id="autosave-status">Drafts auto-save every 4s.</span></p>

        <div class="table-wrap">
        <table class="data grade-table">
            <thead><tr><th>#</th><th>Item</th><th>Max</th><th>Score</th><th>Comment</th></tr></thead>
            <tbody>
            <?php foreach ($items as $i => $it):
                $draftScore   = $draftPayload['score'][$it['id']]        ?? '';
                $draftComment = $draftPayload['item_comment'][$it['id']] ?? '';
            ?>
                <tr>
                    <td data-label="#"><?php echo $i + 1; ?></td>
                    <td data-label="Item"><?php echo nl2br(h($it['label'])); ?></td>
                    <td data-label="Max" class="num"><?php echo (int)$it['max_score']; ?></td>
                    <td data-label="Score">
                        <input class="score-input" type="number" inputmode="numeric"
                               name="score[<?php echo (int)$it['id']; ?>]"
                               min="0" max="<?php echo (int)$it['max_score']; ?>"
                               value="<?php echo h($draftScore); ?>" required
                               style="max-width:90px;">
                    </td>
                    <td data-label="Comment">
                        <?php if ($it['has_comment']): ?>
                            <input type="text" name="item_comment[<?php echo (int)$it['id']; ?>]" value="<?php echo h($draftComment); ?>">
                        <?php else: ?>
                            <span class="muted">—</span>
                        <?php endif; ?>
                    </td>
                </tr>
            <?php endforeach; ?>
            </tbody>
        </table>
        </div>

        <div class="field mt-2">
            <label>Global Comment</label>
            <textarea name="global_comment" rows="3"><?php echo h($draftPayload['global_comment'] ?? ''); ?></textarea>
        </div>

        <button type="submit" class="btn btn-primary btn-lg mt-2">Save Attempt</button>
        <a href="grade.php<?php echo $lockedFormId ? '?form_id=' . (int)$lockedFormId : ''; ?>" class="btn">Cancel</a>
    </form>
<?php endif; ?>

<?php if ($result && $lastAttempt): ?>
    <div class="alert alert-success">
        <strong>✅ Saved successfully.</strong>
        <?php echo (int)$lastAttempt['total']; ?> / <?php echo (int)$lastAttempt['max']; ?>
        (<?php echo h($lastAttempt['percent']); ?>%) – <strong><?php echo h($lastAttempt['grade']); ?></strong>
    </div>
    <p>
        <a href="grade.php<?php echo $lockedFormId ? '?form_id=' . (int)$lockedFormId : ''; ?>" class="btn btn-primary btn-lg">Scan Next Candidate</a>
        <a href="edit_attempt.php?id=<?php echo (int)$lastAttempt['id']; ?>" class="btn">Edit This Attempt</a>

        <!-- 10-minute "Undo submission" recovery -->
        <form method="post" action="undo_attempt.php" style="display:inline" onsubmit="return confirm('Undo submission? The attempt will be soft-deleted and the session re-opened so you can re-grade.');">
            <?php echo csrf_field(); ?>
            <input type="hidden" name="attempt_id" value="<?php echo (int)$lastAttempt['id']; ?>">
            <button type="submit" class="btn btn-warning">↩ Undo Submission</button>
        </form>
    </p>
    <p class="muted">Undo is available for 10 minutes after submission. After that, use <em>Edit This Attempt</em>.</p>
<?php endif; ?>

<script>
/* Central round banner + bell playback – every grading screen subscribes. */
(function () {
    const banner = document.getElementById('round-banner');
    const label  = document.getElementById('round-banner-label');
    const time   = document.getElementById('round-banner-time');
    const localBox = document.getElementById('osce-timer-box');

    const sBeep = new Audio('assets/sounds/beep-soft.mp3');
    const wBeep = new Audio('assets/sounds/beep-warning.mp3');
    const alarm = new Audio('assets/sounds/alarm.mp3');
    function play(a) { try { const x = a.cloneNode(); x.play().catch(()=>{}); } catch (_) {} }
    function chimes(n) {
        const s = n === 3 ? alarm : wBeep;
        for (let i = 0; i < n; i++) setTimeout(() => play(s), i * 350);
    }

    let serverOffset = 0, endTsMs = 0, running = false;
    let lastBellId = parseInt(localStorage.getItem('osceLastBellId') || '0', 10);

    function fmt(sec){ sec=Math.max(0,Math.floor(sec)); return String(Math.floor(sec/60)).padStart(2,'0')+':'+String(sec%60).padStart(2,'0'); }

    function tick() {
        if (!running) return;
        const rem = Math.max(0, Math.floor((endTsMs - (Date.now() - serverOffset)) / 1000));
        time.textContent = fmt(rem);
    }
    setInterval(tick, 250);

    function handleBells(events) {
        for (const e of events) {
            if (e.id <= lastBellId) continue;
            lastBellId = e.id;
            switch (e.event_type) {
                case 'start':     case 'manual_1': chimes(1); break;
                case 'warn_2min': case 'warn_1min': case 'manual_2': chimes(2); break;
                case 'end':       case 'manual_3': chimes(3); break;
            }
        }
        localStorage.setItem('osceLastBellId', String(lastBellId));
    }

    async function poll() {
        try {
            const j = await OSCE.fetchJSON('bell_state.php?since=' + lastBellId);
            const r = j.round || {};
            if (r.running) {
                running = true;
                serverOffset = Date.now() - r.server_now_ms;
                endTsMs = r.end_ts_ms;
                label.textContent = (r.label || 'Round') + ' · ' + r.duration_minutes + ' min';
                banner.style.display = 'block';
                if (localBox) localBox.style.display = 'none';   // hide per-session timer while synced
            } else {
                running = false;
                banner.style.display = 'none';
                if (localBox) localBox.style.display = '';        // restore per-session timer
            }
            handleBells(j.bells || []);
        } catch (e) { /* silent retry */ }
    }
    poll();
    setInterval(poll, 2500);
})();
</script>

<?php if ($timerData): ?>
<script>
document.addEventListener('DOMContentLoaded', function () {
    const box  = document.getElementById('osce-timer-box');
    const span = document.getElementById('osce-timer');
    const s2 = new Audio('assets/sounds/beep-soft.mp3');
    const s1 = new Audio('assets/sounds/beep-warning.mp3');
    const se = new Audio('assets/sounds/alarm.mp3');
    function safePlay(a){ try{ a.play().catch(()=>{}); }catch(_){} }
    OSCE.startTimer({
        endMs:        <?php echo (int)$timerData['end_ms']; ?>,
        serverNowMs:  <?php echo (int)$timerData['server_now_ms']; ?>,
        boxEl: box, textEl: span,
        onWarn2: () => safePlay(s2),
        onWarn1: () => safePlay(s1),
        onEnd:   () => safePlay(se),
    });
});
</script>
<?php endif; ?>

<?php if ($candidate && $form && !$result): ?>
<script>
document.addEventListener('DOMContentLoaded', function () {
    const form   = document.getElementById('grade-form');
    if (!form) return;
    const status = document.getElementById('autosave-status');
    const candidateId = form.dataset.candidate;
    const formId      = form.dataset.form;
    let dirty = false;

    function collect() {
        const fd = new FormData(form);
        const payload = { score: {}, item_comment: {}, global_comment: '' };
        for (const [k, v] of fd.entries()) {
            const m = k.match(/^score\[(\d+)\]$/);
            const c = k.match(/^item_comment\[(\d+)\]$/);
            if (m) payload.score[m[1]] = v;
            else if (c) payload.item_comment[c[1]] = v;
            else if (k === 'global_comment') payload.global_comment = v;
        }
        return payload;
    }

    async function save() {
        if (!dirty) return;
        try {
            status.textContent = 'Saving…';
            status.className = 'autosave-status saving';
            await OSCE.fetchJSON('grade_autosave.php', {
                method: 'POST',
                body: { candidate_id: candidateId, form_id: formId, payload: collect() }
            });
            dirty = false;
            const now = new Date();
            status.textContent = 'Draft saved at ' + now.toLocaleTimeString();
            status.className = 'autosave-status saved';
        } catch (e) {
            status.textContent = 'Autosave failed – will retry';
            status.className = 'autosave-status error';
        }
    }

    form.addEventListener('input', () => { dirty = true; });
    setInterval(save, 4000);
    document.addEventListener('visibilitychange', () => { if (document.hidden) save(); });
});
</script>
<?php endif; ?>

<?php require __DIR__ . '/footer.php'; ?>
