<?php
// helpers.php
if (session_status() === PHP_SESSION_NONE) session_start();

function csrf_token() {
    if (empty($_SESSION['csrf'])) {
        $_SESSION['csrf'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf'];
}
function verify_csrf_token($token) {
    return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}
function verify_csrf($token) {
    return isset($_SESSION['csrf']) && hash_equals($_SESSION['csrf'], $token ?? '');
}

// Append ?v=<mtime> so the browser fetches the fresh file
if (!function_exists('add_cache_bust')) {
  function add_cache_bust(string $url): string {
    $u = trim($url);
    if ($u === '') return $u;

    // Absolute URLs: we can't reliably map to filesystem; still add a time param
    if (preg_match('~^https?://~i', $u)) {
      return $u . (str_contains($u,'?') ? '&' : '?') . 'v=' . time();
    }

    // Try to resolve to a filesystem path
    $path = parse_url($u, PHP_URL_PATH) ?: $u;
    $path = '/' . ltrim($path, '/');

    $candidates = [];
    if (defined('DOCROOT'))                    $candidates[] = rtrim(DOCROOT, '/') . $path;
    if (!empty($_SERVER['DOCUMENT_ROOT']))     $candidates[] = rtrim($_SERVER['DOCUMENT_ROOT'], '/') . $path;
                                               $candidates[] = __DIR__ . $path;
                                               $candidates[] = dirname(__DIR__) . $path;

    $fs = null;
    foreach ($candidates as $c) { if (is_file($c)) { $fs = $c; break; } }

    $v = $fs ? (string)@filemtime($fs) : (string)time();
    return $u . (str_contains($u,'?') ? '&' : '?') . 'v=' . $v;
  }
}
// Add this function to helpers.php
function formatStudentId($student_id) {
    // Remove any existing hyphens and non-digit characters
    $clean_id = preg_replace('/[^\d]/', '', $student_id);
    
    // Format as XX-XXXXXXX (assuming 9 digits total)
    if (strlen($clean_id) >= 9) {
        return substr($clean_id, 0, 2) . '-' . substr($clean_id, 2);
    }
    
    // If it doesn't match expected format, return original
    return $student_id;
}
function require_student() {
    if (empty($_SESSION['student_id'])) {
        header("Location: student_login.php");
        exit;
    }
}

function require_committee() {
    if (empty($_SESSION['committee_id'])) {
        header("Location: committee_login.php");
        exit;
    }
}

function e($v) { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }

function committee_scope(): array {
    return [
        'can_all'    => !empty($_SESSION['committee_can_all']),
        'college_id' => isset($_SESSION['committee_college_id']) ? (int)$_SESSION['committee_college_id'] : null,
    ];
}

/* New: require_doctor() */
function require_doctor() {
    if (empty($_SESSION['doctor_id'])) {
        header("Location: doctor_login.php");
        exit;
    }
}

/* New: logged-in doctor helper */
function current_doctor() {
    return [
        'id'   => $_SESSION['doctor_id']   ?? null,
        'name' => $_SESSION['doctor_name'] ?? null,
    ];
}

/* New: simple redirect with flash */
function flash_set($key, $msg) { $_SESSION['flash'][$key] = $msg; }
function flash_get($key) {
    if (!empty($_SESSION['flash'][$key])) { $m = $_SESSION['flash'][$key]; unset($_SESSION['flash'][$key]); return $m; }
    return null;
}

/* ===================== SMS FUNCTIONS ===================== */
function brq_send_sms(string $to, string $message, string $senderId = 'UOFG', array $opts = []): array {
    $API_BASE  = 'https://dash.brqsms.com/api/http/sms/send';
    $API_TOKEN = '11|lztDoMxzMfbkuNAL8nCFAGdftW0CtkrHxiU0qIBAbf1c0331';
    $LOG_FILE  = __DIR__ . '/logs/sms.log';

    // Normalize: digits only, full intl; many gateways dislike '+'
    $to = preg_replace('/\D+/', '', $to);
    if (!preg_match('/^\d{8,20}$/', $to)) {
        return _sms_fail('Invalid phone number after normalization', 0, null, $LOG_FILE);
    }

    $payload = [
        'recipient'  => $to,
        'sender_id'  => $senderId,
        'message'    => $message,
        'api_token'  => $API_TOKEN,
        'unicode'    => '1', // Arabic
    ];

    // 1) Try JSON POST (what their validator likely expects)
    $jsonResult = _brq_http($API_BASE, 'POST', json_encode($payload, JSON_UNESCAPED_UNICODE), [
        'Content-Type: application/json',
        'Accept: application/json',
        'User-Agent: BRQ-SMS-Client/1.1'
    ]);

    if (_looks_ok($jsonResult)) {
        return _log_and_return($jsonResult, $LOG_FILE, $to, $senderId, 'json');
    }

    // 2) Fallback: form-encoded POST
    $formResult = _brq_http($API_BASE, 'POST', http_build_query($payload, '', '&', PHP_QUERY_RFC3986), [
        'Content-Type: application/x-www-form-urlencoded',
        'Accept: application/json',
        'User-Agent: BRQ-SMS-Client/1.1'
    ]);
    if (_looks_ok($formResult)) {
        return _log_and_return($formResult, $LOG_FILE, $to, $senderId, 'form');
    }

    // 3) Fallback: GET (as their sample URL shows)
    $url = $API_BASE . '?' . http_build_query($payload, '', '&', PHP_QUERY_RFC3986);
    $getResult = _brq_http($url, 'GET', null, [
        'Accept: application/json',
        'User-Agent: BRQ-SMS-Client/1.1'
    ]);
    return _log_and_return($getResult, $LOG_FILE, $to, $senderId, 'get');
}

function _brq_http(string $url, string $method, ?string $body, array $headers): array {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT        => 20,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_HTTPHEADER     => $headers,
    ]);
    if ($method === 'POST') {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $body ?? '');
    }
    $respBody = curl_exec($ch);
    $errno    = curl_errno($ch);
    $errstr   = curl_error($ch);
    $status   = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $json = null;
    if (is_string($respBody)) {
        $json = json_decode($respBody, true);
    }
    $ok = ($errno === 0 && $status >= 200 && $status < 300 && _gateway_success($json, $respBody));

    return [
        'ok'       => $ok,
        'status'   => $status,
        'errno'    => $errno,
        'error'    => $errstr,
        'body'     => $respBody,
        'response' => $json,
    ];
}

function _gateway_success($json, $raw) {
    // Consider success if JSON has status 'success' or 'ok'
    if (is_array($json) && isset($json['status'])) {
        $s = strtolower((string)$json['status']);
        return in_array($s, ['success','ok','sent','queued'], true);
    }
    // If not JSON, a non-empty raw 2xx might still be success—be conservative:
    return false;
}

function _looks_ok(array $r): bool {
    if ($r['errno'] !== 0) return false;
    if ($r['status'] < 200 || $r['status'] >= 300) return false;
    // Must not contain the "recipient field is required" error:
    if (is_string($r['body']) && stripos($r['body'], 'recipient field is required') !== false) return false;
    return _gateway_success($r['response'], $r['body']);
}

function _log_and_return(array $r, string $file, string $to, string $sender, string $mode): array {
    _sms_log($file, [
        'ts'      => date('c'),
        'ok'      => $r['ok'],
        'status'  => $r['status'],
        'errno'   => $r['errno'],
        'error'   => $r['error'],
        'to'      => $to,
        'sender'  => $sender,
        'mode'    => $mode,
        'body'    => is_string($r['body']) ? substr($r['body'], 0, 1000) : $r['body'],
        'note'    => $r['ok'] ? 'Delivered to gateway' : 'Gateway indicated failure',
    ]);
    return $r;
}

function _sms_log(string $file, array $row): void {
    try {
        if (!is_dir(dirname($file))) @mkdir(dirname($file), 0775, true);
        @file_put_contents($file, json_encode($row, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
    } catch (\Throwable $e) { /* ignore logging errors */ }
}

function _sms_fail(string $msg, int $status = 0, $body = null, string $logFile = null): array {
    if ($logFile) _sms_log($logFile, ['ts'=>date('c'), 'ok'=>false, 'status'=>$status, 'error'=>$msg, 'body'=>$body]);
    return ['ok'=>false, 'status'=>$status, 'errno'=>0, 'error'=>$msg, 'body'=>$body, 'response'=>null];
}

/* HTML esc (you already have e()) */
// function e($v){ return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }

/* Arabic-friendly base styles (inject where you output <head>) */
function base_head_css() {
    echo "<style>
    @font-face { font-family:'Cairo'; font-style:normal; font-weight:400; src: local('Cairo'); }
    :root { --font-ar:'Cairo',system-ui,Segoe UI,Arial; }
    html[dir='rtl'] body { font-family: var(--font-ar); }
    .container{max-width:1100px;margin:20px auto;padding:12px}
    .card{background:#fff;border:1px solid #e7e7e7;border-radius:14px;padding:16px;margin:10px 0;box-shadow:0 2px 10px rgba(0,0,0,.04)}
    .btn{display:inline-block;padding:8px 14px;border-radius:10px;border:1px solid #d6d6d6;background:#f7f7f7;text-decoration:none}
    .btn.primary{background:#276ef1;border-color:#276ef1;color:#fff}
    .btn.danger{background:#b00020;border-color:#b00020;color:#fff}
    .btn.success{background:#0f9d58;border-color:#0f9d58;color:#fff}
    .btn.light{background:#f1f3f4}
    table{width:100%;border-collapse:collapse}
    th,td{border-bottom:1px solid #eee;padding:10px}
    .rtl-form label{display:block;margin:6px 0 3px}
    .badge{padding:3px 8px;border-radius:100px;font-size:.85rem}
    .badge.gray{background:#eceff1}
    .badge.green{background:#e8f5e9}
    .badge.red{background:#ffebee}
    .notice{padding:10px;border-radius:10px;background:#eef7ff;border:1px solid #cfe3ff;margin-bottom:12px}
    </style>";
}
?>