<?php
declare(strict_types=1);

if (session_status() !== PHP_SESSION_ACTIVE) {
    session_start();
}
$publicPages = ["login.php", "logout.php", "install.php", "display.php", "ticket.php"];
$currentPage = basename((string) ($_SERVER["PHP_SELF"] ?? "index.php"));
$isInstalled = file_exists(__DIR__ . "/.installed") || file_exists(__DIR__ . "/install.lock");
if (!$isInstalled) {
    try {
        if (file_exists(__DIR__ . '/db/config.php')) {
            require_once __DIR__ . '/db/config.php';
            if (function_exists('db')) {
                $pdo = db();
                $stmt = @$pdo->query("SELECT COUNT(*) FROM users");
                if ($stmt !== false && ((int)$stmt->fetchColumn()) > 0) {
                    $isInstalled = true;
                    @file_put_contents(__DIR__ . '/install.lock', date('Y-m-d H:i:s'));
                }
            }
        }
    } catch (\Throwable $e) {}
}

if (!$isInstalled && $currentPage !== "install.php") {
    header("Location: install.php");
    exit;
}
if (!in_array($currentPage, $publicPages, true)) {
    if (empty($_SESSION["user_id"])) {
        header("Location: login.php");
        exit;
    }
    
    $role = $_SESSION["role"] ?? "admin";
    $allowed = false;
    if ($role === "admin") {
        $allowed = true;
    } elseif ($currentPage === "index.php") {
        $allowed = true;
    } elseif ($role === "reception" && $currentPage === "reception.php") {
        $allowed = true;
    } elseif ($role === "nursing" && $currentPage === "nursing.php") {
        $allowed = true;
    } elseif ($role === "doctor" && $currentPage === "doctor.php") {
        $allowed = true;
    }
    
    if (!$allowed) {
        header("Location: index.php");
        exit;
    }
}


require_once __DIR__ . '/db/config.php';

function qh_boot(): void
{
    static $booted = false;
    if ($booted) {
        return;
    }

    qh_ensure_schema();
    qh_seed_demo_data();
    qh_seed_hospital_profile();

    $profile = qh_fetch_hospital_profile();
    $timezone = $profile['timezone'] ?? 'UTC';
    if ($timezone) {
        date_default_timezone_set($timezone);
        try {
            $offset = (new DateTime('now', new DateTimeZone($timezone)))->format('P');
            db()->exec("SET time_zone = " . db()->quote($offset));
        } catch (\Throwable $e) {}
    }

    $booted = true;
}

function qh_ensure_schema(): void
{
    $sql = <<<SQL
CREATE TABLE IF NOT EXISTS hospital_queue_records (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    item_type VARCHAR(20) NOT NULL,
    code VARCHAR(20) DEFAULT NULL,
    name_en VARCHAR(120) DEFAULT NULL,
    name_ar VARCHAR(120) DEFAULT NULL,
    clinic_id INT UNSIGNED DEFAULT NULL,
    doctor_id INT UNSIGNED DEFAULT NULL,
    room_number VARCHAR(20) DEFAULT NULL,
    requires_vitals TINYINT(1) NOT NULL DEFAULT 0,
    patient_name VARCHAR(120) DEFAULT NULL,
    language_pref VARCHAR(5) DEFAULT 'en',
    ticket_number VARCHAR(20) DEFAULT NULL,
    status VARCHAR(30) DEFAULT 'draft',
    vitals_notes TEXT DEFAULT NULL,
    display_note VARCHAR(255) DEFAULT NULL,
    sort_order INT NOT NULL DEFAULT 0,
    called_at DATETIME DEFAULT NULL,
    served_at DATETIME DEFAULT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_item_type (item_type),
    INDEX idx_status (status),
    INDEX idx_clinic_id (clinic_id),
    INDEX idx_doctor_id (doctor_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL;

    db()->exec($sql);

    $profileSql = <<<SQL
CREATE TABLE IF NOT EXISTS hospital_profile_settings (
    id TINYINT UNSIGNED NOT NULL PRIMARY KEY,
    name_en VARCHAR(160) DEFAULT NULL,
    name_ar VARCHAR(160) DEFAULT NULL,
    short_name VARCHAR(40) DEFAULT NULL,
    tagline_en VARCHAR(255) DEFAULT NULL,
    tagline_ar VARCHAR(255) DEFAULT NULL,
    phone VARCHAR(60) DEFAULT NULL,
    email VARCHAR(160) DEFAULT NULL,
    website VARCHAR(255) DEFAULT NULL,
    address_en VARCHAR(255) DEFAULT NULL,
    address_ar VARCHAR(255) DEFAULT NULL,
    working_hours_en VARCHAR(255) DEFAULT NULL,
    working_hours_ar VARCHAR(255) DEFAULT NULL,
    logo_url VARCHAR(255) DEFAULT NULL,
    favicon_url VARCHAR(255) DEFAULT NULL,
    primary_color VARCHAR(7) DEFAULT NULL,
    secondary_color VARCHAR(7) DEFAULT NULL,
    news_ticker_en VARCHAR(1000) DEFAULT NULL,
    news_ticker_ar VARCHAR(1000) DEFAULT NULL,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL;

    db()->exec($profileSql);
    try { db()->exec("ALTER TABLE hospital_profile_settings ADD COLUMN news_ticker_en VARCHAR(1000) DEFAULT NULL"); } catch (\Throwable $e) {}
    try { db()->exec("ALTER TABLE hospital_profile_settings ADD COLUMN news_ticker_ar VARCHAR(1000) DEFAULT NULL"); } catch (\Throwable $e) {}
    try { db()->exec("ALTER TABLE hospital_profile_settings ADD COLUMN timezone VARCHAR(100) DEFAULT 'UTC'"); } catch (\Throwable $e) {}
    try { db()->exec("ALTER TABLE hospital_profile_settings ADD COLUMN default_language VARCHAR(10) DEFAULT 'en'"); } catch (\Throwable $e) {}
}

    try { db()->exec("CREATE TABLE IF NOT EXISTS users (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, role VARCHAR(20) DEFAULT 'admin', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"); } catch (\Throwable $e) {}
    try { db()->exec("ALTER TABLE users ADD COLUMN role VARCHAR(20) DEFAULT 'admin'"); } catch (\Throwable $e) {}

function qh_seed_demo_data(): void
{
    $pdo = db();

    $clinicCount = (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'clinic'")->fetchColumn();
    if ($clinicCount === 0) {
        $insertClinic = $pdo->prepare(
            'INSERT INTO hospital_queue_records (item_type, code, name_en, name_ar, requires_vitals, sort_order, status)
             VALUES (\'clinic\', :code, :name_en, :name_ar, :requires_vitals, :sort_order, \'active\')'
        );

        $clinics = [
            ['code' => 'GEN', 'name_en' => 'General Medicine', 'name_ar' => 'الطب العام', 'requires_vitals' => 1, 'sort_order' => 10],
            ['code' => 'PED', 'name_en' => 'Pediatrics', 'name_ar' => 'طب الأطفال', 'requires_vitals' => 0, 'sort_order' => 20],
            ['code' => 'CAR', 'name_en' => 'Cardiology', 'name_ar' => 'أمراض القلب', 'requires_vitals' => 1, 'sort_order' => 30],
        ];

        foreach ($clinics as $clinic) {
            $insertClinic->execute($clinic);
        }
    }

    $clinicMap = [];
    foreach (qh_fetch_clinics() as $clinic) {
        $clinicMap[$clinic['code']] = $clinic['id'];
    }

    $doctorCount = (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'doctor'")->fetchColumn();
    if ($doctorCount === 0 && $clinicMap !== []) {
        $insertDoctor = $pdo->prepare(
            'INSERT INTO hospital_queue_records (item_type, name_en, name_ar, clinic_id, room_number, sort_order, status)
             VALUES (\'doctor\', :name_en, :name_ar, :clinic_id, :room_number, :sort_order, \'active\')'
        );

        $doctors = [
            ['name_en' => 'Dr. Sarah Malik', 'name_ar' => 'د. سارة مالك', 'clinic_id' => $clinicMap['GEN'] ?? null, 'room_number' => '201', 'sort_order' => 10],
            ['name_en' => 'Dr. Omar Nasser', 'name_ar' => 'د. عمر ناصر', 'clinic_id' => $clinicMap['GEN'] ?? null, 'room_number' => '202', 'sort_order' => 20],
            ['name_en' => 'Dr. Lina Haddad', 'name_ar' => 'د. لينا حداد', 'clinic_id' => $clinicMap['PED'] ?? null, 'room_number' => '103', 'sort_order' => 30],
            ['name_en' => 'Dr. Ahmad Kareem', 'name_ar' => 'د. أحمد كريم', 'clinic_id' => $clinicMap['CAR'] ?? null, 'room_number' => '305', 'sort_order' => 40],
        ];

        foreach ($doctors as $doctor) {
            if ($doctor['clinic_id']) {
                $insertDoctor->execute($doctor);
            }
        }
    }

    $ticketCount = (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket'")->fetchColumn();
    if ($ticketCount === 0) {
        $doctors = qh_fetch_doctors();
        $doctorByClinic = [];
        foreach ($doctors as $doctor) {
            $doctorByClinic[$doctor['clinic_id']][] = $doctor;
        }

        foreach (qh_fetch_clinics() as $clinic) {
            if (empty($doctorByClinic[$clinic['id']])) {
                continue;
            }
            $assignedDoctor = $doctorByClinic[$clinic['id']][0];
            qh_create_ticket(
                $clinic['name_en'] === 'General Medicine' ? 'Maha Ali' : 'Yousef Karim',
                (int) $clinic['id'],
                (int) $assignedDoctor['id'],
                $clinic['name_en'] === 'General Medicine' ? 'ar' : 'en',
                $clinic['requires_vitals'] ? 'waiting_vitals' : 'ready_for_doctor'
            );
            if ($clinic['name_en'] !== 'General Medicine') {
                break;
            }
        }
    }
}

function qh_seed_hospital_profile(): void
{
    $exists = (int) db()->query('SELECT COUNT(*) FROM hospital_profile_settings')->fetchColumn();
    if ($exists > 0) {
        return;
    }

    $stmt = db()->prepare(
        'INSERT INTO hospital_profile_settings
         (id, name_en, name_ar, short_name, tagline_en, tagline_ar, phone, email, website, address_en, address_ar, working_hours_en, working_hours_ar, logo_url, favicon_url, primary_color, secondary_color, news_ticker_en, news_ticker_ar)
         VALUES
         (1, :name_en, :name_ar, :short_name, :tagline_en, :tagline_ar, :phone, :email, :website, :address_en, :address_ar, :working_hours_en, :working_hours_ar, :logo_url, :favicon_url, :primary_color, :secondary_color, :news_ticker_en, :news_ticker_ar)'
    );

    $stmt->execute([
        'name_en' => qh_project_name('Hospital Queue Center'),
        'name_ar' => 'مركز إدارة الطوابير',
        'short_name' => 'HQC',
        'tagline_en' => 'Organized patient flow, queue control, and staff coordination.',
        'tagline_ar' => 'تنظيم تدفق المرضى وإدارة الطوابير وتنسيق عمل الطاقم.',
        'phone' => '',
        'email' => '',
        'website' => '',
        'address_en' => '',
        'address_ar' => '',
        'working_hours_en' => 'Sun–Thu · 8:00 AM – 8:00 PM',
        'working_hours_ar' => 'الأحد – الخميس · 8:00 ص – 8:00 م',
        'logo_url' => '',
        'favicon_url' => '',
        'primary_color' => '#0f8b8d',
        'secondary_color' => '#16697a',
        'news_ticker_en' => 'Welcome to our hospital.',
        'news_ticker_ar' => 'مرحباً بكم في مستشفانا.',
    ]);
}

function qh_h(?string $value): string
{
    return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}

function qh_project_name(string $fallback = 'Hospital Queue'): string
{
    $candidate = trim((string) ($_SERVER['PROJECT_NAME'] ?? $_SERVER['PROJECT_TITLE'] ?? ''));
    return $candidate !== '' ? $candidate : $fallback;
}

function qh_project_description(string $fallback = 'Bilingual hospital queue workflow for reception, nursing, doctors, and the public display.'): string
{
    $candidate = trim((string) ($_SERVER['PROJECT_DESCRIPTION'] ?? ''));
    return $candidate !== '' ? $candidate : $fallback;
}

function qh_asset_version(string $relativePath): int
{
    $fullPath = __DIR__ . '/' . ltrim($relativePath, '/');
    return is_file($fullPath) ? (int) filemtime($fullPath) : time();
}


function qh_locale(): string
{
    static $locale = null;
    if ($locale !== null) {
        return $locale;
    }

    $requested = strtolower(trim((string) ($_GET['lang'] ?? '')));
    if (in_array($requested, ['en', 'ar'], true)) {
        $_SESSION['qh_lang'] = $requested;
    }

    $sessionLocale = strtolower(trim((string) ($_SESSION['qh_lang'] ?? '')));
    if (in_array($sessionLocale, ['en', 'ar'], true)) {
        $locale = $sessionLocale;
    } else {
        $profile = qh_fetch_hospital_profile();
        $defaultLang = strtolower(trim((string) ($profile['default_language'] ?? 'en')));
        $locale = in_array($defaultLang, ['en', 'ar'], true) ? $defaultLang : 'en';
    }

    return $locale;
}

function qh_is_ar(): bool
{
    return qh_locale() === 'ar';
}

function qh_t(string $en, string $ar): string
{
    return qh_is_ar() ? $ar : $en;
}

function qh_locale_label(?string $locale = null): string
{
    $locale = $locale ?: qh_locale();
    return $locale === 'ar' ? 'العربية' : 'English';
}

function qh_other_locale(): string
{
    return qh_is_ar() ? 'en' : 'ar';
}

function qh_url(string $path, array $params = []): string
{
    $target = basename($path);
    $params['lang'] = $params['lang'] ?? qh_locale();
    $query = http_build_query($params);
    return $query !== '' ? $target . '?' . $query : $target;
}

function qh_switch_lang_url(string $locale): string
{
    $params = $_GET;
    $params['lang'] = in_array($locale, ['en', 'ar'], true) ? $locale : qh_other_locale();
    $target = basename((string) ($_SERVER['PHP_SELF'] ?? 'index.php'));
    $query = http_build_query($params);
    return $query !== '' ? $target . '?' . $query : $target;
}

function qh_name(array $row, string $base = 'name', string $fallback = '—'): string
{
    $primaryKey = $base . '_' . (qh_is_ar() ? 'ar' : 'en');
    $secondaryKey = $base . '_' . (qh_is_ar() ? 'en' : 'ar');

    $primary = trim((string) ($row[$primaryKey] ?? ''));
    if ($primary !== '') {
        return $primary;
    }

    $secondary = trim((string) ($row[$secondaryKey] ?? ''));
    return $secondary !== '' ? $secondary : $fallback;
}

function qh_fetch_hospital_profile(): array
{
    static $profile = null;
    if ($profile !== null) {
        return $profile;
    }

    $row = db()->query('SELECT * FROM hospital_profile_settings WHERE id = 1 LIMIT 1')->fetch();
    $profile = is_array($row) ? $row : [];

    return $profile;
}

function qh_hospital_name(): string
{
    $profile = qh_fetch_hospital_profile();
    $name = qh_name($profile, 'name', '');
    if ($name !== '') {
        return $name;
    }

    $shortName = trim((string) ($profile['short_name'] ?? ''));
    return $shortName !== '' ? $shortName : qh_project_name();
}

function qh_hospital_tagline(): string
{
    $profile = qh_fetch_hospital_profile();
    return qh_name($profile, 'tagline', '');
}

function qh_hospital_logo_url(): string
{
    $profile = qh_fetch_hospital_profile();
    return trim((string) ($profile['logo_url'] ?? ''));
}

function qh_hospital_favicon_url(): string
{
    $profile = qh_fetch_hospital_profile();
    $favicon = trim((string) ($profile['favicon_url'] ?? ''));
    if ($favicon !== '') {
        return $favicon;
    }

    return qh_hospital_logo_url();
}

function qh_hospital_contact_value(string $field): string
{
    $profile = qh_fetch_hospital_profile();
    return trim((string) ($profile[$field] ?? ''));
}

function qh_hospital_brand_initials(): string
{
    $profile = qh_fetch_hospital_profile();
    $source = trim((string) ($profile['short_name'] ?? ''));
    if ($source === '') {
        $source = trim((string) ($profile['name_en'] ?? qh_project_name('Hospital Queue')));
    }

    $parts = preg_split('/[^\p{L}\p{N}]+/u', $source, -1, PREG_SPLIT_NO_EMPTY);
    $initials = [];
    foreach ($parts as $part) {
        if (preg_match('/^[\p{L}\p{N}]/u', $part, $matches)) {
            $initials[] = strtoupper($matches[0]);
        }
        if (count($initials) >= 2) {
            break;
        }
    }

    return $initials !== [] ? implode('', array_slice($initials, 0, 2)) : 'HQ';
}

function qh_sanitize_hex_color(?string $value, string $fallback): string
{
    $candidate = strtoupper(trim((string) $value));
    return preg_match('/^#[0-9A-F]{6}$/', $candidate) ? $candidate : $fallback;
}

function qh_hospital_primary_color(): string
{
    $profile = qh_fetch_hospital_profile();
    return qh_sanitize_hex_color($profile['primary_color'] ?? null, '#0F8B8D');
}

function qh_hospital_secondary_color(): string
{
    $profile = qh_fetch_hospital_profile();
    return qh_sanitize_hex_color($profile['secondary_color'] ?? null, '#16697A');
}

function qh_current_language_badge(): string
{
    return qh_t('English workspace', 'واجهة عربية');
}

function qh_admin_sections(): array
{
    return [
        'admin.php' => [
            'label' => qh_t('Overview', 'نظرة عامة'),
            'description' => qh_t('Admin home and setup summary.', 'الصفحة الرئيسية وملخص الإعدادات.'),
            'icon' => 'overview',
        ],
'admin_ads.php' => [
            'label' => qh_t('Advertisements', 'الإعلانات'),
            'description' => qh_t('Manage videos shown on the queue display.', 'إدارة الفيديوهات المعروضة على شاشة الطابور.'),
            'icon' => 'display',
        ],
        'admin_hospital.php' => [
            'label' => qh_t('Hospital profile', 'ملف المستشفى'),
            'description' => qh_t('Manage logo, favicon, contact details, and brand colors.', 'إدارة الشعار والأيقونة وبيانات التواصل وألوان الهوية.'),
            'icon' => 'hospital',
        ],
        'admin_clinics.php' => [
            'label' => qh_t('Clinics', 'العيادات'),
            'description' => qh_t('Manage clinic codes, routing, and order.', 'إدارة رموز العيادات والمسار والترتيب.'),
            'icon' => 'clinic',
        ],
        'admin_users.php' => [
            'label' => qh_t('Users', 'المستخدمون'),
            'description' => qh_t('Manage system users and access.', 'إدارة مستخدمي النظام وصلاحيات الوصول.'),
            'icon' => 'users',
        ],
        'admin_doctors.php' => [
            'label' => qh_t('Doctors', 'الأطباء'),
            'description' => qh_t('Manage doctors, rooms, and assignments.', 'إدارة الأطباء والغرف والتعيينات.'),
            'icon' => 'doctor',
        ],
    ];
}

function qh_admin_allowed_pages(): array
{
    return array_keys(qh_admin_sections());
}

function qh_admin_return_to(?string $candidate = null): string
{
    $page = basename((string) ($candidate ?? 'admin.php'));
    return in_array($page, qh_admin_allowed_pages(), true) ? $page : 'admin.php';
}

function qh_admin_sidebar_icon(string $icon): string
{
    return match ($icon) {
        'hospital' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 20V7l7-3 7 3v13"/><path d="M9 11h1"/><path d="M14 11h1"/><path d="M11 8h2"/><path d="M11 20v-4h2v4"/><path d="M3 20h18"/></svg>',
        'clinic' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 20h16"/><path d="M6 20V8l6-4 6 4v12"/><path d="M9 12h1"/><path d="M14 12h1"/><path d="M11 20v-4h2v4"/></svg>',
        'doctor' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14"/><path d="M5 12h14"/><circle cx="12" cy="12" r="8.5"/></svg>',
        'users' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>',
        default => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="4" y="4" width="6.5" height="6.5" rx="1.5"/><rect x="13.5" y="4" width="6.5" height="6.5" rx="1.5"/><rect x="4" y="13.5" width="6.5" height="6.5" rx="1.5"/><rect x="13.5" y="13.5" width="6.5" height="6.5" rx="1.5"/></svg>',
    };
}

function qh_admin_stats(): array
{
    $clinics = qh_fetch_clinics();
    $doctors = qh_fetch_doctors();
    $vitalsClinics = count(array_filter($clinics, static fn(array $clinic): bool => (int) ($clinic['requires_vitals'] ?? 0) === 1));

    return [
        'clinics' => count($clinics),
        'doctors' => count($doctors),
        'vitals_clinics' => $vitalsClinics,
        'direct_clinics' => max(count($clinics) - $vitalsClinics, 0),
    ];
}

function qh_render_admin_sidebar(string $activePage, array $stats = []): void
{
    $sections = qh_admin_sections();
    $activePage = qh_admin_return_to($activePage);
    if ($stats === []) {
        $stats = qh_admin_stats();
    }

    echo '<div class="panel-card admin-sidebar">';
    echo '  <div class="admin-sidebar-top">';
    echo '      <span class="section-kicker">' . qh_h(qh_t('Admin panel', 'لوحة الإدارة')) . '</span>';
    echo '      <h1 class="section-title mt-3 mb-1">' . qh_h(qh_hospital_name()) . '</h1>';
    echo '      <p class="section-copy mb-0">' . qh_h(qh_hospital_tagline() !== '' ? qh_hospital_tagline() : qh_t('Move between dedicated pages instead of one long mixed admin screen.', 'تنقل بين صفحات مستقلة بدلاً من شاشة إدارة طويلة ومختلطة.')) . '</p>';
    echo '  </div>';
    echo '  <nav class="admin-sidebar-nav" aria-label="Admin section navigation">';
    foreach ($sections as $file => $section) {
        $activeClass = $file === $activePage ? ' active' : '';
        $icon = qh_admin_sidebar_icon((string) ($section['icon'] ?? 'overview'));
        echo '      <a class="admin-sidebar-link' . $activeClass . '" href="' . qh_h(qh_url($file)) . '" title="' . qh_h($section['description']) . '">';
        echo '          <span class="admin-sidebar-link-icon">' . $icon . '</span>';
        echo '          <span class="admin-sidebar-link-text">' . qh_h($section['label']) . '</span>';
        echo '      </a>';
    }
    echo '  </nav>';
    echo '  <div class="admin-sidebar-meta">';
    echo '      <div class="admin-mini-stat"><span class="admin-mini-stat-value">' . qh_h((string) ($stats['clinics'] ?? 0)) . '</span><span class="admin-mini-stat-label">' . qh_h(qh_t('Clinics', 'العيادات')) . '</span></div>';
    echo '      <div class="admin-mini-stat"><span class="admin-mini-stat-value">' . qh_h((string) ($stats['doctors'] ?? 0)) . '</span><span class="admin-mini-stat-label">' . qh_h(qh_t('Doctors', 'الأطباء')) . '</span></div>';
    echo '      <div class="admin-mini-stat"><span class="admin-mini-stat-value">' . qh_h((string) ($stats['vitals_clinics'] ?? 0)) . '</span><span class="admin-mini-stat-label">' . qh_h(qh_t('Vitals-first clinics', 'العيادات التي تبدأ بالعلامات')) . '</span></div>';
    echo '  </div>';
    echo '</div>';
}

function qh_ticket_next_stop(array $ticket): string
{
    return (int) ($ticket['clinic_requires_vitals'] ?? 0) === 1
        ? qh_t('Nursing vitals', 'العلامات الحيوية في التمريض')
        : qh_t('Doctor waiting area', 'منطقة انتظار الطبيب');
}

function qh_ticket_last_note(array $ticket): string
{
    return match ((string) ($ticket['status'] ?? '')) {
        'waiting_vitals' => qh_t('Proceed to nursing vitals first.', 'يرجى التوجه أولاً إلى العلامات الحيوية في التمريض.'),
        'ready_for_doctor' => qh_t('Wait for the doctor call on the public display.', 'انتظر نداء الطبيب على الشاشة العامة.'),
        'called' => qh_t('The patient has been called to the doctor room.', 'تم نداء المريض إلى غرفة الطبيب.'),
        'in_progress' => qh_t('The consultation is currently in progress.', 'الاستشارة جارية حالياً.'),
        'done' => qh_t('The visit has been completed.', 'تم إكمال الزيارة.'),
        'no_show' => qh_t('The patient was marked as no-show.', 'تم تسجيل المريض كحالة عدم حضور.'),
        default => trim((string) ($ticket['display_note'] ?? '')) !== '' ? (string) $ticket['display_note'] : '—',
    };
}

function qh_label(string $en, string $ar, string $wrapper = 'span'): string
{
    $tag = preg_replace('/[^a-z0-9]/i', '', $wrapper) ?: 'span';
    return sprintf('<%1$s>%2$s</%1$s>', $tag, qh_h(qh_t($en, $ar)));
}



function qh_page_start(string $activePage, string $pageTitle, string $metaDescription = ''): void
{
    $locale = qh_locale();
    $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? qh_project_description();
    $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
    $brandName = qh_hospital_name();
    $faviconUrl = qh_hospital_favicon_url();
    $fullTitle = $pageTitle . ' · ' . $brandName;
    $description = $metaDescription !== '' ? $metaDescription : qh_project_description();
    $bodyClass = 'page-' . preg_replace('/[^a-z0-9\-]/i', '-', $activePage) . ' lang-' . $locale;
    $assetVersionCss = qh_asset_version('assets/css/custom.css');
    $primaryColor = qh_hospital_primary_color();
    $secondaryColor = qh_hospital_secondary_color();

    echo '<!doctype html>';
    echo '<html lang="' . qh_h($locale) . '" dir="' . (qh_is_ar() ? 'rtl' : 'ltr') . '">';
    echo '<head>';
    echo '  <meta charset="utf-8">';
    echo '  <meta name="viewport" content="width=device-width, initial-scale=1">';
    echo '  <title>' . qh_h($fullTitle) . '</title>';
    echo '  <meta name="description" content="' . qh_h($description) . '">';
    if ($projectDescription) {
        echo '  <meta property="og:description" content="' . qh_h((string) $projectDescription) . '">';
        echo '  <meta property="twitter:description" content="' . qh_h((string) $projectDescription) . '">';
    }
    if ($projectImageUrl) {
        echo '  <meta property="og:image" content="' . qh_h((string) $projectImageUrl) . '">';
        echo '  <meta property="twitter:image" content="' . qh_h((string) $projectImageUrl) . '">';
    }
    if ($faviconUrl !== '') {
        echo '  <link rel="icon" href="' . qh_h($faviconUrl) . '">';
        echo '  <link rel="apple-touch-icon" href="' . qh_h($faviconUrl) . '">';
    }
    echo '  <meta name="theme-color" content="' . qh_h($primaryColor) . '">';
    echo '  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">';
    echo '  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">';
    echo '  <link rel="stylesheet" href="assets/css/custom.css?v=' . $assetVersionCss . '">';
    echo '  <style>:root{--accent:' . qh_h($primaryColor) . ';--accent-strong:' . qh_h($secondaryColor) . ';}</style>';
    echo '</head>';
        $profile = qh_fetch_hospital_profile();
    $timezone = qh_h($profile['timezone'] ?? 'UTC');
    echo '<body class="' . qh_h($bodyClass) . '" data-page="' . qh_h($activePage) . '" data-locale="' . qh_h($locale) . '" data-timezone="' . $timezone . '">';
    if ($activePage !== 'display') {
        qh_render_nav($activePage);
    }
    echo '<main class="app-shell py-4 py-lg-5">';
    qh_render_flash();
}



function qh_page_end(): void
{
    $profile = qh_fetch_hospital_profile();
    $newsTicker = trim((string)($profile['news_ticker'] ?? ''));
    
    if ($newsTicker !== '') {
        echo '<div style="position: fixed; bottom: 0; left: 0; width: 100%; height: 40px; line-height: 40px; background: var(--accent-strong, #16697A); color: #fff; z-index: 9999; font-size: 1.25rem; font-weight: bold; overflow: hidden; box-shadow: 0 -2px 10px rgba(0,0,0,0.1);">';
        echo '<marquee direction="right" scrollamount="6" scrolldelay="85">' . qh_h($newsTicker) . '</marquee>';
        echo '</div>';
    }

    $assetVersionJs = qh_asset_version('assets/js/main.js');
    echo '</main>';
    echo '<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>';
    echo '<script src="assets/js/main.js?v=' . $assetVersionJs . '"></script>';
    echo '</body></html>';
}

function qh_render_nav(string $activePage): void
{
    $links = [
        'home' => ['href' => qh_url('index.php'), 'label' => qh_t('Operations', 'العمليات')],
        'admin' => ['href' => qh_url('admin.php'), 'label' => qh_t('Admin', 'الإدارة')],
        'reception' => ['href' => qh_url('reception.php'), 'label' => qh_t('Reception', 'الاستقبال')],
        'nursing' => ['href' => qh_url('nursing.php'), 'label' => qh_t('Nursing', 'التمريض')],
        'doctor' => ['href' => qh_url('doctor.php'), 'label' => qh_t('Doctor', 'الطبيب')],
        'users' => ['href' => qh_url('admin_users.php'), 'label' => qh_t('Users', 'المستخدمون')],
        'display' => ['href' => qh_url('display.php'), 'label' => qh_t('Display', 'الشاشة')],
    ];

    $logoUrl = qh_hospital_logo_url();
    $tagline = qh_hospital_tagline();

    echo '<header class="app-header border-bottom sticky-top shadow-sm">';
    echo '  <nav class="navbar navbar-expand-lg">';
    echo '    <div class="container-fluid container-xxl px-3 px-lg-4">';
    echo '      <a class="navbar-brand d-flex align-items-center" href="' . qh_h(qh_url('index.php')) . '">';
    if ($logoUrl !== '') {
        echo '        <span class="brand-mark brand-mark-image"><img src="' . qh_h($logoUrl) . '" alt="' . qh_h(qh_hospital_name()) . '"></span>';
    } else {
        echo '        <span class="brand-mark">' . qh_h(qh_hospital_brand_initials()) . '</span>';
    }
    echo '        <span class="brand-copy">';
    echo '          <span class="brand-text">' . qh_h(qh_hospital_name()) . '</span>';
    if ($tagline !== '') {
        echo '          <span class="brand-subtext">' . qh_h($tagline) . '</span>';
    }
    echo '        </span>';
    echo '      </a>';
    echo '      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#appNav" aria-controls="appNav" aria-expanded="false" aria-label="' . qh_h(qh_t('Toggle navigation', 'تبديل التنقل')) . '">';
    echo '        <span class="navbar-toggler-icon"></span>';
    echo '      </button>';
    echo '      <div class="collapse navbar-collapse" id="appNav">';
    echo '        <ul class="navbar-nav ms-auto align-items-lg-center gap-lg-2 mt-3 mt-lg-0">';
    if (!empty($_SESSION["user_id"])) {
        $role = $_SESSION["role"] ?? "admin";
        foreach ($links as $key => $link) {
            $showLink = false;
            if ($role === "admin") {
                $showLink = true;
            } elseif ($key === "home" || $key === "display") {
                $showLink = true;
            } elseif ($key === $role) {
                $showLink = true;
            }
            
            if ($showLink) {
                $activeClass = $key === $activePage ? ' active' : '';
                echo '          <li class="nav-item"><a class="nav-link' . $activeClass . '" href="' . qh_h($link['href']) . '">' . qh_h($link['label']) . '</a></li>';
            }
        }
        echo '          <li class="nav-item"><a class="nav-link text-danger fw-semibold" href="' . qh_h(qh_url("logout.php")) . '"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="me-1"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>' . qh_h(qh_t("Logout", "تسجيل الخروج")) . '</a></li>';
    } else {
        // Show public display link only if not logged in
        $activeClass = 'display' === $activePage ? ' active' : '';
        echo '          <li class="nav-item"><a class="nav-link' . $activeClass . '" href="' . qh_h(qh_url('display.php')) . '">' . qh_h(qh_t('Display', 'الشاشة')) . '</a></li>';
    }

    echo '        </ul>';
    echo '        <div class="lang-switcher ms-lg-3 mt-3 mt-lg-0">';
    foreach (['en', 'ar'] as $lang) {
        $activeClass = qh_locale() === $lang ? ' active' : '';
        echo '          <a class="lang-switch-link' . $activeClass . '" href="' . qh_h(qh_switch_lang_url($lang)) . '">' . qh_h(qh_locale_label($lang)) . '</a>';
    }
    echo '        </div>';
    echo '      </div>';
    echo '    </div>';
    echo '  </nav>';
    echo '</header>';
}



function qh_set_flash(string $type, string $message): void
{
    $_SESSION['flash'] = ['type' => $type, 'message' => $message];
}

function qh_render_flash(): void
{
    if (empty($_SESSION['flash']) || !is_array($_SESSION['flash'])) {
        return;
    }

    $flash = $_SESSION['flash'];
    unset($_SESSION['flash']);

    $typeMap = [
        'success' => 'success',
        'danger' => 'danger',
        'warning' => 'warning',
        'info' => 'primary',
    ];
    $toastType = $typeMap[$flash['type']] ?? 'primary';

    echo '<div class="toast-container position-fixed top-0 end-0 p-3">';
    echo '  <div class="toast app-toast js-app-toast text-bg-' . qh_h($toastType) . ' border-0" role="status" aria-live="polite" aria-atomic="true">';
    echo '      <div class="d-flex">';
    echo '          <div class="toast-body">' . qh_h((string) $flash['message']) . '</div>';
    echo '          <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="' . qh_h(qh_t('Close', 'إغلاق')) . '"></button>';
    echo '      </div>';
    echo '  </div>';
    echo '</div>';
}



function qh_redirect(string $location): void
{
    if (strpos($location, 'lang=') === false) {
        $separator = str_contains($location, '?') ? '&' : '?';
        $location .= $separator . 'lang=' . qh_locale();
    }

    header('Location: ' . $location);
    exit;
}



function qh_fetch_clinics(): array
{
    $stmt = db()->query("SELECT * FROM hospital_queue_records WHERE item_type = 'clinic' ORDER BY sort_order ASC, name_en ASC");
    return $stmt->fetchAll();
}

function qh_fetch_doctors(?int $clinicId = null): array
{
    if ($clinicId) {
        $stmt = db()->prepare(
            "SELECT d.*, c.name_en AS clinic_name_en, c.name_ar AS clinic_name_ar, c.code AS clinic_code
             FROM hospital_queue_records d
             LEFT JOIN hospital_queue_records c ON c.id = d.clinic_id AND c.item_type = 'clinic'
             WHERE d.item_type = 'doctor' AND d.clinic_id = :clinic_id
             ORDER BY d.sort_order ASC, d.name_en ASC"
        );
        $stmt->execute(['clinic_id' => $clinicId]);
        return $stmt->fetchAll();
    }

    $stmt = db()->query(
        "SELECT d.*, c.name_en AS clinic_name_en, c.name_ar AS clinic_name_ar, c.code AS clinic_code
         FROM hospital_queue_records d
         LEFT JOIN hospital_queue_records c ON c.id = d.clinic_id AND c.item_type = 'clinic'
         WHERE d.item_type = 'doctor'
         ORDER BY c.sort_order ASC, d.sort_order ASC, d.name_en ASC"
    );
    return $stmt->fetchAll();
}

function qh_fetch_ticket(int $ticketId): ?array
{
    $stmt = db()->prepare(
        "SELECT t.*, c.name_en AS clinic_name_en, c.name_ar AS clinic_name_ar, c.code AS clinic_code, c.requires_vitals AS clinic_requires_vitals,
                d.name_en AS doctor_name_en, d.name_ar AS doctor_name_ar, d.room_number AS doctor_room
         FROM hospital_queue_records t
         LEFT JOIN hospital_queue_records c ON c.id = t.clinic_id AND c.item_type = 'clinic'
         LEFT JOIN hospital_queue_records d ON d.id = t.doctor_id AND d.item_type = 'doctor'
         WHERE t.item_type = 'ticket' AND t.id = :ticket_id
         LIMIT 1"
    );
    $stmt->execute(['ticket_id' => $ticketId]);
    $ticket = $stmt->fetch();
    return $ticket ?: null;
}

function qh_fetch_tickets(array $statuses = [], ?int $doctorId = null, ?int $limit = null): array
{
    $sql = "SELECT t.*, c.name_en AS clinic_name_en, c.name_ar AS clinic_name_ar, c.code AS clinic_code, c.requires_vitals AS clinic_requires_vitals,
                   d.name_en AS doctor_name_en, d.name_ar AS doctor_name_ar, d.room_number AS doctor_room
            FROM hospital_queue_records t
            LEFT JOIN hospital_queue_records c ON c.id = t.clinic_id AND c.item_type = 'clinic'
            LEFT JOIN hospital_queue_records d ON d.id = t.doctor_id AND d.item_type = 'doctor'
            WHERE t.item_type = 'ticket' AND DATE(t.created_at) = CURDATE()";

    $params = [];

    if ($statuses !== []) {
        $statusPlaceholders = [];
        foreach ($statuses as $index => $status) {
            $key = 'status_' . $index;
            $statusPlaceholders[] = ':' . $key;
            $params[$key] = $status;
        }
        $sql .= ' AND t.status IN (' . implode(', ', $statusPlaceholders) . ')';
    }

    if ($doctorId) {
        $sql .= ' AND t.doctor_id = :doctor_id';
        $params['doctor_id'] = $doctorId;
    }

    $sql .= ' ORDER BY COALESCE(t.called_at, t.created_at) DESC, t.id DESC';

    if ($limit) {
        $sql .= ' LIMIT ' . (int) $limit;
    }

    $stmt = db()->prepare($sql);
    $stmt->execute($params);
    return $stmt->fetchAll();
}


function qh_get_waiting_count_for_ticket(array $ticket): int
{
    try {
        $pdo = db();
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE() AND doctor_id = :doctor_id AND status IN ('waiting_vitals', 'nursing_called', 'ready_for_doctor', 'called', 'in_progress') AND id < :ticket_id");
        $stmt->execute(['doctor_id' => (int)$ticket['doctor_id'], 'ticket_id' => (int)$ticket['id']]);
        return (int) $stmt->fetchColumn();
    } catch (Throwable $e) {
        return 0;
    }
}

function qh_queue_overview(): array
{
    $sql = "SELECT c.id, c.name_en, c.name_ar, c.code, c.requires_vitals,
                   SUM(CASE WHEN t.status IN ('waiting_vitals', 'nursing_called') THEN 1 ELSE 0 END) AS vitals_waiting,
                   SUM(CASE WHEN t.status = 'ready_for_doctor' THEN 1 ELSE 0 END) AS doctor_waiting,
                   SUM(CASE WHEN t.status IN ('called', 'in_progress') THEN 1 ELSE 0 END) AS active_calls,
                   COUNT(t.id) AS total_today
            FROM hospital_queue_records c
            LEFT JOIN hospital_queue_records t
                ON t.clinic_id = c.id
               AND t.item_type = 'ticket'
               AND DATE(t.created_at) = CURDATE()
            WHERE c.item_type = 'clinic'
            GROUP BY c.id, c.name_en, c.name_ar, c.code, c.requires_vitals
            ORDER BY c.sort_order ASC, c.name_en ASC";

    return db()->query($sql)->fetchAll();
}

function qh_dashboard_stats(): array
{
    $pdo = db();
    return [
        'issued_today' => (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE()")->fetchColumn(),
        'waiting_vitals' => (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE() AND status IN ('waiting_vitals', 'nursing_called')")->fetchColumn(),
        'ready_for_doctor' => (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE() AND status = 'ready_for_doctor'")->fetchColumn(),
        'active_rooms' => (int) $pdo->query("SELECT COUNT(DISTINCT doctor_id) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE() AND status IN ('called', 'in_progress') AND doctor_id IS NOT NULL")->fetchColumn(),
    ];
}

function qh_create_ticket(string $patientName, int $clinicId, int $doctorId, string $languagePref = 'en', ?string $forcedStatus = null): int
{
    $pdo = db();
    $clinic = qh_fetch_clinic($clinicId);
    if (!$clinic) {
        throw new RuntimeException(qh_t('Clinic not found.', 'لم يتم العثور على العيادة.'));
    }

    $doctor = qh_fetch_doctor($doctorId);
    if (!$doctor || (int) $doctor['clinic_id'] !== $clinicId) {
        throw new RuntimeException(qh_t('The doctor does not belong to the selected clinic.', 'الطبيب لا يتبع العيادة المحددة.'));
    }

    $ticketNumber = qh_generate_ticket_number($clinic['code']);
    $status = $forcedStatus ?: ((int) $clinic['requires_vitals'] === 1 ? 'waiting_vitals' : 'ready_for_doctor');

    $stmt = $pdo->prepare(
        "INSERT INTO hospital_queue_records
            (item_type, clinic_id, doctor_id, patient_name, language_pref, ticket_number, status, display_note)
         VALUES
            ('ticket', :clinic_id, :doctor_id, :patient_name, :language_pref, :ticket_number, :status, :display_note)"
    );
    $stmt->execute([
        'clinic_id' => $clinicId,
        'doctor_id' => $doctorId,
        'patient_name' => $patientName,
        'language_pref' => in_array($languagePref, ['en', 'ar'], true) ? $languagePref : 'en',
        'ticket_number' => $ticketNumber,
        'status' => $status,
        'display_note' => $status === 'waiting_vitals'
            ? 'Proceed to nursing vitals first.'
            : 'Wait for your doctor call on the public screen.',
    ]);

    return (int) $pdo->lastInsertId();
}

function qh_generate_ticket_number(string $clinicCode): string
{
    $prefix = strtoupper(substr(preg_replace('/[^A-Z0-9]/i', '', $clinicCode), 0, 3));
    $stmt = db()->prepare(
        "SELECT COUNT(*)
         FROM hospital_queue_records
         WHERE item_type = 'ticket'
           AND DATE(created_at) = CURDATE()
           AND ticket_number LIKE :prefix"
    );
    $stmt->execute(['prefix' => $prefix . '-%']);
    $next = ((int) $stmt->fetchColumn()) + 1;
    return $prefix . '-' . str_pad((string) $next, 3, '0', STR_PAD_LEFT);
}

function qh_fetch_clinic(int $clinicId): ?array
{
    $stmt = db()->prepare("SELECT * FROM hospital_queue_records WHERE item_type = 'clinic' AND id = :id LIMIT 1");
    $stmt->execute(['id' => $clinicId]);
    $row = $stmt->fetch();
    return $row ?: null;
}

function qh_fetch_doctor(int $doctorId): ?array
{
    $stmt = db()->prepare("SELECT * FROM hospital_queue_records WHERE item_type = 'doctor' AND id = :id LIMIT 1");
    $stmt->execute(['id' => $doctorId]);
    $row = $stmt->fetch();
    return $row ?: null;
}

function qh_status_meta(string $status): array
{
    $map = [
        'waiting_vitals' => ['class' => 'warning', 'en' => 'Waiting for vitals', 'ar' => 'بانتظار العلامات الحيوية'],
        'nursing_called' => ['class' => 'primary', 'en' => 'Nursing Call', 'ar' => 'نداء التمريض'],
        'ready_for_doctor' => ['class' => 'info', 'en' => 'Ready for doctor', 'ar' => 'جاهز للطبيب'],
        'called' => ['class' => 'primary', 'en' => 'Called', 'ar' => 'تم النداء'],
        'in_progress' => ['class' => 'secondary', 'en' => 'In consultation', 'ar' => 'داخل العيادة'],
        'done' => ['class' => 'success', 'en' => 'Completed', 'ar' => 'مكتمل'],
        'no_show' => ['class' => 'danger', 'en' => 'No-show', 'ar' => 'لم يحضر'],
    ];

    return $map[$status] ?? ['class' => 'light', 'en' => ucfirst(str_replace('_', ' ', $status)), 'ar' => $status];
}

function qh_status_badge(string $status): string
{
    $meta = qh_status_meta($status);
    return '<span class="badge text-bg-' . qh_h($meta['class']) . ' status-badge">' . qh_h(qh_t($meta['en'], $meta['ar'])) . '</span>';
}



function qh_call_message(array $ticket): array
{
    $ticketNumber = $ticket['ticket_number'] ?? '---';
    // For English speech, replacing the hyphen with a space helps it say "DRR 001" instead of "DRR minus 001"
    $speechEn = strtoupper(str_replace('-', ' ', $ticketNumber));

    // Map English letters to Arabic phonetics so Arabic TTS pronounces them correctly
    $arMap = [
        'A'=>'إيه ', 'B'=>'بي ', 'C'=>'سي ', 'D'=>'دي ', 'E'=>'إي ', 'F'=>'إف ', 'G'=>'جي ', 'H'=>'إتش ',
        'I'=>'آي ', 'J'=>'جيه ', 'K'=>'كيه ', 'L'=>'إل ', 'M'=>'إم ', 'N'=>'إن ', 'O'=>'أو ', 'P'=>'بي ',
        'Q'=>'كيو ', 'R'=>'آر ', 'S'=>'إس ', 'T'=>'تي ', 'U'=>'يو ', 'V'=>'في ', 'W'=>'دبليو ', 'X'=>'إكس ',
        'Y'=>'واي ', 'Z'=>'زِد '
    ];
    $speechAr = trim(preg_replace('/ +/', ' ', strtr($speechEn, $arMap)));

    if (($ticket['status'] ?? '') === 'nursing_called') {
        return [
            'en' => sprintf('Ticket %s, please proceed to Nursing Station.', $ticketNumber),
            'ar' => sprintf('رقم التذكرة %s، يرجى التوجه إلى محطة التمريض.', $ticketNumber),
            'speech_en' => sprintf('Ticket %s, please proceed to Nursing Station.', $speechEn),
            'speech_ar' => sprintf('رقم التذكرة %s، يرجى التوجه إلى محطة التمريض.', $speechAr),
        ];
    }

    $doctorNameEn = $ticket['doctor_name_en'] ?? 'Doctor';
    $doctorNameAr = $ticket['doctor_name_ar'] ?? 'الطبيب';
    $room = $ticket['doctor_room'] ?? '--';

    return [
        'en' => sprintf('Ticket %s, please proceed to room %s for %s.', $ticketNumber, $room, $doctorNameEn),
        'ar' => sprintf('رقم التذكرة %s، يرجى التوجه إلى الغرفة %s إلى %s.', $ticketNumber, $room, $doctorNameAr),
        'speech_en' => sprintf('Ticket %s, please proceed to room %s for %s.', $speechEn, $room, $doctorNameEn),
        'speech_ar' => sprintf('رقم التذكرة %s، يرجى التوجه إلى الغرفة %s إلى %s.', $speechAr, $room, $doctorNameAr),
    ];
}

function qh_format_datetime(?string $value): string
{
    if (!$value) {
        return '—';
    }
    $timestamp = strtotime($value);
    return $timestamp ? date('M d, Y H:i', $timestamp) : '—';
}

function qh_require_post(): void
{
    if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
        qh_set_flash('danger', qh_t('Invalid request method.', 'طريقة الطلب غير صالحة.'));
        qh_redirect('index.php');
    }
}



function qh_handle_image_upload(string $inputName): string
{
    if (!isset($_FILES[$inputName]) || $_FILES[$inputName]['error'] !== UPLOAD_ERR_OK) {
        return '';
    }
    
    $tmpName = $_FILES[$inputName]['tmp_name'];
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    if ($finfo === false) return '';
    $mime = finfo_file($finfo, $tmpName);
    finfo_close($finfo);
    
    if (!is_string($mime) || !str_starts_with($mime, 'image/')) {
        throw new InvalidArgumentException(qh_t('Invalid image format.', 'تنسيق صورة غير صالح.'));
    }
    
    $ext = match ($mime) {
        'image/jpeg' => '.jpg',
        'image/png' => '.png',
        'image/gif' => '.gif',
        'image/webp' => '.webp',
        'image/svg+xml' => '.svg',
        'image/x-icon' => '.ico',
        'image/vnd.microsoft.icon' => '.ico',
        default => '.bin'
    };
    
    if ($ext === '.bin') {
        throw new InvalidArgumentException(qh_t('Unsupported image type.', 'نوع الصورة غير مدعوم.'));
    }
    
    $uploadDir = __DIR__ . '/assets/images/uploads';
    if (!is_dir($uploadDir)) {
        if (!mkdir($uploadDir, 0775, true)) {
            throw new RuntimeException(qh_t('Failed to create upload directory.', 'فشل إنشاء مجلد الرفع.'));
        }
    }
    
    $filename = uniqid('img_', true) . $ext;
    $dest = $uploadDir . '/' . $filename;
    
    if (!move_uploaded_file($tmpName, $dest)) {
        throw new RuntimeException(qh_t('Failed to save uploaded file.', 'فشل حفظ الملف المرفوع.'));
    }
    
    return 'assets/images/uploads/' . $filename;
}
function qh_admin_handle_request(): void
{
    if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
        return;
    }

    $action = trim((string) ($_POST['action'] ?? ''));
    if ($action === '' || in_array($action, ['add_video', 'delete_video', 'toggle_status', 'add_news', 'delete_news', 'toggle_news_status', 'create_user', 'update_user', 'delete_user'])) {
        return;
    }

    $returnTo = qh_admin_return_to($_POST['return_to'] ?? 'admin.php');
    $pdo = db();

    try {
        if ($action === 'add_clinic') {
            $code = strtoupper(trim((string) ($_POST['code'] ?? '')));
            $nameEn = trim((string) ($_POST['name_en'] ?? ''));
            $nameAr = trim((string) ($_POST['name_ar'] ?? ''));
            $requiresVitals = isset($_POST['requires_vitals']) ? 1 : 0;
            if ($code === '' || $nameEn === '' || $nameAr === '') {
                throw new InvalidArgumentException(qh_t('Please complete the clinic code and both clinic names.', 'يرجى إدخال رمز العيادة والاسمين الإنجليزي والعربي.'));
            }
            $stmt = $pdo->prepare(
                "INSERT INTO hospital_queue_records (item_type, code, name_en, name_ar, requires_vitals, sort_order, status)
                 VALUES ('clinic', :code, :name_en, :name_ar, :requires_vitals, :sort_order, 'active')"
            );
            $stmt->execute([
                'code' => substr($code, 0, 10),
                'name_en' => $nameEn,
                'name_ar' => $nameAr,
                'requires_vitals' => $requiresVitals,
                'sort_order' => max((int) ($_POST['sort_order'] ?? 50), 1),
            ]);
            qh_set_flash('success', qh_t('Clinic saved successfully.', 'تم حفظ العيادة بنجاح.'));
        } elseif ($action === 'update_clinic') {
            $clinicId = (int) ($_POST['clinic_id'] ?? 0);
            $code = strtoupper(trim((string) ($_POST['code'] ?? '')));
            $nameEn = trim((string) ($_POST['name_en'] ?? ''));
            $nameAr = trim((string) ($_POST['name_ar'] ?? ''));
            if ($clinicId <= 0 || $code === '' || $nameEn === '' || $nameAr === '') {
                throw new InvalidArgumentException(qh_t('Please complete the clinic details before updating.', 'يرجى إكمال بيانات العيادة قبل التحديث.'));
            }
            $stmt = $pdo->prepare(
                "UPDATE hospital_queue_records
                 SET code = :code,
                     name_en = :name_en,
                     name_ar = :name_ar,
                     requires_vitals = :requires_vitals,
                     sort_order = :sort_order
                 WHERE item_type = 'clinic' AND id = :clinic_id"
            );
            $stmt->execute([
                'code' => substr($code, 0, 10),
                'name_en' => $nameEn,
                'name_ar' => $nameAr,
                'requires_vitals' => isset($_POST['requires_vitals']) ? 1 : 0,
                'sort_order' => max((int) ($_POST['sort_order'] ?? 50), 1),
                'clinic_id' => $clinicId,
            ]);
            qh_set_flash('success', qh_t('Clinic updated successfully.', 'تم تحديث العيادة بنجاح.'));
        } elseif ($action === 'delete_clinic') {
            $clinicId = (int) ($_POST['clinic_id'] ?? 0);
            if ($clinicId <= 0) {
                throw new InvalidArgumentException(qh_t('Invalid clinic selected.', 'تم اختيار عيادة غير صالحة.'));
            }
            $doctorCountStmt = $pdo->prepare("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'doctor' AND clinic_id = :clinic_id");
            $doctorCountStmt->execute(['clinic_id' => $clinicId]);
            $doctorCount = (int) $doctorCountStmt->fetchColumn();
            $ticketCountStmt = $pdo->prepare("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND clinic_id = :clinic_id");
            $ticketCountStmt->execute(['clinic_id' => $clinicId]);
            $ticketCount = (int) $ticketCountStmt->fetchColumn();
            if ($doctorCount > 0 || $ticketCount > 0) {
                throw new InvalidArgumentException(qh_t('This clinic cannot be deleted because it is linked to doctors or patient tickets.', 'لا يمكن حذف هذه العيادة لأنها مرتبطة بأطباء أو تذاكر مرضى.'));
            }
            $stmt = $pdo->prepare("DELETE FROM hospital_queue_records WHERE item_type = 'clinic' AND id = :clinic_id");
            $stmt->execute(['clinic_id' => $clinicId]);
            qh_set_flash('success', qh_t('Clinic deleted successfully.', 'تم حذف العيادة بنجاح.'));
        } elseif ($action === 'add_doctor') {
            $nameEn = trim((string) ($_POST['name_en'] ?? ''));
            $nameAr = trim((string) ($_POST['name_ar'] ?? ''));
            $clinicId = (int) ($_POST['clinic_id'] ?? 0);
            $roomNumber = trim((string) ($_POST['room_number'] ?? ''));
            if ($nameEn === '' || $nameAr === '' || $clinicId <= 0 || $roomNumber === '') {
                throw new InvalidArgumentException(qh_t('Please complete the doctor form before saving.', 'يرجى إكمال بيانات الطبيب قبل الحفظ.'));
            }
            $stmt = $pdo->prepare(
                "INSERT INTO hospital_queue_records (item_type, name_en, name_ar, clinic_id, room_number, sort_order, status)
                 VALUES ('doctor', :name_en, :name_ar, :clinic_id, :room_number, :sort_order, 'active')"
            );
            $stmt->execute([
                'name_en' => $nameEn,
                'name_ar' => $nameAr,
                'clinic_id' => $clinicId,
                'room_number' => $roomNumber,
                'sort_order' => max((int) ($_POST['sort_order'] ?? 50), 1),
            ]);
            qh_set_flash('success', qh_t('Doctor profile saved.', 'تم حفظ ملف الطبيب.'));
        } elseif ($action === 'update_doctor') {
            $doctorId = (int) ($_POST['doctor_id'] ?? 0);
            $nameEn = trim((string) ($_POST['name_en'] ?? ''));
            $nameAr = trim((string) ($_POST['name_ar'] ?? ''));
            $clinicId = (int) ($_POST['clinic_id'] ?? 0);
            $roomNumber = trim((string) ($_POST['room_number'] ?? ''));
            if ($doctorId <= 0 || $nameEn === '' || $nameAr === '' || $clinicId <= 0 || $roomNumber === '') {
                throw new InvalidArgumentException(qh_t('Please complete the doctor details before updating.', 'يرجى إكمال بيانات الطبيب قبل التحديث.'));
            }
            $stmt = $pdo->prepare(
                "UPDATE hospital_queue_records
                 SET name_en = :name_en,
                     name_ar = :name_ar,
                     clinic_id = :clinic_id,
                     room_number = :room_number,
                     sort_order = :sort_order
                 WHERE item_type = 'doctor' AND id = :doctor_id"
            );
            $stmt->execute([
                'name_en' => $nameEn,
                'name_ar' => $nameAr,
                'clinic_id' => $clinicId,
                'room_number' => $roomNumber,
                'sort_order' => max((int) ($_POST['sort_order'] ?? 50), 1),
                'doctor_id' => $doctorId,
            ]);
            qh_set_flash('success', qh_t('Doctor assignment updated.', 'تم تحديث تعيين الطبيب.'));
        } elseif ($action === 'delete_doctor') {
            $doctorId = (int) ($_POST['doctor_id'] ?? 0);
            if ($doctorId <= 0) {
                throw new InvalidArgumentException(qh_t('Invalid doctor selected.', 'تم اختيار طبيب غير صالح.'));
            }
            $ticketCountStmt = $pdo->prepare("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND doctor_id = :doctor_id");
            $ticketCountStmt->execute(['doctor_id' => $doctorId]);
            $ticketCount = (int) $ticketCountStmt->fetchColumn();
            if ($ticketCount > 0) {
                throw new InvalidArgumentException(qh_t('This doctor cannot be deleted because patient tickets are linked to the profile.', 'لا يمكن حذف هذا الطبيب لأن هناك تذاكر مرضى مرتبطة بالملف.'));
            }
            $stmt = $pdo->prepare("DELETE FROM hospital_queue_records WHERE item_type = 'doctor' AND id = :doctor_id");
            $stmt->execute(['doctor_id' => $doctorId]);
            qh_set_flash('success', qh_t('Doctor deleted successfully.', 'تم حذف الطبيب بنجاح.'));
        } elseif ($action === 'save_hospital_profile') {
            $nameEn = trim((string) ($_POST['name_en'] ?? ''));
            $nameAr = trim((string) ($_POST['name_ar'] ?? ''));
            $shortName = trim((string) ($_POST['short_name'] ?? ''));
            $taglineEn = trim((string) ($_POST['tagline_en'] ?? ''));
            $taglineAr = trim((string) ($_POST['tagline_ar'] ?? ''));
            $phone = trim((string) ($_POST['phone'] ?? ''));
            $email = trim((string) ($_POST['email'] ?? ''));
            $website = trim((string) ($_POST['website'] ?? ''));
            $addressEn = trim((string) ($_POST['address_en'] ?? ''));
            $addressAr = trim((string) ($_POST['address_ar'] ?? ''));
            $workingHoursEn = trim((string) ($_POST['working_hours_en'] ?? ''));
            $workingHoursAr = trim((string) ($_POST['working_hours_ar'] ?? ''));
            $newsTickerEn = trim((string) ($_POST['news_ticker_en'] ?? ''));
            $newsTickerAr = trim((string) ($_POST['news_ticker_ar'] ?? ''));
            $timezone = trim((string) ($_POST['timezone'] ?? ''));
            if ($timezone === '' || !in_array($timezone, timezone_identifiers_list(), true)) $timezone = 'UTC';
            $defaultLanguage = trim((string) ($_POST['default_language'] ?? 'en'));
            if (!in_array($defaultLanguage, ['en', 'ar'], true)) $defaultLanguage = 'en';
            $profile = qh_fetch_hospital_profile();
            $logoUrl = $profile['logo_url'] ?? '';
            $faviconUrl = $profile['favicon_url'] ?? '';

            if (!empty($_POST['remove_logo'])) {
                $logoUrl = '';
            } else {
                $newLogo = qh_handle_image_upload('logo_upload');
                if ($newLogo !== '') $logoUrl = $newLogo;
            }

            if (!empty($_POST['remove_favicon'])) {
                $faviconUrl = '';
            } else {
                $newFavicon = qh_handle_image_upload('favicon_upload');
                if ($newFavicon !== '') $faviconUrl = $newFavicon;
            }
            $primaryColor = qh_sanitize_hex_color($_POST['primary_color'] ?? '', '#0F8B8D');
            $secondaryColor = qh_sanitize_hex_color($_POST['secondary_color'] ?? '', '#16697A');

            if ($nameEn === '' || $nameAr === '') {
                throw new InvalidArgumentException(qh_t('Please enter both the English and Arabic hospital names.', 'يرجى إدخال اسم المستشفى بالإنجليزية والعربية.'));
            }
            if ($email !== '' && filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
                throw new InvalidArgumentException(qh_t('Please enter a valid hospital email address.', 'يرجى إدخال بريد إلكتروني صالح للمستشفى.'));
            }
            if ($website !== '' && filter_var($website, FILTER_VALIDATE_URL) === false) {
                throw new InvalidArgumentException(qh_t('Please enter a valid website URL.', 'يرجى إدخال رابط موقع صالح.'));
            }


            $stmt = $pdo->prepare(
                "UPDATE hospital_profile_settings
                 SET name_en = :name_en,
                     name_ar = :name_ar,
                     short_name = :short_name,
                     tagline_en = :tagline_en,
                     tagline_ar = :tagline_ar,
                     phone = :phone,
                     email = :email,
                     website = :website,
                     address_en = :address_en,
                     address_ar = :address_ar,
                     working_hours_en = :working_hours_en,
                     working_hours_ar = :working_hours_ar,
                     logo_url = :logo_url,
                     favicon_url = :favicon_url,
                     primary_color = :primary_color,
                     secondary_color = :secondary_color,
                     news_ticker_en = :news_ticker_en,
                     news_ticker_ar = :news_ticker_ar,
                     timezone = :timezone,
                     default_language = :default_language
                 WHERE id = 1"
            );
            $stmt->execute([
                'name_en' => $nameEn,
                'name_ar' => $nameAr,
                'short_name' => substr($shortName, 0, 40),
                'tagline_en' => $taglineEn,
                'tagline_ar' => $taglineAr,
                'phone' => $phone,
                'email' => $email,
                'website' => $website,
                'address_en' => $addressEn,
                'address_ar' => $addressAr,
                'working_hours_en' => $workingHoursEn,
                'working_hours_ar' => $workingHoursAr,
                'logo_url' => $logoUrl,
                'favicon_url' => $faviconUrl,
                'primary_color' => $primaryColor,
                'secondary_color' => $secondaryColor,
                'news_ticker_en' => $newsTickerEn,
                'news_ticker_ar' => $newsTickerAr,
                'timezone' => $timezone,
                'default_language' => $defaultLanguage,
            ]);
            qh_set_flash('success', qh_t('Hospital profile updated successfully.', 'تم تحديث ملف المستشفى بنجاح.'));
        }
    } catch (Throwable $exception) {
        qh_set_flash('danger', $exception->getMessage());
    }

    qh_redirect($returnTo);
}

function qh_reception_handle_request(): void
{
    if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
        return;
    }

    try {
        $patientName = trim((string) ($_POST['patient_name'] ?? ''));
        $clinicId = (int) ($_POST['clinic_id'] ?? 0);
        $doctorId = (int) ($_POST['doctor_id'] ?? 0);
        $languagePref = trim((string) ($_POST['language_pref'] ?? 'en'));

        if ($patientName === '' || $clinicId <= 0 || $doctorId <= 0) {
            throw new InvalidArgumentException(qh_t('Please complete the patient name, clinic, and doctor.', 'يرجى إدخال اسم المريض والعيادة والطبيب.'));
        }

        $ticketId = qh_create_ticket($patientName, $clinicId, $doctorId, $languagePref);
        qh_set_flash('success', qh_t('Ticket issued successfully.', 'تم إصدار التذكرة بنجاح.'));
        qh_redirect('reception.php?ticket_id=' . $ticketId);
    } catch (Throwable $exception) {
        qh_set_flash('danger', $exception->getMessage());
        qh_redirect('reception.php');
    }
}

function qh_nursing_handle_request(): void
{
    if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
        return;
    }

    try {
        $ticketId = (int) ($_POST['ticket_id'] ?? 0);
        $action = trim((string) ($_POST['action'] ?? 'send'));
        
        $ticket = qh_fetch_ticket($ticketId);
        if (!$ticket) throw new InvalidArgumentException(qh_t('Invalid ticket.', 'تذكرة غير صالحة.'));

        if ($action === 'call_ticket') {
            $stmt = db()->prepare(
                "UPDATE hospital_queue_records
                 SET status = 'nursing_called', called_at = NOW(), display_note = :display_note
                 WHERE item_type = 'ticket' AND id = :ticket_id"
            );
            $stmt->execute([
                'display_note' => sprintf('Ticket %s, proceed to Nursing Station.', $ticket['ticket_number']),
                'ticket_id' => $ticketId
            ]);
            qh_set_flash('success', qh_t('Patient call was sent to the public display.', 'تم إرسال نداء المريض إلى الشاشة العامة.'));
        } else {
            $vitalsNotes = trim((string) ($_POST['vitals_notes'] ?? ''));
            if ($vitalsNotes === '') throw new InvalidArgumentException(qh_t('Please add a short vitals note before sending the patient forward.', 'يرجى إضافة ملاحظة قصيرة للعلامات الحيوية قبل إرسال المريض.'));

            $stmt = db()->prepare(
                "UPDATE hospital_queue_records
                 SET vitals_notes = :vitals_notes,
                     status = 'ready_for_doctor',
                     display_note = 'Vitals completed. Wait for doctor call.'
                 WHERE item_type = 'ticket' AND id = :ticket_id AND status IN ('waiting_vitals', 'nursing_called')"
            );
            $stmt->execute([
                'vitals_notes' => $vitalsNotes,
                'ticket_id' => $ticketId,
            ]);
            qh_set_flash('success', qh_t('Vitals captured and patient moved to the doctor queue.', 'تم حفظ العلامات الحيوية ونقل المريض إلى طابور الطبيب.'));
        }
    } catch (Throwable $exception) {
        qh_set_flash('danger', $exception->getMessage());
    }

    qh_redirect('nursing.php');
}

function qh_doctor_handle_request(): void
{
    if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
        return;
    }

    try {
        $ticketId = (int) ($_POST['ticket_id'] ?? 0);
        $doctorId = (int) ($_POST['doctor_id'] ?? 0);
        $action = trim((string) ($_POST['action'] ?? ''));
        $ticket = qh_fetch_ticket($ticketId);
        if (!$ticket || $doctorId <= 0 || (int) $ticket['doctor_id'] !== $doctorId) {
            throw new InvalidArgumentException(qh_t('That ticket is not available for the selected doctor.', 'هذه التذكرة غير متاحة للطبيب المحدد.'));
        }

        if ($action === 'call_ticket') {
            $message = qh_call_message($ticket);
            $stmt = db()->prepare(
                "UPDATE hospital_queue_records
                 SET status = 'called', called_at = NOW(), display_note = :display_note
                 WHERE item_type = 'ticket' AND id = :ticket_id"
            );
            $stmt->execute([
                'display_note' => $message['en'],
                'ticket_id' => $ticketId,
            ]);
            qh_set_flash('success', qh_t('Patient call was sent to the public display.', 'تم إرسال نداء المريض إلى الشاشة العامة.'));
        } elseif ($action === 'start_visit') {
            $stmt = db()->prepare(
                "UPDATE hospital_queue_records
                 SET status = 'in_progress', display_note = 'Patient is now in consultation.'
                 WHERE item_type = 'ticket' AND id = :ticket_id"
            );
            $stmt->execute(['ticket_id' => $ticketId]);
            qh_set_flash('success', qh_t('Consultation started.', 'بدأت الاستشارة.'));
        } elseif ($action === 'complete_ticket') {
            $stmt = db()->prepare(
                "UPDATE hospital_queue_records
                 SET status = 'done', served_at = NOW(), display_note = 'Visit completed.'
                 WHERE item_type = 'ticket' AND id = :ticket_id"
            );
            $stmt->execute(['ticket_id' => $ticketId]);
            qh_set_flash('success', qh_t('Visit marked as completed.', 'تم إنهاء الزيارة.'));
        } elseif ($action === 'refer_ticket') {
            $referToDoctorId = (int) ($_POST["refer_to_doctor_id"] ?? 0);
            if ($referToDoctorId <= 0 || $referToDoctorId === $doctorId) {
                throw new InvalidArgumentException(qh_t('Please select a valid doctor to refer the patient to.', 'يرجى اختيار طبيب صالح لتحويل المريض إليه.'));
            }
            $stmt = db()->prepare(
                "UPDATE hospital_queue_records
                 SET status = 'ready_for_doctor', doctor_id = :refer_to_doctor_id, display_note = 'Referred'
                 WHERE item_type = 'ticket' AND id = :ticket_id"
            );
            $stmt->execute([
                'refer_to_doctor_id' => $referToDoctorId,
                'ticket_id' => $ticketId,
            ]);
            qh_set_flash('success', qh_t('Patient referred successfully.', 'تم تحويل المريض بنجاح.'));
        } elseif ($action === 'mark_no_show') {
            $stmt = db()->prepare(
                "UPDATE hospital_queue_records
                 SET status = 'no_show', served_at = NOW(), display_note = 'Marked as no-show.'
                 WHERE item_type = 'ticket' AND id = :ticket_id"
            );
            $stmt->execute(['ticket_id' => $ticketId]);
            qh_set_flash('warning', qh_t('Patient marked as no-show.', 'تم تسجيل المريض كحالة عدم حضور.'));
        }

        qh_redirect('doctor.php?doctor_id=' . $doctorId);
    } catch (Throwable $exception) {
        qh_set_flash('danger', $exception->getMessage());
        qh_redirect('doctor.php');
    }
}
