<?php
/**
 * GET /api/v1/bootstrap.php
 *
 * The "download everything for offline use" call. The app fetches this when
 * online (login / pull-to-refresh) and caches it in local SQLite so an
 * examiner can grade with no connectivity. Everything is facility-scoped with
 * the same rules the web app uses (see grade.php / perms.php).
 *
 * Returns: forms, form_items, grade_bands, candidates, active exams +
 * stations + this examiner's assignments, and this examiner's open drafts.
 */

require_once __DIR__ . '/../../config.php';
require_once __DIR__ . '/../../lib/api.php';

api_require_method('GET');
$user = api_auth($pdo);

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

// ---- GUARD: a non-super user with no facility would silently receive ZERO
// candidates (perms_facility_scope returns "1=0"), which shows up in the app as
// "No candidate matches" for every barcode. Fail loudly with a clear message
// so the user/admin knows to assign a facility, instead of guessing.
if (!$isSuper && empty($facilityId)) {
    http_response_code(409);
    header('Content-Type: application/json');
    echo json_encode([
        'error' => 'Your account has no facility assigned. Ask an administrator to set your facility, then pull to sync again.',
    ]);
    exit;
}

/** Build "?,?,?" placeholder list for an IN() clause. */
$placeholders = static fn(array $a): string => implode(',', array_fill(0, count($a), '?'));

// ---- Forms (same facility scoping as grade.php) ----------------------------
$params = [];
$sql = 'SELECT id, facility_id, name, description, default_duration_minutes
        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';
$st = $pdo->prepare($sql);
$st->execute($params);
$formsRaw = $st->fetchAll();

$forms = array_map(static fn(array $f): array => [
    'id'                       => (int) $f['id'],
    'facility_id'              => $f['facility_id'] !== null ? (int) $f['facility_id'] : null,
    'name'                     => $f['name'],
    'description'              => $f['description'],
    'default_duration_minutes' => (int) ($f['default_duration_minutes'] ?? 8),
], $formsRaw);

$formIds = array_map(static fn(array $f): int => $f['id'], $forms);

// ---- Form items + grade bands for those forms ------------------------------
$formItems = [];
$gradeBands = [];
if ($formIds) {
    $in = $placeholders($formIds);

    $st = $pdo->prepare("SELECT id, form_id, label, max_score, has_comment, sort_order
                         FROM form_items WHERE form_id IN ($in) ORDER BY form_id, sort_order");
    $st->execute($formIds);
    $formItems = array_map(static fn(array $i): array => [
        'id'          => (int) $i['id'],
        'form_id'     => (int) $i['form_id'],
        'label'       => $i['label'],
        'max_score'   => (int) $i['max_score'],
        'has_comment' => (int) $i['has_comment'] === 1,
        'sort_order'  => (int) $i['sort_order'],
    ], $st->fetchAll());

    $st = $pdo->prepare("SELECT id, form_id, label, min_percent, max_percent, sort_order
                         FROM grade_bands WHERE form_id IN ($in) ORDER BY form_id, sort_order");
    $st->execute($formIds);
    $gradeBands = array_map(static fn(array $b): array => [
        'id'          => (int) $b['id'],
        'form_id'     => (int) $b['form_id'],
        'label'       => $b['label'],
        'min_percent' => (float) $b['min_percent'],
        'max_percent' => (float) $b['max_percent'],
        'sort_order'  => (int) $b['sort_order'],
    ], $st->fetchAll());
}

// ---- Candidates (facility scoped) ------------------------------------------
$params = [];
$sql = 'SELECT id, facility_id, candidate_number, name, section, circuit_type, cohort_year, barcode
        FROM candidates WHERE deleted_at IS NULL';
[$where, $wp] = perms_facility_scope($user, 'facility_id');
if ($where) {
    $sql .= " AND $where";
    $params = $wp;
}
$sql .= ' ORDER BY candidate_number';
$st = $pdo->prepare($sql);
$st->execute($params);
$candidates = array_map(static fn(array $c): array => [
    'id'               => (int) $c['id'],
    'facility_id'      => (int) $c['facility_id'],
    'candidate_number' => $c['candidate_number'],
    'name'             => $c['name'],
    'section'          => $c['section'],
    'circuit_type'     => $c['circuit_type'],
    'cohort_year'      => $c['cohort_year'],
    'barcode'          => $c['barcode'],
], $st->fetchAll());

// ---- Active exams + their stations + this examiner's assignments ------------
$params = [];
$sql = "SELECT id, facility_id, name, description, exam_date, status
        FROM exams WHERE deleted_at IS NULL AND status = 'active'";
[$where, $wp] = perms_facility_scope($user, 'facility_id');
if ($where) {
    $sql .= " AND $where";
    $params = $wp;
}
$sql .= ' ORDER BY exam_date DESC, name';
$st = $pdo->prepare($sql);
$st->execute($params);
$exams = array_map(static fn(array $e): array => [
    'id'          => (int) $e['id'],
    'facility_id' => $e['facility_id'] !== null ? (int) $e['facility_id'] : null,
    'name'        => $e['name'],
    'description' => $e['description'],
    'exam_date'   => $e['exam_date'],
    'status'      => $e['status'],
], $st->fetchAll());

$examIds = array_map(static fn(array $e): int => $e['id'], $exams);

$stations    = [];
$assignments = [];
if ($examIds) {
    $in = $placeholders($examIds);
    $st = $pdo->prepare("SELECT id, exam_id, form_id, station_label, room, duration_minutes, sort_order
                         FROM exam_stations WHERE exam_id IN ($in) ORDER BY exam_id, sort_order");
    $st->execute($examIds);
    $stations = array_map(static fn(array $s): array => [
        'id'               => (int) $s['id'],
        'exam_id'          => (int) $s['exam_id'],
        'form_id'          => (int) $s['form_id'],
        'station_label'    => $s['station_label'],
        'room'             => $s['room'],
        'duration_minutes' => (int) ($s['duration_minutes'] ?? 8),
        'sort_order'       => (int) $s['sort_order'],
    ], $st->fetchAll());

    // Only the stations THIS examiner is assigned to.
    $st = $pdo->prepare("
        SELECT ea.id, ea.exam_station_id
        FROM examiner_assignments ea
        JOIN exam_stations es ON es.id = ea.exam_station_id
        WHERE ea.examiner_id = ? AND es.exam_id IN ($in)
    ");
    $st->execute(array_merge([$user['id']], $examIds));
    $assignments = array_map(static fn(array $a): array => [
        'id'              => (int) $a['id'],
        'exam_station_id' => (int) $a['exam_station_id'],
    ], $st->fetchAll());
}

// ---- This examiner's open drafts (to resume mid-grading) --------------------
$st = $pdo->prepare('SELECT candidate_id, form_id, payload, updated_at
                     FROM grade_drafts WHERE examiner_id = ?');
$st->execute([$user['id']]);
$drafts = array_map(static function (array $d): array {
    $payload = json_decode((string) $d['payload'], true);
    return [
        'candidate_id' => (int) $d['candidate_id'],
        'form_id'      => (int) $d['form_id'],
        'payload'      => is_array($payload) ? $payload : new stdClass(),
        'updated_at'   => $d['updated_at'],
    ];
}, $st->fetchAll());

api_ok([
    'server_time' => date('c'),
    'forms'       => $forms,
    'form_items'  => $formItems,
    'grade_bands' => $gradeBands,
    'candidates'  => $candidates,
    'exams'       => $exams,
    'stations'    => $stations,
    'assignments' => $assignments,
    'drafts'      => $drafts,
]);