<?php
declare(strict_types=1);

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

require_login($conn);

function nav_link_inner(string $label, string $icon): string
{
    return '<span class="nav-link-icon" aria-hidden="true">' . nav_icon($icon) . '</span>'
        . '<span class="nav-link-label">' . e($label) . '</span>';
}

function preferred_report_page(mysqli $conn): string
{
    if (can_access($conn, 'sale_report')) {
        return 'sale_report.php';
    }

    if (can_access($conn, 'report_service')) {
        return 'report_service.php';
    }

    if (can_access($conn, 'void_report')) {
        return 'void_report.php';
    }

    if (can_access($conn, 'audit_report')) {
        return 'audit_report.php';
    }

    return 'report_service.php';
}

function ui_text(string $th, string $en): string
{
    return current_language() === 'th' ? $th : $en;
}

function notification_center_order_href(mysqli $conn, array $row): string
{
    $orderId = (int) ($row['order_id'] ?? 0);
    $orderSource = (string) ($row['order_source'] ?? 'booking');
    $status = strtolower(trim((string) ($row['status'] ?? '')));
    $paymentStatus = strtolower(trim((string) ($row['payment_status'] ?? '')));

    if ($orderId <= 0) {
        return '';
    }

    if ($orderSource === 'quick_service') {
        if (
            $status === 'waiting'
            && in_array($paymentStatus, array('unpaid', 'partial'), true)
            && can_access($conn, 'quick_service')
        ) {
            return 'quick_service.php?id=' . $orderId;
        }

        if (can_access($conn, 'queue')) {
            return 'job_details.php?id=' . $orderId;
        }

        if (can_access($conn, 'quick_service')) {
            return 'quick_service.php?id=' . $orderId;
        }

        return '';
    }

    if (can_access($conn, 'queue')) {
        return 'job_details.php?id=' . $orderId;
    }

    return '';
}

function notification_center_data_legacy(mysqli $conn): array
{
    static $cache = array();

    $cacheKey = current_language() . '|' . auth_scope($conn) . '|' . implode('|', auth_assigned_branches($conn));
    if (isset($cache[$cacheKey])) {
        return $cache[$cacheKey];
    }

    $todayStart = date('Y-m-d 00:00:00');
    $tomorrowStart = date('Y-m-d 00:00:00', strtotime('+1 day'));

    $summaryTypes = 'sss';
    $summaryParams = array($tomorrowStart, $todayStart, $tomorrowStart);
    $summaryWhere = array('o.status <> \'cancelled\'');
    $branchCondition = auth_branch_condition($conn, 'o', $summaryTypes, $summaryParams);
    if ($branchCondition !== '') {
        $summaryWhere[] = $branchCondition;
    }

    $summaryStmt = db_prepare($conn, "
        SELECT
            SUM(CASE WHEN o.payment_status <> 'paid' THEN 1 ELSE 0 END) AS outstanding_total,
            SUM(CASE WHEN o.order_source = 'booking' AND o.return_at IS NOT NULL AND o.return_at < ? THEN 1 ELSE 0 END) AS pickup_total,
            SUM(CASE WHEN o.order_source = 'booking' AND o.status = 'waiting' THEN 1 ELSE 0 END) AS waiting_total,
            SUM(CASE WHEN o.order_source = 'booking' AND o.order_date >= ? AND o.order_date < ? THEN 1 ELSE 0 END) AS new_booking_total
        FROM orders o
        WHERE " . implode(' AND ', $summaryWhere) . "
    ");
    $summaryStmt->bind_param($summaryTypes, ...$summaryParams);
    $summaryStmt->execute();
    $summaryRow = $summaryStmt->get_result()->fetch_assoc() ?: array();
    $summaryStmt->close();

    $sections = array(
        'outstanding' => array(
            'key' => 'outstanding',
            'label' => ui_text('บิลค้างชำระ', 'Outstanding bills'),
            'count' => (int) ($summaryRow['outstanding_total'] ?? 0),
            'tone' => 'danger',
            'items' => array(),
        ),
        'pickup' => array(
            'key' => 'pickup',
            'label' => ui_text('รถถึงกำหนดรับ', 'Pickup due'),
            'count' => (int) ($summaryRow['pickup_total'] ?? 0),
            'tone' => 'warning',
            'items' => array(),
        ),
        'waiting' => array(
            'key' => 'waiting',
            'label' => ui_text('คิวรอดำเนินการ', 'Waiting queue'),
            'count' => (int) ($summaryRow['waiting_total'] ?? 0),
            'tone' => 'info',
            'items' => array(),
        ),
        'new_booking' => array(
            'key' => 'new_booking',
            'label' => ui_text('booking งานใหม่', 'New bookings'),
            'count' => (int) ($summaryRow['new_booking_total'] ?? 0),
            'tone' => 'success',
            'items' => array(),
        ),
    );

    if ($sections['outstanding']['count'] > 0) {
        $types = '';
        $params = array();
        $where = array(
            "o.status <> 'cancelled'",
            "o.payment_status <> 'paid'",
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.order_date,
                o.status,
                o.payment_status,
                o.total_price,
                c.name AS customer_name,
                car.plate_number
            FROM orders o
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY
                CASE WHEN o.status = 'done' THEN 0 ELSE 1 END,
                o.order_date DESC,
                o.order_id DESC
            LIMIT 5
        ");
        if ($types !== '') {
            $stmt->bind_param($types, ...$params);
        }
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $billLabel = trim((string) ($row['bill_number'] ?? '')) !== ''
                    ? (string) $row['bill_number']
                    : '#' . (int) ($row['order_id'] ?? 0);
                $balance = max((float) ($row['total_price'] ?? 0) - (float) ($row['paid_amount'] ?? 0), 0);
                $sections['outstanding']['items'][] = array(
                    'title' => $billLabel . ' • ' . trim((string) ($row['plate_number'] ?? '-')),
                    'meta' => implode(' • ', array_filter(array(
                        trim((string) ($row['customer_name'] ?? '')),
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('ค้างชำระ ', 'Balance ') . format_money($balance) . ' • ' . payment_status_label((string) ($row['payment_status'] ?? 'unpaid')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    if ($sections['pickup']['count'] > 0) {
        $types = 's';
        $params = array($tomorrowStart);
        $where = array(
            "o.order_source = 'booking'",
            "o.status <> 'cancelled'",
            'o.return_at IS NOT NULL',
            'o.return_at < ?',
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.return_at,
                c.name AS customer_name,
                car.plate_number
            FROM orders o
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY o.return_at ASC, o.order_id ASC
            LIMIT 5
        ");
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $billLabel = trim((string) ($row['bill_number'] ?? '')) !== ''
                    ? (string) $row['bill_number']
                    : '#' . (int) ($row['order_id'] ?? 0);
                $sections['pickup']['items'][] = array(
                    'title' => trim((string) ($row['plate_number'] ?? '-')) . ' • ' . trim((string) ($row['customer_name'] ?? '')),
                    'meta' => implode(' • ', array_filter(array(
                        $billLabel,
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('กำหนดรับ ', 'Pickup due ') . format_datetime((string) ($row['return_at'] ?? '')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    if ($sections['waiting']['count'] > 0) {
        $types = '';
        $params = array();
        $where = array(
            "o.order_source = 'booking'",
            "o.status = 'waiting'",
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.payment_status,
                o.order_date,
                c.name AS customer_name,
                car.plate_number,
                q.queue_number
            FROM orders o
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            LEFT JOIN queue q ON q.order_id = o.order_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY COALESCE(q.created_at, o.order_date) ASC, o.order_id ASC
            LIMIT 5
        ");
        if ($types !== '') {
            $stmt->bind_param($types, ...$params);
        }
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $queueLabel = (int) ($row['queue_number'] ?? 0) > 0
                    ? ui_text('คิว #', 'Queue #') . (int) ($row['queue_number'] ?? 0)
                    : ui_text('รอดำเนินการ', 'Waiting');
                $sections['waiting']['items'][] = array(
                    'title' => $queueLabel . ' • ' . trim((string) ($row['plate_number'] ?? '-')),
                    'meta' => implode(' • ', array_filter(array(
                        trim((string) ($row['customer_name'] ?? '')),
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('เปิดงาน ', 'Booked ') . format_datetime((string) ($row['order_date'] ?? '')) . ' • ' . payment_status_label((string) ($row['payment_status'] ?? 'unpaid')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    if ($sections['new_booking']['count'] > 0) {
        $types = 'ss';
        $params = array($todayStart, $tomorrowStart);
        $where = array(
            "o.order_source = 'booking'",
            "o.status <> 'cancelled'",
            'o.order_date >= ?',
            'o.order_date < ?',
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.order_date,
                c.name AS customer_name,
                car.plate_number
            FROM orders o
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY o.order_date DESC, o.order_id DESC
            LIMIT 5
        ");
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $billLabel = trim((string) ($row['bill_number'] ?? '')) !== ''
                    ? (string) $row['bill_number']
                    : '#' . (int) ($row['order_id'] ?? 0);
                $sections['new_booking']['items'][] = array(
                    'title' => $billLabel . ' • ' . trim((string) ($row['plate_number'] ?? '-')),
                    'meta' => implode(' • ', array_filter(array(
                        trim((string) ($row['customer_name'] ?? '')),
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('งานใหม่เวลา ', 'New booking at ') . format_datetime((string) ($row['order_date'] ?? '')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    $total = 0;
    foreach ($sections as $section) {
        $total += (int) ($section['count'] ?? 0);
    }

    $cache[$cacheKey] = array(
        'total' => $total,
        'sections' => array_values($sections),
    );

    return $cache[$cacheKey];
}

function render_notification_center_legacy(mysqli $conn, string $buttonClass = '', string $contextClass = ''): string
{
    $data = notification_center_data($conn);
    $total = (int) ($data['total'] ?? 0);
    $sections = is_array($data['sections'] ?? null) ? $data['sections'] : array();
    $buttonClasses = trim('notification-toggle ' . $buttonClass . ($total > 0 ? ' has-alerts' : ''));
    $wrapperClasses = trim('notification-center ' . $contextClass);
    $badgeLabel = $total > 99 ? '99+' : (string) $total;
    $headerTitle = ui_text('การแจ้งเตือน', 'Notifications');
    $headerSubline = $total > 0
        ? (current_language() === 'th' ? 'มี ' . $total . ' รายการต้องติดตาม' : $total . ' items need attention')
        : ui_text('ไม่มีรายการที่ต้องติดตาม', 'No items need attention');

    $summaryCards = array();
    $sectionMarkup = array();

    foreach ($sections as $section) {
        $count = (int) ($section['count'] ?? 0);
        $label = (string) ($section['label'] ?? '');
        $tone = (string) ($section['tone'] ?? 'info');
        $items = is_array($section['items'] ?? null) ? $section['items'] : array();

        $summaryCards[] = '<article class="notification-summary-card is-' . e($tone) . '">'
            . '<span>' . e($label) . '</span>'
            . '<strong>' . $count . '</strong>'
            . '</article>';

        if ($count <= 0) {
            continue;
        }

        $rows = array();
        foreach ($items as $item) {
            $title = (string) ($item['title'] ?? '');
            $meta = (string) ($item['meta'] ?? '');
            $aux = (string) ($item['aux'] ?? '');
            $href = (string) ($item['href'] ?? '');
            $inner = '<span class="notification-item-title">' . e($title) . '</span>'
                . ($meta !== '' ? '<span class="notification-item-meta">' . e($meta) . '</span>' : '')
                . ($aux !== '' ? '<span class="notification-item-aux">' . e($aux) . '</span>' : '');

            if ($href !== '') {
                $rows[] = '<a class="notification-item" href="' . e($href) . '">' . $inner . '</a>';
            } else {
                $rows[] = '<div class="notification-item is-static">' . $inner . '</div>';
            }
        }

        $sectionMarkup[] = '<section class="notification-section is-' . e($tone) . '">'
            . '<div class="notification-section-head">'
            . '<strong>' . e($label) . '</strong>'
            . '<span>' . $count . '</span>'
            . '</div>'
            . implode('', $rows)
            . '</section>';
    }

    if (empty($sectionMarkup)) {
        $sectionMarkup[] = '<div class="notification-empty-state">' . e(ui_text('ยังไม่มีรายการแจ้งเตือนในตอนนี้', 'There are no active notifications right now.')) . '</div>';
    }

    return '<div class="' . e($wrapperClasses) . '" data-notification-center>'
        . '<button class="' . e($buttonClasses) . '" type="button" aria-label="' . e($headerTitle) . '" aria-expanded="false" data-notification-toggle>'
        . nav_icon('bell')
        . ($total > 0 ? '<span class="notification-toggle-badge">' . e($badgeLabel) . '</span>' : '')
        . '</button>'
        . '<section class="notification-panel" hidden data-notification-panel>'
        . '<div class="notification-panel-head">'
        . '<strong>' . e($headerTitle) . '</strong>'
        . '<small>' . e($headerSubline) . '</small>'
        . '</div>'
        . '<div class="notification-summary-grid">'
        . implode('', $summaryCards)
        . '</div>'
        . '<div class="notification-section-list">'
        . implode('', $sectionMarkup)
        . '</div>'
        . '</section>'
        . '</div>';
}

function notification_center_data(mysqli $conn): array
{
    static $cache = array();

    $cacheKey = current_language() . '|' . auth_scope($conn) . '|' . implode('|', auth_assigned_branches($conn));
    if (isset($cache[$cacheKey])) {
        return $cache[$cacheKey];
    }

    $todayStart = date('Y-m-d 00:00:00');
    $tomorrowStart = date('Y-m-d 00:00:00', strtotime('+1 day'));

    $summaryTypes = 'sss';
    $summaryParams = array($tomorrowStart, $todayStart, $tomorrowStart);
    $summaryWhere = array('o.status <> \'cancelled\'');
    $branchCondition = auth_branch_condition($conn, 'o', $summaryTypes, $summaryParams);
    if ($branchCondition !== '') {
        $summaryWhere[] = $branchCondition;
    }

    $summaryStmt = db_prepare($conn, "
        SELECT
            SUM(CASE WHEN o.payment_status <> 'paid' THEN 1 ELSE 0 END) AS outstanding_total,
            SUM(CASE WHEN o.order_source = 'booking' AND o.return_at IS NOT NULL AND o.return_at < ? THEN 1 ELSE 0 END) AS pickup_total,
            SUM(CASE WHEN o.order_source = 'booking' AND o.status = 'waiting' THEN 1 ELSE 0 END) AS waiting_total,
            SUM(CASE WHEN o.order_source = 'booking' AND o.order_date >= ? AND o.order_date < ? THEN 1 ELSE 0 END) AS new_booking_total
        FROM orders o
        WHERE " . implode(' AND ', $summaryWhere) . "
    ");
    $summaryStmt->bind_param($summaryTypes, ...$summaryParams);
    $summaryStmt->execute();
    $summaryRow = $summaryStmt->get_result()->fetch_assoc() ?: array();
    $summaryStmt->close();

    $sections = array(
        'outstanding' => array(
            'key' => 'outstanding',
            'label' => ui_text('บิลค้างชำระ', 'Outstanding bills'),
            'count' => (int) ($summaryRow['outstanding_total'] ?? 0),
            'tone' => 'danger',
            'items' => array(),
        ),
        'pickup' => array(
            'key' => 'pickup',
            'label' => ui_text('รถถึงกำหนดรับ', 'Pickup due'),
            'count' => (int) ($summaryRow['pickup_total'] ?? 0),
            'tone' => 'warning',
            'items' => array(),
        ),
        'waiting' => array(
            'key' => 'waiting',
            'label' => ui_text('คิวรอดำเนินการ', 'Waiting queue'),
            'count' => (int) ($summaryRow['waiting_total'] ?? 0),
            'tone' => 'info',
            'items' => array(),
        ),
        'new_booking' => array(
            'key' => 'new_booking',
            'label' => ui_text('Booking งานใหม่', 'New bookings'),
            'count' => (int) ($summaryRow['new_booking_total'] ?? 0),
            'tone' => 'success',
            'items' => array(),
        ),
    );

    if ($sections['outstanding']['count'] > 0) {
        $types = '';
        $params = array();
        $where = array(
            "o.status <> 'cancelled'",
            "o.payment_status <> 'paid'",
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.order_date,
                o.status,
                o.payment_status,
                o.total_price,
                c.name AS customer_name,
                car.plate_number,
                COALESCE(payments.paid_amount, 0) AS paid_amount
            FROM orders o
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            LEFT JOIN (
                SELECT order_id, SUM(amount) AS paid_amount
                FROM payments
                GROUP BY order_id
            ) payments ON payments.order_id = o.order_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY
                CASE WHEN o.status = 'done' THEN 0 ELSE 1 END,
                o.order_date DESC,
                o.order_id DESC
            LIMIT 5
        ");
        if ($types !== '') {
            $stmt->bind_param($types, ...$params);
        }
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $billLabel = trim((string) ($row['bill_number'] ?? '')) !== ''
                    ? (string) $row['bill_number']
                    : '#' . (int) ($row['order_id'] ?? 0);
                $balance = max((float) ($row['total_price'] ?? 0) - (float) ($row['paid_amount'] ?? 0), 0);
                $sections['outstanding']['items'][] = array(
                    'title' => $billLabel . ' / ' . trim((string) ($row['plate_number'] ?? '-')),
                    'meta' => implode(' / ', array_filter(array(
                        trim((string) ($row['customer_name'] ?? '')),
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('ค้างชำระ ', 'Balance ')
                        . format_money($balance)
                        . ' / '
                        . payment_status_label((string) ($row['payment_status'] ?? 'unpaid')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    if ($sections['pickup']['count'] > 0) {
        $types = 's';
        $params = array($tomorrowStart);
        $where = array(
            "o.order_source = 'booking'",
            "o.status <> 'cancelled'",
            'o.return_at IS NOT NULL',
            'o.return_at < ?',
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.return_at,
                c.name AS customer_name,
                car.plate_number
            FROM orders o
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY o.return_at ASC, o.order_id ASC
            LIMIT 5
        ");
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $billLabel = trim((string) ($row['bill_number'] ?? '')) !== ''
                    ? (string) $row['bill_number']
                    : '#' . (int) ($row['order_id'] ?? 0);
                $sections['pickup']['items'][] = array(
                    'title' => trim((string) ($row['plate_number'] ?? '-')) . ' / ' . trim((string) ($row['customer_name'] ?? '')),
                    'meta' => implode(' / ', array_filter(array(
                        $billLabel,
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('กำหนดรับ ', 'Pickup due ') . format_datetime((string) ($row['return_at'] ?? '')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    if ($sections['waiting']['count'] > 0) {
        $types = '';
        $params = array();
        $where = array(
            "o.order_source = 'booking'",
            "o.status = 'waiting'",
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.payment_status,
                o.order_date,
                c.name AS customer_name,
                car.plate_number,
                q.queue_number
            FROM orders o
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            LEFT JOIN queue q ON q.order_id = o.order_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY COALESCE(q.created_at, o.order_date) ASC, o.order_id ASC
            LIMIT 5
        ");
        if ($types !== '') {
            $stmt->bind_param($types, ...$params);
        }
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $queueLabel = (int) ($row['queue_number'] ?? 0) > 0
                    ? ui_text('คิว #', 'Queue #') . (int) ($row['queue_number'] ?? 0)
                    : ui_text('รอดำเนินการ', 'Waiting');
                $sections['waiting']['items'][] = array(
                    'title' => $queueLabel . ' / ' . trim((string) ($row['plate_number'] ?? '-')),
                    'meta' => implode(' / ', array_filter(array(
                        trim((string) ($row['customer_name'] ?? '')),
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('เปิดงาน ', 'Booked ')
                        . format_datetime((string) ($row['order_date'] ?? ''))
                        . ' / '
                        . payment_status_label((string) ($row['payment_status'] ?? 'unpaid')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    if ($sections['new_booking']['count'] > 0) {
        $types = 'ss';
        $params = array($todayStart, $tomorrowStart);
        $where = array(
            "o.order_source = 'booking'",
            "o.status <> 'cancelled'",
            'o.order_date >= ?',
            'o.order_date < ?',
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.order_date,
                c.name AS customer_name,
                car.plate_number
            FROM orders o
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY o.order_date DESC, o.order_id DESC
            LIMIT 5
        ");
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $billLabel = trim((string) ($row['bill_number'] ?? '')) !== ''
                    ? (string) $row['bill_number']
                    : '#' . (int) ($row['order_id'] ?? 0);
                $sections['new_booking']['items'][] = array(
                    'title' => $billLabel . ' / ' . trim((string) ($row['plate_number'] ?? '-')),
                    'meta' => implode(' / ', array_filter(array(
                        trim((string) ($row['customer_name'] ?? '')),
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('งานใหม่เวลา ', 'New booking at ') . format_datetime((string) ($row['order_date'] ?? '')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    $total = 0;
    foreach ($sections as $section) {
        $total += (int) ($section['count'] ?? 0);
    }

    $cache[$cacheKey] = array(
        'total' => $total,
        'sections' => array_values($sections),
    );

    return $cache[$cacheKey];
}

function notification_center_data_optimized(mysqli $conn): array
{
    static $cache = array();

    $cacheKey = current_language() . '|' . auth_scope($conn) . '|' . implode('|', auth_assigned_branches($conn));
    if (isset($cache[$cacheKey])) {
        return $cache[$cacheKey];
    }

    $todayStart = date('Y-m-d 00:00:00');
    $tomorrowStart = date('Y-m-d 00:00:00', strtotime('+1 day'));

    $summaryTypes = 'sss';
    $summaryParams = array($tomorrowStart, $todayStart, $tomorrowStart);
    $summaryWhere = array("o.status <> 'cancelled'");
    $branchCondition = auth_branch_condition($conn, 'o', $summaryTypes, $summaryParams);
    if ($branchCondition !== '') {
        $summaryWhere[] = $branchCondition;
    }

    $summaryStmt = db_prepare($conn, "
        SELECT
            SUM(CASE WHEN o.payment_status <> 'paid' THEN 1 ELSE 0 END) AS outstanding_total,
            SUM(CASE WHEN o.order_source = 'booking' AND o.return_at IS NOT NULL AND o.return_at < ? THEN 1 ELSE 0 END) AS pickup_total,
            SUM(CASE WHEN o.order_source = 'booking' AND o.status = 'waiting' THEN 1 ELSE 0 END) AS waiting_total,
            SUM(CASE WHEN o.order_source = 'booking' AND o.order_date >= ? AND o.order_date < ? THEN 1 ELSE 0 END) AS new_booking_total
        FROM orders o
        WHERE " . implode(' AND ', $summaryWhere) . "
    ");
    $summaryStmt->bind_param($summaryTypes, ...$summaryParams);
    $summaryStmt->execute();
    $summaryRow = $summaryStmt->get_result()->fetch_assoc() ?: array();
    $summaryStmt->close();

    $sections = array(
        'outstanding' => array(
            'key' => 'outstanding',
            'label' => ui_text('บิลค้างชำระ', 'Outstanding bills'),
            'count' => (int) ($summaryRow['outstanding_total'] ?? 0),
            'tone' => 'danger',
            'items' => array(),
        ),
        'pickup' => array(
            'key' => 'pickup',
            'label' => ui_text('รถถึงกำหนดรับ', 'Pickup due'),
            'count' => (int) ($summaryRow['pickup_total'] ?? 0),
            'tone' => 'warning',
            'items' => array(),
        ),
        'waiting' => array(
            'key' => 'waiting',
            'label' => ui_text('คิวรอดำเนินการ', 'Waiting queue'),
            'count' => (int) ($summaryRow['waiting_total'] ?? 0),
            'tone' => 'info',
            'items' => array(),
        ),
        'new_booking' => array(
            'key' => 'new_booking',
            'label' => ui_text('Booking งานใหม่', 'New bookings'),
            'count' => (int) ($summaryRow['new_booking_total'] ?? 0),
            'tone' => 'success',
            'items' => array(),
        ),
    );

    if ($sections['outstanding']['count'] > 0) {
        $types = '';
        $params = array();
        $where = array(
            "o.status <> 'cancelled'",
            "o.payment_status <> 'paid'",
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.order_date,
                o.status,
                o.payment_status,
                o.total_price,
                c.name AS customer_name,
                car.plate_number
            FROM orders o
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY
                CASE WHEN o.status = 'done' THEN 0 ELSE 1 END,
                o.order_date DESC,
                o.order_id DESC
            LIMIT 5
        ");
        if ($types !== '') {
            $stmt->bind_param($types, ...$params);
        }
        $stmt->execute();
        $result = $stmt->get_result();
        $outstandingRows = array();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $outstandingRows[] = $row;
            }
        }
        $stmt->close();

        $outstandingPaymentMap = order_payment_summary_map($conn, array_column($outstandingRows, 'order_id'));
        foreach ($outstandingRows as $row) {
            $orderId = (int) ($row['order_id'] ?? 0);
            $paymentSummary = $outstandingPaymentMap[$orderId] ?? order_payment_summary_defaults();
            $billLabel = trim((string) ($row['bill_number'] ?? '')) !== ''
                ? (string) ($row['bill_number'] ?? '')
                : '#' . $orderId;
            $balance = max((float) ($row['total_price'] ?? 0) - (float) ($paymentSummary['total_amount'] ?? 0), 0);
            $sections['outstanding']['items'][] = array(
                'title' => $billLabel . ' / ' . trim((string) ($row['plate_number'] ?? '-')),
                'meta' => implode(' / ', array_filter(array(
                    trim((string) ($row['customer_name'] ?? '')),
                    trim((string) ($row['branch_name'] ?? '')),
                ))),
                'aux' => ui_text('ค้างชำระ ', 'Balance ')
                    . format_money($balance)
                    . ' / '
                    . payment_status_label((string) ($row['payment_status'] ?? 'unpaid')),
                'href' => notification_center_order_href($conn, $row),
            );
        }
    }

    if ($sections['pickup']['count'] > 0) {
        $types = 's';
        $params = array($tomorrowStart);
        $where = array(
            "o.order_source = 'booking'",
            "o.status <> 'cancelled'",
            'o.return_at IS NOT NULL',
            'o.return_at < ?',
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.return_at,
                c.name AS customer_name,
                car.plate_number
            FROM orders o FORCE INDEX (idx_orders_pickup_board)
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY o.return_at ASC, o.order_id ASC
            LIMIT 5
        ");
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $billLabel = trim((string) ($row['bill_number'] ?? '')) !== ''
                    ? (string) ($row['bill_number'] ?? '')
                    : '#' . (int) ($row['order_id'] ?? 0);
                $sections['pickup']['items'][] = array(
                    'title' => trim((string) ($row['plate_number'] ?? '-')) . ' / ' . trim((string) ($row['customer_name'] ?? '')),
                    'meta' => implode(' / ', array_filter(array(
                        $billLabel,
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('กำหนดรับ ', 'Pickup due ') . format_datetime((string) ($row['return_at'] ?? '')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    if ($sections['waiting']['count'] > 0) {
        $types = '';
        $params = array();
        $where = array(
            "o.order_source = 'booking'",
            "o.status = 'waiting'",
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.payment_status,
                o.order_date,
                c.name AS customer_name,
                car.plate_number,
                q.queue_number
            FROM orders o FORCE INDEX (idx_orders_queue_board)
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            LEFT JOIN queue q ON q.order_id = o.order_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY COALESCE(q.created_at, o.order_date) ASC, o.order_id ASC
            LIMIT 5
        ");
        if ($types !== '') {
            $stmt->bind_param($types, ...$params);
        }
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $queueLabel = (int) ($row['queue_number'] ?? 0) > 0
                    ? ui_text('คิว #', 'Queue #') . (int) ($row['queue_number'] ?? 0)
                    : ui_text('รอดำเนินการ', 'Waiting');
                $sections['waiting']['items'][] = array(
                    'title' => $queueLabel . ' / ' . trim((string) ($row['plate_number'] ?? '-')),
                    'meta' => implode(' / ', array_filter(array(
                        trim((string) ($row['customer_name'] ?? '')),
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('เปิดงาน ', 'Booked ')
                        . format_datetime((string) ($row['order_date'] ?? ''))
                        . ' / '
                        . payment_status_label((string) ($row['payment_status'] ?? 'unpaid')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    if ($sections['new_booking']['count'] > 0) {
        $types = 'ss';
        $params = array($todayStart, $tomorrowStart);
        $where = array(
            "o.order_source = 'booking'",
            "o.status <> 'cancelled'",
            'o.order_date >= ?',
            'o.order_date < ?',
        );
        $branchCondition = auth_branch_condition($conn, 'o', $types, $params);
        if ($branchCondition !== '') {
            $where[] = $branchCondition;
        }

        $stmt = db_prepare($conn, "
            SELECT
                o.order_id,
                o.bill_number,
                o.order_source,
                o.branch_name,
                o.order_date,
                c.name AS customer_name,
                car.plate_number
            FROM orders o FORCE INDEX (idx_orders_report_period)
            INNER JOIN customers c ON c.customer_id = o.customer_id
            INNER JOIN cars car ON car.car_id = o.car_id
            WHERE " . implode(' AND ', $where) . "
            ORDER BY o.order_date DESC, o.order_id DESC
            LIMIT 5
        ");
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result instanceof mysqli_result) {
            while ($row = $result->fetch_assoc()) {
                $billLabel = trim((string) ($row['bill_number'] ?? '')) !== ''
                    ? (string) ($row['bill_number'] ?? '')
                    : '#' . (int) ($row['order_id'] ?? 0);
                $sections['new_booking']['items'][] = array(
                    'title' => $billLabel . ' / ' . trim((string) ($row['plate_number'] ?? '-')),
                    'meta' => implode(' / ', array_filter(array(
                        trim((string) ($row['customer_name'] ?? '')),
                        trim((string) ($row['branch_name'] ?? '')),
                    ))),
                    'aux' => ui_text('งานใหม่เวลา ', 'New booking at ') . format_datetime((string) ($row['order_date'] ?? '')),
                    'href' => notification_center_order_href($conn, $row),
                );
            }
        }
        $stmt->close();
    }

    $total = 0;
    foreach ($sections as $section) {
        $total += (int) ($section['count'] ?? 0);
    }

    $cache[$cacheKey] = array(
        'total' => $total,
        'sections' => array_values($sections),
    );

    return $cache[$cacheKey];
}

function render_notification_center(mysqli $conn, string $buttonClass = '', string $contextClass = ''): string
{
    $data = notification_center_data_optimized($conn);
    $total = (int) ($data['total'] ?? 0);
    $sections = is_array($data['sections'] ?? null) ? $data['sections'] : array();
    $buttonClasses = trim('notification-toggle ' . $buttonClass . ($total > 0 ? ' has-alerts' : ''));
    $wrapperClasses = trim('notification-center ' . $contextClass);
    $badgeLabel = $total > 99 ? '99+' : (string) $total;
    $headerTitle = ui_text('การแจ้งเตือน', 'Notifications');
    $headerSubline = $total > 0
        ? (current_language() === 'th' ? 'มี ' . $total . ' รายการต้องติดตาม' : $total . ' items need attention')
        : ui_text('ไม่มีรายการที่ต้องติดตาม', 'No items need attention');

    $summaryCards = array();
    $sectionMarkup = array();

    foreach ($sections as $section) {
        $count = (int) ($section['count'] ?? 0);
        $label = (string) ($section['label'] ?? '');
        $tone = (string) ($section['tone'] ?? 'info');
        $items = is_array($section['items'] ?? null) ? $section['items'] : array();

        $summaryCards[] = '<article class="notification-summary-card is-' . e($tone) . '">'
            . '<span>' . e($label) . '</span>'
            . '<strong>' . $count . '</strong>'
            . '</article>';

        if ($count <= 0) {
            continue;
        }

        $rows = array();
        foreach ($items as $item) {
            $title = (string) ($item['title'] ?? '');
            $meta = (string) ($item['meta'] ?? '');
            $aux = (string) ($item['aux'] ?? '');
            $href = (string) ($item['href'] ?? '');
            $inner = '<span class="notification-item-title">' . e($title) . '</span>'
                . ($meta !== '' ? '<span class="notification-item-meta">' . e($meta) . '</span>' : '')
                . ($aux !== '' ? '<span class="notification-item-aux">' . e($aux) . '</span>' : '');

            if ($href !== '') {
                $rows[] = '<a class="notification-item" href="' . e($href) . '">' . $inner . '</a>';
            } else {
                $rows[] = '<div class="notification-item is-static">' . $inner . '</div>';
            }
        }

        $sectionMarkup[] = '<section class="notification-section is-' . e($tone) . '">'
            . '<div class="notification-section-head">'
            . '<strong>' . e($label) . '</strong>'
            . '<span>' . $count . '</span>'
            . '</div>'
            . implode('', $rows)
            . '</section>';
    }

    if (empty($sectionMarkup)) {
        $sectionMarkup[] = '<div class="notification-empty-state">' . e(ui_text('ยังไม่มีรายการแจ้งเตือนในตอนนี้', 'There are no active notifications right now.')) . '</div>';
    }

    return '<div class="' . e($wrapperClasses) . '" data-notification-center>'
        . '<button class="' . e($buttonClasses) . '" type="button" aria-label="' . e($headerTitle) . '" aria-expanded="false" data-notification-toggle>'
        . nav_icon('bell')
        . ($total > 0 ? '<span class="notification-toggle-badge">' . e($badgeLabel) . '</span>' : '')
        . '</button>'
        . '<section class="notification-panel" hidden data-notification-panel>'
        . '<div class="notification-panel-head">'
        . '<strong>' . e($headerTitle) . '</strong>'
        . '<small>' . e($headerSubline) . '</small>'
        . '</div>'
        . '<div class="notification-summary-grid">'
        . implode('', $summaryCards)
        . '</div>'
        . '<div class="notification-section-list">'
        . implode('', $sectionMarkup)
        . '</div>'
        . '</section>'
        . '</div>';
}

function console_scope_label(mysqli $conn): string
{
    $scope = auth_scope($conn);
    $assignedBranches = auth_assigned_branches($conn);

    if ($scope === 'all') {
        return 'All branches';
    }

    if (empty($assignedBranches)) {
        return 'Assigned branches';
    }

    $visibleBranches = array_slice($assignedBranches, 0, 2);
    $label = implode(', ', $visibleBranches);

    if (count($assignedBranches) > 2) {
        $label .= ' +' . (count($assignedBranches) - 2);
    }

    return $label;
}

function console_nav_items(mysqli $conn): array
{
    $items = array(
        array(ui_text('แดชบอร์ด', 'Dashboard'), 'dashboard.php', 'dashboard', 'dashboard'),
        array(ui_text('เปิดงานใหม่', 'New booking'), 'booking.php', 'booking', 'booking'),
        array(ui_text('ควิกเซอร์วิส', 'Quick Service'), 'quick_service.php', 'quick_service', 'quick'),
        array(ui_text('คิวงาน', 'Queue'), 'queue.php', 'queue', 'queue'),
        array(ui_text('สมาชิก', 'Member'), 'member.php', 'member', 'member'),
        array(ui_text('สะสมแต้ม', 'Loyalty'), 'loyalty.php', 'loyalty', 'loyalty'),
    );
    $filtered = array();

    foreach ($items as $item) {
        if ($item[2] === 'member') {
            if (!can_access_member_area($conn)) {
                continue;
            }
        } elseif (!can_access($conn, $item[2])) {
            continue;
        }

        $filtered[] = array(
            'label' => $item[0],
            'href' => $item[1],
            'icon' => $item[3],
            'key' => $item[2],
        );
    }

    return $filtered;
}

function render_language_switcher(string $actionPath, string $returnTo, string $extraClass = ''): string
{
    $currentLanguage = current_language();
    $class = trim('language-switcher ' . $extraClass);
    $buttons = array();

    foreach (language_options() as $languageKey => $languageLabel) {
        $buttonClass = $currentLanguage === $languageKey
            ? 'language-switcher-button is-active'
            : 'language-switcher-button';

        $buttons[] = '<button class="' . e($buttonClass) . '" type="submit" name="language" value="' . e($languageKey) . '" aria-pressed="' . ($currentLanguage === $languageKey ? 'true' : 'false') . '">'
            . e($languageLabel)
            . '</button>';
    }

    return '<form class="' . e($class) . '" method="POST" action="' . e($actionPath) . '" aria-label="' . e(ui_text('สลับภาษา', 'Language switcher')) . '">'
        . csrf_input('set_language')
        . '<input type="hidden" name="return_to" value="' . e($returnTo) . '">'
        . '<span class="language-switcher-label">' . e(ui_text('ภาษา', 'Language')) . '</span>'
        . '<span class="language-switcher-options">'
        . implode('', $buttons)
        . '</span>'
        . '</form>';
}

function nav_item(string $href, string $label, string $activePage, string $key, string $icon): string
{
    global $conn;

    $canOpen = $key === 'member'
        ? can_access_member_area($conn)
        : can_access($conn, $key);

    if (!$canOpen) {
        return '';
    }

    $class = $activePage === $key ? 'nav-link is-active' : 'nav-link';

    return '<a class="' . e($class) . '" href="' . e($href) . '">'
        . nav_link_inner($label, $icon)
        . '</a>';
}

function is_manage_system_page(string $activePage): bool
{
    return in_array($activePage, array('manage_system', 'services', 'service_categories', 'service_groups', 'employees', 'positions', 'quick_service_settings', 'bill_management', 'data_maintenance'), true);
}

function nav_manage_system_item(string $activePage): string
{
    global $conn;

    if (!can_access_manage_system($conn)) {
        return '';
    }

    $class = is_manage_system_page($activePage) ? 'nav-link is-active' : 'nav-link';

    return '<a class="' . e($class) . '" href="manage_system.php">'
        . nav_link_inner(ui_text('จัดการระบบ', 'Manage System'), 'manage')
        . '</a>';
}

function nav_report_group(string $activePage): string
{
    global $conn;

    $items = array(
        array('audit_report.php', ui_text('รายงานตรวจสอบ', 'Audit Report'), 'audit_report', ui_text('ตรวจสอบบิล การชำระเงิน และประวัติการยกเลิกในหน้าเดียว', 'Review bill, payment and void audit trail in one place.')),
        array('report_service.php', ui_text('รายงานบริการ', 'Service Report'), 'report_service', ui_text('ติดตามการใช้บริการ ความต้องการ และผลงานรายวัน', 'Track service usage, demand and daily performance.')),
        array('sale_report.php', ui_text('รายงานยอดขาย', 'Sale Report'), 'sale_report', ui_text('ตรวจสอบรายได้ มัดจำ และรูปแบบการรับชำระรายวัน', 'Review revenue, deposits and payment mix by day.')),
        array('void_report.php', ui_text('รายงานบิลยกเลิก', 'Void Report'), 'void_report', ui_text('ตรวจสอบบิลที่ยกเลิก เหตุผล และประวัติการตรวจสอบ', 'Inspect voided bills, reasons and audit history.')),
    );
    $links = array();
    $isActive = false;
    $defaultHref = '';

    foreach ($items as $item) {
        $href = $item[0];
        $label = $item[1];
        $key = $item[2];
        $description = $item[3];

        if (!can_access($conn, $key)) {
            continue;
        }

        if ($activePage === $key) {
            $isActive = true;
        }

        if ($defaultHref === '') {
            $defaultHref = $href;
        }

        $class = $activePage === $key ? 'nav-report-card is-active' : 'nav-report-card';
        $links[] = '<a class="' . e($class) . '" href="' . e($href) . '">'
            . '<span class="nav-report-card-icon" aria-hidden="true">' . nav_icon('report') . '</span>'
            . '<span class="nav-report-card-copy">'
            . '<strong>' . e($label) . '</strong>'
            . '<small>' . e($description) . '</small>'
            . '</span>'
            . '</a>';
    }

    if (empty($links)) {
        return '';
    }

    $buttonClass = $isActive ? 'nav-link nav-group-toggle is-active' : 'nav-link nav-group-toggle';

    return '<div class="nav-group nav-group-report" data-nav-report-group>'
        . '<a class="' . e($buttonClass) . '" href="' . e($defaultHref) . '" aria-haspopup="true" aria-expanded="false" aria-controls="nav-report-menu" data-nav-report-toggle>'
        . nav_link_inner(ui_text('รายงาน', 'Report'), 'report')
        . '</a>'
        . '<div class="nav-submenu nav-report-submenu" id="nav-report-menu" data-nav-report-menu>'
        . '<div class="nav-report-menu-head">'
        . '<span class="nav-report-menu-eyebrow">' . e(ui_text('รายงาน', 'Reports')) . '</span>'
        . '<strong>' . e(ui_text('สรุปภาพรวมธุรกิจ', 'Open business summaries')) . '</strong>'
        . '<small>' . e(ui_text('เลือกรายงานที่ต้องการตรวจสอบ', 'Choose the report you want to review.')) . '</small>'
        . '</div>'
        . '<div class="nav-report-menu-grid">'
        . implode('', $links)
        . '</div>'
        . '</div>'
        . '</div>';
}

function dashboard_console_report_group(string $activePage): string
{
    global $conn;

    $items = array(
        array('report_service.php', ui_text('รายงานบริการ', 'Service Report'), 'report_service'),
        array('sale_report.php', ui_text('รายงานยอดขาย', 'Sale Report'), 'sale_report'),
        array('void_report.php', ui_text('รายงานบิลยกเลิก', 'Void Report'), 'void_report'),
        array('audit_report.php', ui_text('รายงานตรวจสอบ', 'Audit Report'), 'audit_report'),
    );
    $links = array();
    $isActive = false;

    foreach ($items as $item) {
        $href = $item[0];
        $label = $item[1];
        $key = $item[2];

        if (!can_access($conn, $key)) {
            continue;
        }

        if ($activePage === $key) {
            $isActive = true;
        }

        $class = $activePage === $key
            ? 'dashboard-console-submenu-link is-active'
            : 'dashboard-console-submenu-link';

        $links[] = '<a class="' . e($class) . '" href="' . e($href) . '" title="' . e($label) . '">'
            . '<span class="dashboard-console-submenu-dot" aria-hidden="true"></span>'
            . '<span>' . e($label) . '</span>'
            . '</a>';
    }

    if (empty($links)) {
        return '';
    }

    $groupClass = $isActive ? 'dashboard-console-group is-open' : 'dashboard-console-group';
    $linkClass = $isActive ? 'dashboard-console-link dashboard-console-group-link is-active' : 'dashboard-console-link dashboard-console-group-link';

    return '<div class="' . e($groupClass) . '" data-dashboard-report-group>'
        . '<a class="' . e($linkClass) . '" href="' . e(preferred_report_page($conn)) . '" title="' . e(ui_text('รายงาน', 'Reports')) . '">'
        . '<span class="dashboard-console-link-icon">' . nav_icon('report') . '</span>'
        . '<span>' . e(ui_text('รายงาน', 'Reports')) . '</span>'
        . '<span class="dashboard-console-group-caret" aria-hidden="true">&gt;</span>'
        . '</a>'
        . '<div class="dashboard-console-submenu">'
        . implode('', $links)
        . '</div>'
        . '</div>';
}

function nav_icon(string $name): string
{
    $icons = array(
        'dashboard' => '<svg class="app-nav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5h7v7H4z"></path><path d="M13 5h7v5h-7z"></path><path d="M13 12h7v7h-7z"></path><path d="M4 14h7v5H4z"></path></svg>',
        'booking' => '<svg class="app-nav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M8 4h8"></path><path d="M9 3h6v4H9z"></path><path d="M6 5h12v15H6z"></path><path d="M9 12h6"></path><path d="M12 9v6"></path></svg>',
        'quick' => '<svg class="app-menu-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M13 2L5 14h5l-1 8 10-14h-5l-1-6z"></path></svg>',
        'queue' => '<svg class="app-nav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 7h14"></path><path d="M5 12h14"></path><path d="M5 17h10"></path></svg>',
        'menu' => '<svg class="app-nav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 7h16"></path><path d="M4 12h16"></path><path d="M4 17h16"></path></svg>',
        'service' => '<svg class="app-menu-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 18l7-7"></path><path d="M13 5l6 6"></path><path d="M14 4l6 6-3 3-6-6z"></path></svg>',
        'member' => '<svg class="app-menu-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8z"></path><path d="M4 20a8 8 0 0 1 16 0"></path></svg>',
        'loyalty' => '<svg class="app-menu-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 4l2.4 4.9 5.4.8-3.9 3.8.9 5.4-4.8-2.6-4.8 2.6.9-5.4-3.9-3.8 5.4-.8z"></path></svg>',
        'employees' => '<svg class="app-menu-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"></path><path d="M17 12a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z"></path><path d="M3 20a6 6 0 0 1 12 0"></path><path d="M14 17a5 5 0 0 1 7 3"></path></svg>',
        'report' => '<svg class="app-menu-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4h14v16H5z"></path><path d="M8 15l2-3 3 2 3-5"></path><path d="M8 8h4"></path></svg>',
        'bell' => '<svg class="app-menu-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M15 17H5l1.4-1.4A2 2 0 0 0 7 14.2V11a5 5 0 0 1 10 0v3.2a2 2 0 0 0 .6 1.4L19 17h-4"></path><path d="M10 20a2 2 0 0 0 4 0"></path></svg>',
        'manage' => '<svg class="app-menu-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3l1.8 2.2 2.8-.2.8 2.7 2.6 1.1-1 2.6 1 2.6-2.6 1.1-.8 2.7-2.8-.2L12 21l-1.8-2.2-2.8.2-.8-2.7-2.6-1.1 1-2.6-1-2.6 2.6-1.1.8-2.7 2.8.2z"></path><circle cx="12" cy="12" r="3.2"></circle></svg>',
        'logout' => '<svg class="app-menu-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M10 5H5v14h5"></path><path d="M13 8l4 4-4 4"></path><path d="M8 12h9"></path></svg>',
        'close' => '<svg class="app-nav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12"></path><path d="M18 6L6 18"></path></svg>',
    );

    return $icons[$name] ?? $icons['menu'];
}

function nav_app_primary_item(string $href, string $label, string $activePage, string $key, string $icon): string
{
    global $conn;

    $canOpen = $key === 'member'
        ? can_access_member_area($conn)
        : can_access($conn, $key);

    if (!$canOpen) {
        return '';
    }

    $class = $activePage === $key ? 'app-nav-link is-active' : 'app-nav-link';

    return '<a class="' . e($class) . '" href="' . e($href) . '">'
        . nav_icon($icon)
        . '<span>' . e($label) . '</span>'
        . '</a>';
}

function nav_app_menu_link(string $href, string $label, string $activePage, string $key, string $icon): string
{
    global $conn;

    if ($key === 'manage_system') {
        if (!can_access_manage_system($conn)) {
            return '';
        }

        $isActive = is_manage_system_page($activePage);
    } else {
        $canOpen = $key === 'member'
            ? can_access_member_area($conn)
            : ($key === '' || can_access($conn, $key));

        if (!$canOpen) {
            return '';
        }

        $isActive = $activePage === $key;
    }

    $class = $isActive ? 'app-menu-link is-active' : 'app-menu-link';

    return '<a class="' . e($class) . '" href="' . e($href) . '">'
        . '<span class="app-menu-link-icon">' . nav_icon($icon) . '</span>'
        . '<span>' . e($label) . '</span>'
        . '</a>';
}

function nav_app_menu_group(string $title, array $items, string $activePage): string
{
    $links = array();

    foreach ($items as $item) {
        $links[] = nav_app_menu_link($item[0], $item[1], $activePage, $item[2], $item[3]);
    }

    $links = array_values(array_filter($links));

    if (empty($links)) {
        return '';
    }

    return '<section class="app-menu-section">'
        . '<h3>' . e($title) . '</h3>'
        . '<div class="app-menu-list">'
        . implode('', $links)
        . '</div>'
        . '</section>';
}

function render_app_navigation(string $activePage): string
{
    $secondaryPages = array(
        'manage_system',
        'services',
        'service_categories',
        'service_groups',
        'quick_service_settings',
        'data_maintenance',
        'bill_management',
        'member',
        'quick_service',
        'audit_report',
        'report_service',
        'sale_report',
        'void_report',
        'loyalty',
        'employees',
        'positions',
    );
    $isMenuActive = in_array($activePage, $secondaryPages, true);
    $menuClass = $isMenuActive ? 'app-nav-link app-menu-toggle is-active' : 'app-nav-link app-menu-toggle';

    $menuGroups = array(
        nav_app_menu_group('งานบริการ', array(
            array('member.php', ui_text('สมาชิก', 'Member'), 'member', 'member'),
            array('quick_service.php', ui_text('ควิกเซอร์วิส', 'Quick Service'), 'quick_service', 'quick'),
            array('loyalty.php', ui_text('สะสมแต้ม', 'Loyalty'), 'loyalty', 'loyalty'),
        ), $activePage),
        nav_app_menu_group('Report', array(
            array('audit_report.php', ui_text('รายงานตรวจสอบ', 'Audit Report'), 'audit_report', 'report'),
            array('report_service.php', ui_text('รายงานบริการ', 'Service Report'), 'report_service', 'report'),
            array('sale_report.php', ui_text('รายงานยอดขาย', 'Sale Report'), 'sale_report', 'report'),
            array('void_report.php', ui_text('รายงานบิลยกเลิก', 'Void Report'), 'void_report', 'report'),
        ), $activePage),
        nav_app_menu_group('ระบบ', array(
            array('manage_system.php', ui_text('จัดการระบบ', 'Manage System'), 'manage_system', 'manage'),
            array('../process/logout.php', ui_text('ออกจากระบบ', 'Log out'), '', 'logout'),
        ), $activePage),
    );
    $menuGroups = array_values(array_filter($menuGroups));

    if (empty($menuGroups)) {
        return '';
    }

    return '<nav class="app-bottom-nav" aria-label="' . e(ui_text('เมนูแอป', 'App navigation')) . '">'
        . nav_app_primary_item('dashboard.php', ui_text('หน้าหลัก', 'Home'), $activePage, 'dashboard', 'dashboard')
        . nav_app_primary_item('booking.php', ui_text('เปิดงานใหม่', 'New booking'), $activePage, 'booking', 'booking')
        . nav_app_primary_item('quick_service.php', ui_text('ควิกเซอร์วิส', 'Quick Service'), $activePage, 'quick_service', 'quick')
        . nav_app_primary_item('queue.php', ui_text('คิวงาน', 'Queue'), $activePage, 'queue', 'queue')
        . '<button class="' . e($menuClass) . '" type="button" aria-expanded="false" aria-controls="app-menu-panel" data-app-menu-toggle>'
        . nav_icon('menu')
        . '<span>' . e(ui_text('เมนู', 'Menu')) . '</span>'
        . '</button>'
        . '</nav>'
        . '<div class="app-menu-backdrop" hidden data-app-menu-backdrop></div>'
        . '<section class="app-menu-panel" id="app-menu-panel" aria-labelledby="app-menu-title" aria-hidden="true" hidden data-app-menu-panel>'
        . '<div class="app-menu-grip" aria-hidden="true"></div>'
        . '<div class="app-menu-head">'
        . '<h2 id="app-menu-title">' . e(ui_text('เมนู', 'Menu')) . '</h2>'
        . '<button class="app-menu-close" type="button" aria-label="' . e(ui_text('ปิดเมนู', 'Close menu')) . '" data-app-menu-close>' . nav_icon('close') . '</button>'
        . '</div>'
        . implode('', $menuGroups)
        . '</section>';
}

function render_page_start(string $title, string $activePage, array $options = array()): void
{
    global $conn;

    require_login($conn);
    $useTranslationBuffer = array_key_exists('translation_buffer', $options)
        ? (bool) $options['translation_buffer']
        : false;

    $GLOBALS['ccw_page_translation_buffer_enabled'] = $useTranslationBuffer;
    if ($useTranslationBuffer) {
        language_start_buffer();
    }

    $flash = pull_flash();
    $currentUser = auth_current_user($conn);
    $positionName = trim((string) ($currentUser['position_name'] ?? $currentUser['position'] ?? ''));
    $displayMode = current_display_mode();
    $languageReturnTo = current_page_return($activePage . '.php');
    $useSidebarLayout = $displayMode === 'web' && $activePage !== 'dashboard';
    $assetPath = dirname(__DIR__) . '/assets';
    $cssVersion = is_file($assetPath . '/app.css') ? (string) filemtime($assetPath . '/app.css') : '1';
    $jsVersion = is_file($assetPath . '/app.js') ? (string) filemtime($assetPath . '/app.js') : '1';
    $clientTranslationsJson = current_language_dictionary_json();
    $bodyClass = 'page-' . $activePage . ' display-' . $displayMode . ' lang-' . current_language();
    $brandSubtitle = ui_text('เชื่อมต่อฐานข้อมูล: CCW', 'Connected to database: CCW');
    $closeMenuLabel = ui_text('ปิดเมนู', 'Close menu');
    $sidebarNavigationLabel = ui_text('เมนูด้านข้าง', 'Sidebar navigation');
    $manageSystemLabel = ui_text('จัดการระบบ', 'Manage System');
    $logoutLabel = ui_text('ออกจากระบบ', 'Logout');
    $menuLabel = ui_text('เมนู', 'Menu');
    $userFallbackLabel = ui_text('ผู้ใช้', 'User');
    $staffFallbackLabel = ui_text('พนักงาน', 'Staff');
    $mainNavigationLabel = ui_text('เมนูหลัก', 'Main navigation');
    $dashboardLinkLabel = ui_text('แดชบอร์ด CCW', 'CCW dashboard');
    if ($useSidebarLayout) {
        $bodyClass .= ' layout-sidebar';
    }
    ?>
    <!DOCTYPE html>
    <html lang="<?= e(current_language_html_code()) ?>">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="theme-color" content="#06213f">
        <title><?= e($title) ?> | CCW</title>
        <?= render_web_app_meta_tags() . "\n" ?>
        <link rel="preconnect" href="https://fonts.googleapis.com">
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Kanit:wght@400;500;600;700&family=Sarabun:wght@300;400;500;600;700&display=swap">
        <link rel="stylesheet" href="../assets/app.css?v=<?= e($cssVersion) ?>">
        <script>
            window.CCW_LANG = <?= json_encode(current_language(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
            window.CCW_I18N = <?= $clientTranslationsJson ?>;
        </script>
        <script src="../assets/app.js?v=<?= e($jsVersion) ?>" defer></script>
        <?= render_web_app_bootstrap_script() . "\n" ?>
    </head>
    <body class="<?= e($bodyClass) ?>">
    <main class="app-shell">
        <?php if ($useSidebarLayout): ?>
            <?php
            $GLOBALS['ccw_sidebar_layout_open'] = true;
            $consoleNavItems = console_nav_items($conn);
            $scopeLabel = console_scope_label($conn);
            ?>
            <section class="dashboard-console" data-dashboard-console>
                <aside class="dashboard-console-sidebar">
                    <div class="dashboard-console-brand">
                        <span class="dashboard-console-logo">CCW</span>
                        <div>
                            <strong>CCW Car Care</strong>
                            <small><?= e($scopeLabel) ?></small>
                        </div>
                        <button class="dashboard-console-sidebar-close" type="button" aria-label="<?= e($closeMenuLabel) ?>" data-dashboard-sidebar-close>
                            <?= nav_icon('close') ?>
                        </button>
                    </div>

                    <nav class="dashboard-console-nav" aria-label="<?= e($sidebarNavigationLabel) ?>">
                        <?php foreach ($consoleNavItems as $item): ?>
                            <?php
                            $key = (string) ($item['key'] ?? '');
                            $isActive = $activePage === $key;
                            ?>
                            <a class="dashboard-console-link<?= $isActive ? ' is-active' : '' ?>" href="<?= e((string) ($item['href'] ?? '#')) ?>" title="<?= e((string) ($item['label'] ?? '')) ?>">
                                <span class="dashboard-console-link-icon"><?= nav_icon((string) ($item['icon'] ?? 'menu')) ?></span>
                                <span><?= e((string) ($item['label'] ?? '')) ?></span>
                            </a>
                        <?php endforeach; ?>
                        <?= dashboard_console_report_group($activePage) ?>
                    </nav>

                    <div class="dashboard-console-footer">
                        <?php if (can_access_manage_system($conn)): ?>
                            <a class="dashboard-console-footer-link<?= is_manage_system_page($activePage) ? ' is-active' : '' ?>" href="manage_system.php" title="<?= e($manageSystemLabel) ?>">
                                <span class="dashboard-console-link-icon"><?= nav_icon('manage') ?></span>
                                <span><?= e($manageSystemLabel) ?></span>
                            </a>
                        <?php endif; ?>
                        <a class="dashboard-console-footer-link" href="../process/logout.php" title="<?= e($logoutLabel) ?>">
                            <span class="dashboard-console-link-icon"><?= nav_icon('logout') ?></span>
                            <span><?= e($logoutLabel) ?></span>
                        </a>
                    </div>
                </aside>

                <button class="dashboard-console-backdrop" type="button" hidden aria-label="<?= e($closeMenuLabel) ?>" data-dashboard-sidebar-backdrop></button>

                <div class="dashboard-console-main">
                    <section class="dashboard-console-toolbar">
                        <div class="dashboard-console-toolbar-copy">
                            <h2><?= e($title) ?></h2>
                            <p><?= e($scopeLabel) ?> / <?= e($brandSubtitle) ?></p>
                        </div>
                        <div class="dashboard-console-toolbar-side">
                            <button class="dashboard-console-toggle" type="button" aria-label="<?= e($menuLabel) ?>" aria-expanded="true" data-dashboard-sidebar-toggle>
                                <?= nav_icon('menu') ?>
                            </button>
                            <?= render_notification_center($conn, 'dashboard-console-bell', 'notification-center-toolbar') ?>
                            <?= render_language_switcher('../process/set_language.php', $languageReturnTo) ?>
                            <div class="dashboard-console-user">
                                <span class="dashboard-console-avatar"><?= e(substr((string) ($currentUser['name'] ?? 'U'), 0, 1)) ?></span>
                                <div>
                                    <strong><?= e((string) ($currentUser['name'] ?? $userFallbackLabel)) ?></strong>
                                    <small><?= e($positionName !== '' ? $positionName : $staffFallbackLabel) ?></small>
                                </div>
                            </div>
                        </div>
                    </section>
        <?php else: ?>
            <header class="topbar">
                <div class="topbar-brand-zone">
                    <a class="brand" href="dashboard.php" aria-label="<?= e($dashboardLinkLabel) ?>">
                        <span class="brand-mark">CCW</span>
                        <span>
                            <strong>CCW Car Care</strong>
                            <small><?= e($brandSubtitle) ?></small>
                        </span>
                    </a>
                </div>

                <div class="topbar-nav-zone">
                    <nav class="nav" aria-label="<?= e($mainNavigationLabel) ?>">
                        <?= nav_item('dashboard.php', ui_text('แดชบอร์ด', 'Dashboard'), $activePage, 'dashboard', 'dashboard') ?>
                        <?= nav_item('booking.php', ui_text('เปิดงานใหม่', 'New booking'), $activePage, 'booking', 'booking') ?>
                        <?= nav_item('quick_service.php', ui_text('ควิกเซอร์วิส', 'Quick Service'), $activePage, 'quick_service', 'quick') ?>
                        <?= nav_item('queue.php', ui_text('คิวงาน', 'Queue'), $activePage, 'queue', 'queue') ?>
                        <?= nav_item('member.php', ui_text('สมาชิก', 'Member'), $activePage, 'member', 'member') ?>
                        <?= nav_report_group($activePage) ?>
                        <?= nav_item('loyalty.php', ui_text('สะสมแต้ม', 'Loyalty'), $activePage, 'loyalty', 'loyalty') ?>
                        <?= nav_manage_system_item($activePage) ?>
                        <a class="nav-link nav-logout-app" href="../process/logout.php">
                            <?= nav_link_inner(ui_text('ออกจากระบบ', 'Log out'), 'logout') ?>
                        </a>
                    </nav>
                </div>

                <div class="topbar-user-zone">
                    <div class="user-menu">
                        <span class="user-menu-card">
                            <span class="user-menu-avatar" aria-hidden="true"><?= nav_icon('member') ?></span>
                            <span class="user-menu-copy">
                                    <strong><?= e((string) ($currentUser['name'] ?? $userFallbackLabel)) ?></strong>
                                    <small><?= e($positionName !== '' ? $positionName : $staffFallbackLabel) ?></small>
                                </span>
                        </span>
                        <?= render_notification_center($conn, 'topbar-notification', 'notification-center-topbar') ?>
                        <?= render_language_switcher('../process/set_language.php', $languageReturnTo) ?>
                        <a class="button button-ghost topbar-logout" href="../process/logout.php"><?= e($logoutLabel) ?></a>
                    </div>
                </div>
            </header>
            <?= render_app_navigation($activePage) ?>
        <?php endif; ?>

        <?php if ($flash): ?>
            <div class="flash flash-<?= e((string) ($flash['type'] ?? 'success')) ?>">
                <span data-no-translate="1"><?= e(resolve_localized_flash_message($flash['message'] ?? '')) ?></span>
            </div>
        <?php endif; ?>
        <div class="app-notification-dock" hidden data-app-notification-dock></div>
    <?php
}

function render_page_end(): void
{
    ?>
    <?php if (!empty($GLOBALS['ccw_sidebar_layout_open'])): ?>
                </div>
            </section>
        <?php $GLOBALS['ccw_sidebar_layout_open'] = false; ?>
    <?php endif; ?>
    </main>
    </body>
    </html>
    <?php
    $useTranslationBuffer = !empty($GLOBALS['ccw_page_translation_buffer_enabled']);
    unset($GLOBALS['ccw_page_translation_buffer_enabled']);
    if ($useTranslationBuffer) {
        language_end_buffer();
    }
}
