<?php
if (!defined('LUNA_APP')) {
    http_response_code(403);
    exit('Forbidden');
}

// Start output buffering early to prevent any unwanted output
if (ob_get_level() == 0) {
    ob_start();
}

// Helper function to send JSON response (cleans output buffer first)
function send_json_response($data, $isAjax = false) {
    if ($isAjax) {
        // Clean any previous output
        while (ob_get_level() > 0) {
            ob_end_clean();
        }
        // Prevent any output
        if (headers_sent($file, $line)) {
            error_log("Headers already sent in $file on line $line");
        }
        header('Content-Type: application/json; charset=utf-8');
        header('Cache-Control: no-cache, must-revalidate');
        header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
        echo json_encode($data, JSON_UNESCAPED_UNICODE);
        exit;
    }
}

// Helper: chuẩn hóa datetime, build key ổn định cho bản ghi chấm công
function attendance_normalize_datetime($log): string {
    $datetime = trim((string)($log['datetime'] ?? ''));
    $date = trim((string)($log['date'] ?? ''));
    $time = trim((string)($log['time'] ?? ''));
    if ($datetime === '' && $date !== '' && $time !== '') {
        $datetime = $date . ' ' . $time;
    }
    return $datetime;
}

function attendance_build_log_key($log): string {
    $pin = (string)($log['pin'] ?? '');
    $date = (string)($log['date'] ?? '');
    $datetime = attendance_normalize_datetime($log);
    return md5($pin . '|' . $date . '|' . $datetime . '|' . ($log['verify'] ?? '') . '|' . ($log['device_name'] ?? ''));
}

function build_attendance_lan_map(array $logs): array {
    $buckets = [];
    foreach ($logs as $log) {
        $pin = (string)($log['pin'] ?? '');
        $date = (string)($log['date'] ?? '');
        $datetime = attendance_normalize_datetime($log);
        if ($pin === '' || $date === '') continue;
        $key = $pin . '|' . $date;
        if (!isset($buckets[$key])) { $buckets[$key] = []; }
        $buckets[$key][] = [
            'datetime' => $datetime,
            'log' => $log,
        ];
    }
    $lanMap = [];
    foreach ($buckets as &$group) {
        usort($group, function($a, $b) {
            $ta = strtotime($a['datetime']);
            if ($ta === false && !empty($a['log']['date']) && !empty($a['log']['time'])) {
                $ta = strtotime($a['log']['date'] . ' ' . $a['log']['time']);
            }
            $tb = strtotime($b['datetime']);
            if ($tb === false && !empty($b['log']['date']) && !empty($b['log']['time'])) {
                $tb = strtotime($b['log']['date'] . ' ' . $b['log']['time']);
            }
            if ($ta === false) $ta = 0;
            if ($tb === false) $tb = 0;
            return ($ta < $tb) ? -1 : (($ta > $tb) ? 1 : 0);
        });
        $lan = 1;
        foreach ($group as $item) {
            $lanMap[attendance_build_log_key($item['log'])] = $lan++;
        }
    }
    unset($group);
    return $lanMap;
}

// XỬ LÝ CẬP NHẬT THỜI GIAN LÊN MÁY CHẤM CÔNG - XỬ LÝ TRƯỚC TẤT CẢ
// Phải xử lý trước để tránh output từ require, session_start, etc.
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['attendance_update_device_time'])) {
    // Check if this is an AJAX request
    $isAjax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
    
    // For AJAX requests, start output buffering and suppress errors
    if ($isAjax) {
        // Clean any previous output
        while (ob_get_level() > 0) {
            ob_end_clean();
        }
        // Start output buffering with error suppression
        ob_start();
        // Suppress warnings/notices that might be output
        $oldErrorReporting = error_reporting(E_ALL & ~E_WARNING & ~E_NOTICE & ~E_DEPRECATED);
    }
    
    // Start session BEFORE requiring messages.php (it needs session)
    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }
    
    // Chỉ require những gì cần thiết cho xử lý POST
    // Suppress any output from requires
    if ($isAjax) {
        ob_start();
    }
    require_once __DIR__ . '/config/messages.php';
    $messages = $messages ?? load_messages();
    require_once __DIR__ . '/lib/ZKLibrary.php';
    if ($isAjax) {
        ob_end_clean();
        // Restore error reporting
        error_reporting($oldErrorReporting);
    }
    
    $deviceName = isset($_POST['device_name']) ? trim((string)$_POST['device_name']) : '';
    $deviceIp   = isset($_POST['device_ip']) && filter_var($_POST['device_ip'], FILTER_VALIDATE_IP) ? $_POST['device_ip'] : '';
    $devicePort = isset($_POST['device_port']) && (int)$_POST['device_port'] > 0 ? (int)$_POST['device_port'] : 0;
    $useCurrentTime = isset($_POST['use_current_time']) && $_POST['use_current_time'] === '1';
    
    // Nếu checkbox "Thời gian hiện tại" được tick, lấy thời gian hiện tại
    if ($useCurrentTime) {
        $now = new DateTime('now', new DateTimeZone('Asia/Ho_Chi_Minh'));
        $updateDate = $now->format('Y-m-d');
        $updateTime = $now->format('H:i:s');
    } else {
        $updateDate = isset($_POST['update_date']) ? trim((string)$_POST['update_date']) : '';
        $updateTime = isset($_POST['update_time']) ? trim((string)$_POST['update_time']) : '';
    }
    
    $errors = [];
    if ($deviceName === '' || $deviceIp === '' || $devicePort === 0) {
        $errors[] = $messages['attendance_error_device_required'] ?? 'Vui lòng chọn thiết bị chấm công.';
    }
    if ($updateDate === '') {
        $errors[] = $messages['attendance_validation_date_required'] ?? 'Ngày không được để trống.';
    }
    if ($updateTime === '' || !preg_match('/^\d{2}:\d{2}:\d{2}$/', $updateTime)) {
        $errors[] = $messages['attendance_validation_time_required'] ?? 'Giờ không được để trống (định dạng hh:mm:ss).';
    }
    
    if (!empty($errors)) {
        send_json_response(['ok' => false, 'message' => implode('<br>', $errors)], $isAjax);
    }
    
    // Ghép date và time thành datetime với format YYYY-MM-DD HH:MM:SS
    $dateFormatted = '';
    $timeFormatted = '';
    
    // Validate và format date (YYYY-MM-DD)
    if (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $updateDate, $dateMatches)) {
        $dateFormatted = $updateDate;
    } else {
        $timestamp = strtotime($updateDate);
        if ($timestamp !== false) {
            $dateFormatted = date('Y-m-d', $timestamp);
        } else {
            $errorMsg = $messages['attendance_error_invalid_date'] ?? 'Ngày không hợp lệ.';
            send_json_response(['ok' => false, 'message' => $errorMsg], $isAjax);
        }
    }
    
    // Validate và format time (HH:MM:SS)
    if (preg_match('/^(\d{2}):(\d{2}):(\d{2})$/', $updateTime, $timeMatches)) {
        $timeFormatted = $updateTime;
    } else if (preg_match('/^(\d{2}):(\d{2})$/', $updateTime, $timeMatches)) {
        $timeFormatted = $updateTime . ':00';
    } else {
        $errorMsg = $messages['attendance_error_invalid_time'] ?? 'Giờ không hợp lệ. Vui lòng nhập định dạng HH:MM:SS.';
        send_json_response(['ok' => false, 'message' => $errorMsg], $isAjax);
    }
    
    // Ghép lại thành format YYYY-MM-DD HH:MM:SS cho setTime()
    $datetime = $dateFormatted . ' ' . $timeFormatted;
    
    // Validate lại datetime cuối cùng
    $timestamp = strtotime($datetime);
    if ($timestamp === false) {
        $errorMsg = $messages['attendance_error_invalid_datetime'] ?? 'Ngày và giờ không hợp lệ.';
        send_json_response(['ok' => false, 'message' => $errorMsg], $isAjax);
    }
    
    // Kết nối và cập nhật thời gian lên máy chấm công
    // For AJAX, ensure output buffer is active during ZKLibrary operations
    if ($isAjax) {
        ob_start();
    }
    
    $zk = new ZKLibrary($deviceIp, $devicePort);
    if (method_exists($zk, 'setTimeout')) {
        $zk->setTimeout(5, 0);
    }
    
    $success = false;
    $errorMsg = '';
    
    try {
        if ($zk->connect()) {
            $zk->disableDevice();
            // Set time lên máy chấm công - truyền datetime string với format YYYY-MM-DD HH:MM:SS
            $result = $zk->setTime($datetime);
            $zk->enableDevice();
            $zk->disconnect();
            
            if ($result !== false) {
                $success = true;
            } else {
                $errorMsg = $messages['attendance_error_set_time_failed'] ?? 'Không thể cập nhật thời gian lên máy chấm công. Vui lòng kiểm tra kết nối và thử lại.';
            }
        } else {
            $errorMsgTemplate = $messages['attendance_error_connection_failed'] ?? 'Không thể kết nối tới máy chấm công tại ' . $deviceIp . ':' . $devicePort . '. Vui lòng kiểm tra kết nối mạng.';
            $errorMsg = str_replace(
                ['{device}', '{ip}', '{port}'],
                [
                    htmlspecialchars($deviceName, ENT_QUOTES, 'UTF-8'),
                    htmlspecialchars($deviceIp, ENT_QUOTES, 'UTF-8'),
                    $devicePort
                ],
                $errorMsgTemplate
            );
        }
    } catch (Throwable $e) {
        $errorMsg = ($messages['attendance_error_exception'] ?? 'Lỗi') . ': ' . $e->getMessage();
        error_log('Attendance update time error: ' . $e->getMessage() . ' | Device: ' . $deviceIp . ':' . $devicePort . ' | DateTime: ' . $datetime);
    } catch (Exception $e) {
        $errorMsg = ($messages['attendance_error_exception'] ?? 'Lỗi') . ': ' . $e->getMessage();
        error_log('Attendance update time error (Exception): ' . $e->getMessage() . ' | Device: ' . $deviceIp . ':' . $devicePort . ' | DateTime: ' . $datetime);
    }
    
    // Clean any output from ZKLibrary operations
    if ($isAjax) {
        ob_end_clean();
    }
    
    if ($isAjax) {
        // Clean any output that might have been generated during processing
        while (ob_get_level() > 0) {
            ob_end_clean();
        }
        if ($success) {
            // Format datetime for display (DD/MM/YYYY HH:MM:SS)
            $displayDate = date('d/m/Y', $timestamp);
            $displayTime = date('H:i:s', $timestamp);
            $displayDateTime = $displayDate . ' ' . $displayTime;
            
            // Build success message with device info
            $baseMsg = $messages['attendance_success_time_updated'] ?? 'Đã cập nhật thời gian lên <strong>{device}</strong> (<strong>{ip}:{port}</strong>) thành công.';
            $successMsg = str_replace(
                ['{device}', '{ip}', '{port}'],
                [
                    htmlspecialchars($deviceName, ENT_QUOTES, 'UTF-8'),
                    htmlspecialchars($deviceIp, ENT_QUOTES, 'UTF-8'),
                    $devicePort
                ],
                $baseMsg
            );
            
            // Lưu thông báo vào session để hiển thị sau khi reload
            if (session_status() === PHP_SESSION_NONE) { session_start(); }
            // #region agent log
            file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.time().'_set_edit_toast','timestamp'=>time()*1000,'location'=>'profile_attendance.php:268','message'=>'Setting attendance_edit_toast session','data'=>['has_edit_toast'=>!empty($_SESSION['attendance_edit_toast']),'has_fetch_done'=>!empty($_SESSION['attendance_fetch_done']),'success_msg_length'=>strlen($successMsg)],'sessionId'=>'debug-session','runId'=>'run1','hypothesisId'=>'A,C,E'])."\n", FILE_APPEND);
            // #endregion
            $_SESSION['attendance_edit_toast'] = $successMsg;
            // Không set attendance_edit_success_pending để tránh redirect, chỉ reload và hiển thị toast
            // Dọn sạch các cờ/toast xóa cũ và fetch/export để tránh hiện nhầm
            unset($_SESSION['attendance_deleted'], $_SESSION['attendance_deleted_toast'], $_SESSION['attendance_edit_success_pending'], $_SESSION['attendance_edit_redirect_url']);
            // Clear fetch/export related session variables để tránh hiển thị toast fetch sau khi cập nhật thời gian
            // Lưu flag để clear fetch done khi reload (vì $__att_fetch_done là biến PHP, không phải session)
            $_SESSION['attendance_clear_fetch_toast'] = true;
            
            send_json_response(['ok' => true, 'message' => $successMsg], $isAjax);
        } else {
            send_json_response(['ok' => false, 'message' => $errorMsg], $isAjax);
        }
    } 
}

// Tiếp tục với các require và code khác
require_once __DIR__ . '/config/messages.php';
$messages = $messages ?? load_messages();
require_once __DIR__ . '/config/database.php';

// Simple flash helper
function set_flash(string $type, string $msg): void {
    if (session_status() === PHP_SESSION_NONE) session_start();
    $_SESSION['flash'][$type] = $msg;
}

if (session_status() === PHP_SESSION_NONE) { session_start(); }
$logs = $_SESSION['attendance_logs'] ?? [];
$error = null;

// Xử lý request clear flag trước khi fetch mới (từ JS khi user click)
if (isset($_POST['clear_fetch_toast_for_new_fetch']) && $_POST['clear_fetch_toast_for_new_fetch'] === '1') {
    unset($_SESSION['attendance_clear_fetch_toast']);
    // Also clear last shown error when user initiates new fetch (allow new errors to show)
    unset($_SESSION['attendance_last_shown_error']);
    if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(['ok' => true, 'cleared' => true]);
        exit;
    }
}

// Xử lý request set clear fetch toast flag
if (isset($_POST['set_clear_fetch_toast']) && $_POST['set_clear_fetch_toast'] === '1') {
    // #region agent log
    $before_set = isset($_SESSION['attendance_clear_fetch_toast']);
    file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.microtime(true).'_before_set_flag','timestamp'=>microtime(true)*1000,'location'=>'profile_attendance.php:301','message'=>'BEFORE setting clear_fetch_toast flag','data'=>['before_set'=>$before_set,'request_method'=>$_SERVER['REQUEST_METHOD'],'is_ajax'=>isset($_SERVER['HTTP_X_REQUESTED_WITH'])],'sessionId'=>'debug-session','hypothesisId'=>'A,B,E'])."\n", FILE_APPEND);
    // #endregion
    $_SESSION['attendance_clear_fetch_toast'] = true;
    // #region agent log
    file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.microtime(true).'_after_set_flag','timestamp'=>microtime(true)*1000,'location'=>'profile_attendance.php:308','message'=>'AFTER setting clear_fetch_toast flag','data'=>['now_set'=>isset($_SESSION['attendance_clear_fetch_toast']),'request_method'=>$_SERVER['REQUEST_METHOD']],'sessionId'=>'debug-session','hypothesisId'=>'A,B,E'])."\n", FILE_APPEND);
    // #endregion
    // Trả về response để tránh xử lý tiếp
    if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(['ok' => true]);
        exit;
    }
}

// Nếu có flag clear fetch toast (từ cập nhật thời gian hoặc từ request set), reset fetch done để tránh hiển thị toast fetch
// #region agent log
$has_clear_flag_before = !empty($_SESSION['attendance_clear_fetch_toast']);
$has_edit_toast_before = !empty($_SESSION['attendance_edit_toast']);
$request_type = $_SERVER['REQUEST_METHOD'] . (isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? ' (AJAX)' : ' (Normal)');
file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.microtime(true).'_page_load_start','timestamp'=>microtime(true)*1000,'location'=>'profile_attendance.php:315','message'=>'PAGE LOAD START - checking flags','data'=>['has_clear_flag'=>$has_clear_flag_before,'has_edit_toast'=>$has_edit_toast_before,'request_type'=>$request_type,'has_post_set_clear'=>isset($_POST['set_clear_fetch_toast']),'has_post_fetch'=>isset($_POST['fetch_attendance'])],'sessionId'=>'debug-session','hypothesisId'=>'A,B,C,D'])."\n", FILE_APPEND);
// #endregion
if (!empty($_SESSION['attendance_clear_fetch_toast'])) {
    $__att_fetch_done = false;
    $__att_success_count = 0;
    $should_clear = (!isset($_POST['set_clear_fetch_toast']) || $_POST['set_clear_fetch_toast'] !== '1') && 
                    (!isset($_POST['fetch_attendance']) || empty($_POST['fetch_attendance']));
    // #region agent log
    file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.microtime(true).'_before_clear_flag','timestamp'=>microtime(true)*1000,'location'=>'profile_attendance.php:323','message'=>'BEFORE clearing flag','data'=>['should_clear'=>$should_clear,'has_flag_now'=>isset($_SESSION['attendance_clear_fetch_toast'])],'sessionId'=>'debug-session','hypothesisId'=>'A,B'])."\n", FILE_APPEND);
    // #endregion
    // Clear flag sau khi sử dụng (chỉ clear khi không phải là request set flag và không có POST data fetch)
    // Nếu có POST data fetch, giữ flag để tránh code fetch chạy và set lại các biến
    if ($should_clear) {
        unset($_SESSION['attendance_clear_fetch_toast']);
        // #region agent log
        file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.microtime(true).'_after_clear_flag','timestamp'=>microtime(true)*1000,'location'=>'profile_attendance.php:327','message'=>'AFTER clearing flag','data'=>['has_flag_now'=>isset($_SESSION['attendance_clear_fetch_toast'])],'sessionId'=>'debug-session','hypothesisId'=>'A,B'])."\n", FILE_APPEND);
        // #endregion
    }
} else {
    $__att_fetch_done = false;
    $__att_success_count = 0;
    // #region agent log
    file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.microtime(true).'_no_clear_flag','timestamp'=>microtime(true)*1000,'location'=>'profile_attendance.php:335','message'=>'NO clear_fetch_toast flag found','data'=>['request_type'=>$request_type],'sessionId'=>'debug-session','hypothesisId'=>'C,D'])."\n", FILE_APPEND);
    // #endregion
}
$__att_device = '';
$__att_device_ipport = '';
$__att_created = false;
$__att_created_msg = '';
$attendanceLanReady = $_SESSION['attendance_lan_ready'] ?? false;


// Chuẩn hoá mã nhân viên: tối thiểu 5 chữ số, thêm số 0 ở đầu
function format_pin($pin) {
    $s = preg_replace('/\D/', '', (string)$pin);
    if ($s === '') return '';
    if (strlen($s) < 5) return str_pad($s, 5, '0', STR_PAD_LEFT);
    return $s; // nếu dài hơn 5 giữ nguyên
}

// Lấy tên nhân viên theo danh sách mã (tối thiểu 5 chữ số)
function fetch_employee_names(array $pins): array {
    $pins = array_values(array_unique(array_filter(array_map('format_pin', $pins))));
    if (empty($pins)) return [];
    $conn = null; $map = [];
    try {
        $conn = db_connect();
        $ph = implode(',', array_fill(0, count($pins), '?'));
        // Cách 1: so khớp theo chuẩn hóa 5 chữ số (bao phủ trường hợp Maso_NV dạng số hoặc chuỗi có/không 0 đầu)
        $sql1 = "SELECT Maso_NV, Hoten FROM Datawork WHERE RIGHT(REPLICATE('0',5)+RTRIM(CAST(Maso_NV AS NVARCHAR(50))),5) IN ($ph)";
        $stmt = sqlsrv_query($conn, $sql1, $pins, ['Scrollable' => SQLSRV_CURSOR_KEYSET]);
        if ($stmt !== false) {
            while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
                $k = format_pin($row['Maso_NV'] ?? '');
                if ($k !== '') {
                    $map[$k] = (string)($row['Hoten'] ?? '');
                }
            }
            sqlsrv_free_stmt($stmt);
        }
        // Nếu vẫn chưa có kết quả, thử khớp trực tiếp theo chuỗi gốc (trường hợp DB lưu đúng 00092 dạng text)
        if (!$map) {
            $sql2 = "SELECT Maso_NV, Hoten FROM Datawork WHERE CAST(RTRIM(CAST(Maso_NV AS NVARCHAR(50))) AS NVARCHAR(50)) IN ($ph)";
            $stmt2 = sqlsrv_query($conn, $sql2, $pins, ['Scrollable' => SQLSRV_CURSOR_KEYSET]);
            if ($stmt2 !== false) {
                while ($row = sqlsrv_fetch_array($stmt2, SQLSRV_FETCH_ASSOC)) {
                    $k = format_pin($row['Maso_NV'] ?? '');
                    if ($k !== '') {
                        $map[$k] = (string)($row['Hoten'] ?? '');
                    }
                }
                sqlsrv_free_stmt($stmt2);
            }
        }
        // Nếu vẫn rỗng, thử khớp theo số nguyên (DB lưu 92 còn máy trả 00092)
        if (!$map) {
            $pinsInt = array_map('intval', $pins);
            $phi = implode(',', array_fill(0, count($pinsInt), '?'));
            $sql3 = "SELECT Maso_NV, Hoten FROM Datawork WHERE TRY_CONVERT(INT, RTRIM(CAST(Maso_NV AS NVARCHAR(50)))) IN ($phi)";
            $stmt3 = sqlsrv_query($conn, $sql3, $pinsInt, ['Scrollable' => SQLSRV_CURSOR_KEYSET]);
            if ($stmt3 !== false) {
                while ($row = sqlsrv_fetch_array($stmt3, SQLSRV_FETCH_ASSOC)) {
                    $k = format_pin($row['Maso_NV'] ?? '');
                    if ($k !== '') {
                        $map[$k] = (string)($row['Hoten'] ?? '');
                    }
                }
                sqlsrv_free_stmt($stmt3);
            }
        }
    } catch (Throwable $e) {
        // Bỏ qua; không chặn luồng hiển thị nếu DB lỗi
    } finally {
        if ($conn) { db_disconnect($conn); }
    }
    return $map;
}

// Tách Ngày/Giờ từ chuỗi thời gian (định dạng dd/mm/yyyy và hh:mm:ss)
function split_datetime_display(?string $dt): array {
    $dt = trim((string)$dt);
    if ($dt === '') return ['', ''];
    $ts = strtotime($dt);
    if ($ts === false) return [$dt, ''];
    return [date('d/m/Y', $ts), date('H:i:s', $ts)];
}

// Sắp xếp dữ liệu theo: Mã nhân viên (asc) -> Ngày (asc) -> Giờ (asc)
function sort_attendance_logs_by_pin_date_time(array $rows): array {
    usort($rows, function($a, $b){
        $pa = (string)($a['pin'] ?? '');
        $pb = (string)($b['pin'] ?? '');
        if ($pa !== $pb) return strcmp($pa, $pb);
        $dta = (string)($a['datetime'] ?? '');
        $dtb = (string)($b['datetime'] ?? '');
        $ta = strtotime($dta);
        $tb = strtotime($dtb);
        if ($ta === false) $ta = 0;
        if ($tb === false) $tb = 0;
        if ($ta === $tb) return 0;
        return ($ta < $tb) ? -1 : 1;
    });
    return $rows;
}

// XỬ LÝ THÊM MỚI THỦ CÔNG
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['attendance_create'])) {
    $pin  = isset($_POST['att_pin']) ? format_pin($_POST['att_pin']) : '';
    $name = trim((string)($_POST['att_name'] ?? ''));
    $date = trim((string)($_POST['att_date'] ?? ''));
    $time = trim((string)($_POST['att_time'] ?? ''));

    $errors = [];
    if ($pin === '')  { $errors[] = $messages['attendance_validation_employee_id_required'] ?? 'Mã nhân viên không được để trống.'; }
    if ($name === '') { $errors[] = $messages['attendance_validation_full_name_required'] ?? 'Họ tên không được để trống.'; }
    if ($date === '') { $errors[] = $messages['attendance_validation_date_required'] ?? 'Ngày không được để trống.'; }

    if (!empty($errors)) {
        $__att_create_error = implode('<br>', $errors);
    } else {
        // Ghép datetime từ ngày + giờ (ưu tiên chuẩn Y-m-d H:i:s)
        $datetime = '';
        if ($date !== '' && $time !== '') {
            $datetime = date('Y-m-d H:i:s', strtotime($date . ' ' . $time));
        } elseif ($date !== '') {
            // Cho phép giờ trống, mặc định 00:00:00
            $datetime = date('Y-m-d 00:00:00', strtotime($date));
        }

        // Tạo record và thêm vào session
        $new = [
            'pin'      => $pin,
            'name'     => $name,
            'datetime' => $datetime,
            'date'     => split_datetime_display($datetime)[0],
            'time'     => ($time === '' ? '' : split_datetime_display($datetime)[1]),
            'verify'   => '-----',
        ];

        $cur = $_SESSION['attendance_logs'] ?? [];
        $cur[] = $new;
        $cur = sort_attendance_logs_by_pin_date_time($cur);
        $_SESSION['attendance_logs'] = $cur;
        $logs = $cur; // cập nhật biến hiển thị ngay

        $__att_created = true;
        // Build localized success message with placeholders
        $template = $messages['attendance_success_row_added'] ?? 'Đã thêm vân tay ngày {date}-{time} cho nhân viên {pin} thành công!';
        $displayDate = split_datetime_display($datetime)[0] ?? $date;
        $displayTime = ($time === '' ? '' : (split_datetime_display($datetime)[1] ?? $time));
        $replacements = [
            '{date}' => $displayDate,
            '{time}' => $displayTime,
            '{pin}'  => $pin,
        ];
        $__att_created_msg = strtr($template, $replacements);
        // Dữ liệu vừa thay đổi, cần lọc trùng lại để tính cột Lần
        $_SESSION['attendance_lan_ready'] = false;
        unset($_SESSION['attendance_lan_map']);
        $attendanceLanReady = false;
    }
}

// XỬ LÝ CHỈNH SỬA THỜI GIAN (chỉ cho phép sửa Giờ, giữ nguyên Ngày)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['attendance_edit'])) {
    $pin  = isset($_POST['att_edit_pin']) ? format_pin($_POST['att_edit_pin']) : '';
    $time = trim((string)($_POST['att_edit_time'] ?? ''));

    $errors = [];
    if ($pin === '')  { $errors[] = $messages['attendance_validation_employee_id_required'] ?? 'Mã nhân viên không được để trống.'; }

    if (!empty($errors)) {
        $__att_edit_error = implode('<br>', $errors);
    } else {
        // Tìm record theo pin và datetime
        $cur = $_SESSION['attendance_logs'] ?? [];
        $oldDatetime = isset($_POST['att_edit_old_datetime']) ? trim((string)$_POST['att_edit_old_datetime']) : '';
        
        $found = false;
        foreach ($cur as $i => $r) {
            if (($r['pin'] ?? '') === $pin && ($r['datetime'] ?? '') === $oldDatetime) {
                // Lấy Ngày cũ (ISO) từ old datetime
                $oldDateIso = date('Y-m-d', strtotime($oldDatetime));
                // Nếu người dùng cung cấp giờ mới thì ghép vào; nếu để trống thì set 00:00:00
                if ($time !== '') {
                    $newDatetime = date('Y-m-d H:i:s', strtotime($oldDateIso . ' ' . $time));
                } else {
                    $newDatetime = date('Y-m-d 00:00:00', strtotime($oldDateIso));
                }
                
                $cur[$i]['datetime'] = $newDatetime;
                $cur[$i]['date'] = split_datetime_display($newDatetime)[0];
                $cur[$i]['time'] = ($time === '' ? '' : split_datetime_display($newDatetime)[1]);
                $cur[$i]['verify'] = '-----';
                $found = true;
                break;
            }
        }
        
        if ($found) {
            $cur = sort_attendance_logs_by_pin_date_time($cur);
            $_SESSION['attendance_logs'] = $cur;
            $logs = $cur;
            $__att_edited = false; // không hiện toast ngay, sẽ hiện sau khi reload
            $__att_edited_msg = $messages['attendance_success_updated_time'] ?? 'Đã cập nhật giờ chấm công.';
            // Dọn sạch các cờ/toast xóa cũ để tránh hiện nhầm sau khi cập nhật giờ
            unset($_SESSION['attendance_deleted'], $_SESSION['attendance_deleted_toast'], $_SESSION['attendance_redirect_url']);
            // Lưu toast và yêu cầu redirect để tránh toast trước reload
            $_SESSION['attendance_edit_toast'] = $__att_edited_msg;
            $_SESSION['attendance_edit_success_pending'] = true;
            $redirectUrl = 'index.php?attendance&page=1';
            if (!empty($_GET['page_size'])) {
                $redirectUrl .= '&page_size=' . (int)$_GET['page_size'];
            }
            if (!empty($_GET['search_query'])) {
                $redirectUrl .= '&search_query=' . urlencode($_GET['search_query']);
            }
            if (!empty($_GET['lang'])) {
                $redirectUrl .= '&lang=' . urlencode($_GET['lang']);
            }
            $_SESSION['attendance_edit_redirect_url'] = $redirectUrl;
            // Dữ liệu vừa thay đổi, cần lọc trùng lại để tính cột Lần
            $_SESSION['attendance_lan_ready'] = false;
            unset($_SESSION['attendance_lan_map']);
            $attendanceLanReady = false;
        } else {
            $__att_edit_error = $messages['attendance_error_record_not_found'] ?? 'Không tìm thấy bản ghi để chỉnh sửa.';
        }
    }
}

// XỬ LÝ NÚT LẤY DỮ LIỆU
// Luôn xử lý fetch khi có POST request - toast sẽ được kiểm soát riêng bởi flag ở phần hiển thị
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['fetch_attendance'])) {
    // Nếu vừa thực hiện fetch, bỏ cờ thông báo xóa (tránh hiện toast xóa ở lần load tiếp theo)
    if (isset($_SESSION['attendance_deleted_toast'])) {
        unset($_SESSION['attendance_deleted_toast']);
    }
    // LƯU DỮ LIỆU CŨ NGAY LẬP TỨC (TRƯỚC KHI XỬ LÝ BẤT CỨ ĐIỀU GÌ)
    // Để đảm bảo có dữ liệu cũ khi cần merge trong append mode
    // Ưu tiên lấy từ biến $logs đã load ở đầu file (dòng 18), sau đó mới lấy từ session
    // Lưu vào một biến session riêng để đảm bảo không bị mất
    $existingLogsForAppend = !empty($logs) ? $logs : ($_SESSION['attendance_logs'] ?? []);
    // Lưu vào session riêng để đảm bảo không bị mất khi xử lý
    if (!empty($existingLogsForAppend)) {
        $_SESSION['attendance_logs_backup'] = $existingLogsForAppend;
    }
    
    // Validation: Kiểm tra thiết bị đã được chọn chưa
    $deviceName = isset($_POST['device_name']) ? trim((string)$_POST['device_name']) : '';
    $deviceIp   = isset($_POST['device_ip']) && filter_var($_POST['device_ip'], FILTER_VALIDATE_IP) ? $_POST['device_ip'] : '';
    $devicePort = isset($_POST['device_port']) && (int)$_POST['device_port'] > 0 ? (int)$_POST['device_port'] : 0;
    
    // Nếu thiết bị chưa được chọn (thiếu device_name, IP hoặc Port), báo lỗi
    if ($deviceName === '' || $deviceIp === '' || $devicePort === 0) {
        $_SESSION['attendance_last_error'] = $messages['attendance_error_device_required'] ?? 'Vui lòng chọn thiết bị chấm công trước khi tải dữ liệu.';
        // Không redirect, để hiển thị lỗi trên trang
    } else {
        // Lấy tên máy: ưu tiên từ form (thiết bị người dùng đã chọn), sau đó mới query database
        // Ưu tiên 1: Lấy từ POST (thiết bị người dùng đã chọn trong form) - đã có ở trên
        // Ưu tiên 2: Nếu không có trong POST, query database theo IP/PORT để đảm bảo
        if ($deviceName === '') {
            try {
                $connTmp = db_connect();
                if ($connTmp) {
                    $stmtTmp = sqlsrv_query($connTmp, 'SELECT TOP 1 Name FROM ATTManager WHERE IP = ? AND PORT = ?', [$deviceIp, $devicePort]);
                    if ($stmtTmp !== false) {
                        $rowTmp = sqlsrv_fetch_array($stmtTmp, SQLSRV_FETCH_ASSOC);
                        if ($rowTmp && isset($rowTmp['Name'])) $deviceName = (string)$rowTmp['Name'];
                        sqlsrv_free_stmt($stmtTmp);
                    }
                    db_disconnect($connTmp);
                }
            } catch (Throwable $e) { /* ignore */ }
        }
        // Ưu tiên 3: Fallback cuối cùng (nếu có $selectedDevice)
        if ($deviceName === '' && !empty($selectedDevice['name'])) {
            $deviceName = (string)$selectedDevice['name'];
        }

        // Sử dụng dữ liệu cũ đã lưu ở đầu (trước khi xử lý)
        // Nếu không có trong biến, lấy từ backup session
        $existingLogs = !empty($existingLogsForAppend) ? $existingLogsForAppend : ($_SESSION['attendance_logs_backup'] ?? []);
        
    $logs = [];
    $error = null;
    $prevLanMap = $_SESSION['attendance_lan_map'] ?? [];

        // Luôn dùng UDP (ZKLibrary)
        require_once __DIR__ . '/lib/ZKLibrary.php';
        $zk = new ZKLibrary($deviceIp, $devicePort);
        if (method_exists($zk, 'setTimeout')) { $zk->setTimeout(5, 0); }

        // Đọc phạm vi thời gian người dùng chọn (tùy chọn)
        $fromDate = isset($_POST['fetch_from']) ? trim((string)$_POST['fetch_from']) : '';
        $toDate   = isset($_POST['fetch_to'])   ? trim((string)$_POST['fetch_to'])   : '';
        $fromTs = $fromDate ? strtotime($fromDate . ' 00:00:00') : null;
        $toTs   = $toDate   ? strtotime($toDate   . ' 23:59:59') : null;

        if ($zk->connect()) {
            $zk->disableDevice();
            $raw = $zk->getAttendance();
            $zk->enableDevice();
            $zk->disconnect();

            if (is_array($raw)) {
                foreach ($raw as $r) {
                    // ZKLibrary trả: [$uid, $id, $state, $timestamp]
                    $dtStr = isset($r[3]) ? (string)$r[3] : '';
                    $ts = $dtStr ? strtotime($dtStr) : null;
                    if ($fromTs && $ts && $ts < $fromTs) continue;
                    if ($toTs && $ts && $ts > $toTs) continue;
                    $logs[] = [
                        'pin'      => isset($r[1]) ? format_pin((string)$r[1]) : '',
                        'verify'   => isset($r[2]) ? (string)$r[2] : '',
                        'datetime' => $dtStr,
                        'date'     => split_datetime_display($dtStr)[0],
                        'time'     => split_datetime_display($dtStr)[1],
                        'device_name' => (string)$deviceName,
                    ];
                }
            }
            if (!$logs) {
                $error = $messages['attendance_error_no_data_received'] ?? 'Không nhận được dữ liệu chấm công nào từ thiết bị (UDP).';
            } else {
                // Luôn set fetch done khi có dữ liệu - toast sẽ được kiểm soát bởi flag ở phần hiển thị (line 3038)
                $__att_fetch_done = true;
                $__att_success_count = count($logs);
                // Clear last shown error on successful fetch (allow new errors to show)
                unset($_SESSION['attendance_last_shown_error']);
                // #region agent log
                file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.time().'_fetch_success','timestamp'=>time()*1000,'location'=>'profile_attendance.php:670','message'=>'Fetch successful','data'=>['logs_count'=>count($logs),'has_clear_flag'=>isset($_SESSION['attendance_clear_fetch_toast'])],'sessionId'=>'debug-session','hypothesisId'=>'FIX'])."\n", FILE_APPEND);
                // #endregion
                // Sử dụng tên thiết bị đã được chọn trong form, fallback về session hoặc selectedDevice nếu rỗng
                $__att_device = $deviceName ?: ($_SESSION['attendance_device'] ?? ($selectedDevice['name'] ?? ''));
                $__att_device_ipport = $deviceIp . ':' . $devicePort;
            }
        } else {
            $errno  = method_exists($zk, 'getLastErrno') ? ($zk->getLastErrno() ?? '-') : '-';
            $errstr = method_exists($zk, 'getLastError') ? ($zk->getLastError() ?? ($messages['attendance_error_unknown'] ?? 'Không rõ lỗi')) : ($messages['attendance_error_unknown'] ?? 'Không rõ lỗi');
            $hint   = '';
            if ($errno === 10013) { $hint = $messages['attendance_error_firewall_blocked'] ?? ' (bị chặn bởi tường lửa/permission denied)'; }
            if ($errno === 10060) { $hint = $messages['attendance_error_timeout'] ?? ' (hết thời gian chờ/timeout)'; }
            
            // Sử dụng tên thiết bị đã được lấy từ POST ở đầu (dòng 217-246)
            // $deviceName đã được set từ POST hoặc query database, sử dụng trực tiếp
            $deviceNameForError = trim($deviceName ?? '');
            
            // Format: "tên thiết bị (IP:Port)" nếu có tên, hoặc chỉ "(IP:Port)" nếu không có
            $deviceDisplay = !empty($deviceNameForError) ? ($deviceNameForError . ' ') : '';
            $errorTemplate = $messages['attendance_error_udp_connection_failed'] ?? 'Không thể kết nối UDP tới thiết bị {device}({ip}:{port}). Lỗi: {error} [errno={errno}]{hint}';
            $error = str_replace(['{device}', '{ip}', '{port}', '{error}', '{errno}', '{hint}'], [$deviceDisplay, $deviceIp, $devicePort, $errstr, $errno, $hint], $errorTemplate);
        }

        // Ghép họ tên theo mã NV
        if (!empty($logs)) {
            $pinList = array_column($logs, 'pin');
            $nameMap = fetch_employee_names($pinList);
            foreach ($logs as $i => $r) {
                $p = $r['pin'] ?? '';
                $logs[$i]['name'] = $nameMap[$p] ?? '';
            }
        }

        // Sắp xếp theo: Mã NV -> Ngày/Giờ
        $logs = sort_attendance_logs_by_pin_date_time($logs);

        // Ghi nhận trạng thái cột Lần trước khi fetch (đã được tính sau khi lọc trùng)
        $prevLanReady = $_SESSION['attendance_lan_ready'] ?? false;

        // Kiểm tra chế độ append hay overwrite
        $appendMode = isset($_POST['append_mode']) && $_POST['append_mode'] === '1';
        
        if ($appendMode && !empty($existingLogs)) {
            // Ghi tiếp: Merge dữ liệu mới với dữ liệu cũ
            // KHÔNG loại bỏ duplicate - giữ nguyên tất cả dữ liệu
            $mergedLogs = array_merge($existingLogs, $logs);
            
            // Chỉ sắp xếp lại, không loại bỏ duplicate
            $logs = sort_attendance_logs_by_pin_date_time($mergedLogs);
        }
        // Nếu không phải append mode hoặc không có dữ liệu cũ, sẽ overwrite (giữ nguyên logic cũ)

        // Lưu dữ liệu vào biến/phiên nhưng KHÔNG redirect (tránh lỗi headers sent)
        $_SESSION['attendance_logs'] = $logs; // cho phép rời trang vẫn còn dữ liệu
        // DON'T persist error to session - it will be re-shown on form resubmit
        // Only use local $error variable which exists only on the actual fetch POST response
        // $_SESSION['attendance_last_error'] = $error;  // REMOVED to prevent error persistence on refresh
        // Quyết định trạng thái cột Lần:
        // - Nếu append: giữ nguyên flag nhưng KHÔNG tính lại cho dữ liệu mới, sử dụng lan_map cũ để tránh tự cập nhật cho bản ghi mới.
        // - Nếu overwrite hoặc trước đó chưa tính -> cần lọc trùng lại, nên đặt false.
        if ($appendMode && $prevLanReady) {
        $_SESSION['attendance_lan_ready'] = true;
        $_SESSION['attendance_lan_map'] = is_array($prevLanMap) ? $prevLanMap : [];
        $attendanceLanReady = true;
        } else {
            $_SESSION['attendance_lan_ready'] = false;
            unset($_SESSION['attendance_lan_map']);
            $attendanceLanReady = false;
        }
        // Xóa backup sau khi đã lưu dữ liệu mới
        if (isset($_SESSION['attendance_logs_backup'])) {
            unset($_SESSION['attendance_logs_backup']);
        }
        // Không header redirect; để render thẳng dưới đây
    }
}

// XỬ LÝ LỌC TRÙNG DỮ LIỆU CHẤM CÔNG
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['attendance_filter_duplicate'])) {
    $logs = $_SESSION['attendance_logs'] ?? [];
    if (empty($logs)) {
        $_SESSION['attendance_filter_duplicate_error'] = $messages['attendance_filter_duplicate_no_data'] ?? 'Không có dữ liệu để lọc trùng.';
    } else {
        // Nhóm dữ liệu theo pin và date
        $grouped = [];
        foreach ($logs as $log) {
            $pin = (string)($log['pin'] ?? '');
            $date = (string)($log['date'] ?? '');
            if ($pin !== '' && $date !== '') {
                $key = $pin . '|' . $date;
                if (!isset($grouped[$key])) {
                    $grouped[$key] = [];
                }
                $grouped[$key][] = $log;
            }
        }
        
        // Lọc trùng trong mỗi nhóm
        $filteredLogs = [];
        foreach ($grouped as $key => $group) {
            // Sắp xếp theo datetime
            usort($group, function($a, $b) {
                $ta = strtotime($a['datetime'] ?? '');
                $tb = strtotime($b['datetime'] ?? '');
                if ($ta === false) $ta = 0;
                if ($tb === false) $tb = 0;
                return ($ta < $tb) ? -1 : (($ta > $tb) ? 1 : 0);
            });
            
            // Giữ lại bản ghi đầu tiên, loại bỏ các bản ghi cách nhau <= 5 phút
            $lastKept = null;
            foreach ($group as $log) {
                $currentTime = strtotime($log['datetime'] ?? '');
                if ($currentTime === false) {
                    // Nếu không parse được datetime, giữ lại
                    $filteredLogs[] = $log;
                    continue;
                }
                
                if ($lastKept === null) {
                    // Bản ghi đầu tiên luôn được giữ lại
                    $filteredLogs[] = $log;
                    $lastKept = $currentTime;
                } else {
                    // Kiểm tra xem có cách nhau > 5 phút không (300 giây)
                    $diff = abs($currentTime - $lastKept);
                    if ($diff > 300) {
                        // Cách nhau > 5 phút, giữ lại
                        $filteredLogs[] = $log;
                        $lastKept = $currentTime;
                    }
                    // Nếu <= 5 phút thì bỏ qua (không thêm vào filteredLogs)
                }
            }
        }
        
        // Sắp xếp lại và cập nhật session
        $filteredLogs = sort_attendance_logs_by_pin_date_time($filteredLogs);
        $_SESSION['attendance_logs'] = $filteredLogs;
        $_SESSION['attendance_filter_duplicate_success'] = true;
        $removedCount = count($logs) - count($filteredLogs);
        $_SESSION['attendance_filter_duplicate_removed'] = $removedCount;
        // Sau khi lọc trùng xong, cho phép hiển thị cột Lần
        $_SESSION['attendance_lan_ready'] = true;
        $_SESSION['attendance_lan_map'] = build_attendance_lan_map($filteredLogs);
        $attendanceLanReady = true;
    }
    
    // Lưu URL redirect vào session (tránh lỗi headers already sent)
    $redirectUrl = 'index.php?attendance&page=1';
    if (!empty($_GET['page_size'])) {
        $redirectUrl .= '&page_size=' . (int)$_GET['page_size'];
    }
    if (!empty($_GET['search_query'])) {
        $redirectUrl .= '&search_query=' . urlencode($_GET['search_query']);
    }
    if (!empty($_GET['lang'])) {
        $redirectUrl .= '&lang=' . urlencode($_GET['lang']);
    }
    $_SESSION['attendance_filter_duplicate_redirect_url'] = $redirectUrl;
    $_SESSION['attendance_filter_duplicate_needs_reload'] = true;
    // Không dùng header redirect, để JavaScript xử lý
}

// XỬ LÝ XÓA DỮ LIỆU CHẤM CÔNG
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_attendance'])) {
    $deleteType = isset($_POST['delete_type']) ? $_POST['delete_type'] : 'table';
    
    if ($deleteType === 'table') {
        // Xóa toàn bộ dữ liệu chấm công trong session
        $_SESSION['attendance_logs'] = [];
        $_SESSION['attendance_last_error'] = null;
        $_SESSION['attendance_lan_ready'] = false;
        unset($_SESSION['attendance_lan_map']);
        $attendanceLanReady = false;
        // Đánh dấu đã xóa để hiển thị thông báo và redirect bằng JavaScript
        $_SESSION['attendance_deleted'] = true;
        $_SESSION['attendance_deleted_toast'] = true; // hiển thị thông báo sau khi sang trang mới
    } else if ($deleteType === 'device') {
        // Xóa dữ liệu từ máy chấm công
        $deviceName = isset($_POST['delete_device_name']) ? $_POST['delete_device_name'] : '';
        $deviceIp = isset($_POST['delete_device_ip']) ? $_POST['delete_device_ip'] : '';
        $devicePort = isset($_POST['delete_device_port']) ? (int)$_POST['delete_device_port'] : 4370;
        
        if (!empty($deviceIp)) {
            try {
                require_once __DIR__ . '/lib/ZKLibrary.php';
                $zk = new ZKLibrary($deviceIp, $devicePort);
                
                // Connect to device
                $connected = $zk->connect();
                if (!$connected) {
                    throw new Exception('Không thể kết nối đến máy chấm công ' . $deviceIp . ':' . $devicePort);
                }
                
                // Disable device before clearing (required by most ZK devices)
                $disabled = $zk->disableDevice();
                if ($disabled === false) {
                    throw new Exception('Không thể tắt máy chấm công. Vui lòng kiểm tra quyền truy cập.');
                }
                
                // Clear attendance data from device (only attendance logs, not users/fingerprints)
                // Note: execCommand returns false on error, or data (including empty string) on success
                $cleared = $zk->clearAttendance();
                if ($cleared === false) {
                    $zk->enableDevice(); // Try to re-enable before throwing
                    throw new Exception('Lệnh xóa dữ liệu thất bại. Máy chấm công có thể đang bị khóa hoặc cần quyền admin.');
                }
                
                // Enable device after clearing
                $enabled = $zk->enableDevice();
                if ($enabled === false) {
                    throw new Exception('Xóa dữ liệu thành công nhưng không thể bật lại máy chấm công.');
                }
                
                $zk->disconnect();
                
                // Success
                $_SESSION['attendance_device_deleted'] = true;
                $_SESSION['attendance_device_deleted_toast'] = true;
                $_SESSION['attendance_device_deleted_name'] = $deviceName;
                $_SESSION['attendance_device_deleted_ip'] = $deviceIp . ':' . $devicePort;
            } catch (Exception $e) {
                $_SESSION['attendance_device_delete_error'] = true;
                $_SESSION['attendance_device_delete_error_msg'] = 'Lỗi: ' . $e->getMessage();
            }
        } else {
            $_SESSION['attendance_device_delete_error'] = true;
            $_SESSION['attendance_device_delete_error_msg'] = 'Thiếu thông tin IP máy chấm công.';
        }
    }
    
    // Lưu URL redirect vào session (tránh lỗi headers already sent)
    $redirectUrl = 'index.php?attendance&page=1';
    if (!empty($_GET['page_size'])) {
        $redirectUrl .= '&page_size=' . (int)$_GET['page_size'];
    }
    if (!empty($_GET['search_query'])) {
        $redirectUrl .= '&search_query=' . urlencode($_GET['search_query']);
    }
    if (!empty($_GET['lang'])) {
        $redirectUrl .= '&lang=' . urlencode($_GET['lang']);
    }
    // Gắn cờ vào URL để fallback khi session bị reset
    $redirectUrl .= '&att_del=1';
    $_SESSION['attendance_redirect_url'] = $redirectUrl;
    // Không dùng header redirect, để JavaScript xử lý
}

// Load verifyMap từ database (cần trước khi search)
$verifyMap = [];
try {
    $conn = db_connect();
    if ($conn) {
        $stmt = sqlsrv_query($conn, 'SELECT Id, Name_VN, Name_ENG FROM ATT_Type_Connect');
        if ($stmt !== false) {
            $isEng = (($_SESSION['lang'] ?? 'vn') === 'eng');
            while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
                $id = (string)($row['Id'] ?? '');
                $label = $isEng ? (string)($row['Name_ENG'] ?? '') : (string)($row['Name_VN'] ?? '');
                if ($id !== '') { $verifyMap[$id] = $label; }
            }
            sqlsrv_free_stmt($stmt);
        }
        db_disconnect($conn);
    }
} catch (Throwable $e) { /* ignore */ }

// Search query
$searchQuery = !empty($_GET['search_query']) ? trim($_GET['search_query']) : '';

// Filter logs by search query (search in pin, name, verify)
$filteredLogs = $logs;
if (!empty($searchQuery)) {
    $searchLower = mb_strtolower($searchQuery, 'UTF-8');
    $filteredLogs = array_filter($logs, function($row) use ($searchLower, $verifyMap) {
        $pin = mb_strtolower($row['pin'] ?? '', 'UTF-8');
        $name = mb_strtolower($row['name'] ?? '', 'UTF-8');
        $verify = $row['verify'] ?? '';
        $verifyLabel = mb_strtolower($verifyMap[$verify] ?? $verify, 'UTF-8');
        return (strpos($pin, $searchLower) !== false) || 
               (strpos($name, $searchLower) !== false) || 
               (strpos($verifyLabel, $searchLower) !== false);
    });
    $filteredLogs = array_values($filteredLogs); // Re-index array
}

// Tuỳ chọn số dòng mỗi trang (giống công văn đến)
$allowedPageSizes = [5, 10, 20, 50, 100];
$pageSize = isset($_GET['page_size']) ? (int)$_GET['page_size'] : (isset($_SESSION['attendance_page_size']) ? (int)$_SESSION['attendance_page_size'] : 5);
if (!in_array($pageSize, $allowedPageSizes, true)) { $pageSize = 5; }
$_SESSION['attendance_page_size'] = $pageSize;

// Phân trang tương tự trang công văn đến
$itemsPerPage = $pageSize;
$currentPage = (int)($_GET['page'] ?? 1);
$currentPage = max(1, $currentPage);
$totalItems = is_array($filteredLogs) ? count($filteredLogs) : 0;
$totalPages = ($itemsPerPage > 0) ? (int)ceil($totalItems / $itemsPerPage) : 1;
$offset = ($currentPage - 1) * $itemsPerPage;
$pageLogs = array_slice($filteredLogs, $offset, $itemsPerPage, true); // preserve keys for stable "Lần"
?>

<section class="panel-grid attendance-grid">
    <div class="panel wide attendance-panel">
        <header class="panel-header">
            <h3 style="text-transform: uppercase;"><?= htmlspecialchars($messages['control_nav_attendance_data'] ?? 'Dữ liệu chấm công', ENT_QUOTES, 'UTF-8') ?></h3>
            <style>
            /* Attendance page scoped styles - do not touch global CSS */
            .attendance-panel { overflow-x:hidden; }
            .attendance-panel .panel-header { overflow-x:hidden; }
            .attendance-panel .attendance-controls { display:flex; gap:12px; flex-wrap:nowrap; justify-content:flex-end; align-items:center; overflow-x:hidden; }
            .attendance-panel #attendance-fetch-form { display:flex; gap:12px; align-items:center; }
            .attendance-panel #attendance-fetch-form > * { min-width:0; }
            .attendance-panel .attendance-btn { padding:8px 16px !important; font-size:13px !important; font-weight:500 !important; border-radius:8px !important; min-height:36px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; gap:8px !important; white-space:nowrap !important; text-decoration:none !important; background:linear-gradient(135deg, rgba(100,167,166,0.9), rgba(122,220,201,0.95)) !important; color:#052729 !important; border:1px solid rgba(122,220,201,0.4) !important; }
            .attendance-panel .attendance-btn:hover { background:linear-gradient(135deg, rgba(122,220,201,0.95), rgba(100,167,166,0.9)) !important; transform:translateY(-1px) !important; box-shadow:0 4px 12px rgba(122,220,201,0.3) !important; }
            .attendance-panel .attendance-controls .btn-icon-wrapper { display:inline-grid; place-items:center; width:14px; height:14px; }
            .attendance-panel .attendance-controls .btn-icon-wrapper svg { width:14px; height:14px; }
            .attendance-panel .attendance-controls .btn-text-wrapper { font-size:13px; font-weight:500; color:inherit; }
            .attendance-panel .attendance-btn:focus-visible { outline:2px solid rgba(122,220,201,0.6) !important; outline-offset:2px !important; }
            .attendance-panel #attendance-device-custom-select { width:auto; min-width:0; }
            .attendance-panel #attendance-device-custom-select .custom-select-toggle { max-width:100%; }
            .attendance-panel #attendance-device-custom-select .custom-select-menu { z-index: 20; }

            /* Mobile fixes */
            @media (max-width: 768px) {
              .attendance-panel .panel-header { display:flex; flex-direction:column; align-items:stretch; }
              .attendance-panel .attendance-controls { width: 100%; display:block !important; }
              /* Custom Select ở hàng riêng; 2 nút ở hàng kế tiếp */
              .attendance-panel #attendance-fetch-form {
                width: 100% !important;
                display: grid !important;
                grid-template-columns: 1fr 1fr !important;
                gap: 8px !important;
                align-items: stretch !important;
              }
              .attendance-panel #attendance-device-custom-select { grid-column: 1 / -1 !important; width: 100%; min-width: 0; }
              .attendance-panel #attendance-device-custom-select .custom-select-toggle { width: 100%; }
              .attendance-panel #attendance-device-custom-select .custom-select-toggle span { display:flex; flex-direction:column; overflow:hidden; }
              .attendance-panel #attendance-device-custom-select .custom-select-toggle span > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
              .attendance-panel #attendance-device-custom-select .custom-select-menu { width: 100%; min-width: 100%; }
              .attendance-panel #attendance-fetch-form .attendance-btn { width: 100% !important; font-size:13px !important; padding:8px 10px !important; position:relative !important; float:none !important; align-self:stretch !important; display:grid !important; grid-template-rows: 18px 1fr !important; align-items:center !important; justify-items:center !important; gap:4px !important; line-height:1.3 !important; min-height:60px !important; height:100% !important; overflow:visible !important; }
              .attendance-panel #attendance-open-create { width: 100% !important; margin-top: 0 !important; }
              /* Allow full label, avoid clipping */
              .attendance-panel #attendance-fetch-form .attendance-btn .btn-text-wrapper { white-space:normal !important; overflow:visible !important; text-overflow:unset !important; text-align:center !important; display:block !important; width:100% !important; }
              .attendance-panel #attendance-fetch-form .attendance-btn .btn-icon-wrapper { width:18px !important; height:18px !important; margin:0 !important; display:block !important; }
            }
            @media (max-width: 390px) {
              .attendance-panel #attendance-device-custom-select .custom-select-toggle { padding: 6px 10px; }
            }
            </style>
            <style>
            /* Additional strict mobile fixes */
            @media (max-width: 768px) {
              .attendance-panel .panel-header { display:block; height: 20px;}
              .attendance-panel .attendance-controls { width: 100% !important; justify-content: flex-start !important; overflow:hidden; }
              .attendance-panel #attendance-fetch-form { width: 100% !important; display:grid !important; grid-template-columns: 1fr 1fr !important; gap:8px !important; align-items:stretch !important; }
              .attendance-panel #attendance-device-custom-select { width: 100% !important; min-width: 0 !important; display:block; }
              .attendance-panel #attendance-device-custom-select .custom-select-toggle { width: 100% !important; }
              .attendance-panel #attendance-fetch-form .attendance-btn { width: 100% !important; display:inline-flex !important; margin-top:0 !important; }
              .attendance-panel .attendance-controls, 
              .attendance-panel #attendance-fetch-form,
              .attendance-panel #attendance-device-custom-select,
              .attendance-panel #attendance-device-custom-select .custom-select-toggle,
              .attendance-panel .attendance-btn { box-sizing: border-box; max-width:100%; }
            }
            .att-actions { display:flex; gap:8px;     justify-content: center; }
            .att-btn-icon { background:transparent; border:1px solid rgba(122,220,201,.28); color:#bfeee3; border-radius:6px; width:28px; height:28px; display:inline-grid; place-items:center; cursor:pointer; transition:.2s; }
            .att-btn-icon:hover { background:rgba(122,220,201,.12); color:#7adcc9; border-color:rgba(122,220,201,.45); }
            </style>
            <div class="panel-controls attendance-controls">

                <?php
                // Load time clock devices
                $devices = [];
                try {
                    $conn = db_connect();
                    if ($conn) {
                        $stmt = sqlsrv_query($conn, 'SELECT Name, IP, PORT FROM ATTManager ORDER BY Name ASC');
                        if ($stmt !== false) {
                            while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
                                $devices[] = [
                                    'key' => (string)($row['Name'] ?? ''),
                                    'name' => (string)($row['Name'] ?? ''),
                                    'ip' => (string)($row['IP'] ?? ''),
                                    'port' => (int)($row['PORT'] ?? 4370),
                                ];
                            }
                            sqlsrv_free_stmt($stmt);
                        }
                        db_disconnect($conn);
                    }
                } catch (Throwable $e) { /* ignore */ }
                // Chọn thiết bị mặc định theo Name (ATTManager không có Id)
                $selectedKey = isset($_GET['device']) ? (string)$_GET['device'] : (isset($_SESSION['attendance_device']) ? (string)$_SESSION['attendance_device'] : (count($devices) ? (string)$devices[0]['key'] : ''));
                if (isset($_GET['device'])) { $_SESSION['attendance_device'] = $selectedKey; }
                $selectedDevice = null;
                foreach ($devices as $d) { if ((($d['key'] ?? $d['name']) === $selectedKey)) { $selectedDevice = $d; break; } }
                if ($selectedDevice === null && count($devices)) { $selectedDevice = $devices[0]; $selectedKey = $selectedDevice['key'] ?? $selectedDevice['name']; }
                $uiIp = isset($_POST['device_ip']) ? (string)$_POST['device_ip'] : ($selectedDevice['ip'] ?? '192.168.1.227');
                $uiPort = isset($_POST['device_port']) ? (int)$_POST['device_port'] : ($selectedDevice['port'] ?? 4370);
                ?>
                <form id="attendance-fetch-form" method="post" class="inline-form" style="display:flex; gap:12px; align-items:center; flex-wrap:nowrap;">
                    <div class="custom-select" id="attendance-device-custom-select" style="display:none !important;">
                        <button type="button" class="custom-select-toggle" style="min-width:240px; display:flex; justify-content:space-between; align-items:center; padding:8px 12px;" data-placeholder="<?= htmlspecialchars($selectedDevice['name'] ?? 'Chọn máy chấm công', ENT_QUOTES, 'UTF-8') ?>">
                            <span style="display:flex; flex-direction:column; align-items:flex-start; gap:2px;">
                                <span style="font-size:13px; font-weight:500;"><?= htmlspecialchars($selectedDevice['name'] ?? 'Chọn máy chấm công', ENT_QUOTES, 'UTF-8') ?></span>
                                <span style="font-size:11px; color:#7eb8b0;" id="attendance-info-display"><?= htmlspecialchars($uiIp . ':' . $uiPort, ENT_QUOTES, 'UTF-8') ?></span>
                            </span>
                            <svg style="width:16px; height:16px; fill:currentColor; flex-shrink:0;" viewBox="0 0 24 24"><path d="M7 10l5 5 5-5z"/></svg>
                        </button>
                        <div class="custom-select-menu" role="listbox">
                            <?php foreach ($devices as $dev): ?>
                                <div class="custom-select-option<?= ((($dev['key'] ?? $dev['name']) === $selectedKey) ? ' is-selected' : '') ?>" role="option" data-value="<?= htmlspecialchars($dev['key'] ?? $dev['name'], ENT_QUOTES, 'UTF-8') ?>" data-ip="<?= htmlspecialchars($dev['ip'], ENT_QUOTES, 'UTF-8') ?>" data-port="<?= (int)$dev['port'] ?>" style="padding:4px 12px;">
                                    <div style="font-size:13px; font-weight:500;"><?= htmlspecialchars($dev['name'], ENT_QUOTES, 'UTF-8') ?></div>
                                    <div style="font-size:11px; color:#7eb8b0; margin-top:2px;">&lrm;<?= htmlspecialchars($dev['ip'] . ':' . $dev['port'], ENT_QUOTES, 'UTF-8') ?></div>
                                </div>
                            <?php endforeach; ?>
                        </div>
                        <input type="hidden" id="attendance-device-key" value="<?= htmlspecialchars($selectedKey, ENT_QUOTES, 'UTF-8') ?>" />
                    </div>
                    <input id="attendance-ip" type="hidden" name="device_ip" value="<?= htmlspecialchars($uiIp, ENT_QUOTES, 'UTF-8') ?>" />
                    <input id="attendance-port" type="hidden" name="device_port" value="<?= htmlspecialchars((string)$uiPort, ENT_QUOTES, 'UTF-8') ?>" />
                    <input id="attendance-device-name" type="hidden" name="device_name" value="<?= htmlspecialchars($selectedDevice['name'] ?? '', ENT_QUOTES, 'UTF-8') ?>" />
                    <input type="hidden" id="attendance-fetch-from" name="fetch_from" value="" />
                    <input type="hidden" id="attendance-fetch-to" name="fetch_to" value="" />
                    <input type="hidden" id="attendance-fetch-flag" name="fetch_attendance" value="" />
                    <input type="hidden" id="attendance-fetch-all" name="fetch_all" value="" />
                    <input type="hidden" id="attendance-append-mode" name="append_mode" value="0" />
                    <button type="button" id="attendance-open-fetch" class="btn btn-primary attendance-btn">
                        <span aria-hidden="true" class="btn-icon-wrapper">
                            <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M12 3v12"></path>
                                <path d="M8 11l4 4 4-4"></path>
                                <path d="M5 21h14"></path>
                            </svg>
                        </span>
                        <span class="btn-text-wrapper">Lấy dữ liệu từ máy</span>
                    </button>
                    <button type="button" class="btn btn-primary attendance-btn" id="attendance-open-create">
                        <span aria-hidden="true" class="btn-icon-wrapper">
                            <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <line x1="12" y1="5" x2="12" y2="19"></line>
                                <line x1="5" y1="12" x2="19" y2="12"></line>
                            </svg>
                        </span>
                        <span class="btn-text-wrapper">Thêm mới</span>
                    </button>
                    
                </form>
                <style id="attendance-sprin-fix">
                  /* Do not clip the header controls */
                  .attendance-panel, .attendance-panel .panel-header, .attendance-panel .attendance-controls { overflow: visible !important; }
                  /* Always hide old buttons */
                  .attendance-panel #attendance-open-fetch, .attendance-panel #attendance-open-create { display:none !important; }
                  /* Place and lift the sprint menu */
                  .attendance-panel .menu-sprin-wrapper { position: relative !important; display:inline-block !important; z-index: 100000 !important; }
                  .attendance-panel .menu-sprin-btn, .attendance-panel .menu-sprin-item { z-index: 100001 !important; }
                  /* Base (closed) state for items */
                  .attendance-panel .menu-sprin-wrapper .menu-sprin-item { opacity:0; pointer-events:none; transform: scale(.6); transition: transform .25s cubic-bezier(.68,-.55,.27,1.55), opacity .18s ease; }
                  /* Open state controlled by wrapper.open class (JS toggles) */
                  .attendance-panel .menu-sprin-wrapper.open .item1 { transform: translate(0,56px) scale(1);   opacity:1; pointer-events:auto; }
                  .attendance-panel .menu-sprin-wrapper.open .item2 { transform: translate(-46px,46px) scale(1); opacity:1; pointer-events:auto; }
                  .attendance-panel .menu-sprin-wrapper.open .item3 { transform: translate(-56px,0)  scale(1);  opacity:1; pointer-events:auto; }
                  .attendance-panel .menu-sprin-wrapper.open .item4 { transform: translate(-46px,-46px) scale(1);opacity:1; pointer-events:auto; }
                  .attendance-panel .menu-sprin-wrapper.open .item5 { transform: translate(0,-56px)  scale(1);  opacity:1; pointer-events:auto; }
                  .attendance-panel .menu-sprin-wrapper.open .item6 { transform: translate(46px,-46px) scale(1); opacity:1; pointer-events:auto; }
                  .attendance-panel .menu-sprin-wrapper.open .item7 { transform: translate(56px,0)  scale(1);  opacity:1; pointer-events:auto; }
                  .attendance-panel .menu-sprin-wrapper.open .item8 { transform: translate(46px,46px) scale(1); opacity:1; pointer-events:auto; }
                </style>
                <style id="attendance-sprin-drag-style">
                  /* Inline tooltip style to ensure visibility even if external CSS not loaded */
                  .menu-sprin-item::after{content:attr(data-tooltip);position:absolute;background:rgba(17,46,51,.95);color:#e8fbf6;border:1px solid rgba(122,220,201,.30);border-radius:8px;padding:4px 8px;font-size:11px;white-space:nowrap;box-shadow:0 8px 20px rgba(3,15,21,.4);z-index:2147483000;opacity:0;transition:opacity .15s ease;pointer-events:none}
                  .menu-sprin-wrapper.tips-on .menu-sprin-item::after{opacity:1}
                  /* Position by data-tip-pos attribute */
                  .menu-sprin-wrapper.tips-on .menu-sprin-item[data-tip-pos="right"]::after{left:calc(100% + 10px);top:50%;bottom:auto;transform:translateY(-50%)}
                  .menu-sprin-wrapper.tips-on .menu-sprin-item[data-tip-pos="left"]::after{right:calc(100% + 10px);left:auto;top:50%;bottom:auto;transform:translateY(-50%)}
                  .menu-sprin-wrapper.tips-on .menu-sprin-item[data-tip-pos="top"]::after{left:50%;top:auto;bottom:calc(100% + 10px);transform:translateX(-50%)}
                  .menu-sprin-wrapper.tips-on .menu-sprin-item[data-tip-pos="bottom"]::after{left:50%;top:calc(100% + 10px);bottom:auto;transform:translateX(-50%)}
                  /* Default: right; special case item1 (Export) left ONLY if no override present */
                  .menu-sprin-wrapper.tips-on .menu-sprin-item:not([data-tip-pos])::after{left:calc(100% + 10px);top:50%;transform:translateY(-50%)}
                  .menu-sprin-wrapper.tips-on .item1:not([data-tip-pos])::after{left:auto;right:calc(100% + 10px);top:50%;transform:translateY(-50%)}

                  .panel-grid.attendance-grid { position: relative; }
                  .menu-sprin-wrapper.draggable { position: absolute !important; width:44px; height:44px; z-index: 999 !important; }
                  .menu-sprin-wrapper.draggable.dragging { cursor: grabbing !important; }
                </style>
                <!-- Force-hide legacy header buttons on mobile -->
                <style id="attendance-mobile-hide-old-buttons">
                  @media (max-width: 768px) {
                    .attendance-panel #attendance-open-fetch,
                    .attendance-panel #attendance-open-create { display:none !important; visibility:hidden !important; }
                  }
                </style>
                <div class="menu-sprin-wrapper">
                    <!-- Checkbox điều khiển trạng thái mở/đóng -->
                    <input type="checkbox" id="menu-sprin-toggle" class="menu-sprin-toggle" />

                    <!-- Nút trung tâm: dùng emoji để khỏi cần CDN -->
                    <label class="menu-sprin-btn" for="menu-sprin-toggle" aria-label="Mở menu">
                    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                        <path d="M3 11l9-8 9 8"/>
                        <path d="M9 22V12h6v10"/>
                    </svg>
                    </label>

                    <!-- Các nút con: cũng dùng emoji, sau này bạn thay bằng icon FontAwesome/SVG tuỳ ý -->
                    <div class="menu-sprin-item item1" role="button" aria-label="Tài khoản" data-tooltip="<?= htmlspecialchars($messages['attendance_sprin_export'] ?? 'Export data', ENT_QUOTES, 'UTF-8') ?>" data-tip-pos="bottom">
                    <svg viewBox="0 0 24 24" width="26" height="26" aria-hidden="true">
                        <!-- Khay / hộp dữ liệu -->
                        <path d="M4 13h4l2 3h4l2-3h4v5a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-5z" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"></path>
                        <!-- Mũi tên xuất lên trên -->
                        <path d="M12 3v9" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"></path>
                        <path d="M8.5 7.5L12 4l3.5 3.5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"></path>
                    </svg>
                    </div>
                    <div class="menu-sprin-item item2" role="button" aria-label="Đào tạo" data-tooltip="<?= htmlspecialchars($messages['attendance_sprin_add_row'] ?? 'Add new row', ENT_QUOTES, 'UTF-8') ?>" data-tip-pos="left">
                    <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <line x1="12" y1="5" x2="12" y2="19"></line>
                                <line x1="5" y1="12" x2="19" y2="12"></line>
                            </svg>
                    </div>
                    <div class="menu-sprin-item item3" role="button" aria-label="<?= htmlspecialchars($messages['attendance_sprin_update'] ?? 'Cập nhật', ENT_QUOTES, 'UTF-8') ?>" data-tooltip="<?= htmlspecialchars($messages['attendance_sprin_update'] ?? 'Cập nhật', ENT_QUOTES, 'UTF-8') ?>" data-tip-pos="left" id="attendance-update-btn">
                    <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                        <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
                        <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
                    </svg>
                    </div>
                    <div class="menu-sprin-item item4" role="button" aria-label="Lọc trùng" data-tooltip="<?= htmlspecialchars($messages['attendance_sprin_filter_duplicate'] ?? 'Lọc trùng', ENT_QUOTES, 'UTF-8') ?>" data-tip-pos="left" id="attendance-filter-duplicate-btn">
                    <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                        <path d="M22 3H2l8 9.46V19l4 2v-8.54L22 3z"/>
                        <path d="M2 3l20 0"/>
                    </svg>
                    </div>
                    <div class="menu-sprin-item item5" role="button" aria-label="Xóa" data-tooltip="<?= htmlspecialchars($messages['attendance_sprin_delete'] ?? 'Xóa dữ liệu', ENT_QUOTES, 'UTF-8') ?>" data-tip-pos="top" id="attendance-delete-btn">
                    <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                        <polyline points="3 6 5 6 21 6"/>
                        <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
                        <line x1="10" y1="11" x2="10" y2="17"/>
                        <line x1="14" y1="11" x2="14" y2="17"/>
                    </svg>
                    </div>
                    <div class="menu-sprin-item item6" role="button" aria-label="Icon 6" data-tooltip="Icon 6" data-tip-pos="right">
                    <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                        <circle cx="12" cy="12" r="10"/>
                        <path d="M12 6v6l4 2"/>
                    </svg>
                    </div>
                    <div class="menu-sprin-item item7" role="button" aria-label="Icon 7" data-tooltip="Icon 7" data-tip-pos="right">
                    <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                        <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/>
                        <polyline points="3.27 6.96 12 12.01 20.73 6.96"/>
                        <line x1="12" y1="22.08" x2="12" y2="12"/>
                    </svg>
                    </div>
                    <div class="menu-sprin-item item8" role="button" aria-label="Icon 8" data-tooltip="Icon 8" data-tip-pos="right">
                    <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                        <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
                    </svg>
                    </div>
                </div>

                <script>
                // Sprint menu: simple toggle via checkbox -> wrapper.open
                (function(){
                  var wrap = document.querySelector('.attendance-panel .menu-sprin-wrapper');
                  var toggle = document.getElementById('menu-sprin-toggle');
                  if (!wrap || !toggle) return;
                  function sync(){ wrap.classList.toggle('open', !!toggle.checked); if (toggle.checked) { wrap.classList.add('tips-on'); } else { wrap.classList.remove('tips-on'); } try{ if (toggle.checked && window.__sprinTipsOpen) window.__sprinTipsOpen(); else if (!toggle.checked && window.__sprinTipsClose) window.__sprinTipsClose(); }catch(_){ } }
                  // initialize and bind
                  sync();
                  toggle.addEventListener('change', sync);
                  // Map actions to hidden buttons
                  function fire(id){ var el=document.getElementById(id); if (el) el.click(); }
                  var itemFetch  = wrap.querySelector('.item1');
                  var itemCreate = wrap.querySelector('.item2');
                  if (itemFetch){ itemFetch.addEventListener('click', function(){ toggle.checked=false; sync(); fire('attendance-open-fetch'); }); }
                  if (itemCreate){ itemCreate.addEventListener('click', function(){ toggle.checked=false; sync(); fire('attendance-open-create'); }); }
                })();
                </script>

                <script>
                // Custom Select inside Fetch modal (device selector)
                (function(){
                  var custom = document.getElementById('attendance-device-custom-select-modal');
                  if (!custom) return;
                  var toggle = custom.querySelector('.custom-select-toggle');
                  var menu = custom.querySelector('.custom-select-menu');
                  if (!toggle || !menu) return;

                  var ipInput = document.getElementById('attendance-ip');
                  var portInput = document.getElementById('attendance-port');
                  var infoDisplay = document.getElementById('attendance-info-display');
                  var nameHidden = document.getElementById('attendance-device-name');
                  var devKeyHidden = document.getElementById('attendance-device-key');

                  // Header select to keep both in sync
                  var headerSelect = document.getElementById('attendance-device-custom-select');
                  var headerToggle = headerSelect ? headerSelect.querySelector('.custom-select-toggle') : null;
                  var headerMenu   = headerSelect ? headerSelect.querySelector('.custom-select-menu') : null;

                  var anchorParent = null, anchorNext = null, isPortaled = false;
                  var closeOnScroll = null, closeOnResize = null;

                  function mountMenu(){ if (isPortaled) return; anchorParent = menu.parentNode; anchorNext = menu.nextSibling; document.body.appendChild(menu); isPortaled = true; }
                  function unmountMenu(){ if (!isPortaled) return; if (anchorParent){ if (anchorNext){ anchorParent.insertBefore(menu, anchorNext); } else { anchorParent.appendChild(menu); } } isPortaled = false; }
                  function positionMenu(){
                    var r = toggle.getBoundingClientRect(); var pad = 12; var maxH = Math.min(320, Math.max(200, window.innerHeight - r.bottom - 16));
                    var left = Math.round(r.left); var width = Math.round(r.width);
                    if (left < pad) left = pad; if (left + width + pad > window.innerWidth){ left = Math.max(pad, window.innerWidth - width - pad); }
                    menu.style.position = 'fixed'; menu.style.left = left + 'px'; menu.style.top = Math.round(r.bottom + 6) + 'px';
                    menu.style.width = width + 'px'; menu.style.minWidth = width + 'px'; menu.style.maxWidth = width + 'px';
                    menu.style.maxHeight = maxH + 'px'; menu.style.overflowY = 'auto'; menu.style.zIndex = '2147483647'; menu.style.display = 'block';
                  }
                  function clearStyles(){ menu.style.position = ''; menu.style.left = ''; menu.style.top = ''; menu.style.width = ''; menu.style.minWidth = ''; menu.style.maxWidth = ''; menu.style.maxHeight = ''; menu.style.overflowY = ''; menu.style.zIndex = ''; menu.style.display = ''; }
                  function closeAll(){ custom.classList.remove('open'); clearStyles(); unmountMenu(); if (closeOnScroll){ window.removeEventListener('scroll', closeOnScroll, true); closeOnScroll = null; } if (closeOnResize){ window.removeEventListener('resize', closeOnResize); closeOnResize = null; } }

                  var justOpenedAt = 0;
                  // Open/close
                  document.addEventListener('click', function(e){
                    var now = Date.now();
                    if (now - justOpenedAt < 150) return; // ignore first click after opening
                    if (!custom.contains(e.target) && !menu.contains(e.target)) closeAll();
                  });
                  toggle.addEventListener('click', function(e){
                    e.stopPropagation();
                    var willOpen = !custom.classList.contains('open');
                    custom.classList.toggle('open');
                    if (willOpen){
                      mountMenu(); positionMenu();
                      justOpenedAt = Date.now();
                      closeOnScroll = function(ev){ if (menu.contains(ev.target)) return; closeAll(); };
                      closeOnResize = function(){ closeAll(); };
                      window.addEventListener('scroll', closeOnScroll, true); window.addEventListener('resize', closeOnResize);
                    } else { closeAll(); }
                  });

                  // Choose option
                  menu.addEventListener('click', function(e){
                    var opt = e.target.closest('.custom-select-option'); if (!opt) return;
                    var nameEl = opt.querySelector('div:first-child'); var name = nameEl ? nameEl.textContent.trim() : opt.textContent.trim();
                    var ip = opt.getAttribute('data-ip') || ''; var port = opt.getAttribute('data-port') || ''; var devKey = opt.getAttribute('data-value') || '';
                    var span = toggle.querySelector('span'); if (span){ span.innerHTML = '<span style="font-size:13px; font-weight:500;">' + name + '</span><span style="font-size:11px; color:#7eb8b0; margin-top:2px;">' + ip + ':' + port + '</span>'; }
                    menu.querySelectorAll('.custom-select-option').forEach(function(el){ el.classList.toggle('is-selected', el===opt); });
                    if (ipInput) ipInput.value = ip; if (portInput) portInput.value = port; if (nameHidden) nameHidden.value = name; if (devKeyHidden) devKeyHidden.value = devKey;
                    if (infoDisplay) infoDisplay.textContent = ip + ':' + port; // header small line

                    // Sync header select UI
                    try {
                      if (headerToggle) {
                        var s = headerToggle.querySelector('span'); if (s) s.innerHTML = '<span style="font-size:13px; font-weight:500;">' + name + '</span><span style="font-size:11px; color:#7eb8b0; margin-top:2px;">' + ip + ':' + port + '</span>';
                      }
                      if (headerMenu) {
                        headerMenu.querySelectorAll('.custom-select-option').forEach(function(el){ el.classList.toggle('is-selected', (el.getAttribute('data-value')||'') === devKey); });
                      }
                      // Keep selected device across pagination & page-size
                      document.querySelectorAll('.pagination a').forEach(function(a){ var href = a.getAttribute('href') || ''; if (!href) return; if (href.indexOf('device=') >= 0) { href = href.replace(/([?&]device=)[^&]*/, '$1' + encodeURIComponent(devKey)); } else { href += (href.indexOf('?') >= 0 ? '&' : '?') + 'device=' + encodeURIComponent(devKey); } a.setAttribute('href', href); });
                      var devHidden = document.getElementById('attendance-pagesize-device'); if (devHidden) devHidden.value = devKey;
                    } catch(_) {}

                    closeAll();
                  });

                  // Prevent page scroll while scrolling inside menu
                  menu.addEventListener('wheel', function(e){ e.stopPropagation(); }, { passive:true });
                  menu.addEventListener('touchmove', function(e){ e.stopPropagation(); }, { passive:true });
                  menu.addEventListener('mousedown', function(e){ e.stopPropagation(); });
                })();
                </script>

                <script>
                // Draggable home icon inside attendance grid - minimal change
                (function(){
                  var grid = document.querySelector('.panel-grid.attendance-grid');
                  var wrap = document.querySelector('.attendance-panel .menu-sprin-wrapper');
                  var toggle = document.getElementById('menu-sprin-toggle');
                  var handle = wrap ? wrap.querySelector('.menu-sprin-btn') : null;
                  if (!grid || !wrap || !handle) return;

                  var POS_KEY = 'attendance_sprin_pos_v1';
                  wrap.classList.add('draggable');
                  handle.style.touchAction = 'none';

                  // Ensure wrapper is inside grid so absolute positioning uses grid bounds
                  try{
                    if (wrap.parentElement !== grid) {
                      var rb = wrap.getBoundingClientRect();
                      var gb = grid.getBoundingClientRect();
                      grid.appendChild(wrap);
                      wrap.style.left = Math.round(rb.left - gb.left) + 'px';
                      wrap.style.top  = Math.round(rb.top  - gb.top)  + 'px';
                    }
                  }catch(_){ }

                  function clamp(n, min, max){ return Math.max(min, Math.min(max, n)); }
                  function bounds(){ return grid.getBoundingClientRect(); }
                  function apply(p){ if (!p) return; wrap.style.left = Math.round(p.x) + 'px'; wrap.style.top = Math.round(p.y) + 'px'; }
                  function load(){ try { return JSON.parse(localStorage.getItem(POS_KEY)||'null'); } catch(_) { return null; } }
                  function save(p){ try { localStorage.setItem(POS_KEY, JSON.stringify(p)); } catch(_) {} }

                  // Initial position
                  (function(){
                    var b = bounds();
                    var p = load();
                    if (!p) p = { x: b.width - 64, y: 16 };
                    p.x = clamp(p.x, 0, Math.max(0, b.width - 44));
                    p.y = clamp(p.y, 0, Math.max(0, b.height - 44));
                    apply(p);
                  })();

                  var start = null, base = null, dragging = false, lastDX=0, lastDY=0, cancelClick=false;

                  function down(e){
                    var cx = e.clientX, cy = e.clientY;
                    if (cx == null && e.touches && e.touches[0]) { cx = e.touches[0].clientX; cy = e.touches[0].clientY; }
                    if (cx == null) return;
                    // Không ngăn hành vi mặc định để click label vẫn toggle (nếu không kéo)
                    dragging = false; cancelClick=false; lastDX=0; lastDY=0;
                    var rb = wrap.getBoundingClientRect(); var gb = bounds();
                    start = { x: cx, y: cy }; base = { x: rb.left - gb.left, y: rb.top - gb.top };
                    window.addEventListener('mousemove', move, { passive:false });
                    window.addEventListener('mouseup', up, { passive:false, once:true });
                    window.addEventListener('touchmove', move, { passive:false });
                    window.addEventListener('touchend', up, { passive:false, once:true });
                  }
                  function move(e){ if (!start) return; var cx = e.clientX, cy = e.clientY; if (cx==null && e.touches && e.touches[0]) { cx=e.touches[0].clientX; cy=e.touches[0].clientY; }
                    var dx = cx - start.x, dy = cy - start.y; lastDX = dx; lastDY = dy;
                    if (!dragging && (Math.abs(dx) > 8 || Math.abs(dy) > 8)) { dragging = true; cancelClick = true; wrap.classList.add('dragging'); if (toggle){ toggle.checked = false; wrap.classList.remove('open'); } }
                    if (!dragging) return;
                    e.preventDefault();
                    var b = bounds();
                    var x = clamp(base.x + dx, 0, Math.max(0, b.width - 44));
                    var y = clamp(base.y + dy, 0, Math.max(0, b.height - 44));
                    apply({x:x,y:y});
                  }
                  function up(){
                    window.removeEventListener('mousemove', move);
                    window.removeEventListener('touchmove', move);
                    wrap.classList.remove('dragging');
                    if (!start) return; var b = bounds(); var rb = wrap.getBoundingClientRect();
                    var p = { x: rb.left - b.left, y: rb.top - b.top };
                    p.x = clamp(p.x, 0, Math.max(0, b.width - 44)); p.y = clamp(p.y, 0, Math.max(0, b.height - 44));
                    if (dragging) { save(p); }
                    start = null; dragging = false;
                  }

                  // Ngăn click toggle khi vừa kéo
                  handle.addEventListener('click', function(e){ if (cancelClick){ e.preventDefault(); e.stopPropagation(); cancelClick=false; } });

                  // Bind
                  handle.addEventListener('mousedown', down, { passive:false });
                  handle.addEventListener('touchstart', down, { passive:false });

                  // Re-clamp on resize
                  window.addEventListener('resize', function(){ var p = load(); if (!p) return; var b = bounds(); p.x = clamp(p.x, 0, Math.max(0, b.width - 44)); p.y = clamp(p.y, 0, Math.max(0, b.height - 44)); apply(p); save(p); });
                })();
                </script>

                <style id="sprin-live-tip-style">
                  .sprin-live-tip{position:fixed; background:rgba(17,46,51,0.95); color:#e8fbf6; padding:6px 10px; font-size:12px; line-height:1; border:1px solid rgba(122,220,201,0.3); border-radius:8px; white-space:nowrap; box-shadow:0 8px 20px rgba(3,15,21,0.4); z-index:2147483647; opacity:0; transform:translateY(-2px); transition:opacity .15s ease, transform .15s ease; pointer-events:none;}
                  .sprin-live-tip.show{opacity:1; transform:translateY(0);}
                </style>
                <script>
                // Show static tooltips next to fan icons when menu is open (no change to icon nodes)
                (function(){
                  var wrap = document.querySelector('.attendance-panel .menu-sprin-wrapper');
                  var toggle = document.getElementById('menu-sprin-toggle');
                  if (!wrap || !toggle) return;
                  var LABELS = {
                    item1: <?= json_encode($messages['attendance_sprin_export'] ?? 'Export data') ?>,
                    item2: <?= json_encode($messages['attendance_sprin_add_row'] ?? 'Add new row') ?>,
                    item3: <?= json_encode($messages['attendance_sprin_update'] ?? 'Cập nhật') ?>,
                    item4: <?= json_encode($messages['attendance_sprin_filter_duplicate'] ?? 'Lọc trùng') ?>,
                    item5: <?= json_encode($messages['attendance_sprin_delete'] ?? 'Xóa dữ liệu') ?>
                  };
                  var tips = [];
                  function clearTips(){ tips.forEach(function(t){ try{t.remove();}catch(_){}}); tips = []; window.removeEventListener('scroll', positionAll, true); window.removeEventListener('resize', positionAll); }
                  function createTips(){
                    ['item1','item2','item3','item4','item5'].forEach(function(key){
                      var el = wrap.querySelector('.'+key); if (!el) return;
                      var tip = document.createElement('div'); tip.className='sprin-live-tip'; tip.textContent = LABELS[key] || (el.getAttribute('aria-label')||'');
                      document.body.appendChild(tip); tips.push(tip);
                    });
                  }
                  function positionAll(){
                    ['item1','item2','item3','item4','item5'].forEach(function(key, idx){
                      var el = wrap.querySelector('.'+key); var tip = tips[idx]; if (!el || !tip) return;
                      var r = el.getBoundingClientRect();
                      var top = r.top + r.height/2 - tip.offsetHeight/2;
                      var left;
                      if (key === 'item1') {
                        // Always place Export data tooltip on the LEFT of the icon
                        left = r.left - 10 - tip.offsetWidth;
                    } else {
                        // Default: place to the right, fallback to left if overflow
                        left = r.right + 10;
                        if (left + tip.offsetWidth > window.innerWidth - 8) left = r.left - 10 - tip.offsetWidth;
                      }
                      if (top < 8) top = 8; var maxTop = window.innerHeight - 8 - tip.offsetHeight; if (top > maxTop) top = maxTop;
                      tip.style.left = Math.round(left)+'px'; tip.style.top = Math.round(top)+'px';
                    });
                  }
                  function openTips(){ clearTips(); createTips(); positionAll(); setTimeout(function(){ tips.forEach(function(t){ t.classList.add('show'); }); }, 80); // re-position a few times to ensure after animation
  var i=0, iv=setInterval(function(){ if (++i>6){clearInterval(iv);} positionAll(); }, 60);
  window.addEventListener('scroll', positionAll, true); window.addEventListener('resize', positionAll); }
                  function closeTips(){ clearTips(); }

                  // Expose to global so other scripts can trigger if needed
                  window.__sprinTipsOpen = openTips;
                  window.__sprinTipsClose = closeTips;

                  // React to the checkbox state
                  function sync(){ if (toggle.checked) openTips(); else closeTips(); }
                  toggle.addEventListener('change', sync);
                  // Also observe wrapper class changes (in case toggled programmatically)
                  var mo = new MutationObserver(sync); mo.observe(wrap, { attributes:true, attributeFilter:['class'] });
                  // Also respond to clicking the central button (label)
                  var btn = wrap.querySelector('.menu-sprin-btn');
                  if (btn){ btn.addEventListener('click', function(){ setTimeout(sync, 60); setTimeout(sync, 200); setTimeout(positionAll, 300); }); }
                  // Safety: polling in case events are swallowed by drag logic
                  var __poll = setInterval(function(){ try { sync(); } catch(_){} }, 250);
                  // Initial state on load
                  sync();
                })();
                </script>

                <!-- Fetch Range Modal -->
                <div id="attendance-fetch-modal" class="modal-backdrop" aria-hidden="true">
                    <div class="modal">
                        <div class="modal-header">
                            <h4><?= htmlspecialchars($messages['attendance_filter_heading'] ?? 'LỌC THỜI GIAN', ENT_QUOTES, 'UTF-8') ?></h4>
                            <button type="button" class="modal-close" data-modal-close>&times;</button>
                        </div>
                        <div class="modal-body">
                            <form id="attendance-fetch-range-form" class="form-grid grid-2" onsubmit="return false;">
                                <div class="form-row full">
                                    <label><?= htmlspecialchars($messages['attendance_sprin_device'] ?? 'Thiết bị', ENT_QUOTES, 'UTF-8') ?></label>
                                    <div class="input-wrap" style="border:none; background:transparent; padding:0;">
                                        <div class="custom-select" id="attendance-device-custom-select-modal">
                                            <button type="button" class="custom-select-toggle" style="width:100%; min-width:0; display:flex; justify-content:space-between; align-items:center; padding:8px 12px;" data-placeholder="<?= htmlspecialchars($messages['attendance_placeholder_device'] ?? 'Chọn máy chấm công', ENT_QUOTES, 'UTF-8') ?>">
                                                <span style="font-size:13px; font-weight:400; font-style:italic; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; color:rgba(122,220,201,0.6);">
                                                    <?= htmlspecialchars($messages['attendance_placeholder_device'] ?? 'Chọn máy chấm công', ENT_QUOTES, 'UTF-8') ?>
                                                </span>
                                                <svg style="width:16px; height:16px; fill:currentColor; flex-shrink:0; opacity:0.6;" viewBox="0 0 24 24"><path d="M7 10l5 5 5-5z"/></svg>
                                            </button>
                                            <div class="custom-select-menu" role="listbox">
                                                <?php foreach ($devices as $dev): ?>
                                                    <div class="custom-select-option" role="option" data-value="<?= htmlspecialchars($dev['key'] ?? $dev['name'], ENT_QUOTES, 'UTF-8') ?>" data-ip="<?= htmlspecialchars($dev['ip'], ENT_QUOTES, 'UTF-8') ?>" data-port="<?= (int)$dev['port'] ?>" style="padding:4px 12px;">
                                                        <div style="font-size:13px; font-weight:500; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%;"><?= htmlspecialchars($dev['name'], ENT_QUOTES, 'UTF-8') ?></div>
                                                        <div style="font-size:11px; color:#7eb8b0; margin-top:2px;">&lrm;<?= htmlspecialchars($dev['ip'] . ':' . $dev['port'], ENT_QUOTES, 'UTF-8') ?></div>
                                                    </div>
                                                <?php endforeach; ?>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="form-row">
                                    <label for="att-fetch-from"><?= htmlspecialchars($messages['attendance_filter_from_date'] ?? 'Từ ngày', ENT_QUOTES, 'UTF-8') ?></label>
                                    <div class="input-wrap">
                                        <span class="icon date-icon" data-target="att-fetch-from">
                                            <svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
                                        </span>
                                        <input type="date" id="att-fetch-from" autocomplete="off" style="font-size:14px;">
                                    </div>
                                </div>
                                <div class="form-row">
                                    <label for="att-fetch-to"><?= htmlspecialchars($messages['attendance_filter_to_date'] ?? 'Đến ngày', ENT_QUOTES, 'UTF-8') ?></label>
                                    <div class="input-wrap">
                                        <span class="icon date-icon" data-target="att-fetch-to">
                                            <svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
                                        </span>
                                        <input type="date" id="att-fetch-to" autocomplete="off" style="font-size:14px;">
                                    </div>
                                </div>
                                <div class="form-row full">
                                    <label></label>
                                    <div class="input-wrap" style="display:flex; align-items:center; gap:8px; border:none; background:transparent; padding:0;font-size: 14px;justify-content: center;font-family: monospace;">
                                        <input type="checkbox" id="att-fetch-all" style="width:16px;height:16px;">
                                        <span><?= htmlspecialchars($messages['attendance_filter_all_time'] ?? 'Tất cả thời gian', ENT_QUOTES, 'UTF-8') ?></span>
                                    </div>
                                </div>
                                <div class="form-actions full">
                                    <button type="button" class="btn btn-primary" id="attendance-fetch-apply"><?= htmlspecialchars($messages['attendance_filter_load_data'] ?? 'Tải dữ liệu', ENT_QUOTES, 'UTF-8') ?></button>
                                    <button type="button" class="btn btn-secondary" data-modal-close><?= htmlspecialchars($messages['attendance_btn_cancel'] ?? 'Hủy', ENT_QUOTES, 'UTF-8') ?></button>

  
 
                                </div>
                                
                            </form>
                        </div>
                    </div>
                </div>

                <style>
                  /* Strong mobile-friendly sizing for the fetch range modal - bao phủ toàn bộ trang web */
                  #attendance-fetch-modal { position: fixed !important; inset: 0 !important; display: none; align-items: center !important; justify-content: center !important; overflow: auto !important; padding: 12px 12px max(16px, env(safe-area-inset-bottom)) 12px !important; z-index: 10000 !important; }
                  #attendance-fetch-modal .modal { width: min(560px, calc(100% - 24px)) !important; max-width: 100% !important; max-height: calc(100dvh - 24px) !important; height: auto !important; box-sizing: border-box !important; overflow: auto !important; }
                  @supports not (height: 100dvh) {
                    #attendance-fetch-modal .modal { max-height: calc(100vh - 24px) !important; }
                  }
                  #attendance-fetch-modal .modal-body { flex: 1 1 auto !important; overflow: auto !important; padding-bottom: 20px !important; -webkit-overflow-scrolling: touch !important; }
                  #attendance-fetch-modal .form-actions { position: sticky !important; bottom: 0 !important; background: rgba(12,38,43,.00) !important; padding-top: 10px !important; margin-top: 10px !important; z-index: 1 !important; }
                  /* If viewport height is small, anchor to top so footer buttons are reachable */
                  @media (max-height: 700px) {
                    #attendance-fetch-modal { align-items: flex-start !important; }
                    #attendance-fetch-modal .modal { margin-top: 12px !important; }
                  }
                  /* Keep action buttons visible on narrow devices */
                  @media (max-width: 480px) {
                    #attendance-fetch-modal .form-actions { position: sticky !important; bottom: 0 !important; background: rgba(12,38,43,.00) !important; padding-top: 10px !important; margin-top: 10px !important; z-index: 1 !important; }
                  }
                </style>

                <style>
                  /* Modal xác nhận xóa - bao phủ toàn bộ trang web */
                  #attendance-confirm-delete-modal { 
                    position: fixed !important; 
                    inset: 0 !important; 
                    display: none; 
                    align-items: center !important; 
                    justify-content: center !important; 
                    overflow: auto !important; 
                    z-index: 10000 !important;
                    padding: 12px !important; 
                    background: rgba(6, 22, 28, 0.65) !important;
                    isolation: isolate !important;
                  }
                  #attendance-confirm-delete-modal.show { 
                    display: flex !important; 
                  }
                  #attendance-confirm-delete-modal .modal { 
                    width: min(560px, calc(100% - 24px)) !important; 
                    max-width: 100% !important; 
                    position: relative !important;
                    isolation: isolate !important;
                    overflow: visible !important;
                  }
                  #attendance-confirm-delete-modal .modal-body {
                    overflow: visible !important;
                  }
                  #attendance-confirm-delete-modal .form-grid {
                    overflow: visible !important;
                  }
                  #attendance-confirm-delete-modal .custom-select {
                    position: relative;
                    overflow: visible;
                  }
                  #attendance-confirm-delete-modal .custom-select-menu {
                    display: none;
                    position: absolute;
                    top: 100%;
                    left: 0;
                    right: 0;
                    z-index: 10001;
                    background: rgba(17, 46, 51, 0.98);
                    border: 1px solid rgba(122, 220, 201, 0.3);
                    border-radius: 8px;
                    max-height: none;
                    overflow-y: visible;
                    margin-top: 4px;
                    box-shadow: 0 8px 20px rgba(3, 15, 21, 0.4);
                  }
                  #attendance-confirm-delete-modal .custom-select.is-active .custom-select-menu {
                    display: block;
                  }
                  #attendance-confirm-delete-modal .custom-select-option {
                    cursor: pointer;
                    transition: background-color 0.2s;
                  }
                  #attendance-confirm-delete-modal .custom-select-option:hover {
                    background-color: rgba(122, 220, 201, 0.1);
                  }
                  #attendance-confirm-delete-modal .custom-select-option.is-selected {
                    background-color: rgba(122, 220, 201, 0.15);
                  }
                  /* Ẩn và disable các icon khi modal xóa mở */
                  body.attendance-delete-modal-open .attendance-panel .menu-sprin-wrapper,
                  body.attendance-delete-modal-open .menu-sprin-wrapper,
                  body.attendance-create-modal-open .attendance-panel .menu-sprin-wrapper,
                  body.attendance-create-modal-open .menu-sprin-wrapper,
                  body.attendance-fetch-modal-open .attendance-panel .menu-sprin-wrapper,
                  body.attendance-fetch-modal-open .menu-sprin-wrapper,
                  body.attendance-update-modal-open .attendance-panel .menu-sprin-wrapper,
                  body.attendance-update-modal-open .menu-sprin-wrapper,
                  body.attendance-filter-duplicate-modal-open .attendance-panel .menu-sprin-wrapper,
                  body.attendance-filter-duplicate-modal-open .menu-sprin-wrapper {
                    z-index: -1 !important;
                    pointer-events: none !important;
                    opacity: 0.1 !important;
                    visibility: hidden !important;
                  }
                  body.attendance-delete-modal-open .attendance-panel .menu-sprin-item,
                  body.attendance-delete-modal-open .menu-sprin-item,
                  body.attendance-create-modal-open .attendance-panel .menu-sprin-item,
                  body.attendance-create-modal-open .menu-sprin-item,
                  body.attendance-fetch-modal-open .attendance-panel .menu-sprin-item,
                  body.attendance-fetch-modal-open .menu-sprin-item,
                  body.attendance-update-modal-open .attendance-panel .menu-sprin-item,
                  body.attendance-update-modal-open .menu-sprin-item,
                  body.attendance-filter-duplicate-modal-open .attendance-panel .menu-sprin-item,
                  body.attendance-filter-duplicate-modal-open .menu-sprin-item {
                    z-index: -1 !important;
                    pointer-events: none !important;
                    opacity: 0.1 !important;
                    visibility: hidden !important;
                  }
                  body.attendance-delete-modal-open .menu-sprin-item::after,
                  body.attendance-create-modal-open .menu-sprin-item::after,
                  body.attendance-fetch-modal-open .menu-sprin-item::after,
                  body.attendance-update-modal-open .menu-sprin-item::after,
                  body.attendance-filter-duplicate-modal-open .menu-sprin-item::after {
                    display: none !important;
                  }
                  body.attendance-delete-modal-open .sprin-live-tip,
                  body.attendance-create-modal-open .sprin-live-tip,
                  body.attendance-fetch-modal-open .sprin-live-tip,
                  body.attendance-update-modal-open .sprin-live-tip,
                  body.attendance-filter-duplicate-modal-open .sprin-live-tip {
                    display: none !important;
                    z-index: -1 !important;
                  }
                </style>

                <style>
                  /* Modal xác nhận ghi dữ liệu - bao phủ toàn bộ trang web */
                  #attendance-confirm-overwrite-modal {
                    position: fixed !important;
                    inset: 0 !important;
                    display: none;
                    align-items: center !important;
                    justify-content: center !important;
                    overflow: auto !important;
                    z-index: 10000 !important;
                    padding: 12px !important;
                    background: rgba(6, 22, 28, 0.65) !important;
                  }
                  #attendance-confirm-overwrite-modal.show {
                    display: flex !important;
                  }
                  #attendance-confirm-overwrite-modal .modal {
                    width: min(460px, calc(100% - 24px)) !important;
                    max-width: 100% !important;
                    position: relative !important;
                  }
                </style>

                <style>
                  /* Modal xác nhận lọc trùng - bao phủ toàn bộ trang web */
                  #attendance-confirm-filter-duplicate-modal {
                    position: fixed !important;
                    inset: 0 !important;
                    display: none;
                    align-items: center !important;
                    justify-content: center !important;
                    overflow: auto !important;
                    z-index: 10000 !important;
                    padding: 12px !important;
                    background: rgba(6, 22, 28, 0.65) !important;
                  }
                  #attendance-confirm-filter-duplicate-modal.show {
                    display: flex !important;
                  }
                  #attendance-confirm-filter-duplicate-modal .modal {
                    width: min(460px, calc(100% - 24px)) !important;
                    max-width: 100% !important;
                    position: relative !important;
                  }
                </style>

                <!-- Confirm Overwrite Modal -->
                <div id="attendance-confirm-overwrite-modal" class="modal-backdrop" aria-hidden="true">
                    <div class="modal">
                        <div class="modal-header">
                            <h4 id="attendance-confirm-overwrite-title"><?= htmlspecialchars($messages['attendance_confirm_overwrite_title'] ?? 'CHỌN CÁCH GHI DỮ LIỆU', ENT_QUOTES, 'UTF-8') ?></h4>
                            <button type="button" class="modal-close" data-modal-close>&times;</button>
                        </div>
                        <div class="modal-body">
                            <p id="attendance-confirm-overwrite-message" style="margin: 0 0 20px; color: #e8fbf6; line-height: 1.6;">
                                <?= htmlspecialchars($messages['attendance_confirm_overwrite_message'] ?? 'Bảng dữ liệu chấm công hiện đã có dữ liệu. Bạn muốn ghi tiếp dữ liệu mới hay chỉ ghi dữ liệu mới?', ENT_QUOTES, 'UTF-8') ?>
                            </p>
                            <div class="form-actions" style="display: flex; gap: 12px; justify-content: flex-end;">
                                <button type="button" class="btn btn-primary" id="attendance-append-data-btn"><?= htmlspecialchars($messages['attendance_append_data'] ?? 'Ghi tiếp dữ liệu', ENT_QUOTES, 'UTF-8') ?></button>
                                <button type="button" class="btn btn-primary" id="attendance-overwrite-data-btn"><?= htmlspecialchars($messages['attendance_overwrite_data'] ?? 'Chỉ ghi dữ liệu mới', ENT_QUOTES, 'UTF-8') ?></button>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Confirm Delete Modal -->
                <div id="attendance-confirm-delete-modal" class="modal-backdrop" aria-hidden="true">
                    <div class="modal">
                        <div class="modal-header">
                            <h4 id="attendance-confirm-delete-title"><?= htmlspecialchars($messages['attendance_confirm_delete_title'] ?? 'XÁC NHẬN XÓA DỮ LIỆU', ENT_QUOTES, 'UTF-8') ?></h4>
                            <button type="button" class="modal-close" data-modal-close>&times;</button>
                        </div>
                        <div class="modal-body">
                            <form id="attendance-delete-form" class="form-grid grid-1" onsubmit="return false;">
                                <div class="form-row full">
                                    <label style="font-size: 12px; color: #e8fbf6; margin-bottom: 12px;">
                                        <?= htmlspecialchars($messages['attendance_delete_type_label'] ?? 'Chọn loại xóa dữ liệu:', ENT_QUOTES, 'UTF-8') ?>
                                    </label>
                                    <div style="display: flex; flex-direction: column; gap: 12px;">
                                        <div style="display: flex; align-items: center; gap: 10px; padding: 10px; border: 1px solid rgba(122,220,201,0.2); border-radius: 6px; cursor: pointer; transition: all 0.2s;" id="delete-table-option">
                                            <input type="checkbox" id="delete-table-checkbox" name="delete_type" value="table" style="width: 18px; height: 18px; cursor: pointer;">
                                            <label for="delete-table-checkbox" style="cursor: pointer; margin: 0; font-size: 12px; color: #e8fbf6;">
                                                <?= htmlspecialchars($messages['attendance_delete_table_data'] ?? 'Xóa dữ liệu bảng', ENT_QUOTES, 'UTF-8') ?>
                                            </label>
                                        </div>
                                        <div style="display: flex; align-items: center; gap: 10px; padding: 10px; border: 1px solid rgba(122,220,201,0.2); border-radius: 6px; cursor: pointer; transition: all 0.2s;" id="delete-device-option">
                                            <input type="checkbox" id="delete-device-checkbox" name="delete_type" value="device" style="width: 18px; height: 18px; cursor: pointer;">
                                            <label for="delete-device-checkbox" style="cursor: pointer; margin: 0; font-size: 12px; color: #e8fbf6;">
                                                <?= htmlspecialchars($messages['attendance_delete_device_data'] ?? 'Xóa dữ liệu máy chấm công', ENT_QUOTES, 'UTF-8') ?>
                                            </label>
                                        </div>
                                    </div>
                                </div>
                                <div class="form-row full" id="delete-device-select-row" style="display: none; margin-top: 12px;">
                                    <label><?= htmlspecialchars($messages['attendance_sprin_device'] ?? 'Thiết bị', ENT_QUOTES, 'UTF-8') ?></label>
                                    <div class="input-wrap" style="border:none; background:transparent; padding:0;">
                                        <div class="custom-select" id="attendance-delete-device-custom-select">
                                            <button type="button" class="custom-select-toggle" style="width:100%; min-width:0; display:flex; justify-content:space-between; align-items:center; padding:8px 12px;" data-placeholder="<?= htmlspecialchars($messages['attendance_placeholder_device'] ?? 'Chọn máy chấm công', ENT_QUOTES, 'UTF-8') ?>">
                                                <span style="font-size:13px; font-weight:400; font-style:italic; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; color:rgba(122,220,201,0.6);">
                                                    <?= htmlspecialchars($messages['attendance_placeholder_device'] ?? 'Chọn máy chấm công', ENT_QUOTES, 'UTF-8') ?>
                                                </span>
                                                <svg style="width:16px; height:16px; fill:currentColor; flex-shrink:0; opacity:0.6;" viewBox="0 0 24 24"><path d="M7 10l5 5 5-5z"/></svg>
                                            </button>
                                            <div class="custom-select-menu" role="listbox">
                                                <?php foreach ($devices as $dev): ?>
                                                    <div class="custom-select-option" role="option" data-value="<?= htmlspecialchars($dev['key'] ?? $dev['name'], ENT_QUOTES, 'UTF-8') ?>" data-ip="<?= htmlspecialchars($dev['ip'], ENT_QUOTES, 'UTF-8') ?>" data-port="<?= (int)$dev['port'] ?>" style="padding:4px 12px;">
                                                        <div style="font-size:13px; font-weight:500; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%;"><?= htmlspecialchars($dev['name'], ENT_QUOTES, 'UTF-8') ?></div>
                                                        <div style="font-size:11px; color:#7eb8b0; margin-top:2px;">&lrm;<?= htmlspecialchars($dev['ip'] . ':' . $dev['port'], ENT_QUOTES, 'UTF-8') ?></div>
                                                    </div>
                                                <?php endforeach; ?>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="form-actions full" style="margin-top: 20px;">
                                    <button type="button" class="btn btn-primary" id="attendance-confirm-delete-btn"><?= htmlspecialchars($messages['attendance_confirm_delete_confirm'] ?? 'Xác nhận xóa', ENT_QUOTES, 'UTF-8') ?></button>
                                    <button type="button" class="btn btn-secondary" data-modal-close><?= htmlspecialchars($messages['attendance_confirm_delete_cancel'] ?? 'Hủy', ENT_QUOTES, 'UTF-8') ?></button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>

                <!-- Confirm Filter Duplicate Modal -->
                <div id="attendance-confirm-filter-duplicate-modal" class="modal-backdrop" aria-hidden="true">
                    <div class="modal">
                        <div class="modal-header">
                            <h4 id="attendance-confirm-filter-duplicate-title"><?= htmlspecialchars($messages['attendance_confirm_filter_duplicate_title'] ?? 'localhost cho biết', ENT_QUOTES, 'UTF-8') ?></h4>
                            <button type="button" class="modal-close" data-modal-close>&times;</button>
                        </div>
                        <div class="modal-body">
                            <p id="attendance-confirm-filter-duplicate-message" style="margin: 0 0 20px; color: #e8fbf6; line-height: 1.6;">
                                <?= htmlspecialchars($messages['attendance_filter_duplicate_confirm'] ?? 'Bạn có chắc chắn muốn lọc trùng dữ liệu chấm công? Các bản ghi trùng (cùng nhân viên, cùng ngày, giờ cách nhau <= 5 phút) sẽ bị xóa, chỉ giữ lại bản ghi đầu tiên.', ENT_QUOTES, 'UTF-8') ?>
                            </p>
                            <div class="form-actions" style="display: flex; gap: 12px; justify-content: flex-end;">
                                <button type="button" class="btn btn-primary" id="attendance-confirm-filter-duplicate-btn"><?= htmlspecialchars($messages['attendance_btn_ok'] ?? 'OK', ENT_QUOTES, 'UTF-8') ?></button>
                                <button type="button" class="btn btn-secondary" data-modal-close><?= htmlspecialchars($messages['attendance_btn_cancel'] ?? 'Hủy', ENT_QUOTES, 'UTF-8') ?></button>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Update Modal -->
                <div id="attendance-update-modal" class="modal-backdrop" aria-hidden="true">
                    <div class="modal">
                        <div class="modal-header">
                            <h4><?= htmlspecialchars($messages['attendance_update_heading'] ?? 'CẬP NHẬT', ENT_QUOTES, 'UTF-8') ?></h4>
                            <button type="button" class="modal-close" data-modal-close>&times;</button>
                        </div>
                        <div class="modal-body">
                            <form id="attendance-update-form" class="form-grid grid-2" onsubmit="return false;" method="POST" action="">
                                <input type="hidden" name="attendance_update_device_time" value="1">
                                <input type="hidden" id="attendance-update-device-ip" name="device_ip" value="">
                                <input type="hidden" id="attendance-update-device-port" name="device_port" value="">
                                <input type="hidden" id="attendance-update-device-name" name="device_name" value="">
                                <div class="form-row full">
                                    <label><?= htmlspecialchars($messages['attendance_sprin_device'] ?? 'Thiết bị', ENT_QUOTES, 'UTF-8') ?></label>
                                    <div class="input-wrap" style="border:none; background:transparent; padding:0;">
                                        <div class="custom-select" id="attendance-update-device-custom-select">
                                            <button type="button" class="custom-select-toggle" style="width:100%; min-width:0; display:flex; justify-content:space-between; align-items:center; padding:8px 12px;" data-placeholder="<?= htmlspecialchars($messages['attendance_placeholder_device'] ?? 'Chọn máy chấm công', ENT_QUOTES, 'UTF-8') ?>">
                                                <span style="font-size:13px; font-weight:400; font-style:italic; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; color:rgba(122,220,201,0.6);">
                                                    <?= htmlspecialchars($messages['attendance_placeholder_device'] ?? 'Chọn máy chấm công', ENT_QUOTES, 'UTF-8') ?>
                                                </span>
                                                <svg style="width:16px; height:16px; fill:currentColor; flex-shrink:0; opacity:0.6;" viewBox="0 0 24 24"><path d="M7 10l5 5 5-5z"/></svg>
                                            </button>
                                            <div class="custom-select-menu" role="listbox">
                                                <?php foreach ($devices as $dev): ?>
                                                    <div class="custom-select-option" role="option" data-value="<?= htmlspecialchars($dev['key'] ?? $dev['name'], ENT_QUOTES, 'UTF-8') ?>" data-ip="<?= htmlspecialchars($dev['ip'], ENT_QUOTES, 'UTF-8') ?>" data-port="<?= (int)$dev['port'] ?>" style="padding:4px 12px;">
                                                        <div style="font-size:13px; font-weight:500; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%;"><?= htmlspecialchars($dev['name'], ENT_QUOTES, 'UTF-8') ?></div>
                                                        <div style="font-size:11px; color:#7eb8b0; margin-top:2px;">&lrm;<?= htmlspecialchars($dev['ip'] . ':' . $dev['port'], ENT_QUOTES, 'UTF-8') ?></div>
                                                    </div>
                                                <?php endforeach; ?>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="form-row">
                                    <label for="att-update-date"><?= htmlspecialchars($messages['attendance_form_date_label'] ?? 'Ngày', ENT_QUOTES, 'UTF-8') ?></label>
                                    <div class="input-wrap" id="att-update-date-wrap">
                                        <span class="icon date-icon" data-target="att-update-date">
                                            <svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
                                        </span>
                                        <input type="date" id="att-update-date" autocomplete="off" style="font-size:14px;">
                                    </div>
                                </div>
                                <div class="form-row">
                                    <label for="att-update-time"><?= htmlspecialchars($messages['attendance_form_time_label'] ?? 'Giờ', ENT_QUOTES, 'UTF-8') ?></label>
                                    <div class="input-wrap" id="att-update-time-wrap">
                                        <span class="icon time-icon" data-target="att-update-time">
                                            <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12,6 12,12 16,14"/></svg>
                                        </span>
                                        <input type="text" id="att-update-time" placeholder="hh:mm:ss" autocomplete="off" inputmode="numeric" pattern="^\d{2}:\d{2}:\d{2}$" style="font-size:14px;cursor: default;" onclick="window.openTimePickerAttUpdate && window.openTimePickerAttUpdate(); return false;" onfocus="window.openTimePickerAttUpdate && window.openTimePickerAttUpdate(); return false;">
                                    </div>
                                </div>
                                <div class="form-row full">
                                    <label></label>
                                    <div class="input-wrap" style="display:flex; align-items:center; gap:8px; border:none; background:transparent; padding:0;font-size: 14px;justify-content: center;font-family: monospace;">
                                        <input type="checkbox" id="att-update-use-current-time" style="width:16px;height:16px;">
                                        <span><?= htmlspecialchars($messages['attendance_update_use_current_time'] ?? 'Thời gian hiện tại', ENT_QUOTES, 'UTF-8') ?></span>
                                    </div>
                                </div>
                                <div class="form-actions full">
                                    <button type="button" class="btn btn-primary" id="attendance-update-submit-btn"><?= htmlspecialchars($messages['attendance_update_submit'] ?? 'Cập nhật', ENT_QUOTES, 'UTF-8') ?></button>
                                    <button type="button" class="btn btn-secondary" data-modal-close><?= htmlspecialchars($messages['attendance_btn_cancel'] ?? 'Hủy', ENT_QUOTES, 'UTF-8') ?></button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>

                <script>
                (function(){
                    var openFetchBtn = document.getElementById('attendance-open-fetch');
                    var fetchModal = document.getElementById('attendance-fetch-modal');
                    var fetchApply = document.getElementById('attendance-fetch-apply');
                    var fetchFrom = document.getElementById('att-fetch-from');
                    var fetchTo = document.getElementById('att-fetch-to');
                    var hiddenFrom = document.getElementById('attendance-fetch-from');
                    var hiddenTo = document.getElementById('attendance-fetch-to');
                    var hiddenFlag = document.getElementById('attendance-fetch-flag');
                    var hiddenAll = document.getElementById('attendance-fetch-all');
                    var hiddenAppendMode = document.getElementById('attendance-append-mode');
                    var chkAll = document.getElementById('att-fetch-all');
                    var fetchForm = document.getElementById('attendance-fetch-form');

                    // Modal device custom-select initializer (runs once on first open)
                    var __modalDevSelectInited = false;
                    function initModalDeviceSelect(){
                        if (__modalDevSelectInited) return;
                        var custom = document.getElementById('attendance-device-custom-select-modal');
                        if (!custom) return; // wait until modal exists
                        var toggle = custom.querySelector('.custom-select-toggle');
                        var menu = custom.querySelector('.custom-select-menu');
                        if (!toggle || !menu) return;

                        __modalDevSelectInited = true;
                        var ipInput = document.getElementById('attendance-ip');
                        var portInput = document.getElementById('attendance-port');
                        var infoDisplay = document.getElementById('attendance-info-display');
                        var nameHidden = document.getElementById('attendance-device-name');
                        var devKeyHidden = document.getElementById('attendance-device-key');

                        var headerSelect = document.getElementById('attendance-device-custom-select');
                        var headerToggle = headerSelect ? headerSelect.querySelector('.custom-select-toggle') : null;
                        var headerMenu   = headerSelect ? headerSelect.querySelector('.custom-select-menu') : null;

                        var anchorParent = null, anchorNext = null, isPortaled = false;
                        var closeOnScroll = null, closeOnResize = null;

                        function mountMenu(){ if (isPortaled) return; anchorParent = menu.parentNode; anchorNext = menu.nextSibling; document.body.appendChild(menu); isPortaled = true; }
                        function unmountMenu(){ if (!isPortaled) return; if (anchorParent){ if (anchorNext){ anchorParent.insertBefore(menu, anchorNext); } else { anchorParent.appendChild(menu); } } isPortaled = false; }
                        function positionMenu(){
                            var r = toggle.getBoundingClientRect(); var pad = 12; var maxH = Math.min(320, Math.max(200, window.innerHeight - r.bottom - 16));
                            var left = Math.round(r.left); var width = Math.round(r.width);
                            if (left < pad) left = pad; if (left + width + pad > window.innerWidth){ left = Math.max(pad, window.innerWidth - width - pad); }
                            menu.style.position = 'fixed'; menu.style.left = left + 'px'; menu.style.top = Math.round(r.bottom + 6) + 'px';
                            menu.style.width = width + 'px'; menu.style.minWidth = width + 'px'; menu.style.maxWidth = width + 'px';
                            menu.style.maxHeight = maxH + 'px'; menu.style.overflowY = 'auto'; menu.style.zIndex = '2147483647'; menu.style.display = 'block';
                        }
                        function clearStyles(){ menu.style.position = ''; menu.style.left = ''; menu.style.top = ''; menu.style.width = ''; menu.style.minWidth = ''; menu.style.maxWidth = ''; menu.style.maxHeight = ''; menu.style.overflowY = ''; menu.style.zIndex = ''; menu.style.display = ''; }
                        function closeAll(){ custom.classList.remove('open'); clearStyles(); unmountMenu(); if (closeOnScroll){ window.removeEventListener('scroll', closeOnScroll, true); closeOnScroll = null; } if (closeOnResize){ window.removeEventListener('resize', closeOnResize); closeOnResize = null; } }

                        var justOpenedAt = 0;
                        document.addEventListener('click', function(e){ var now = Date.now(); if (now - justOpenedAt < 150) return; if (!custom.contains(e.target) && !menu.contains(e.target)) closeAll(); });
                        toggle.addEventListener('click', function(e){ e.stopPropagation(); var willOpen = !custom.classList.contains('open'); custom.classList.toggle('open'); if (willOpen){ mountMenu(); positionMenu(); justOpenedAt = Date.now(); closeOnScroll = function(ev){ if (menu.contains(ev.target)) return; closeAll(); }; closeOnResize = function(){ closeAll(); }; window.addEventListener('scroll', closeOnScroll, true); window.addEventListener('resize', closeOnResize); } else { closeAll(); } });

                        menu.addEventListener('click', function(e){
                            var opt = e.target.closest('.custom-select-option'); if (!opt) return;
                            var nameEl = opt.querySelector('div:first-child'); var name = nameEl ? nameEl.textContent.trim() : opt.textContent.trim();
                            var ip = opt.getAttribute('data-ip') || ''; var port = opt.getAttribute('data-port') || ''; var devKey = opt.getAttribute('data-value') || '';
                            var span = toggle.querySelector('span'); if (span){ span.innerHTML = '<span style="font-size:13px; font-weight:500;">' + name + '</span> <span style="font-size:11px; color:#7eb8b0; margin-top:2px;">(' + ip + ':' + port + ')</span>'; }
                            var arrow = toggle.querySelector('svg'); if (arrow) arrow.style.opacity = '1';
                            menu.querySelectorAll('.custom-select-option').forEach(function(el){ el.classList.toggle('is-selected', el===opt); });
                            if (ipInput) ipInput.value = ip; if (portInput) portInput.value = port; if (nameHidden) nameHidden.value = name; if (devKeyHidden) devKeyHidden.value = devKey;
                            if (infoDisplay) infoDisplay.textContent = ip + ':' + port;
                            try {
                                if (headerToggle) { var s = headerToggle.querySelector('span'); if (s) s.innerHTML = '<span style="font-size:13px; font-weight:500;">' + name + '</span><span style="font-size:11px; color:#7eb8b0; margin-top:2px;">' + ip + ':' + port + '</span>'; }
                                if (headerMenu) { headerMenu.querySelectorAll('.custom-select-option').forEach(function(el){ el.classList.toggle('is-selected', (el.getAttribute('data-value')||'') === devKey); }); }
                                document.querySelectorAll('.pagination a').forEach(function(a){ var href = a.getAttribute('href') || ''; if (!href) return; if (href.indexOf('device=') >= 0) { href = href.replace(/([?&]device=)[^&]*/, '$1' + encodeURIComponent(devKey)); } else { href += (href.indexOf('?') >= 0 ? '&' : '?') + 'device=' + encodeURIComponent(devKey); } a.setAttribute('href', href); });
                                var devHidden = document.getElementById('attendance-pagesize-device'); if (devHidden) devHidden.value = devKey;
                            } catch(_) {}
                            closeAll();
                        });

                        menu.addEventListener('wheel', function(e){ e.stopPropagation(); }, { passive:true });
                        menu.addEventListener('touchmove', function(e){ e.stopPropagation(); }, { passive:true });
                        menu.addEventListener('mousedown', function(e){ e.stopPropagation(); });
                    }

                    function applyAllState(){
                        var all = !!(chkAll && chkAll.checked);
                        if (fetchFrom) fetchFrom.disabled = all;
                        if (fetchTo) fetchTo.disabled = all;
                        if (hiddenAll) hiddenAll.value = all ? '1' : '';
                    }

                    function ensureConfirmModalPortaled(modal){
                        if (!modal) return;
                        try {
                            if (modal.parentElement !== document.body) {
                                document.body.appendChild(modal);
                                modal.__portaled = true;
                            }
                        } catch(_){}
                    }

                    function openFetch(){
                        // Đóng sprint menu và ẩn icon giống modal create/delete
                        if (window.__sprinTipsClose) window.__sprinTipsClose();
                        var sprintToggle = document.getElementById('menu-sprin-toggle');
                        if (sprintToggle) sprintToggle.checked = false;
                        var sprintWrapper = document.querySelector('.attendance-panel .menu-sprin-wrapper');
                        if (sprintWrapper) {
                            sprintWrapper.classList.remove('open');
                        }
                        document.body.classList.add('attendance-fetch-modal-open');

                        if (!fetchModal) return;
                        // Đảm bảo modal ở trong body để bao phủ toàn bộ trang
                        try {
                          if (fetchModal.parentElement !== document.body) {
                            document.body.appendChild(fetchModal);
                            fetchModal.__portaled = true;
                          }
                        } catch(_){}
                        // Prefill last 7 days by default if empty
                        try{
                          var today = new Date();
                          var toStr = today.toISOString().slice(0,10);
                          var fromD = new Date(today); fromD.setDate(fromD.getDate()-6);
                          var fromStr = fromD.toISOString().slice(0,10);
                          if (fetchFrom && !fetchFrom.value) fetchFrom.value = fromStr;
                          if (fetchTo && !fetchTo.value) fetchTo.value = toStr;
                        }catch(_){}
                        // Reset modal device select to no selection when opening modal
                        try {
                          var modalSelect = document.getElementById('attendance-device-custom-select-modal');
                          if (modalSelect) {
                            var modalToggle = modalSelect.querySelector('.custom-select-toggle');
                            var placeholder = (window.__MESSAGES__ && window.__MESSAGES__['attendance_placeholder_device']) ? window.__MESSAGES__['attendance_placeholder_device'] : (modalToggle ? modalToggle.getAttribute('data-placeholder') || 'Chọn máy chấm công' : 'Chọn máy chấm công');
                            if (modalToggle) {
                              var span = modalToggle.querySelector('span');
                              if (span) {
                                span.innerHTML = '<span style="font-size:13px; font-weight:400; font-style:italic; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; color:rgba(122,220,201,0.6);">' + placeholder + '</span>';
                              }
                              // Reset arrow opacity
                              var arrow = modalToggle.querySelector('svg');
                              if (arrow) arrow.style.opacity = '0.6';
                            }
                            // Remove all selected states
                            modalSelect.querySelectorAll('.custom-select-option').forEach(function(el){ el.classList.remove('is-selected'); });
                            // Clear hidden inputs
                            var nameHidden = document.getElementById('attendance-device-name');
                            var devKeyHidden = document.getElementById('attendance-device-key');
                            var ipInput = document.getElementById('attendance-ip');
                            var portInput = document.getElementById('attendance-port');
                            if (nameHidden) nameHidden.value = '';
                            if (devKeyHidden) devKeyHidden.value = '';
                            if (ipInput) ipInput.value = '';
                            if (portInput) portInput.value = '';
                          }
                        } catch(_){}
                        // Ensure modal custom select is bound
                        try { if (typeof initModalDeviceSelect === 'function') initModalDeviceSelect(); } catch(_){}
                        applyAllState();
                        // Show fetch modal - bao phủ toàn bộ trang web
                        fetchModal.style.position='fixed';
                        fetchModal.style.inset='0';
                        fetchModal.style.zIndex='10000';
                        fetchModal.classList.add('show');
                        fetchModal.style.display='flex';
                        fetchModal.setAttribute('aria-hidden','false');
                    }
                    function closeFetch(){ if(!fetchModal) return; fetchModal.classList.remove('show'); fetchModal.style.display='none'; fetchModal.setAttribute('aria-hidden','true'); document.body.classList.remove('attendance-fetch-modal-open'); }

                    if (openFetchBtn) openFetchBtn.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); openFetch(); });
                    // Fallback delegated binding in case the button is re-rendered
                    document.addEventListener('click', function(e){ var t=e.target && e.target.closest ? e.target.closest('#attendance-open-fetch') : null; if (t){ e.preventDefault(); e.stopPropagation(); openFetch(); }}, true);
                    if (chkAll){ chkAll.addEventListener('change', applyAllState); }
                    // Function to check if table has data
                    function hasTableData(){
                        var table = document.getElementById('attendance-table');
                        if (!table) return false;
                        var tbody = table.querySelector('tbody');
                        if (!tbody) return false;
                        var rows = tbody.querySelectorAll('tr');
                        // Check if there are any data rows (exclude the "no data" row)
                        for (var i = 0; i < rows.length; i++) {
                            var row = rows[i];
                            var cells = row.querySelectorAll('td');
                            if (cells.length <= 1) { continue; }
                                var firstCellText = (cells[0].textContent || '').trim();
                                var noDataText = (window.__MESSAGES__ && window.__MESSAGES__['attendance_no_data']) ? window.__MESSAGES__['attendance_no_data'] : 'Chưa có dữ liệu hiển thị';
                                if (firstCellText && firstCellText !== noDataText) {
                                    return true;
                            }
                        }
                        return false;
                    }
                    
                    // Function to actually submit the form
                    function doSubmitFetchForm(){
                        var all = !!(chkAll && chkAll.checked);
                        var fv = fetchFrom ? fetchFrom.value : '';
                        var tv = fetchTo ? fetchTo.value : '';
                        if (hiddenFrom) hiddenFrom.value = all ? '' : fv;
                        if (hiddenTo) hiddenTo.value = all ? '' : tv;
                        if (hiddenFlag) hiddenFlag.value = '1';
                        if (hiddenAll) hiddenAll.value = all ? '1' : '';
                        // Reset append mode to 0 (overwrite) if not set by modal buttons
                        if (hiddenAppendMode && hiddenAppendMode.value === '') {
                            hiddenAppendMode.value = '0';
                        }
                        // Clear flag trước khi submit để phân biệt user click vs browser re-submit
                        // Khi user thực sự click, flag sẽ được clear -> toast sẽ hiển thị
                        // Khi browser re-submit (reload), không có JS để clear flag -> toast không hiển thị
                        fetch(window.location.href, {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/x-www-form-urlencoded',
                                'X-Requested-With': 'XMLHttpRequest'
                            },
                            body: 'clear_fetch_toast_for_new_fetch=1'
                        }).then(function() {
                            if (fetchForm) fetchForm.submit();
                            closeFetch();
                        }).catch(function() {
                            // Nếu AJAX thất bại, vẫn submit form
                            if (fetchForm) fetchForm.submit();
                            closeFetch();
                        });
                    }
                    
                    if (fetchApply){
                        fetchApply.addEventListener('click', function(){
                            // Kiểm tra thiết bị đã được chọn chưa
                            var nameHidden = document.getElementById('attendance-device-name');
                            var deviceName = nameHidden ? nameHidden.value.trim() : '';
                            var deviceIp = document.getElementById('attendance-ip') ? document.getElementById('attendance-ip').value.trim() : '';
                            var devicePort = document.getElementById('attendance-port') ? document.getElementById('attendance-port').value.trim() : '';
                            
                            if (!deviceName || !deviceIp || !devicePort){
                                var errorTitle = (window.__MESSAGES__ && window.__MESSAGES__['error_notification_title']) ? window.__MESSAGES__['error_notification_title'] : 'THÔNG BÁO';
                                var errorMsg = (window.__MESSAGES__ && window.__MESSAGES__['attendance_filter_validation_device_required']) ? window.__MESSAGES__['attendance_filter_validation_device_required'] : 'Vui lòng chọn thiết bị chấm công trước khi tải dữ liệu.';
                                if (window.showToast) window.showToast('error', '<div class="error-header">' + errorTitle + '</div>' + errorMsg);
                                return;
                            }
                            
                            var all = !!(chkAll && chkAll.checked);
                            var fv = fetchFrom ? fetchFrom.value : '';
                            var tv = fetchTo ? fetchTo.value : '';
                            if (!all && fv && tv && fv > tv){
                                var errorTitle = (window.__MESSAGES__ && window.__MESSAGES__['error_notification_title']) ? window.__MESSAGES__['error_notification_title'] : 'THÔNG BÁO';
                                var errorMsg = (window.__MESSAGES__ && window.__MESSAGES__['attendance_filter_validation_date_range']) ? window.__MESSAGES__['attendance_filter_validation_date_range'] : 'Từ ngày phải nhỏ hơn hoặc bằng Đến ngày';
                                if (window.showToast) window.showToast('error', '<div class="error-header">' + errorTitle + '</div>' + errorMsg);
                                return;
                            }
                            
                            // Kiểm tra xem table đã có dữ liệu chưa
                            if (hasTableData()) {
                                // Có dữ liệu, hiển thị popup xác nhận
                                var confirmModal = document.getElementById('attendance-confirm-overwrite-modal');
                                if (confirmModal) {
                                    ensureConfirmModalPortaled(confirmModal);
                                    // Update modal text with current language
                                    var titleEl = document.getElementById('attendance-confirm-overwrite-title');
                                    var msgEl = document.getElementById('attendance-confirm-overwrite-message');
                                    var appendBtn = document.getElementById('attendance-append-data-btn');
                                    var overwriteBtn = document.getElementById('attendance-overwrite-data-btn');
                                    if (titleEl && window.__MESSAGES__ && window.__MESSAGES__['attendance_confirm_overwrite_title']) {
                                        titleEl.textContent = window.__MESSAGES__['attendance_confirm_overwrite_title'];
                                    }
                                    if (msgEl && window.__MESSAGES__ && window.__MESSAGES__['attendance_confirm_overwrite_message']) {
                                        msgEl.textContent = window.__MESSAGES__['attendance_confirm_overwrite_message'];
                                    }
                                    if (appendBtn && window.__MESSAGES__ && window.__MESSAGES__['attendance_append_data']) {
                                        appendBtn.textContent = window.__MESSAGES__['attendance_append_data'];
                                    }
                                    if (overwriteBtn && window.__MESSAGES__ && window.__MESSAGES__['attendance_overwrite_data']) {
                                        overwriteBtn.textContent = window.__MESSAGES__['attendance_overwrite_data'];
                                    }
                                    
                                    // Show confirm modal
                                    confirmModal.style.position = 'fixed';
                                    confirmModal.style.inset = '0';
                                    confirmModal.style.zIndex = '2147483001';
                                    confirmModal.classList.add('show');
                                    confirmModal.style.display = 'flex';
                                    confirmModal.setAttribute('aria-hidden', 'false');
                                    
                                    // Close fetch modal first
                                    closeFetch();
                                } else {
                                    // Fallback: submit directly if modal not found
                                    doSubmitFetchForm();
                                }
                            } else {
                                // Chưa có dữ liệu, submit ngay
                                doSubmitFetchForm();
                            }
                        });
                    }
                    
                    // Handle confirm overwrite modal
                    var confirmModal = document.getElementById('attendance-confirm-overwrite-modal');
                    if (confirmModal) {
                        ensureConfirmModalPortaled(confirmModal);
                        var appendBtn = document.getElementById('attendance-append-data-btn');
                        var overwriteBtn = document.getElementById('attendance-overwrite-data-btn');
                        var confirmCloseBtns = confirmModal.querySelectorAll('[data-modal-close]');
                        
                        function closeConfirmModal() {
                            if (!confirmModal) return;
                            confirmModal.classList.remove('show');
                            confirmModal.style.display = 'none';
                            confirmModal.setAttribute('aria-hidden', 'true');
                            // KHÔNG reset append mode khi đóng modal bằng nút action
                            // Chỉ reset khi đóng bằng nút Hủy hoặc click outside
                        }
                        
                        if (appendBtn) {
                            appendBtn.addEventListener('click', function(e) {
                                e.preventDefault();
                                e.stopPropagation();
                                // Set append mode to 1 (append) TRƯỚC KHI đóng modal
                                if (hiddenAppendMode) {
                                    hiddenAppendMode.value = '1';
                                }
                                // Đóng modal nhưng KHÔNG reset append mode
                                confirmModal.classList.remove('show');
                                confirmModal.style.display = 'none';
                                confirmModal.setAttribute('aria-hidden', 'true');
                                // Submit form
                                doSubmitFetchForm();
                            });
                        }
                        
                        if (overwriteBtn) {
                            overwriteBtn.addEventListener('click', function(e) {
                                e.preventDefault();
                                e.stopPropagation();
                                // Set append mode to 0 (overwrite) TRƯỚC KHI đóng modal
                                if (hiddenAppendMode) {
                                    hiddenAppendMode.value = '0';
                                }
                                // Đóng modal
                                confirmModal.classList.remove('show');
                                confirmModal.style.display = 'none';
                                confirmModal.setAttribute('aria-hidden', 'true');
                                // Submit form
                                doSubmitFetchForm();
                            });
                        }
                        
                        confirmCloseBtns.forEach(function(btn) {
                            btn.addEventListener('click', function(e) {
                                // Reset append mode khi đóng bằng nút Hủy hoặc X
                                if (hiddenAppendMode) hiddenAppendMode.value = '0';
                                closeConfirmModal();
                            });
                        });
                        
                        // Disabled: click outside to close modal
                        // confirmModal.addEventListener('click', function(e) {
                        //     if (e.target === confirmModal) {
                        //         // Reset append mode khi click outside
                        //         if (hiddenAppendMode) hiddenAppendMode.value = '0';
                        //         closeConfirmModal();
                        //     }
                        // });
                        
                        document.addEventListener('keydown', function(e) {
                            if (confirmModal.classList.contains('show') && e.key === 'Escape') {
                                closeConfirmModal();
                            }
                        });
                    }
                    if (fetchModal){
                        fetchModal.querySelectorAll('[data-modal-close]').forEach(function(btn){ btn.addEventListener('click', closeFetch); });
                        // Disabled: click outside to close modal
                        // fetchModal.addEventListener('click', function(e){ if (e.target === fetchModal) closeFetch(); });
                        document.addEventListener('keydown', function(e){ if (fetchModal.classList.contains('show') && e.key==='Escape') closeFetch();                         });
                    }
                    
                    // Handle update button (item3)
                    var updateBtn = document.getElementById('attendance-update-btn');
                    var updateModal = document.getElementById('attendance-update-modal');
                    if (updateBtn && updateModal) {
                        function openUpdateModal() {
                            // Close sprint menu
                            if (window.__sprinTipsClose) window.__sprinTipsClose();
                            var sprintToggle = document.getElementById('menu-sprin-toggle');
                            if (sprintToggle) sprintToggle.checked = false;
                            var sprintWrapper = document.querySelector('.attendance-panel .menu-sprin-wrapper');
                            if (sprintWrapper) {
                                sprintWrapper.classList.remove('open');
                            }
                            document.body.classList.add('attendance-update-modal-open');
                            // Đảm bảo modal ở trong body để bao phủ toàn bộ trang
                            if (updateModal.parentElement !== document.body) {
                                document.body.appendChild(updateModal);
                            }
                            // Show update modal - bao phủ toàn bộ trang web
                            updateModal.style.setProperty('position', 'fixed', 'important');
                            updateModal.style.setProperty('inset', '0', 'important');
                            updateModal.style.setProperty('z-index', '10000', 'important');
                            updateModal.classList.add('show');
                            updateModal.style.display = 'flex';
                            updateModal.setAttribute('aria-hidden', 'false');
                            
                            // Reset checkbox "Thời gian hiện tại" và các field
                            var useCurrentTimeCheckbox = document.getElementById('att-update-use-current-time');
                            var updateDateInput = document.getElementById('att-update-date');
                            var updateTimeInput = document.getElementById('att-update-time');
                            
                            if (useCurrentTimeCheckbox) {
                                useCurrentTimeCheckbox.checked = false;
                            }
                            if (updateDateInput) {
                                updateDateInput.disabled = false;
                                updateDateInput.style.opacity = '1';
                                updateDateInput.style.cursor = '';
                                updateDateInput.value = '';
                            }
                            if (updateTimeInput) {
                                updateTimeInput.disabled = false;
                                updateTimeInput.style.opacity = '1';
                                updateTimeInput.style.cursor = '';
                                updateTimeInput.value = '';
                            }
                        }
                        function closeUpdateModal() {
                            updateModal.classList.remove('show');
                            updateModal.style.display = 'none';
                            updateModal.setAttribute('aria-hidden', 'true');
                            document.body.classList.remove('attendance-update-modal-open');
                        }
                        updateBtn.addEventListener('click', function(e) {
                            e.preventDefault();
                            e.stopPropagation();
                            openUpdateModal();
                        });
                        updateModal.querySelectorAll('[data-modal-close]').forEach(function(btn) {
                            btn.addEventListener('click', closeUpdateModal);
                        });
                        // Disabled: click outside to close modal
                        // updateModal.addEventListener('click', function(e) {
                        //     if (e.target === updateModal) closeUpdateModal();
                        // });
                        document.addEventListener('keydown', function(e) {
                            if (updateModal.classList.contains('show') && e.key === 'Escape') {
                                closeUpdateModal();
                            }
                        });
                        
                        // Setup custom select for device in update modal (portal to body like fetch modal)
                        var updateDeviceSelect = document.getElementById('attendance-update-device-custom-select');
                        if (updateDeviceSelect) {
                            var updateDeviceToggle = updateDeviceSelect.querySelector('.custom-select-toggle');
                            var updateDeviceMenu = updateDeviceSelect.querySelector('.custom-select-menu');
                            if (updateDeviceToggle && updateDeviceMenu) {
                                var anchorParent = null, anchorNext = null, isPortaled = false;
                                var closeOnScroll = null, closeOnResize = null;
                                
                                function mountMenu() {
                                    if (isPortaled) return;
                                    anchorParent = updateDeviceMenu.parentNode;
                                    anchorNext = updateDeviceMenu.nextSibling;
                                    document.body.appendChild(updateDeviceMenu);
                                    isPortaled = true;
                                }
                                function unmountMenu() {
                                    if (!isPortaled) return;
                                    if (anchorParent) {
                                        if (anchorNext) {
                                            anchorParent.insertBefore(updateDeviceMenu, anchorNext);
                                        } else {
                                            anchorParent.appendChild(updateDeviceMenu);
                                        }
                                    }
                                    isPortaled = false;
                                }
                                function positionMenu() {
                                    var r = updateDeviceToggle.getBoundingClientRect();
                                    var pad = 12;
                                    var maxH = Math.min(320, Math.max(200, window.innerHeight - r.bottom - 16));
                                    var left = Math.round(r.left);
                                    var width = Math.round(r.width);
                                    if (left < pad) left = pad;
                                    if (left + width + pad > window.innerWidth) {
                                        left = Math.max(pad, window.innerWidth - width - pad);
                                    }
                                    updateDeviceMenu.style.position = 'fixed';
                                    updateDeviceMenu.style.left = left + 'px';
                                    updateDeviceMenu.style.top = Math.round(r.bottom + 6) + 'px';
                                    updateDeviceMenu.style.width = width + 'px';
                                    updateDeviceMenu.style.minWidth = width + 'px';
                                    updateDeviceMenu.style.maxWidth = width + 'px';
                                    updateDeviceMenu.style.maxHeight = maxH + 'px';
                                    updateDeviceMenu.style.overflowY = 'auto';
                                    updateDeviceMenu.style.zIndex = '2147483647';
                                    updateDeviceMenu.style.display = 'block';
                                }
                                function clearStyles() {
                                    updateDeviceMenu.style.position = '';
                                    updateDeviceMenu.style.left = '';
                                    updateDeviceMenu.style.top = '';
                                    updateDeviceMenu.style.width = '';
                                    updateDeviceMenu.style.minWidth = '';
                                    updateDeviceMenu.style.maxWidth = '';
                                    updateDeviceMenu.style.maxHeight = '';
                                    updateDeviceMenu.style.overflowY = '';
                                    updateDeviceMenu.style.zIndex = '';
                                    updateDeviceMenu.style.display = '';
                                }
                                function closeAll() {
                                    updateDeviceSelect.classList.remove('open');
                                    clearStyles();
                                    unmountMenu();
                                    if (closeOnScroll) {
                                        window.removeEventListener('scroll', closeOnScroll, true);
                                        closeOnScroll = null;
                                    }
                                    if (closeOnResize) {
                                        window.removeEventListener('resize', closeOnResize);
                                        closeOnResize = null;
                                    }
                                }
                                
                                var justOpenedAt = 0;
                                updateDeviceToggle.addEventListener('click', function(e) {
                                    e.stopPropagation();
                                    var willOpen = !updateDeviceSelect.classList.contains('open');
                                    updateDeviceSelect.classList.toggle('open');
                                    if (willOpen) {
                                        mountMenu();
                                        positionMenu();
                                        justOpenedAt = Date.now();
                                        closeOnScroll = function(ev) {
                                            if (updateDeviceMenu.contains(ev.target)) return;
                                            closeAll();
                                        };
                                        closeOnResize = function() {
                                            closeAll();
                                        };
                                        window.addEventListener('scroll', closeOnScroll, true);
                                        window.addEventListener('resize', closeOnResize);
                                    } else {
                                        closeAll();
                                    }
                                });
                                
                                updateDeviceMenu.addEventListener('click', function(e) {
                                    var opt = e.target.closest('.custom-select-option');
                                    if (!opt) return;
                                    e.stopPropagation();
                                    var name = opt.getAttribute('data-value') || '';
                                    var ip = opt.getAttribute('data-ip') || '';
                                    var port = opt.getAttribute('data-port') || '';
                                    var nameEl = opt.querySelector('div:first-child');
                                    var label = nameEl ? nameEl.textContent.trim() : opt.textContent.trim();
                                    var span = updateDeviceToggle.querySelector('span');
                                    if (span) {
                                        span.innerHTML = '<span style="font-size:13px; font-weight:500;">' + label + '</span> <span style="font-size:11px; color:#7eb8b0; margin-top:2px;">(' + ip + ':' + port + ')</span>';
                                    }
                                    var arrow = updateDeviceToggle.querySelector('svg');
                                    if (arrow) arrow.style.opacity = '1';
                                    updateDeviceMenu.querySelectorAll('.custom-select-option').forEach(function(el) {
                                        el.classList.toggle('is-selected', el === opt);
                                    });
                                    // Lưu IP và Port vào hidden inputs
                                    var ipInput = document.getElementById('attendance-update-device-ip');
                                    var portInput = document.getElementById('attendance-update-device-port');
                                    var nameInput = document.getElementById('attendance-update-device-name');
                                    if (ipInput) ipInput.value = ip;
                                    if (portInput) portInput.value = port;
                                    if (nameInput) nameInput.value = name;
                                    closeAll();
                                });
                                
                                document.addEventListener('click', function(e) {
                                    var now = Date.now();
                                    if (now - justOpenedAt < 150) return;
                                    if (!updateDeviceSelect.contains(e.target) && !updateDeviceMenu.contains(e.target)) {
                                        closeAll();
                                    }
                                });
                                
                                updateDeviceMenu.addEventListener('wheel', function(e) {
                                    e.stopPropagation();
                                }, { passive: true });
                                updateDeviceMenu.addEventListener('touchmove', function(e) {
                                    e.stopPropagation();
                                }, { passive: true });
                                updateDeviceMenu.addEventListener('mousedown', function(e) {
                                    e.stopPropagation();
                                });
                            }
                        }
                        
                        // Setup date picker for update modal
                        try {
                            if (typeof setupDatePickerForModal === 'function') {
                                setupDatePickerForModal(updateModal);
                            }
                        } catch(_) {}
                        
                        // Time picker is already set up in the global DOMContentLoaded handler below
                        
                        // Handle update submit button
                        var updateSubmitBtn = document.getElementById('attendance-update-submit-btn');
                        var updateForm = document.getElementById('attendance-update-form');
                        var useCurrentTimeCheckbox = document.getElementById('att-update-use-current-time');
                        var updateDateInput = document.getElementById('att-update-date');
                        var updateTimeInput = document.getElementById('att-update-time');
                        
                        // Xử lý checkbox "Thời gian hiện tại"
                        if (useCurrentTimeCheckbox && updateDateInput && updateTimeInput) {
                            useCurrentTimeCheckbox.addEventListener('change', function() {
                                if (this.checked) {
                                    // Disable date và time fields
                                    updateDateInput.disabled = true;
                                    updateTimeInput.disabled = true;
                                    updateDateInput.style.opacity = '0.6';
                                    updateTimeInput.style.opacity = '0.6';
                                    updateDateInput.style.cursor = 'not-allowed';
                                    updateTimeInput.style.cursor = 'not-allowed';
                                    
                                    // Tự động set thời gian hiện tại
                                    var now = new Date();
                                    var year = now.getFullYear();
                                    var month = String(now.getMonth() + 1).padStart(2, '0');
                                    var day = String(now.getDate()).padStart(2, '0');
                                    var hours = String(now.getHours()).padStart(2, '0');
                                    var minutes = String(now.getMinutes()).padStart(2, '0');
                                    var seconds = String(now.getSeconds()).padStart(2, '0');
                                    
                                    updateDateInput.value = year + '-' + month + '-' + day;
                                    updateTimeInput.value = hours + ':' + minutes + ':' + seconds;
                                } else {
                                    // Enable lại date và time fields
                                    updateDateInput.disabled = false;
                                    updateTimeInput.disabled = false;
                                    updateDateInput.style.opacity = '1';
                                    updateTimeInput.style.opacity = '1';
                                    updateDateInput.style.cursor = '';
                                    updateTimeInput.style.cursor = '';
                                }
                            });
                        }
                        
                        if (updateSubmitBtn && updateForm) {
                            updateSubmitBtn.addEventListener('click', function(e) {
                                e.preventDefault();
                                // Get values
                                var deviceSelect = document.getElementById('attendance-update-device-custom-select');
                                var selectedOption = deviceSelect ? deviceSelect.querySelector('.custom-select-option.is-selected') : null;
                                var deviceNameEl = selectedOption ? selectedOption.querySelector('div:first-child') : null;
                                var deviceName = deviceNameEl ? deviceNameEl.textContent.trim() : (selectedOption ? selectedOption.getAttribute('data-value') : '');
                                var deviceIp = document.getElementById('attendance-update-device-ip') ? document.getElementById('attendance-update-device-ip').value : '';
                                var devicePort = document.getElementById('attendance-update-device-port') ? document.getElementById('attendance-update-device-port').value : '';
                                
                                // Kiểm tra checkbox "Thời gian hiện tại"
                                var useCurrentTime = useCurrentTimeCheckbox && useCurrentTimeCheckbox.checked;
                                var date, time;
                                
                                if (useCurrentTime) {
                                    // Lấy thời gian hiện tại
                                    var now = new Date();
                                    var year = now.getFullYear();
                                    var month = String(now.getMonth() + 1).padStart(2, '0');
                                    var day = String(now.getDate()).padStart(2, '0');
                                    var hours = String(now.getHours()).padStart(2, '0');
                                    var minutes = String(now.getMinutes()).padStart(2, '0');
                                    var seconds = String(now.getSeconds()).padStart(2, '0');
                                    
                                    date = year + '-' + month + '-' + day;
                                    time = hours + ':' + minutes + ':' + seconds;
                                } else {
                                    date = updateDateInput ? updateDateInput.value : '';
                                    time = updateTimeInput ? updateTimeInput.value : '';
                                }
                                
                                // Validation
                                var errorTitle = (window.__MESSAGES__ && window.__MESSAGES__['error_notification_title']) ? window.__MESSAGES__['error_notification_title'] : 'THÔNG BÁO';
                                var errors = [];
                                
                                // Helper to read message key with fallback
                                function getMsg(key, fallback) {
                                    return (window.__MESSAGES__ && window.__MESSAGES__[key]) ? window.__MESSAGES__[key] : fallback;
                                }
                                
                                if (!deviceName || !deviceIp || !devicePort) {
                                    errors.push(getMsg('attendance_error_device_required', 'Vui lòng chọn thiết bị chấm công.'));
                                }
                                if (!date) {
                                    errors.push(getMsg('attendance_validation_date_required', 'Ngày không được để trống.'));
                                }
                                if (!time || !/^\d{2}:\d{2}:\d{2}$/.test(time)) {
                                    errors.push(getMsg('attendance_validation_time_required', 'Giờ không được để trống (định dạng hh:mm:ss).'));
                                }
                                
                                if (errors.length > 0) {
                                    var errorMsg = '<div class="error-header">' + errorTitle + '</div>' + errors.join('<br>');
                                    if (window.showToast) {
                                        window.showToast('error', errorMsg);
                                    } else {
                                        alert(errors.join('\n'));
                                    }
                                    return;
                                }
                                
                                // Disable button during processing
                                updateSubmitBtn.disabled = true;
                                var originalText = updateSubmitBtn.textContent;
                                var processingText = (window.__MESSAGES__ && window.__MESSAGES__['attendance_update_processing']) ? window.__MESSAGES__['attendance_update_processing'] : 'Đang cập nhật...';
                                updateSubmitBtn.textContent = processingText;
                                
                                // Submit form via AJAX
                                var formData = new FormData(updateForm);
                                formData.append('update_date', date);
                                formData.append('update_time', time);
                                if (useCurrentTime) {
                                    formData.append('use_current_time', '1');
                                }
                                
                                fetch(window.location.href, {
                                    method: 'POST',
                                    headers: {
                                        'X-Requested-With': 'XMLHttpRequest',
                                        'Accept': 'application/json'
                                    },
                                    body: formData
                                })
                                .then(function(response) {
                                    // Check if response is JSON
                                    var contentType = response.headers.get('content-type');
                                    if (contentType && contentType.includes('application/json')) {
                                        return response.json();
                                    } else {
                                        return response.text().then(function(text) {
                                            console.error('Non-JSON response:', text);
                                            throw new Error('Server returned non-JSON response');
                                        });
                                    }
                                })
                                .then(function(json) {
                                    if (json && json.ok) {
                                        closeUpdateModal();
                                        // Reload page ngay lập tức, thông báo sẽ hiển thị sau khi reload
                                        window.location.reload();
                                    } else {
                                        var errorMsg = '<div class="error-header">' + errorTitle + '</div>' + (json && json.message ? json.message : 'Có lỗi xảy ra khi cập nhật thời gian');
                                        if (window.showToast) {
                                            window.showToast('error', errorMsg);
                                        } else {
                                            alert(json && json.message ? json.message : 'Có lỗi xảy ra khi cập nhật thời gian');
                                        }
                                        updateSubmitBtn.disabled = false;
                                        updateSubmitBtn.textContent = originalText;
                                    }
                                })
                                .catch(function(error) {
                                    console.error('Update error:', error);
                                    var errorMsg = '<div class="error-header">' + errorTitle + '</div>' + (error.message || 'Có lỗi xảy ra khi cập nhật thời gian. Vui lòng kiểm tra kết nối và thử lại.');
                                    if (window.showToast) {
                                        window.showToast('error', errorMsg);
                                    } else {
                                        alert(error.message || 'Có lỗi xảy ra khi cập nhật thời gian');
                                    }
                                    updateSubmitBtn.disabled = false;
                                    updateSubmitBtn.textContent = originalText;
                                });
                            });
                        }
                    }
                    
                    // Handle filter duplicate button (item4)
                    var filterDuplicateBtn = document.getElementById('attendance-filter-duplicate-btn');
                    if (filterDuplicateBtn) {
                        filterDuplicateBtn.addEventListener('click', function(e) {
                            e.preventDefault();
                            e.stopPropagation();
                            // Close sprint menu
                            if (window.__sprinTipsClose) window.__sprinTipsClose();
                            var sprintToggle = document.getElementById('menu-sprin-toggle');
                            if (sprintToggle) sprintToggle.checked = false;
                            var sprintWrapper = document.querySelector('.attendance-panel .menu-sprin-wrapper');
                            if (sprintWrapper) {
                                sprintWrapper.classList.remove('open');
                            }
                            
                            // Check if table has data
                            function hasTableData(){
                                var table = document.getElementById('attendance-table');
                                if (!table) return false;
                                var tbody = table.querySelector('tbody');
                                if (!tbody) return false;
                                var rows = tbody.querySelectorAll('tr');
                                for (var i = 0; i < rows.length; i++) {
                                    var row = rows[i];
                                    var cells = row.querySelectorAll('td');
                                    if (cells.length >= 8) {
                                        var firstCellText = (cells[0].textContent || '').trim();
                                        var noDataText = (window.__MESSAGES__ && window.__MESSAGES__['attendance_no_data']) ? window.__MESSAGES__['attendance_no_data'] : 'Chưa có dữ liệu hiển thị';
                                        if (firstCellText && firstCellText !== noDataText) {
                                            return true;
                                        }
                                    }
                                }
                                return false;
                            }
                            
                            if (!hasTableData()) {
                                var errorTitle = (window.__MESSAGES__ && window.__MESSAGES__['error_notification_title']) ? window.__MESSAGES__['error_notification_title'] : 'THÔNG BÁO';
                                var errorMsg = (window.__MESSAGES__ && window.__MESSAGES__['attendance_filter_duplicate_no_data']) ? window.__MESSAGES__['attendance_filter_duplicate_no_data'] : 'Không có dữ liệu để lọc trùng.';
                                if (window.showToast) {
                                    window.showToast('error', '<div class="error-header">' + errorTitle + '</div>' + errorMsg);
                                } else {
                                    alert(errorMsg);
                                }
                                return;
                            }
                            
                            // Show confirm modal before filtering
                            var confirmModal = document.getElementById('attendance-confirm-filter-duplicate-modal');
                            if (confirmModal) {
                                // Update modal text with current language
                                var titleEl = document.getElementById('attendance-confirm-filter-duplicate-title');
                                var msgEl = document.getElementById('attendance-confirm-filter-duplicate-message');
                                var okBtn = document.getElementById('attendance-confirm-filter-duplicate-btn');
                                
                                if (titleEl && window.__MESSAGES__ && window.__MESSAGES__['attendance_confirm_filter_duplicate_title']) {
                                    titleEl.textContent = window.__MESSAGES__['attendance_confirm_filter_duplicate_title'];
                                }
                                if (msgEl && window.__MESSAGES__ && window.__MESSAGES__['attendance_filter_duplicate_confirm']) {
                                    msgEl.textContent = window.__MESSAGES__['attendance_filter_duplicate_confirm'];
                                }
                                if (okBtn && window.__MESSAGES__ && window.__MESSAGES__['attendance_btn_ok']) {
                                    okBtn.textContent = window.__MESSAGES__['attendance_btn_ok'];
                                }
                                
                                // Force ẩn TẤT CẢ các icon sprint menu
                                var sprintWrapper = document.querySelector('.attendance-panel .menu-sprin-wrapper');
                                if (sprintWrapper) {
                                    sprintWrapper.style.setProperty('z-index', '-1', 'important');
                                    sprintWrapper.style.setProperty('pointer-events', 'none', 'important');
                                    sprintWrapper.style.setProperty('opacity', '0.1', 'important');
                                    sprintWrapper.style.setProperty('visibility', 'hidden', 'important');
                                }
                                // Ẩn tất cả các icon item
                                var sprintItems = document.querySelectorAll('.attendance-panel .menu-sprin-item, .menu-sprin-item');
                                sprintItems.forEach(function(item) {
                                    item.style.setProperty('z-index', '-1', 'important');
                                    item.style.setProperty('pointer-events', 'none', 'important');
                                    item.style.setProperty('opacity', '0.1', 'important');
                                    item.style.setProperty('visibility', 'hidden', 'important');
                                });
                                // Ẩn tooltips và pseudo-elements
                                var tooltips = document.querySelectorAll('.sprin-live-tip');
                                tooltips.forEach(function(tip) {
                                    tip.style.setProperty('display', 'none', 'important');
                                    tip.style.setProperty('z-index', '-1', 'important');
                                });
                                // Thêm class vào body
                                document.body.classList.add('attendance-filter-duplicate-modal-open');
                                // Đảm bảo modal ở trong body để bao phủ toàn bộ trang
                                if (confirmModal.parentElement !== document.body) {
                                    document.body.appendChild(confirmModal);
                                }
                                // Show confirm modal - bao phủ toàn bộ trang web
                                confirmModal.style.setProperty('position', 'fixed', 'important');
                                confirmModal.style.setProperty('inset', '0', 'important');
                                confirmModal.style.setProperty('z-index', '10000', 'important');
                                confirmModal.style.setProperty('isolation', 'isolate', 'important');
                                confirmModal.classList.add('show');
                                confirmModal.style.setProperty('display', 'flex', 'important');
                                confirmModal.setAttribute('aria-hidden', 'false');
                                
                                // Function to close modal
                                function closeFilterDuplicateModal() {
                                    if (!confirmModal) return;
                                    confirmModal.classList.remove('show');
                                    confirmModal.style.setProperty('display', 'none', 'important');
                                    confirmModal.setAttribute('aria-hidden', 'true');
                                    // Xóa class khỏi body để khôi phục các icon
                                    document.body.classList.remove('attendance-filter-duplicate-modal-open');
                                    // Khôi phục sprint menu
                                    var sprintWrapper = document.querySelector('.attendance-panel .menu-sprin-wrapper');
                                    if (sprintWrapper) {
                                        sprintWrapper.style.zIndex = '';
                                        sprintWrapper.style.pointerEvents = '';
                                        sprintWrapper.style.opacity = '';
                                        sprintWrapper.style.visibility = '';
                                    }
                                    // Khôi phục tất cả các icon item
                                    var sprintItems = document.querySelectorAll('.attendance-panel .menu-sprin-item, .menu-sprin-item');
                                    sprintItems.forEach(function(item) {
                                        item.style.zIndex = '';
                                        item.style.pointerEvents = '';
                                        item.style.opacity = '';
                                        item.style.visibility = '';
                                    });
                                    // Khôi phục tooltips
                                    var tooltips = document.querySelectorAll('.sprin-live-tip');
                                    tooltips.forEach(function(tip) {
                                        tip.style.display = '';
                                        tip.style.zIndex = '';
                                    });
                                }
                                
                                // Function to submit filter duplicate request
                                function submitFilterDuplicate() {
                                    closeFilterDuplicateModal();
                                    var form = document.createElement('form');
                                    form.method = 'POST';
                                    var urlParams = new URLSearchParams(window.location.search);
                                    urlParams.set('page', '1');
                                    form.action = window.location.pathname + '?' + urlParams.toString();
                                    var input = document.createElement('input');
                                    input.type = 'hidden';
                                    input.name = 'attendance_filter_duplicate';
                                    input.value = '1';
                                    form.appendChild(input);
                                    document.body.appendChild(form);
                                    form.submit();
                                }
                                
                                // Add event listener to OK button
                                if (okBtn) {
                                    okBtn.addEventListener('click', function(e) {
                                        e.preventDefault();
                                        e.stopPropagation();
                                        submitFilterDuplicate();
                                    });
                                }
                                
                                // Add event listeners to close buttons
                                var closeBtns = confirmModal.querySelectorAll('[data-modal-close]');
                                closeBtns.forEach(function(btn) {
                                    btn.addEventListener('click', function(e) {
                                        e.preventDefault();
                                        e.stopPropagation();
                                        closeFilterDuplicateModal();
                                    });
                                });
                                
                                // Close on backdrop click
                                confirmModal.addEventListener('click', function(e) {
                                    if (e.target === confirmModal) {
                                        closeFilterDuplicateModal();
                                    }
                                });
                            } else {
                                // Fallback to confirm if modal not found
                                var confirmMsg = (window.__MESSAGES__ && window.__MESSAGES__['attendance_filter_duplicate_confirm']) ? window.__MESSAGES__['attendance_filter_duplicate_confirm'] : 'Bạn có chắc chắn muốn lọc trùng dữ liệu chấm công? Các bản ghi trùng (cùng nhân viên, cùng ngày, giờ cách nhau <= 5 phút) sẽ bị xóa, chỉ giữ lại bản ghi đầu tiên.';
                                if (!confirm(confirmMsg)) {
                                    return;
                                }
                                
                                // Submit filter duplicate request
                                var form = document.createElement('form');
                                form.method = 'POST';
                                var urlParams = new URLSearchParams(window.location.search);
                                urlParams.set('page', '1');
                                form.action = window.location.pathname + '?' + urlParams.toString();
                                var input = document.createElement('input');
                                input.type = 'hidden';
                                input.name = 'attendance_filter_duplicate';
                                input.value = '1';
                                form.appendChild(input);
                                document.body.appendChild(form);
                                form.submit();
                            }
                        });
                    }
                    
                    // Handle delete button (item5)
                    var deleteBtn = document.getElementById('attendance-delete-btn');
                    var deleteModal = document.getElementById('attendance-confirm-delete-modal');
                    if (deleteBtn && deleteModal) {
                        // Initialize delete modal checkboxes and device selector
                        var deleteTableCheckbox = document.getElementById('delete-table-checkbox');
                        var deleteDeviceCheckbox = document.getElementById('delete-device-checkbox');
                        var deleteDeviceSelectRow = document.getElementById('delete-device-select-row');
                        var deleteDeviceSelect = document.getElementById('attendance-delete-device-custom-select');
                        var deleteTableOption = document.getElementById('delete-table-option');
                        var deleteDeviceOption = document.getElementById('delete-device-option');
                        
                        // Checkbox behavior: only one can be selected (like radio buttons)
                        if (deleteTableCheckbox && deleteDeviceCheckbox) {
                            deleteTableCheckbox.addEventListener('change', function() {
                                if (this.checked) {
                                    deleteDeviceCheckbox.checked = false;
                                    if (deleteDeviceSelectRow) deleteDeviceSelectRow.style.display = 'none';
                                    if (deleteTableOption) {
                                        deleteTableOption.style.borderColor = 'rgba(122,220,201,0.6)';
                                        deleteTableOption.style.backgroundColor = 'rgba(122,220,201,0.1)';
                                    }
                                    if (deleteDeviceOption) {
                                        deleteDeviceOption.style.borderColor = 'rgba(122,220,201,0.2)';
                                        deleteDeviceOption.style.backgroundColor = 'transparent';
                                    }
                                } else {
                                    if (deleteTableOption) {
                                        deleteTableOption.style.borderColor = 'rgba(122,220,201,0.2)';
                                        deleteTableOption.style.backgroundColor = 'transparent';
                                    }
                                }
                            });
                            
                            deleteDeviceCheckbox.addEventListener('change', function() {
                                if (this.checked) {
                                    deleteTableCheckbox.checked = false;
                                    if (deleteDeviceSelectRow) deleteDeviceSelectRow.style.display = 'block';
                                    if (deleteDeviceOption) {
                                        deleteDeviceOption.style.borderColor = 'rgba(122,220,201,0.6)';
                                        deleteDeviceOption.style.backgroundColor = 'rgba(122,220,201,0.1)';
                                    }
                                    if (deleteTableOption) {
                                        deleteTableOption.style.borderColor = 'rgba(122,220,201,0.2)';
                                        deleteTableOption.style.backgroundColor = 'transparent';
                                    }
                                } else {
                                    if (deleteDeviceSelectRow) deleteDeviceSelectRow.style.display = 'none';
                                    if (deleteDeviceOption) {
                                        deleteDeviceOption.style.borderColor = 'rgba(122,220,201,0.2)';
                                        deleteDeviceOption.style.backgroundColor = 'transparent';
                                    }
                                }
                            });
                            
                            // Allow clicking on the option div to toggle checkbox
                            if (deleteTableOption) {
                                deleteTableOption.addEventListener('click', function(e) {
                                    if (e.target.tagName !== 'INPUT') {
                                        deleteTableCheckbox.checked = !deleteTableCheckbox.checked;
                                        deleteTableCheckbox.dispatchEvent(new Event('change'));
                                    }
                                });
                            }
                            if (deleteDeviceOption) {
                                deleteDeviceOption.addEventListener('click', function(e) {
                                    if (e.target.tagName !== 'INPUT') {
                                        deleteDeviceCheckbox.checked = !deleteDeviceCheckbox.checked;
                                        deleteDeviceCheckbox.dispatchEvent(new Event('change'));
                                    }
                                });
                            }
                        }
                        
                        // Initialize device selector in delete modal
                        if (deleteDeviceSelect) {
                            var deleteDeviceToggle = deleteDeviceSelect.querySelector('.custom-select-toggle');
                            var deleteDeviceMenu = deleteDeviceSelect.querySelector('.custom-select-menu');
                            var selectedDeviceName = '';
                            var selectedDeviceIp = '';
                            var selectedDevicePort = '';
                            
                            if (deleteDeviceToggle && deleteDeviceMenu) {
                                deleteDeviceToggle.addEventListener('click', function(e) {
                                    e.preventDefault();
                                    e.stopPropagation();
                                    deleteDeviceSelect.classList.toggle('is-active');
                                    deleteDeviceMenu.style.display = deleteDeviceSelect.classList.contains('is-active') ? 'block' : 'none';
                                });
                                
                                var deleteDeviceOptions = deleteDeviceMenu.querySelectorAll('.custom-select-option');
                                deleteDeviceOptions.forEach(function(option) {
                                    option.addEventListener('click', function(e) {
                                        e.preventDefault();
                                        e.stopPropagation();
                                        selectedDeviceName = this.getAttribute('data-value') || '';
                                        selectedDeviceIp = this.getAttribute('data-ip') || '';
                                        selectedDevicePort = this.getAttribute('data-port') || '';
                                        
                                        var nameText = this.querySelector('div:first-child')?.textContent || selectedDeviceName;
                                        var ipText = this.querySelector('div:last-child')?.textContent || (selectedDeviceIp + ':' + selectedDevicePort);
                                        
                                        var toggleSpan = deleteDeviceToggle.querySelector('span');
                                        if (toggleSpan) {
                                            toggleSpan.innerHTML = '<div style="font-size:13px; font-weight:500;">' + nameText + '</div><div style="font-size:11px; color:#7eb8b0; margin-top:2px;">' + ipText + '</div>';
                                            toggleSpan.style.fontStyle = 'normal';
                                            toggleSpan.style.color = '#e8fbf6';
                                        }
                                        
                                        deleteDeviceOptions.forEach(function(opt) { opt.classList.remove('is-selected'); });
                                        this.classList.add('is-selected');
                                        
                                        deleteDeviceSelect.classList.remove('is-active');
                                        deleteDeviceMenu.style.display = 'none';
                                    });
                                });
                                
                                document.addEventListener('click', function(e) {
                                    if (!deleteDeviceSelect.contains(e.target)) {
                                        deleteDeviceSelect.classList.remove('is-active');
                                        deleteDeviceMenu.style.display = 'none';
                                    }
                                });
                            }
                        }
                        
                        deleteBtn.addEventListener('click', function(e) {
                            e.preventDefault();
                            e.stopPropagation();
                            // Reset checkboxes
                            if (deleteTableCheckbox) deleteTableCheckbox.checked = false;
                            if (deleteDeviceCheckbox) deleteDeviceCheckbox.checked = false;
                            if (deleteDeviceSelectRow) deleteDeviceSelectRow.style.display = 'none';
                            if (deleteTableOption) {
                                deleteTableOption.style.borderColor = 'rgba(122,220,201,0.2)';
                                deleteTableOption.style.backgroundColor = 'transparent';
                            }
                            if (deleteDeviceOption) {
                                deleteDeviceOption.style.borderColor = 'rgba(122,220,201,0.2)';
                                deleteDeviceOption.style.backgroundColor = 'transparent';
                            }
                            // Close sprint menu
                            if (window.__sprinTipsClose) window.__sprinTipsClose();
                            // Đóng sprint menu bằng cách uncheck toggle
                            var sprintToggle = document.getElementById('menu-sprin-toggle');
                            if (sprintToggle) sprintToggle.checked = false;
                            // Force ẩn TẤT CẢ các icon sprint menu
                            var sprintWrapper = document.querySelector('.attendance-panel .menu-sprin-wrapper');
                            if (sprintWrapper) {
                                sprintWrapper.classList.remove('open');
                                sprintWrapper.style.setProperty('z-index', '-1', 'important');
                                sprintWrapper.style.setProperty('pointer-events', 'none', 'important');
                                sprintWrapper.style.setProperty('opacity', '0.1', 'important');
                                sprintWrapper.style.setProperty('visibility', 'hidden', 'important');
                            }
                            // Ẩn tất cả các icon item
                            var sprintItems = document.querySelectorAll('.attendance-panel .menu-sprin-item, .menu-sprin-item');
                            sprintItems.forEach(function(item) {
                                item.style.setProperty('z-index', '-1', 'important');
                                item.style.setProperty('pointer-events', 'none', 'important');
                                item.style.setProperty('opacity', '0.1', 'important');
                                item.style.setProperty('visibility', 'hidden', 'important');
                            });
                            // Ẩn tooltips và pseudo-elements
                            var tooltips = document.querySelectorAll('.sprin-live-tip');
                            tooltips.forEach(function(tip) {
                                tip.style.setProperty('display', 'none', 'important');
                                tip.style.setProperty('z-index', '-1', 'important');
                            });
                            // Thêm class vào body
                            document.body.classList.add('attendance-delete-modal-open');
                            // Đảm bảo modal ở trong body để bao phủ toàn bộ trang
                            if (deleteModal.parentElement !== document.body) {
                                document.body.appendChild(deleteModal);
                            }
                            // Show delete confirmation modal - bao phủ toàn bộ trang web
                            deleteModal.style.setProperty('position', 'fixed', 'important');
                            deleteModal.style.setProperty('inset', '0', 'important');
                            deleteModal.style.setProperty('z-index', '10000', 'important');
                            deleteModal.style.setProperty('isolation', 'isolate', 'important');
                            deleteModal.classList.add('show');
                            deleteModal.style.setProperty('display', 'flex', 'important');
                            deleteModal.setAttribute('aria-hidden', 'false');
                        });
                        
                        var confirmDeleteBtn = document.getElementById('attendance-confirm-delete-btn');
                        var deleteCloseBtns = deleteModal.querySelectorAll('[data-modal-close]');
                        
                        function closeDeleteModal() {
                            if (!deleteModal) return;
                            deleteModal.classList.remove('show');
                            deleteModal.style.display = 'none';
                            deleteModal.setAttribute('aria-hidden', 'true');
                            // Xóa class khỏi body để khôi phục các icon
                            document.body.classList.remove('attendance-delete-modal-open');
                            // Khôi phục sprint menu
                            var sprintWrapper = document.querySelector('.attendance-panel .menu-sprin-wrapper');
                            if (sprintWrapper) {
                                sprintWrapper.style.zIndex = '';
                                sprintWrapper.style.pointerEvents = '';
                                sprintWrapper.style.opacity = '';
                                sprintWrapper.style.visibility = '';
                            }
                            // Khôi phục tất cả các icon item
                            var sprintItems = document.querySelectorAll('.attendance-panel .menu-sprin-item, .menu-sprin-item');
                            sprintItems.forEach(function(item) {
                                item.style.zIndex = '';
                                item.style.pointerEvents = '';
                                item.style.opacity = '';
                                item.style.visibility = '';
                            });
                            // Khôi phục tooltips
                            var tooltips = document.querySelectorAll('.sprin-live-tip');
                            tooltips.forEach(function(tip) {
                                tip.style.display = '';
                                tip.style.zIndex = '';
                            });
                        }
                        
                        if (confirmDeleteBtn) {
                            confirmDeleteBtn.addEventListener('click', function() {
                                // Check which option is selected
                                var deleteTableCheckbox = document.getElementById('delete-table-checkbox');
                                var deleteDeviceCheckbox = document.getElementById('delete-device-checkbox');
                                
                                if (!deleteTableCheckbox.checked && !deleteDeviceCheckbox.checked) {
                                    alert('Vui lòng chọn loại xóa dữ liệu!');
                                    return;
                                }
                                
                                // If device delete is selected, check if a device is selected
                                if (deleteDeviceCheckbox.checked) {
                                    var deleteDeviceSelect = document.getElementById('attendance-delete-device-custom-select');
                                    var selectedOption = deleteDeviceSelect?.querySelector('.custom-select-option.is-selected');
                                    if (!selectedOption) {
                                        alert('Vui lòng chọn máy chấm công!');
                                        return;
                                    }
                                }
                                
                                closeDeleteModal();
                                // Submit delete form
                                var form = document.createElement('form');
                                form.method = 'POST';
                                // Build URL: keep existing params but set page=1
                                var urlParams = new URLSearchParams(window.location.search);
                                urlParams.set('page', '1');
                                form.action = window.location.pathname + '?' + urlParams.toString();
                                
                                var input = document.createElement('input');
                                input.type = 'hidden';
                                input.name = 'delete_attendance';
                                input.value = '1';
                                form.appendChild(input);
                                
                                // Add delete type
                                var deleteTypeInput = document.createElement('input');
                                deleteTypeInput.type = 'hidden';
                                deleteTypeInput.name = 'delete_type';
                                deleteTypeInput.value = deleteTableCheckbox.checked ? 'table' : 'device';
                                form.appendChild(deleteTypeInput);
                                
                                // If device delete, add device info
                                if (deleteDeviceCheckbox.checked) {
                                    var deleteDeviceSelect = document.getElementById('attendance-delete-device-custom-select');
                                    var selectedOption = deleteDeviceSelect?.querySelector('.custom-select-option.is-selected');
                                    if (selectedOption) {
                                        var deviceNameInput = document.createElement('input');
                                        deviceNameInput.type = 'hidden';
                                        deviceNameInput.name = 'delete_device_name';
                                        deviceNameInput.value = selectedOption.getAttribute('data-value') || '';
                                        form.appendChild(deviceNameInput);
                                        
                                        var deviceIpInput = document.createElement('input');
                                        deviceIpInput.type = 'hidden';
                                        deviceIpInput.name = 'delete_device_ip';
                                        deviceIpInput.value = selectedOption.getAttribute('data-ip') || '';
                                        form.appendChild(deviceIpInput);
                                        
                                        var devicePortInput = document.createElement('input');
                                        devicePortInput.type = 'hidden';
                                        devicePortInput.name = 'delete_device_port';
                                        devicePortInput.value = selectedOption.getAttribute('data-port') || '';
                                        form.appendChild(devicePortInput);
                                    }
                                }
                                
                                document.body.appendChild(form);
                                form.submit();
                            });
                        }
                        
                        deleteCloseBtns.forEach(function(btn) {
                            btn.addEventListener('click', closeDeleteModal);
                        });
                        
                        // Disabled: click outside to close modal
                        // deleteModal.addEventListener('click', function(e) {
                        //     if (e.target === deleteModal) closeDeleteModal();
                        // });
                        
                        document.addEventListener('keydown', function(e) {
                            if (deleteModal.classList.contains('show') && e.key === 'Escape') {
                                closeDeleteModal();
                            }
                        });
                    }

                    // Init date picker for fetch modal
                    try{ var m = document.getElementById('attendance-fetch-modal'); if (m && typeof setupDatePickerForModal==='function') setupDatePickerForModal(m); }catch(_){}

                    var custom = document.getElementById('attendance-device-custom-select');
                    if (!custom) return;
                    var toggle = custom.querySelector('.custom-select-toggle');
                    var menu = custom.querySelector('.custom-select-menu');
                    var ipInput = document.getElementById('attendance-ip');
                    var portInput = document.getElementById('attendance-port');
                    var infoDisplay = document.getElementById('attendance-info-display');
                    var devInfoName = document.getElementById('att-device-info-name');
                    var devInfoIp   = document.getElementById('att-device-info-ip');
                    if (!toggle || !menu) return;

                    var anchorParent = null, anchorNext = null, isPortaled = false;
                    var closeOnScroll = null, closeOnResize = null;

                    function mountMenu(){
                        if (isPortaled) return;
                        anchorParent = menu.parentNode;
                        anchorNext = menu.nextSibling;
                        document.body.appendChild(menu);
                        isPortaled = true;
                    }
                    function unmountMenu(){
                        if (!isPortaled) return;
                        if (anchorParent){
                            if (anchorNext){ anchorParent.insertBefore(menu, anchorNext); }
                            else { anchorParent.appendChild(menu); }
                        }
                        isPortaled = false;
                    }
                    function positionMenu(){
                        var r = toggle.getBoundingClientRect();
                        var pad = 12;
                        var maxH = Math.min(320, Math.max(200, window.innerHeight - r.bottom - 16));
                        var left = Math.round(r.left);
                        var width = Math.round(r.width);
                        if (left < pad) left = pad;
                        if (left + width + pad > window.innerWidth){
                            left = Math.max(pad, window.innerWidth - width - pad);
                        }
                        menu.style.position = 'fixed';
                        menu.style.left = left + 'px';
                        menu.style.top  = Math.round(r.bottom + 6) + 'px';
                        menu.style.width = width + 'px';
                        menu.style.minWidth = width + 'px';
                        menu.style.maxWidth = width + 'px';
                        menu.style.maxHeight = maxH + 'px';
                        menu.style.overflowY = 'auto';
                        /*menu.style.zIndex = '2147483000';*/
                        menu.style.display = 'block';
                    }
                    function clearMenuStyles(){
                        menu.style.position = '';
                        menu.style.left = '';
                        menu.style.top = '';
                        menu.style.width = '';
                        menu.style.minWidth = '';
                        menu.style.maxWidth = '';
                        menu.style.maxHeight = '';
                        menu.style.overflowY = '';
                        menu.style.zIndex = '';
                        menu.style.display = '';
                    }
                    function closeAll(){
                        custom.classList.remove('open');
                        clearMenuStyles();
                        unmountMenu();
                        if (closeOnScroll){ window.removeEventListener('scroll', closeOnScroll, true); closeOnScroll = null; }
                        if (closeOnResize){ window.removeEventListener('resize', closeOnResize); closeOnResize = null; }
                    }

                    // prevent page scroll when scrolling inside menu
                    menu.addEventListener('wheel', function(e){ e.stopPropagation(); }, { passive: true });
                    menu.addEventListener('touchmove', function(e){ e.stopPropagation(); }, { passive: true });
                    menu.addEventListener('mousedown', function(e){ e.stopPropagation(); });

                    document.addEventListener('click', function(e){ if (!custom.contains(e.target) && !menu.contains(e.target)) closeAll(); });
                    toggle.addEventListener('click', function(e){
                        e.stopPropagation();
                        var willOpen = !custom.classList.contains('open');
                        custom.classList.toggle('open');
                        if (willOpen){
                            mountMenu();
                            positionMenu();
                            closeOnScroll = function(ev){ if (menu.contains(ev.target)) return; closeAll(); };
                            closeOnResize = function(){ closeAll(); };
                            window.addEventListener('scroll', closeOnScroll, true);
                            window.addEventListener('resize', closeOnResize);
                        } else {
                            closeAll();
                        }
                    });

                    menu.addEventListener('click', function(e){
                        var opt = e.target.closest('.custom-select-option');
                        if (!opt) return;
                        var nameEl = opt.querySelector('div:first-child');
                        var name = nameEl ? nameEl.textContent.trim() : opt.textContent.trim();
                        var ip = opt.getAttribute('data-ip') || '';
                        var port = opt.getAttribute('data-port') || '';
                        var toggleContent = toggle.querySelector('span');
                        if (toggleContent) {
                            toggleContent.innerHTML = '<span style="font-size:13px; font-weight:500;">' + name + '</span><span style="font-size:11px; color:#7eb8b0; margin-top:2px;">' + ip + ':' + port + '</span>';
                        }
                        menu.querySelectorAll('.custom-select-option').forEach(function(el){ el.classList.toggle('is-selected', el===opt); });
                        if (ipInput) ipInput.value = ip;
                        if (portInput) portInput.value = port;
                        var nameHidden = document.getElementById('attendance-device-name');
                        if (nameHidden) nameHidden.value = name;
                        if (infoDisplay) infoDisplay.textContent = ip + ':' + port;
                        // Keep selected device across pagination & page-size
                        try {
                          var devKey = opt.getAttribute('data-value') || '';
                          // update all pagination links
                          document.querySelectorAll('.pagination a').forEach(function(a){
                            var href = a.getAttribute('href') || '';
                            if (!href) return;
                            if (href.indexOf('device=') >= 0) {
                              href = href.replace(/([?&]device=)[^&]*/, '$1' + encodeURIComponent(devKey));
                            } else {
                              href += (href.indexOf('?') >= 0 ? '&' : '?') + 'device=' + encodeURIComponent(devKey);
                            }
                            a.setAttribute('href', href);
                          });
                          // update hidden device in page-size form
                          var devHidden = document.getElementById('attendance-pagesize-device');
                          if (devHidden) devHidden.value = devKey;
                        } catch (e) { /* ignore */ }
                        closeAll();
                    });
                })();
                </script>
            </div>
        </header>


        <?php 
        $__att_err = $error ?? ($_SESSION['attendance_last_error'] ?? null);
        // Check if this specific error was already shown (to prevent showing on form resubmit)
        $__att_last_shown_error = $_SESSION['attendance_last_shown_error'] ?? '';
        $__att_error_already_shown = (!empty($__att_err) && $__att_err === $__att_last_shown_error);
        // Only show error if it exists AND is different from last shown error
        if (!empty($__att_err) && !$__att_error_already_shown): ?>
        <script>
        document.addEventListener('DOMContentLoaded', function(){
            try {
                var msg = <?= json_encode($__att_err, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
                var title = (window.__MESSAGES__ && window.__MESSAGES__['error_notification_title']) ? window.__MESSAGES__['error_notification_title'] : 'THÔNG BÁO';
                if (typeof window.showToast === 'function') {
                    window.showToast('error', '<div class="error-header">' + title + '</div>' + msg);
                }
            } catch (e) {}
        });
        </script>
        <?php 
        // Mark this error as shown to prevent showing again on form resubmit
        $_SESSION['attendance_last_shown_error'] = $__att_err;
        $_SESSION['attendance_last_error'] = null;
        endif; ?>

<?php 
// Xử lý redirect sau khi xóa dữ liệu: chuyển trang ngay, hiển thị toast ở lần load tiếp theo
if (isset($_SESSION['attendance_deleted']) && $_SESSION['attendance_deleted']) {
    $redirectUrl = $_SESSION['attendance_redirect_url'] ?? 'index.php?attendance&page=1';
    // Giữ attendance_deleted_toast để hiển thị sau redirect
    unset($_SESSION['attendance_deleted']); // tránh loop
    unset($_SESSION['attendance_redirect_url']);
?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    try {
        window.location.href = <?= json_encode($redirectUrl, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    } catch (e) {}
});
</script>
<?php } ?>

<?php 
// Xử lý redirect sau khi xóa dữ liệu máy chấm công: chuyển trang ngay, hiển thị toast ở lần load tiếp theo
if (isset($_SESSION['attendance_device_deleted']) && $_SESSION['attendance_device_deleted']) {
    $redirectUrl = $_SESSION['attendance_redirect_url'] ?? 'index.php?attendance&page=1';
    // Giữ attendance_device_deleted_toast để hiển thị sau redirect
    unset($_SESSION['attendance_device_deleted']); // tránh loop
    unset($_SESSION['attendance_redirect_url']);
?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    try {
        window.location.href = <?= json_encode($redirectUrl, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    } catch (e) {}
});
</script>
<?php } ?>

<?php 
// Xử lý redirect sau khi có lỗi xóa dữ liệu máy chấm công (nhưng giữ lại cờ error để hiển thị toast)
$__att_should_redirect_device_error = false;
if (isset($_SESSION['attendance_device_delete_error']) && isset($_SESSION['attendance_redirect_url']) && !isset($_GET['att_del'])) {
    $redirectUrl = $_SESSION['attendance_redirect_url'];
    $__att_should_redirect_device_error = true;
    unset($_SESSION['attendance_redirect_url']);
}
if ($__att_should_redirect_device_error) {
?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    try {
        window.location.href = <?= json_encode($redirectUrl, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    } catch (e) {}
});
</script>
<?php } ?>

<?php
// Xử lý redirect + toast sau khi cập nhật giờ (update time)
$__att_edit_redirecting = false;
if (!empty($_SESSION['attendance_edit_success_pending'])) {
    $__att_edit_redirecting = true;
    $redirectUrl = $_SESSION['attendance_edit_redirect_url'] ?? 'index.php?attendance&page=1';
    unset($_SESSION['attendance_edit_success_pending']);
?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    try {
        window.location.href = <?= json_encode($redirectUrl, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    } catch (e) {}
});
</script>
<?php } ?>

<?php
// Hiển thị toast cập nhật giờ sau khi reload (chỉ khi không còn redirect pending)
$editToastMsg = null;
// #region agent log
$has_edit_toast_before = !empty($_SESSION['attendance_edit_toast']);
$has_fetch_done_before = !empty($__att_fetch_done) && !empty($__att_success_count) && $__att_success_count > 0;
// Log all session variables related to export and toast
$all_export_session_vars = [];
foreach ($_SESSION as $key => $value) {
    if (stripos($key, 'export') !== false || stripos($key, 'toast') !== false || stripos($key, 'success') !== false) {
        $all_export_session_vars[$key] = is_string($value) ? substr($value, 0, 100) : (is_bool($value) ? ($value ? 'true' : 'false') : gettype($value));
    }
}
file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.time().'_check_all_toast_vars','timestamp'=>time()*1000,'location'=>'profile_attendance.php:2796','message'=>'Checking all export/toast session variables','data'=>['has_edit_toast'=>$has_edit_toast_before,'has_fetch_done'=>$has_fetch_done_before,'is_redirecting'=>$__att_edit_redirecting,'fetch_count'=>$__att_success_count ?? 0,'all_export_vars'=>$all_export_session_vars],'sessionId'=>'debug-session','runId'=>'run2','hypothesisId'=>'A,B,C,D,E'])."\n", FILE_APPEND);
// #endregion
if (!$__att_edit_redirecting && !empty($_SESSION['attendance_edit_toast'])) {
    $editToastMsg = $_SESSION['attendance_edit_toast'];
    unset($_SESSION['attendance_edit_toast']);
}
if (!empty($editToastMsg)):
?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    try {
        // #region agent log
        fetch('http://127.0.0.1:7242/ingest/8f5276d8-e618-4f6a-9932-e03cf8afed36',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'profile_attendance.php:2803','message':'Update time toast DOMContentLoaded triggered','data':{'msg_length':<?= strlen($editToastMsg) ?>,'timestamp':Date.now()},sessionId:'debug-session',runId:'run1',hypothesisId:'A,B,D'})}).catch(()=>{});
        // #endregion
        var title = (window.__MESSAGES__ && window.__MESSAGES__['success_notification_title']) ? window.__MESSAGES__['success_notification_title'] : 'THÔNG BÁO';
        var msg = <?= json_encode($editToastMsg, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        var body = '<div class="success-header">' + title + '</div>' + msg;
        var tries = 0;
        var timer = setInterval(function(){
            tries++;
            if (typeof window.showToast === 'function') {
                clearInterval(timer);
                // #region agent log
                fetch('http://127.0.0.1:7242/ingest/8f5276d8-e618-4f6a-9932-e03cf8afed36',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'profile_attendance.php:2813','message':'About to show update time toast','data':{'tries':tries,'timestamp':Date.now()},sessionId:'debug-session',runId:'run1',hypothesisId:'D'})}).catch(()=>{});
                // #endregion
                window.showToast('success', body);
            } else if (tries > 30) { // ~3s
                clearInterval(timer);
                alert(msg);
            }
        }, 100);
    } catch(e) {}
});
</script>
<?php endif; ?>

<?php
// Hiển thị thông báo xóa thành công sau khi đã redirect sang trang mới
// IMPORTANT: Only show toast on GET request AFTER redirect (same fix as device deletion)
$__att_is_get_request_table = ($_SERVER['REQUEST_METHOD'] === 'GET');
$__att_has_delete_flag_in_url_table = (isset($_GET['att_del']) && $_GET['att_del'] == '1');
$__att_should_show_deleted_toast = (
    $__att_is_get_request_table &&  // Only on GET request (destination page after redirect)
    $__att_has_delete_flag_in_url_table &&  // URL has att_del=1 flag
    (empty($__att_fetch_done)) && 
    (!empty($_SESSION['attendance_deleted_toast']))
);
if (!empty($_SESSION['attendance_deleted_toast'])) {
    // CRITICAL: Only unset on GET request (destination page), NOT on POST page (redirect trigger)
    if ($__att_is_get_request_table) {
        unset($_SESSION['attendance_deleted_toast']);
    }
}
if ($__att_should_show_deleted_toast) {
?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    try {
        var title = (window.__MESSAGES__ && window.__MESSAGES__['success_notification_title']) ? window.__MESSAGES__['success_notification_title'] : 'THÔNG BÁO';
        var msg = (window.__MESSAGES__ && window.__MESSAGES__['attendance_success_deleted']) ? window.__MESSAGES__['attendance_success_deleted'] : 'Đã xóa toàn bộ dữ liệu chấm công.';
        var body = '<div class="success-header">' + title + '</div>' + msg;
        // Đợi showToast sẵn sàng (giống cách toast xuất dữ liệu)
        var tries = 0;
        var timer = setInterval(function(){
            tries++;
            if (typeof window.showToast === 'function') {
                clearInterval(timer);
                window.showToast('success', body);
            } else if (tries > 30) { // ~3s
                clearInterval(timer);
                alert(msg);
            }
        }, 100);
    } catch (e) {}
});
</script>
<?php } ?>

<?php
// Hiển thị thông báo xóa dữ liệu máy chấm công thành công
// IMPORTANT: Only show toast on GET request AFTER redirect (not on POST page)
$__att_has_delete_flag_in_url = (isset($_GET['att_del']) && $_GET['att_del'] == '1');
$__att_is_get_request = ($_SERVER['REQUEST_METHOD'] === 'GET');
$__att_should_show_device_deleted_toast = (
    $__att_is_get_request &&  // Only on GET request (destination page after redirect)
    $__att_has_delete_flag_in_url &&  // URL has att_del=1 flag
    (empty($__att_fetch_done)) && 
    (!empty($_SESSION['attendance_device_deleted_toast']))
);
$__att_device_deleted_name = '';
$__att_device_deleted_ip = '';
if (!empty($_SESSION['attendance_device_deleted_toast'])) {
    $__att_device_deleted_name = $_SESSION['attendance_device_deleted_name'] ?? '';
    $__att_device_deleted_ip = $_SESSION['attendance_device_deleted_ip'] ?? '';
    // CRITICAL: Only unset on GET request (destination page), NOT on POST page (redirect trigger)
    // This preserves session vars through the redirect
    if ($__att_is_get_request) {
        unset($_SESSION['attendance_device_deleted_toast'], $_SESSION['attendance_device_deleted'], $_SESSION['attendance_device_deleted_name'], $_SESSION['attendance_device_deleted_ip']);
    }
}
if ($__att_should_show_device_deleted_toast) {
?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    try {
        var title = (window.__MESSAGES__ && window.__MESSAGES__['success_notification_title']) ? window.__MESSAGES__['success_notification_title'] : 'THÔNG BÁO';
        var deviceName = <?= json_encode($__att_device_deleted_name, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        var deviceIp = <?= json_encode($__att_device_deleted_ip, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        var msgTemplate = (window.__MESSAGES__ && window.__MESSAGES__['attendance_success_device_deleted']) ? window.__MESSAGES__['attendance_success_device_deleted'] : 'Đã xóa dữ liệu từ máy chấm công <strong>{device}</strong> ({ip})';
        var msg = msgTemplate.replace('{device}', deviceName).replace('{ip}', deviceIp);
        var body = '<div class="success-header">' + title + '</div>' + msg;
        var tries = 0;
        var timer = setInterval(function(){
            tries++;
            if (typeof window.showToast === 'function') {
                clearInterval(timer);
                window.showToast('success', body);
            } else if (tries > 30) {
                clearInterval(timer);
                alert('Đã xóa dữ liệu từ máy chấm công ' + deviceName);
            }
        }, 100);
    } catch (e) {}
});
</script>
<?php } ?>

<?php
// Hiển thị thông báo lỗi khi xóa dữ liệu máy chấm công
$__att_should_show_device_delete_error = (
    (empty($__att_fetch_done)) && 
    (!empty($_SESSION['attendance_device_delete_error']))
);
$__att_device_delete_error_msg = '';
if (!empty($_SESSION['attendance_device_delete_error'])) {
    $__att_device_delete_error_msg = $_SESSION['attendance_device_delete_error_msg'] ?? 'Không thể xóa dữ liệu từ máy chấm công.';
    unset($_SESSION['attendance_device_delete_error'], $_SESSION['attendance_device_delete_error_msg']);
}
if ($__att_should_show_device_delete_error) {
?>
<script>
document.addEventListener('DOMContentLoaded', function(){
    try {
        var title = 'LỖI';
        var msg = <?= json_encode($__att_device_delete_error_msg, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        var body = '<div class="error-header">' + title + '</div>' + msg;
        var tries = 0;
        var timer = setInterval(function(){
            tries++;
            if (typeof window.showToast === 'function') {
                clearInterval(timer);
                window.showToast('error', body);
            } else if (tries > 30) {
                clearInterval(timer);
                alert(msg);
            }
        }, 100);
    } catch (e) {}
});
</script>
<?php } ?>
        
        <?php
        // Hiển thị thông báo sau khi lọc trùng
        if (isset($_SESSION['attendance_filter_duplicate_success']) && $_SESSION['attendance_filter_duplicate_success']) {
            $removedCount = isset($_SESSION['attendance_filter_duplicate_removed']) ? (int)$_SESSION['attendance_filter_duplicate_removed'] : 0;
            $redirectUrl = $_SESSION['attendance_filter_duplicate_redirect_url'] ?? 'index.php?attendance&page=1';
            $needsReload = isset($_SESSION['attendance_filter_duplicate_needs_reload']) ? (bool)$_SESSION['attendance_filter_duplicate_needs_reload'] : false;
            if ($needsReload) {
                $_SESSION['attendance_filter_duplicate_needs_reload'] = false;
            } else {
            unset($_SESSION['attendance_filter_duplicate_success']);
            unset($_SESSION['attendance_filter_duplicate_removed']);
            unset($_SESSION['attendance_filter_duplicate_redirect_url']);
                unset($_SESSION['attendance_filter_duplicate_needs_reload']);
            }
        ?>
        <?php if ($needsReload): ?>
        <script>
        document.addEventListener('DOMContentLoaded', function(){
            try {
                window.location.href = <?= json_encode($redirectUrl, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
            } catch (e) {}
        });
        </script>
        <?php else: ?>
        <script>
        document.addEventListener('DOMContentLoaded', function(){
            try {
                var title = (window.__MESSAGES__ && window.__MESSAGES__['success_notification_title']) ? window.__MESSAGES__['success_notification_title'] : 'THÔNG BÁO';
                var msg = (window.__MESSAGES__ && window.__MESSAGES__['attendance_filter_duplicate_success']) ? window.__MESSAGES__['attendance_filter_duplicate_success'] : 'Đã lọc trùng dữ liệu chấm công.';
                if (<?= $removedCount ?> > 0) {
                    msg = msg.replace('{count}', <?= $removedCount ?>);
                }
                var successMsg = '<div class="success-header">' + title + '</div>' + msg;
                if (window.showToast) {
                    window.showToast('success', successMsg, 3000);
                } else {
                    alert(msg);
                }
            } catch (e) {}
        });
        </script>
        <?php endif; ?>
        <?php } ?>
        
        <?php
        // Hiển thị lỗi nếu không có dữ liệu để lọc trùng
        if (isset($_SESSION['attendance_filter_duplicate_error'])) {
            $errorMsg = $_SESSION['attendance_filter_duplicate_error'];
            unset($_SESSION['attendance_filter_duplicate_error']);
        ?>
        <script>
        document.addEventListener('DOMContentLoaded', function(){
            try {
                var title = (window.__MESSAGES__ && window.__MESSAGES__['error_notification_title']) ? window.__MESSAGES__['error_notification_title'] : 'THÔNG BÁO';
                var errorMsg = <?= json_encode($errorMsg, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
                var errorDisplay = '<div class="error-header">' + title + '</div>' + errorMsg;
                if (window.showToast) {
                    window.showToast('error', errorDisplay, 3000);
                } else {
                    alert(errorMsg);
                }
            } catch (e) {}
        });
        </script>
        <?php } ?>

        <script>
        // Set language and tooltips for JavaScript
        window.APP_LANG = '<?= ($_SESSION['lang'] ?? 'vn') ?>';
        // Function to get current language from various sources
        window.getCurrentLanguage = function() {
            // Check URL parameter first
            const urlParams = new URLSearchParams(window.location.search);
            const urlLang = urlParams.get('lang');
            if (urlLang && ['vn', 'eng'].includes(urlLang)) {
                return urlLang;
            }
            
            // Check session language from PHP
            if (window.APP_LANG && ['vn', 'eng'].includes(window.APP_LANG)) {
                return window.APP_LANG;
            }
            
            // Default to Vietnamese
            return 'vn';
        };
        // Load messages for JavaScript
        window.__MESSAGES__ = <?= json_encode($messages, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) ?>;
        </script>

        <?php 
        // Chỉ hiển thị toast fetch nếu không có toast "update time" và không có flag clear fetch toast
        // #region agent log
        $check_fetch_done = $__att_fetch_done;
        $check_success_count = $__att_success_count;
        $check_edit_toast = empty($editToastMsg);
        $check_clear_flag = empty($_SESSION['attendance_clear_fetch_toast']);
        file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.microtime(true).'_toast_condition_check','timestamp'=>microtime(true)*1000,'location'=>'profile_attendance.php:3014','message'=>'Checking if should show fetch toast','data'=>['fetch_done'=>$check_fetch_done,'success_count'=>$check_success_count,'no_edit_toast'=>$check_edit_toast,'no_clear_flag'=>$check_clear_flag,'has_clear_flag_in_session'=>isset($_SESSION['attendance_clear_fetch_toast'])],'sessionId'=>'debug-session','hypothesisId'=>'C,D,E'])."\n", FILE_APPEND);
        // #endregion
        $should_show_fetch_toast = $__att_fetch_done && $__att_success_count > 0 && empty($editToastMsg) && empty($_SESSION['attendance_clear_fetch_toast']);
        // #region agent log
        file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.microtime(true).'_toast_decision','timestamp'=>microtime(true)*1000,'location'=>'profile_attendance.php:3018','message'=>'Toast decision made','data'=>['should_show'=>$should_show_fetch_toast],'sessionId'=>'debug-session','hypothesisId'=>'D'])."\n", FILE_APPEND);
        // #endregion
        // Clear flag sau khi kiểm tra - CHỈ clear khi không có POST fetch để tránh clear sớm khi browser re-submit form
        if (isset($_SESSION['attendance_clear_fetch_toast']) && empty($_POST['fetch_attendance'])) {
            // #region agent log
            file_put_contents('t:\Xampp\htdocs\Luna Project\.cursor\debug.log', json_encode(['id'=>'log_'.microtime(true).'_second_clear_attempt','timestamp'=>microtime(true)*1000,'location'=>'profile_attendance.php:3023','message'=>'Second clear attempt - safe to clear (no POST fetch)','data'=>['has_flag'=>true,'has_post_fetch'=>!empty($_POST['fetch_attendance'])],'sessionId'=>'debug-session','hypothesisId'=>'B'])."\n", FILE_APPEND);
            // #endregion
            unset($_SESSION['attendance_clear_fetch_toast']);
        }
        if ($should_show_fetch_toast): ?>
        <script>
        document.addEventListener('DOMContentLoaded', function(){
            try {
                // #region agent log
                fetch('http://127.0.0.1:7242/ingest/8f5276d8-e618-4f6a-9932-e03cf8afed36',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'profile_attendance.php:2951','message':'Fetch records toast DOMContentLoaded triggered','data':{'has_edit_toast':<?= !empty($editToastMsg) ? 'true' : 'false' ?>,'edit_toast_msg':<?= !empty($editToastMsg) ? json_encode($editToastMsg, JSON_UNESCAPED_UNICODE) : 'null' ?>,'timestamp':Date.now()},sessionId:'debug-session','runId':'run1','hypothesisId':'A,B,D'})}).catch(()=>{});
                // #endregion
                var hasEditToast = <?= !empty($editToastMsg) ? 'true' : 'false' ?>;
                // Nếu có toast "update time", delay toast "fetch records" để ưu tiên hiển thị toast "update time" trước
                var delayMs = hasEditToast ? 2000 : 0; // Delay 2 giây nếu có toast update time
                setTimeout(function() {
                    var cnt = <?= (int)$__att_success_count ?>;
                    var dev = <?= json_encode($__att_device, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
                    var ip  = <?= json_encode($__att_device_ipport, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
                    var title = (window.__MESSAGES__ && window.__MESSAGES__['success_notification_title']) ? window.__MESSAGES__['success_notification_title'] : 'THÔNG BÁO';
            var msgTemplate = (window.__MESSAGES__ && window.__MESSAGES__['attendance_success_fetched_records']) ? window.__MESSAGES__['attendance_success_fetched_records'] : 'Đã lấy <strong>{count}</strong> bản ghi từ {device} ({ip})';
                    var body = msgTemplate.replace('{count}', cnt).replace('{device}', dev || '').replace('{ip}', ip);
                    // #region agent log
                    fetch('http://127.0.0.1:7242/ingest/8f5276d8-e618-4f6a-9932-e03cf8afed36',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'profile_attendance.php:2960','message':'About to show fetch records toast','data':{'has_showToast':typeof window.showToast === 'function','has_edit_toast':hasEditToast,'delay_ms':delayMs,'timestamp':Date.now()},sessionId:'debug-session','runId':'run1','hypothesisId':'C,E'})}).catch(()=>{});
                    // #endregion
                    if (typeof window.showToast === 'function') {
                        window.showToast('success', '<div class="success-header">' + title + '</div>' + body);
                        // Set flag trong session để clear fetch done khi reload, tránh hiển thị lại toast
                        // Gửi request để set session flag
                        fetch(window.location.href, {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/x-www-form-urlencoded',
                                'X-Requested-With': 'XMLHttpRequest'
                            },
                            body: 'set_clear_fetch_toast=1'
                        }).catch(function() {});
                    }
                }, delayMs);
                
                // Redirect về page=1 sau khi tải dữ liệu thành công
                var urlParams = new URLSearchParams(window.location.search);
                var currentPage = urlParams.get('page');
                if (currentPage && currentPage !== '1') {
                    // Cập nhật page thành 1, giữ nguyên các tham số khác
                    urlParams.set('page', '1');
                    var newUrl = window.location.pathname + '?' + urlParams.toString();
                    // Sử dụng replace để không tạo history entry mới
                    window.location.replace(newUrl);
                }
            } catch(e) {}
        });
        </script>
        <?php endif; ?>

        <!-- Simple Search Bar -->
        <div class="search-filter-section" style="padding: 16px; background: rgba(255, 255, 255, 0.02); border-bottom: 1px solid rgba(255, 255, 255, 0.1); display: flex; justify-content: center;">
            <form id="attendance-search-form" autocomplete="on" style="display: flex; align-items: center; max-width: 600px; width: 100%;">
                <div class="input-wrap" style="flex: 1; position: relative;">
                    <span class="icon" style="position: absolute; left: 12px; top: 50%; transform: translateY(-50%); opacity: 0.5; pointer-events: none; z-index: 1;">
                        <svg viewBox="0 0 24 24" style="width: 18px; height: 18px; fill: currentColor;">
                            <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
                        </svg>
                    </span>
                    <input type="text" 
                           id="search-query-attendance" 
                           name="search_query" 
                           autocomplete="on" autocorrect="off" autocapitalize="none" spellcheck="false" role="searchbox" inputmode="search" enterkeyhint="search"
                           placeholder="<?= htmlspecialchars($messages['attendance_search_placeholder'] ?? 'Tìm kiếm theo mã số nhân viên, họ tên, kiểu xác thực...', ENT_QUOTES, 'UTF-8') ?>" 
                           value="<?= htmlspecialchars($searchQuery, ENT_QUOTES, 'UTF-8') ?>"
                           style="width: 100%; padding: 10px 50px 10px 42px; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 6px; color: #fff; font-size: 12px; transition: all 0.3s ease;">
                    <button type="submit" 
                            id="attendance-search-submit-btn"
                            style="position: absolute; right: 8px; top: 50%; transform: translateY(-50%); background: #7adcc9; border: none; border-radius: 4px; padding: 6px 10px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; z-index: 10; pointer-events: auto; width: 34px; height: 28px;"
                            title="<?= htmlspecialchars($messages['search_button'] ?? 'Tìm kiếm', ENT_QUOTES, 'UTF-8') ?>">
                        <svg viewBox="0 0 24 24" style="width: 16px; height: 16px; fill: #1a3a3a;">
                            <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
                        </svg>
                    </button>
                </div>
            </form>
        </div>
        <?php if (!empty($searchQuery)): ?>
        <script>
        document.addEventListener('DOMContentLoaded', function() {
            try {
                var count = <?= (int)($totalItems ?? 0) ?>;
                var q = "<?= htmlspecialchars($searchQuery, ENT_QUOTES, 'UTF-8') ?>";
                var foundText = "<?= htmlspecialchars($messages['search_results_found'] ?? 'Tìm thấy', ENT_QUOTES, 'UTF-8') ?>";
                var forText = "<?= htmlspecialchars($messages['search_results_for'] ?? 'kết quả cho', ENT_QUOTES, 'UTF-8') ?>";
                var successTitle = (window.__MESSAGES__ && window.__MESSAGES__['success_notification_title']) ? window.__MESSAGES__['success_notification_title'] : 'THÔNG BÁO';
                var errorTitle = (window.__MESSAGES__ && window.__MESSAGES__['error_notification_title']) ? window.__MESSAGES__['error_notification_title'] : 'THÔNG BÁO';
                var msg = foundText + ' <strong style="color:#7adcc9">' + count + '</strong> ' + forText + ' "<strong>' + q + '</strong>"';
                if (typeof window.showToast === 'function') {
                    if (count > 0) {
                        window.showToast('success', '<div class="success-header">' + successTitle + '</div>' + msg);
                    } else {
                        window.showToast('error', '<div class="error-header">' + errorTitle + '</div>' + msg);
                    }
                }
            } catch (_) {}
        });
        </script>
        <?php endif; ?>

        <script>
        // Simple Search Form functionality for Attendance Data
        document.addEventListener('DOMContentLoaded', function() {
            const searchForm = document.getElementById('attendance-search-form');
            const searchInput = document.getElementById('search-query-attendance');
            const searchButton = document.getElementById('attendance-search-submit-btn');
            
            // Handle search form submission
            if (searchForm && searchInput) {
                searchForm.addEventListener('submit', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    
                    const query = searchInput.value.trim();
                    const urlParams = new URLSearchParams(window.location.search);
                    const device = urlParams.get('device') || '';
                    const pageSize = urlParams.get('page_size') || '';
                    
                    let url = 'index.php?attendance';
                    if (device) url += '&device=' + encodeURIComponent(device);
                    if (pageSize) url += '&page_size=' + encodeURIComponent(pageSize);
                    if (query) {
                        url += '&search_query=' + encodeURIComponent(query);
                    }
                    
                    window.location.href = url;
                });
                
                // Also handle button click directly
                if (searchButton) {
                    searchButton.addEventListener('click', function(e) {
                        e.preventDefault();
                        e.stopPropagation();
                        
                        const query = searchInput.value.trim();
                        const urlParams = new URLSearchParams(window.location.search);
                        const device = urlParams.get('device') || '';
                        const pageSize = urlParams.get('page_size') || '';
                        
                        let url = 'index.php?attendance';
                        if (device) url += '&device=' + encodeURIComponent(device);
                        if (pageSize) url += '&page_size=' + encodeURIComponent(pageSize);
                        if (query) {
                            url += '&search_query=' + encodeURIComponent(query);
                        }
                        
                        window.location.href = url;
                    });
                    
                    // Add mousedown event as backup
                    searchButton.addEventListener('mousedown', function(e) {
                        e.preventDefault();
                        e.stopPropagation();
                        
                        const query = searchInput.value.trim();
                        const urlParams = new URLSearchParams(window.location.search);
                        const device = urlParams.get('device') || '';
                        const pageSize = urlParams.get('page_size') || '';
                        
                        let url = 'index.php?attendance';
                        if (device) url += '&device=' + encodeURIComponent(device);
                        if (pageSize) url += '&page_size=' + encodeURIComponent(pageSize);
                        if (query) {
                            url += '&search_query=' + encodeURIComponent(query);
                        }
                        
                        window.location.href = url;
                    });
                }
            }
            
            // Add focus effect to input
            if (searchInput) {
                searchInput.addEventListener('focus', function() {
                    this.style.borderColor = 'rgba(124, 220, 201, 0.5)';
                    this.style.boxShadow = '0 0 0 3px rgba(124, 220, 201, 0.1)';
                });
                
                searchInput.addEventListener('blur', function() {
                    this.style.borderColor = 'rgba(255, 255, 255, 0.1)';
                    this.style.boxShadow = 'none';
                });
                
                // Allow Enter key to submit
                searchInput.addEventListener('keypress', function(e) {
                    if (e.key === 'Enter') {
                        e.preventDefault();
                        const query = searchInput.value.trim();
                        const urlParams = new URLSearchParams(window.location.search);
                        const device = urlParams.get('device') || '';
                        const pageSize = urlParams.get('page_size') || '';
                        
                        let url = 'index.php?attendance';
                        if (device) url += '&device=' + encodeURIComponent(device);
                        if (pageSize) url += '&page_size=' + encodeURIComponent(pageSize);
                        if (query) {
                            url += '&search_query=' + encodeURIComponent(query);
                        }
                        
                        window.location.href = url;
                    }
                });
            }
            
            // Add hover effect to search button
            if (searchButton) {
                searchButton.addEventListener('mouseenter', function() {
                    this.style.background = '#92e4d4';
                    this.style.transform = 'translateY(-50%) scale(1.05)';
                });
                
                searchButton.addEventListener('mouseleave', function() {
                    this.style.background = '#7adcc9';
                    this.style.transform = 'translateY(-50%)';
                });
            }
        });
        </script>

        <div class="table-wrapper">
            <table class="data-table data-table--responsive" id="attendance-table">
                <thead>
                    <tr>
                        <th><?= htmlspecialchars($messages['attendance_col_employee_id'] ?? 'Mã nhân viên', ENT_QUOTES, 'UTF-8') ?></th>
                        <th><?= htmlspecialchars($messages['attendance_col_full_name'] ?? 'Họ tên', ENT_QUOTES, 'UTF-8') ?></th>
                        <th style="display: none;"><?= htmlspecialchars($messages['attendance_col_time'] ?? 'Thời gian', ENT_QUOTES, 'UTF-8') ?></th>
                        <th><?= htmlspecialchars($messages['attendance_col_date'] ?? 'Ngày', ENT_QUOTES, 'UTF-8') ?></th>
                        <th><?= htmlspecialchars($messages['attendance_col_hour'] ?? 'Giờ', ENT_QUOTES, 'UTF-8') ?></th>
                        <th><?= htmlspecialchars($messages['attendance_col_lan'] ?? 'Lần', ENT_QUOTES, 'UTF-8') ?></th>
                        <th><?= htmlspecialchars($messages['attendance_col_auth_type'] ?? 'Kiểu xác thực', ENT_QUOTES, 'UTF-8') ?></th>
                        <th><?= htmlspecialchars($messages['attendance_col_machine_name'] ?? 'Tên máy', ENT_QUOTES, 'UTF-8') ?></th>
                        <th><?= htmlspecialchars($messages['attendance_col_actions'] ?? 'Thao tác', ENT_QUOTES, 'UTF-8') ?></th>
                    </tr>
                </thead>
                <tbody>
                    <?php if (!empty($pageLogs)): ?>
                        <?php 
                        $normalizeDatetime = function($log) {
                            $datetime = trim((string)($log['datetime'] ?? ''));
                            $date = trim((string)($log['date'] ?? ''));
                            $time = trim((string)($log['time'] ?? ''));
                            if ($datetime === '' && $date !== '' && $time !== '') {
                                $datetime = $date . ' ' . $time;
                            }
                            return $datetime;
                        };
                        $buildLogKey = function($log) use ($normalizeDatetime) {
                            $pin = (string)($log['pin'] ?? '');
                            $date = (string)($log['date'] ?? '');
                            $datetime = $normalizeDatetime($log);
                            return md5($pin . '|' . $date . '|' . $datetime . '|' . ($log['verify'] ?? '') . '|' . ($log['device_name'] ?? ''));
                        };

                        // Ưu tiên dùng lan_map đã lưu sau khi lọc trùng để giữ nguyên Lần cho dữ liệu cũ khi ghi tiếp
                        $lanLookup = [];
                        if ($attendanceLanReady && !empty($_SESSION['attendance_lan_map']) && is_array($_SESSION['attendance_lan_map'])) {
                            $lanLookup = $_SESSION['attendance_lan_map'];
                        } elseif ($attendanceLanReady) {
                            // Nếu chưa có map (trường hợp lần đầu sau lọc trùng), tính và lưu lại
                            $lanBuckets = [];
                            foreach ($filteredLogs as $log) {
                                $pin = (string)($log['pin'] ?? '');
                                $date = (string)($log['date'] ?? '');
                                $datetime = $normalizeDatetime($log);
                                if ($pin !== '' && $date !== '') {
                                    $key = $pin . '|' . $date;
                                    if (!isset($lanBuckets[$key])) {
                                        $lanBuckets[$key] = [];
                                    }
                                    $lanBuckets[$key][] = [
                                        'datetime' => $datetime,
                                        'log' => $log
                                    ];
                                }
                            }
                            foreach ($lanBuckets as &$group) {
                                usort($group, function($a, $b) {
                                    $ta = strtotime($a['datetime']);
                                    if ($ta === false && !empty($a['log']['date']) && !empty($a['log']['time'])) {
                                        $ta = strtotime($a['log']['date'] . ' ' . $a['log']['time']);
                                    }
                                    $tb = strtotime($b['datetime']);
                                    if ($tb === false && !empty($b['log']['date']) && !empty($b['log']['time'])) {
                                        $tb = strtotime($b['log']['date'] . ' ' . $b['log']['time']);
                                    }
                                    if ($ta === false) $ta = 0;
                                    if ($tb === false) $tb = 0;
                                    return ($ta < $tb) ? -1 : (($ta > $tb) ? 1 : 0);
                                });
                                $lanCounter = 1;
                                foreach ($group as $item) {
                                    $lanLookup[$buildLogKey($item['log'])] = $lanCounter++;
                                }
                            }
                            unset($group);
                            $_SESSION['attendance_lan_map'] = $lanLookup;
                        }
                        ?>
                        <?php foreach ($pageLogs as $row): ?>
                            <?php
                            $logKey = $buildLogKey($row);
                            $lan = ($attendanceLanReady && isset($lanLookup[$logKey])) ? $lanLookup[$logKey] : '';
                            ?>
                            <tr>
                                <td data-label="<?= htmlspecialchars($messages['attendance_col_employee_id'] ?? 'Mã nhân viên', ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($row['pin'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
                                <td data-label="<?= htmlspecialchars($messages['attendance_col_full_name'] ?? 'Họ tên', ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($row['name'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
                                <td data-label="<?= htmlspecialchars($messages['attendance_col_time'] ?? 'Thời gian', ENT_QUOTES, 'UTF-8') ?>" style="display: none;"><?= htmlspecialchars($row['datetime'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
                                <td data-label="<?= htmlspecialchars($messages['attendance_col_date'] ?? 'Ngày', ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($row['date'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
                                <td data-label="<?= htmlspecialchars($messages['attendance_col_hour'] ?? 'Giờ', ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($row['time'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
                                <td data-label="<?= htmlspecialchars($messages['attendance_col_lan'] ?? 'Lần', ENT_QUOTES, 'UTF-8') ?>"><?= $lan ?></td>
                                <td data-label="<?= htmlspecialchars($messages['attendance_col_auth_type'] ?? 'Kiểu xác thực', ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($verifyMap[(string)($row['verify'] ?? '')] ?? (string)($row['verify'] ?? ''), ENT_QUOTES, 'UTF-8') ?></td>
                                <td data-label="<?= htmlspecialchars($messages['attendance_col_machine_name'] ?? 'Tên máy', ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($row['device_name'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
                                <td data-label="<?= htmlspecialchars($messages['attendance_col_actions'] ?? 'Thao tác', ENT_QUOTES, 'UTF-8') ?>">
                                <div class="att-actions">
                                    <button type="button"
                                            class="att-btn-icon att-edit-btn"
                                            title="<?= htmlspecialchars($messages['attendance_btn_edit'] ?? 'Sửa', ENT_QUOTES, 'UTF-8') ?>"
                                            data-att-edit-pin="<?= htmlspecialchars($row['pin'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
                                            data-att-edit-name="<?= htmlspecialchars($row['name'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
                                            data-att-edit-datetime="<?= htmlspecialchars($row['datetime'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
                                            data-att-edit-date="<?= htmlspecialchars($row['date'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
                                            data-att-edit-time="<?= htmlspecialchars($row['time'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
                                    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                        <path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 1 1 3 3L7 19l-4 1 1-4 12.5-12.5z"/>
                                    </svg>
                                    </button>
                                </div>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                        <tr>
                            <td colspan="9" style="text-align:center;opacity:.7;"><?= htmlspecialchars($messages['attendance_no_data'] ?? 'Chưa có dữ liệu hiển thị', ENT_QUOTES, 'UTF-8') ?></td>
                        </tr>
                    <?php endif; ?>
                </tbody>
            </table>
        </div>
        <style>
          /* Đổi màu chữ cho dòng có Kiểu xác thực = '-----' */
          .attendance-panel .att-row-dash { background-color: transparent !important; color: #1AC6D9 !important; }
          .attendance-panel .att-row-dash td { color: #1AC6D9 !important; }
          .attendance-panel .att-row-dash td * { color: #1AC6D9 !important; }
          
          /* Mobile/Responsive styles - đảm bảo màu chữ áp dụng trên mobile với specificity cao */
          @media (max-width: 768px) {
            .attendance-panel .att-row-dash { color: #1AC6D9 !important; }
            .attendance-panel .att-row-dash td { color: #1AC6D9 !important; }
            .attendance-panel .att-row-dash td * { color: #1AC6D9 !important; }
            .attendance-panel table.data-table--responsive .att-row-dash { color: #1AC6D9 !important; }
            .attendance-panel table.data-table--responsive .att-row-dash td { color: #1AC6D9 !important; }
            .attendance-panel table.data-table--responsive .att-row-dash td * { color: #1AC6D9 !important; }
            /* Override ::before pseudo-element color for labels on mobile */
            .attendance-panel table.data-table--responsive .att-row-dash td::before { 
              color: #1AC6D9 !important; 
            }
            /* Maximum specificity for mobile */
            html body .attendance-panel table.data-table--responsive tbody .att-row-dash { 
              color: #1AC6D9 !important; 
            }
            html body .attendance-panel table.data-table--responsive tbody .att-row-dash td { 
              color: #1AC6D9 !important; 
            }
            html body .attendance-panel table.data-table--responsive tbody .att-row-dash td::before { 
              color: #1AC6D9 !important; 
            }
            html body .attendance-panel table.data-table--responsive tbody .att-row-dash td * { 
              color: #1AC6D9 !important; 
            }
          }
        </style>
        <script>
          // Hàm kiểm tra và đổi màu dòng có Kiểu xác thực = '-----'
          function highlightAttendanceRowsDash(){
            var table = document.getElementById('attendance-table');
            if (!table) return;
            var authTypeLabel = (window.__MESSAGES__ && window.__MESSAGES__['attendance_col_auth_type']) ? window.__MESSAGES__['attendance_col_auth_type'] : 'Kiểu xác thực';
            var rows = table.querySelectorAll('tbody tr');
            var isMobile = window.innerWidth <= 768;
            
            rows.forEach(function(tr){
              var cell = tr.querySelector('td[data-label="' + authTypeLabel + '"]');
              if (!cell) return;
              var txt = (cell.textContent || '').trim();
              if (txt === '-----') {
                tr.classList.add('att-row-dash');
                // Force apply color on mobile using inline styles for maximum priority
                if (isMobile) {
                  tr.style.setProperty('color', '#1AC6D9', 'important');
                  var tds = tr.querySelectorAll('td');
                  tds.forEach(function(td){
                    td.style.setProperty('color', '#1AC6D9', 'important');
                    // For ::before, we need to inject a style tag since we can't directly style pseudo-elements
                    var cellId = 'att-dash-cell-' + Math.random().toString(36).substr(2, 9);
                    if (!td.id) td.id = cellId;
                    // Inject style for this specific cell's ::before
                    var styleId = 'style-' + cellId;
                    if (!document.getElementById(styleId)) {
                      var style = document.createElement('style');
                      style.id = styleId;
                      style.textContent = '#attendance-table tbody tr.att-row-dash td#' + cellId + '::before { color: #1AC6D9 !important; }';
                      document.head.appendChild(style);
                    }
                  });
                }
              } else {
                tr.classList.remove('att-row-dash');
                if (isMobile) {
                  tr.style.removeProperty('color');
                  var tds = tr.querySelectorAll('td');
                  tds.forEach(function(td){
                    td.style.removeProperty('color');
                    // Remove injected style if exists
                    if (td.id && td.id.startsWith('att-dash-cell-')) {
                      var styleId = 'style-' + td.id;
                      var styleEl = document.getElementById(styleId);
                      if (styleEl) styleEl.remove();
                      td.removeAttribute('id');
                    }
                  });
                }
              }
            });
          }
          
          document.addEventListener('DOMContentLoaded', function(){
            highlightAttendanceRowsDash();
            // Re-run on resize to handle mobile/desktop switch
            var resizeTimeout;
            window.addEventListener('resize', function(){
              clearTimeout(resizeTimeout);
              resizeTimeout = setTimeout(highlightAttendanceRowsDash, 100);
            });
          });
          
          // Re-run after pagination or any table updates
          var observer = new MutationObserver(function(mutations) {
            highlightAttendanceRowsDash();
          });
          
          document.addEventListener('DOMContentLoaded', function() {
            var table = document.getElementById('attendance-table');
            if (table) {
              observer.observe(table, { childList: true, subtree: true });
            }
          });
        </script>

        <?php 
        // Helper function to build pagination URL with search and device params
        function buildAttendancePaginationUrl($page, $pageSize, $searchQuery = '', $device = '') {
            $url = 'index.php?attendance&page=' . (int)$page . '&page_size=' . (int)$pageSize;
            if (!empty($searchQuery)) {
                $url .= '&search_query=' . urlencode($searchQuery);
            }
            if (!empty($device)) {
                $url .= '&device=' . urlencode($device);
            }
            return $url;
        }
        $paginationDevice = isset($_GET['device']) ? (string)$_GET['device'] : '';
        ?>
        <?php if ($totalPages > 1): ?>
        <div class="pagination-wrapper">
            <div class="pagination">
                <?php if ($currentPage > 1): ?>
                    <a href="<?= buildAttendancePaginationUrl($currentPage - 1, $pageSize, $searchQuery, $paginationDevice) ?>" class="pagination-btn pagination-prev">
                        <svg viewBox="0 0 24 24" style="width: 16px; height: 16px; fill: currentColor;">
                            <path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
                        </svg>
                        <?= htmlspecialchars($messages['pagination_previous'] ?? 'Trước', ENT_QUOTES, 'UTF-8') ?>
                    </a>
                <?php endif; ?>

                <div class="pagination-numbers">
                    <?php
                    $startPage = max(1, $currentPage - 2);
                    $endPage = min($totalPages, $currentPage + 2);
                    if ($startPage > 1): ?>
                        <a href="<?= buildAttendancePaginationUrl(1, $pageSize, $searchQuery, $paginationDevice) ?>" class="pagination-number">1</a>
                        <?php if ($startPage > 2): ?>
                            <span class="pagination-ellipsis">...</span>
                        <?php endif; ?>
                    <?php endif; ?>

                    <?php for ($i = $startPage; $i <= $endPage; $i++): ?>
                        <a href="<?= buildAttendancePaginationUrl($i, $pageSize, $searchQuery, $paginationDevice) ?>" class="pagination-number <?php echo ($i === $currentPage ? 'active' : ''); ?>"><?= $i ?></a>
                    <?php endfor; ?>

                    <?php if ($endPage < $totalPages): ?>
                        <?php if ($endPage < $totalPages - 1): ?>
                            <span class="pagination-ellipsis">...</span>
                        <?php endif; ?>
                        <a href="<?= buildAttendancePaginationUrl($totalPages, $pageSize, $searchQuery, $paginationDevice) ?>" class="pagination-number"><?= $totalPages ?></a>
                    <?php endif; ?>
                </div>

                <?php if ($currentPage < $totalPages): ?>
                    <a href="<?= buildAttendancePaginationUrl($currentPage + 1, $pageSize, $searchQuery, $paginationDevice) ?>" class="pagination-btn pagination-next">
                        <?= htmlspecialchars($messages['pagination_next'] ?? 'Sau', ENT_QUOTES, 'UTF-8') ?>
                        <svg viewBox="0 0 24 24" style="width: 16px; height: 16px; fill: currentColor;">
                            <path d="M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z"/>
                        </svg>
                    </a>
                <?php endif; ?>
            </div>
        </div>
        <?php endif; ?>

        <!-- Page size selector (custom select like theme) -->
        <div class="pagination-extras" style="margin: 8px 0 20px; display:flex; justify-content:center;">
            <form id="attendance-page-size-form" method="get" action="index.php">
                <input type="hidden" name="attendance" value="" />
                <input type="hidden" name="page" value="1" />
                <?php if (!empty($searchQuery)): ?>
                    <input type="hidden" name="search_query" value="<?= htmlspecialchars($searchQuery, ENT_QUOTES, 'UTF-8') ?>" />
                <?php endif; ?>
                <?php if (!empty($paginationDevice)): ?>
                    <input type="hidden" name="device" value="<?= htmlspecialchars($paginationDevice, ENT_QUOTES, 'UTF-8') ?>" />
                <?php endif; ?>
                <div class="page-size-pill" style="display:inline-flex; align-items:center; gap:8px; padding:6px 12px; background: rgba(255,255,255,0.03); border:1px solid rgba(255,255,255,0.08); border-radius:10px; white-space:nowrap;">
                    <span style="font-size:12px; color:#9ec9c1; display:inline-block;"><?= htmlspecialchars($messages['attendance_display_rows_per_page'] ?? 'Hiển thị', ENT_QUOTES, 'UTF-8') ?>:</span>
                    <div class="custom-select" id="attendance-pagesize-custom-select" style="display:inline-block;">
                        <button type="button" class="custom-select-toggle" style="min-width:54px; height:28px; line-height:28px; padding:0 28px 0 12px;" data-placeholder="<?= (int)$pageSize ?>" aria-label="<?= htmlspecialchars($messages['attendance_select_rows_per_page'] ?? 'Chọn số dòng mỗi trang', ENT_QUOTES, 'UTF-8') ?>">
                            <?= (int)$pageSize ?>
                        </button>
                        <div class="custom-select-menu" role="listbox">
                            <?php foreach ($allowedPageSizes as $opt): ?>
                                <div class="custom-select-option<?= ($opt === $pageSize ? ' is-selected' : '') ?>" role="option" data-value="<?= (int)$opt ?>"><?= (int)$opt ?></div>
                            <?php endforeach; ?>
                        </div>
                        <input type="hidden" name="page_size" id="attendance-page-size" value="<?= (int)$pageSize ?>" />
                    </div>
                    <span style="font-size:12px; color:#9ec9c1; display:inline-block;"><?= htmlspecialchars($messages['attendance_rows_per_page'] ?? 'dòng/trang', ENT_QUOTES, 'UTF-8') ?></span>
                </div>
            </form>
        </div>
        <script>
        (function(){
            var custom = document.getElementById('attendance-pagesize-custom-select');
            if (!custom) return;
            var toggle = custom.querySelector('.custom-select-toggle');
            var menu = custom.querySelector('.custom-select-menu');
            var hidden = document.getElementById('attendance-page-size');
            var form = document.getElementById('attendance-page-size-form');
            if (!toggle || !menu || !hidden || !form) return;

            var anchorParent = null, anchorNext = null, isPortaled = false;
            var closeOnScroll = null, closeOnResize = null;

            function mountMenu(){
                if (isPortaled) return;
                anchorParent = menu.parentNode;
                anchorNext = menu.nextSibling;
                document.body.appendChild(menu);
                isPortaled = true;
            }
            function unmountMenu(){
                if (!isPortaled) return;
                if (anchorParent){
                    if (anchorNext){ anchorParent.insertBefore(menu, anchorNext); }
                    else { anchorParent.appendChild(menu); }
                }
                isPortaled = false;
            }
            function positionMenu(){
                var r = toggle.getBoundingClientRect();
                var pad = 12;
                var OFFSET_X = 2; // fine-tune horizontally
                var OFFSET_Y = 2; // fine-tune vertically
                var scrollX = (window.pageXOffset || document.documentElement.scrollLeft);
                var scrollY = (window.pageYOffset || document.documentElement.scrollTop);
                var left = Math.floor(scrollX + r.left + OFFSET_X);
                var width = Math.round(r.width);
                if (left < pad) left = pad;
                var viewportWidth = (window.innerWidth || document.documentElement.clientWidth);
                if (left + width + pad > (scrollX + viewportWidth)){
                    left = Math.max(pad, (scrollX + viewportWidth) - width - pad);
                }
                var spacing = 2 + OFFSET_Y;
                var top = Math.floor(scrollY + r.top + toggle.offsetHeight + spacing);
                // If not enough space below, open upward
                var desiredHeight = 220;
                var viewportBottom = scrollY + (window.innerHeight || document.documentElement.clientHeight) - 8;
                if (top + desiredHeight > viewportBottom){
                    top = Math.max(8, Math.floor(scrollY + r.top - desiredHeight - spacing));
                }
                menu.style.position = 'absolute';
                menu.style.left = left + 'px';
                menu.style.top  = top + 'px';
                menu.style.width = width + 'px';
                menu.style.minWidth = width + 'px';
                menu.style.maxWidth = width + 'px';
                menu.style.maxHeight = '260px';
                menu.style.overflowY = 'auto';
                menu.style.zIndex = '2147483000';
                menu.style.display = 'block';
            }
            function clearStyles(){
                menu.style.position = '';
                menu.style.left = '';
                menu.style.top = '';
                menu.style.width = '';
                menu.style.minWidth = '';
                menu.style.maxWidth = '';
                menu.style.maxHeight = '';
                menu.style.overflowY = '';
                menu.style.zIndex = '';
                menu.style.display = '';
            }
            function closeAll(){
                custom.classList.remove('open');
                clearStyles();
                unmountMenu();
                if (closeOnScroll){ window.removeEventListener('scroll', closeOnScroll, true); closeOnScroll = null; }
                if (closeOnResize){ window.removeEventListener('resize', closeOnResize); closeOnResize = null; }
            }

            // Prevent page scrolling when interacting with menu
            menu.addEventListener('wheel', function(e){ e.stopPropagation(); }, { passive: true });
            menu.addEventListener('touchmove', function(e){ e.stopPropagation(); }, { passive: true });
            menu.addEventListener('mousedown', function(e){ e.stopPropagation(); });

            document.addEventListener('click', function(e){ if (!custom.contains(e.target) && !menu.contains(e.target)) closeAll(); });
            toggle.addEventListener('click', function(e){
                e.stopPropagation();
                var willOpen = !custom.classList.contains('open');
                custom.classList.toggle('open');
                if (willOpen){
                    mountMenu();
                    positionMenu();
                    closeOnScroll = function(ev){ if (menu.contains(ev.target)) return; closeAll(); };
                    closeOnResize = function(){ closeAll(); };
                    window.addEventListener('scroll', closeOnScroll, true);
                    window.addEventListener('resize', closeOnResize);
                } else {
                    closeAll();
                }
            });

            menu.addEventListener('click', function(e){
                var opt = e.target.closest('.custom-select-option');
                if (!opt) return;
                var value = opt.getAttribute('data-value');
                hidden.value = value;
                toggle.textContent = value;
                menu.querySelectorAll('.custom-select-option').forEach(function(el){ el.classList.toggle('is-selected', el===opt); });
                closeAll();
                form.submit();
            });
        })();
        </script>
    </div>
</section>

<!-- Time Picker Styles (scoped) --><style>.luna-time-picker{position:fixed;width:220px;height:240px;background:rgba(12,38,43,.98);border:1px solid rgba(122,220,201,.35);border-radius:12px;box-shadow:0 18px 38px rgba(3,15,21,.75);z-index:2147483000;display:none;padding:12px;box-sizing:border-box}.luna-time-picker.show{display:block}.luna-time-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid rgba(122,220,201,.2)}.luna-time-display{font-size:13px;font-weight:600;color:#e8fbf6;letter-spacing:1px}.luna-time-actions{display:flex;gap:6px;justify-content:flex-end}.luna-time-actions button{background:transparent;border:1px solid rgba(122,220,201,.28);color:#bfeee3;border-radius:6px;padding:4px 8px;cursor:pointer; font-size:9px;}.luna-time-actions button:hover{background:rgba(122,220,201,.12);color:#7adcc9}.luna-time-columns{display:grid;grid-template-columns:1fr 20px 1fr 20px 1fr;gap:6px;height:150px}.time-col{overflow-y:auto;border:1px solid rgba(122,220,201,.18);border-radius:8px;padding:4px}.time-sep{display:grid;place-items:center;color:#9ec9c1;font-weight:600}.time-item{text-align:center;padding:3px 0;color:#e8fbf6;border-radius:6px;cursor:pointer;font-size:13px}.time-item:hover{background:rgba(122,220,201,.12)}.time-item.selected{background:#7adcc9;color:#0b2228;font-weight:600}.time-labels{display:grid;grid-template-columns:1fr 20px 1fr 20px 1fr;gap:6px;margin-top:6px;color:#9ec9c1;font-size:11px;font-weight:600;text-align:center}.time-labels .spacer{width:20px}.luna-time-actions .ok-btn-header{background: #7adcc9;color:#052729 ;}.luna-time-actions .ok-btn-header:hover{color:#052729;background: rgba(121, 219, 200, 0.58) ;}</style>
<style>
#attendance-modal #att-time{font-size:14px!important;font-family: monospace;line-height:1.2;color:#e8fbf6;font-weight:400;-webkit-text-fill-color:#e8fbf6;border:0!important;background:transparent!important}
#attendance-modal #att-time::placeholder{color:#9ec9c1;opacity:.8}
#attendance-edit-modal #att-edit-time{font-size:14px!important;font-family: monospace;line-height:1.2;color:#e8fbf6;font-weight:400;-webkit-text-fill-color:#e8fbf6;border:0!important;background:transparent!important}
#attendance-edit-modal #att-edit-time::placeholder{color:#9ec9c1;opacity:.8}
#attendance-modal #att-time-wrap, #attendance-edit-modal #att-edit-time-wrap{border:1px solid rgba(122,220,201,.28)!important;border-radius:16px!important;background:rgba(11, 31, 34, 0.65)!important}
#attendance-modal #att-time-wrap:focus-within, #attendance-edit-modal #att-edit-time-wrap:focus-within{border-color:rgba(122,220,201,.45)!important;box-shadow:0 0 0 2px rgba(122,220,201,.08)!important}
/* Modal THÊM DÒNG CHẤM CÔNG - bao phủ toàn bộ trang web */
#attendance-modal { 
  position: fixed !important; 
  inset: 0 !important; 
  z-index: 10000 !important;
}
/* Modal CHỈNH SỬA THỜI GIAN - chỉ phủ trong dashboard-main */
#attendance-edit-modal { 
  position: absolute !important; 
  inset: 0 !important; 
}
/* Modal CẬP NHẬT - bao phủ toàn bộ trang web */
#attendance-update-modal { 
  position: fixed !important; 
  inset: 0 !important; 
  z-index: 10000 !important;
}
#attendance-update-modal #att-update-time{font-size:14px!important;font-family: monospace;line-height:1.2;color:#e8fbf6;font-weight:400;-webkit-text-fill-color:#e8fbf6;background:transparent!important;caret-color:transparent;cursor:default;}
#attendance-update-modal #att-update-time::placeholder{color:#9ec9c1;opacity:.8}
#attendance-update-modal #att-update-date-wrap,
#attendance-update-modal #att-update-time-wrap{border-radius:16px!important;background:rgba(11, 31, 34, 0.65)!important}
#attendance-update-modal #att-update-date-wrap:focus-within,
#attendance-update-modal #att-update-time-wrap:focus-within{border-color:rgba(122,220,201,.45)!important;box-shadow:0 0 0 2px rgba(122,220,201,.08)!important}
</style>
<!-- Attendance Create Modal -->
<div id="attendance-modal" class="modal-backdrop" aria-hidden="true">
    <div class="modal">
        <div class="modal-header">
            <h4><?= htmlspecialchars($messages['attendance_create_heading'] ?? 'THÊM DÒNG CHẤM CÔNG', ENT_QUOTES, 'UTF-8') ?></h4>
            <button type="button" class="modal-close" data-modal-close>&times;</button>
        </div>
        <div class="modal-body">
            <form id="attendance-form" method="POST" class="form-grid grid-2" novalidate>
                <input type="hidden" name="attendance_create" value="1">

                <div class="form-row">
                    <label for="att-pin"><?= htmlspecialchars($messages['attendance_form_employee_id_label'] ?? 'Mã nhân viên', ENT_QUOTES, 'UTF-8') ?></label>
                    <div class="input-wrap">
                        <span class="icon">
                            <svg viewBox="0 0 24 24"><path d="M4 4h16v4H4zM4 12h10v8H4zM16 12h4v8h-4z"/></svg>
                        </span>
                        <input type="text" id="att-pin" name="att_pin" placeholder="VD: 00092" required>
                    </div>
                </div>

                <div class="form-row">
                    <label for="att-name"><?= htmlspecialchars($messages['attendance_form_full_name_label'] ?? 'Họ tên', ENT_QUOTES, 'UTF-8') ?></label>
                    <div class="input-wrap">
                        <span class="icon">
                            <svg viewBox="0 0 24 24"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
                        </span>
                        <input type="text" id="att-name" name="att_name" placeholder="<?= htmlspecialchars($messages['attendance_form_full_name_placeholder'] ?? 'Nhập họ tên', ENT_QUOTES, 'UTF-8') ?>">
                    </div>
                </div>

                <div class="form-row">
                    <label for="att-date"><?= htmlspecialchars($messages['attendance_form_date_label'] ?? 'Ngày', ENT_QUOTES, 'UTF-8') ?></label>
                    <div class="input-wrap">
                        <span class="icon date-icon" data-target="att-date">
                            <svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
                        </span>
                        <input type="date" id="att-date" name="att_date" required autocomplete="off" style="font-size:14px;">
                    </div>
                </div>

                <div class="form-row">
                    <label for="att-time"><?= htmlspecialchars($messages['attendance_form_time_label'] ?? 'Giờ', ENT_QUOTES, 'UTF-8') ?></label>
                    <div class="input-wrap" id="att-time-wrap">
                        <span class="icon time-icon" data-target="att-time">
                            <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12,6 12,12 16,14"/></svg>
                        </span>
                        <input type="text" id="att-time" name="att_time" placeholder="hh:mm:ss" autocomplete="off" inputmode="numeric" pattern="^\d{2}:\d{2}:\d{2}$" style="font-size:14px;" readonly onclick="window.openTimePickerAtt && window.openTimePickerAtt(); return false;" onfocus="window.openTimePickerAtt && window.openTimePickerAtt(); return false;">
                    </div>
                </div>

                <div class="form-actions full">
                    <button type="submit" class="btn btn-primary"><?= htmlspecialchars($messages['attendance_btn_save'] ?? 'Lưu', ENT_QUOTES, 'UTF-8') ?></button>
                    <button type="button" class="btn btn-secondary" data-modal-close><?= htmlspecialchars($messages['attendance_btn_cancel'] ?? 'Hủy', ENT_QUOTES, 'UTF-8') ?></button>
                </div>
            </form>
        </div>
    </div>
</div>

<!-- Attendance Edit Modal -->
<div id="attendance-edit-modal" class="modal-backdrop" aria-hidden="true">
    <div class="modal">
        <div class="modal-header">
            <h4><?= htmlspecialchars($messages['attendance_edit_heading'] ?? 'CHỈNH SỬA THỜI GIAN', ENT_QUOTES, 'UTF-8') ?></h4>
            <button type="button" class="modal-close" data-modal-close>&times;</button>
        </div>
        <div class="modal-body">
            <form id="attendance-edit-form" method="POST" class="form-grid grid-2" novalidate>
                <input type="hidden" name="attendance_edit" value="1">
                <input type="hidden" id="att-edit-pin" name="att_edit_pin">
                <input type="hidden" id="att-edit-old-datetime" name="att_edit_old_datetime">

                <div class="form-row">
                    <label for="att-edit-pin-display"><?= htmlspecialchars($messages['attendance_form_employee_id_label'] ?? 'Mã nhân viên', ENT_QUOTES, 'UTF-8') ?></label>
                    <div class="input-wrap">
                        <span class="icon">
                            <svg viewBox="0 0 24 24"><path d="M4 4h16v4H4zM4 12h10v8H4zM16 12h4v8h-4z"/></svg>
                        </span>
                        <input type="text" id="att-edit-pin-display" placeholder="<?= htmlspecialchars($messages['attendance_form_employee_id_label'] ?? 'Mã nhân viên', ENT_QUOTES, 'UTF-8') ?>" disabled style="background:rgba(255,255,255,0.05); cursor:not-allowed;">
                    </div>
                </div>

                <div class="form-row">
                    <label for="att-edit-name-display"><?= htmlspecialchars($messages['attendance_form_full_name_label'] ?? 'Họ tên', ENT_QUOTES, 'UTF-8') ?></label>
                    <div class="input-wrap">
                        <span class="icon">
                            <svg viewBox="0 0 24 24"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
                        </span>
                        <input type="text" id="att-edit-name-display" placeholder="<?= htmlspecialchars($messages['attendance_form_full_name_label'] ?? 'Họ tên', ENT_QUOTES, 'UTF-8') ?>" disabled style="background:rgba(255,255,255,0.05); cursor:not-allowed;">
                    </div>
                </div>

                <div class="form-row">
                    <label for="att-edit-date"><?= htmlspecialchars($messages['attendance_form_date_label'] ?? 'Ngày', ENT_QUOTES, 'UTF-8') ?></label>
                    <div class="input-wrap">
                        <span class="icon date-icon is-disabled" data-target="att-edit-date" disabled style="pointer-events:none; opacity:.6;">
                            <svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
                        </span>
                        <input type="date" id="att-edit-date" name="att_edit_date" autocomplete="off" style="font-size:14px;background: rgba(255, 255, 255, 0.05);cursor:not-allowed;" disabled readonly data-no-picker="1">
                    </div>
                </div>

                <div class="form-row">
                    <label for="att-edit-time"><?= htmlspecialchars($messages['attendance_form_time_label'] ?? 'Giờ', ENT_QUOTES, 'UTF-8') ?></label>
                    <div class="input-wrap" id="att-edit-time-wrap">
                        <span class="icon time-icon" data-target="att-edit-time">
                            <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12,6 12,12 16,14"/></svg>
                        </span>
                        <input type="text" id="att-edit-time" name="att_edit_time" placeholder="hh:mm:ss" autocomplete="off" inputmode="numeric" pattern="^\d{2}:\d{2}:\d{2}$" style="font-size:14px;" readonly onclick="window.openTimePickerAttEdit && window.openTimePickerAttEdit(); return false;" onfocus="window.openTimePickerAttEdit && window.openTimePickerAttEdit(); return false;">
                    </div>
                </div>

                <div class="form-actions full">
                    <button type="submit" class="btn btn-primary"><?= htmlspecialchars($messages['attendance_btn_save'] ?? 'Lưu', ENT_QUOTES, 'UTF-8') ?></button>
                    <button type="button" class="btn btn-secondary" data-modal-close><?= htmlspecialchars($messages['attendance_btn_cancel'] ?? 'Hủy', ENT_QUOTES, 'UTF-8') ?></button>
                </div>
            </form>
        </div>
    </div>
</div>

<script>
// Attendance modal open/close (match behavior of Incoming modal)
(function(){
  var openBtn = document.getElementById('attendance-open-create');
  var modal = document.getElementById('attendance-modal');
  if (!openBtn || !modal) return;
  var closeButtons = modal.querySelectorAll('[data-modal-close]');
  function open(){
    // Đóng sprint menu và ẩn icon ngôi nhà giống confirm delete (dùng class)
    if (window.__sprinTipsClose) window.__sprinTipsClose();
    var sprintToggle = document.getElementById('menu-sprin-toggle');
    if (sprintToggle) sprintToggle.checked = false;
    var sprintWrapper = document.querySelector('.attendance-panel .menu-sprin-wrapper');
    if (sprintWrapper) {
      sprintWrapper.classList.remove('open');
    }
    document.body.classList.add('attendance-create-modal-open');

    // Đảm bảo modal ở trong body để bao phủ toàn bộ trang
    if (modal.parentElement !== document.body) {
      document.body.appendChild(modal);
    }
    // Show create modal - bao phủ toàn bộ trang web
    modal.style.setProperty('position', 'fixed', 'important');
    modal.style.setProperty('inset', '0', 'important');
    modal.style.setProperty('z-index', '10000', 'important');
    modal.classList.add('show');
    modal.removeAttribute('aria-hidden');
    modal.setAttribute('aria-hidden','false');
    modal.style.display = 'flex';
    setTimeout(function(){
      var first = document.getElementById('att-pin');
      if (first) { try { first.focus(); } catch(_) {} }
    }, 50);
  }
  function close(){
    var active = document.activeElement;
    if (active && modal.contains(active)) { try { active.blur(); } catch(_) {} }
    modal.classList.remove('show');
    modal.setAttribute('aria-hidden','true');
    modal.style.display = 'none';
    document.body.classList.remove('attendance-create-modal-open');
  }
  openBtn.addEventListener('click', open);
  closeButtons.forEach(function(btn){ btn.addEventListener('click', close); });
  // Disabled: click outside to close modal
  // modal.addEventListener('click', function(e){ if (e.target === modal) close(); });
  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') close(); });
})();

// Attendance edit modal open/close
(function(){
  var editModal = document.getElementById('attendance-edit-modal');
  if (!editModal) return;
  var closeButtons = editModal.querySelectorAll('[data-modal-close]');
  
  function open(pin, name, datetime, date, time){
    document.getElementById('att-edit-pin').value = pin;
    document.getElementById('att-edit-old-datetime').value = datetime;
    document.getElementById('att-edit-pin-display').value = pin;
    document.getElementById('att-edit-name-display').value = name;
    
    function toIsoDate(str){
      if (!str) return '';
      str = String(str).trim();
      // Already ISO yyyy-mm-dd
      var m = str.match(/^(\d{4})-(\d{2})-(\d{2})/);
      if (m) return m[1] + '-' + m[2] + '-' + m[3];
      // dd/mm/yyyy or dd-mm-yyyy
      m = str.match(/^(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})$/);
      if (m){
        var d = ('0'+m[1]).slice(-2), mo = ('0'+m[2]).slice(-2), y = m[3];
        return y + '-' + mo + '-' + d;
      }
      // Try parsing generic date
      try {
        var d2 = new Date(str);
        if (!isNaN(d2.getTime())){
          var mm = ('0'+(d2.getMonth()+1)).slice(-2);
          var dd = ('0'+d2.getDate()).slice(-2);
          return d2.getFullYear() + '-' + mm + '-' + dd;
        }
      } catch(_) {}
      return '';
    }

    var isoDate = toIsoDate(date) || toIsoDate(datetime);
    var dateInputEl = document.getElementById('att-edit-date');
    if (dateInputEl) dateInputEl.value = isoDate;

    // Time: prefer explicit time, fallback to datetime
    var timeVal = '';
    if (time && /^\d{2}:\d{2}(:\d{2})?$/.test(time.trim())) {
      timeVal = time.trim().length===5 ? time.trim()+':00' : time.trim();
    } else if (datetime){
      var t = String(datetime).split(' ')[1] || String(datetime).split('T')[1] || '';
      timeVal = t ? t.substring(0,8) : '';
    }
    var timeInputEl = document.getElementById('att-edit-time');
    if (timeInputEl) timeInputEl.value = timeVal;
    
    // Di chuyển modal vào dashboard-main thay vì body
    var dashboardMain = document.querySelector('.dashboard-main');
    if (dashboardMain && editModal.parentElement !== dashboardMain) {
      dashboardMain.appendChild(editModal);
    }
    // Đảm bảo dashboard-main có position relative
    if (dashboardMain) {
      dashboardMain.style.setProperty('position', 'relative', 'important');
    }
    editModal.style.setProperty('position', 'absolute', 'important');
    editModal.classList.add('show');
    editModal.removeAttribute('aria-hidden');
    editModal.setAttribute('aria-hidden','false');
    editModal.style.display = 'flex';
    editModal.style.zIndex = '100000';
    setTimeout(function(){
      var el = document.getElementById('att-edit-time');
      if (el) { try { el.focus(); } catch(_) {} }
    }, 50);
  }
  
  function close(){
    var active = document.activeElement;
    if (active && editModal.contains(active)) { try { active.blur(); } catch(_) {} }
    editModal.classList.remove('show');
    editModal.setAttribute('aria-hidden','true');
    editModal.style.display = 'none';
  }
  
  closeButtons.forEach(function(btn){ btn.addEventListener('click', close); });
  // Disabled: click outside to close modal
  // editModal.addEventListener('click', function(e){ if (e.target === editModal) close(); });
  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') close(); });
  
  // Expose globally
  window.openAttendanceEditModal = open;
  
  // Bind edit buttons
  document.addEventListener('click', function(e){
    var btn = e.target.closest('.att-edit-btn');
    if (!btn) return;
    var pin = btn.getAttribute('data-att-edit-pin') || '';
    var name = btn.getAttribute('data-att-edit-name') || '';
    var datetime = btn.getAttribute('data-att-edit-datetime') || '';
    var date = btn.getAttribute('data-att-edit-date') || '';
    var time = btn.getAttribute('data-att-edit-time') || '';
    open(pin, name, datetime, date, time);
  });
})();
</script>

<script>
// Custom Date Picker for Attendance modal (reuse same component as Incoming)
document.addEventListener('DOMContentLoaded', function(){
  var attendanceModal = document.getElementById('attendance-modal');
  if (!attendanceModal) return;
  
  setupDatePickerForModal(attendanceModal);
});

// Custom Date Picker for Attendance Edit modal
document.addEventListener('DOMContentLoaded', function(){
  var editModal = document.getElementById('attendance-edit-modal');
  if (!editModal) return;
  
  setupDatePickerForModal(editModal);
});

// Custom Date Picker for Fetch Range modal
document.addEventListener('DOMContentLoaded', function(){
  var fetchModal = document.getElementById('attendance-fetch-modal');
  if (!fetchModal) return;

  setupDatePickerForModal(fetchModal);
});

function setupDatePickerForModal(attendanceModal){
  if (!attendanceModal) return;

  // Get current language
  function getLang() {
    return window.getCurrentLanguage ? window.getCurrentLanguage() : (window.APP_LANG || 'vn');
  }

  // Language-specific texts
  var texts = {
    vn: {
      months: ['Tháng Một','Tháng Hai','Tháng Ba','Tháng Tư','Tháng Năm','Tháng Sáu','Tháng Bảy','Tháng Tám','Tháng Chín','Tháng Mười','Tháng Mười Một','Tháng Mười Hai'],
      days: ['CN','T2','T3','T4','T5','T6','T7'],
      prevYear: 'Năm trước',
      prevMonth: 'Tháng trước',
      nextMonth: 'Tháng sau',
      nextYear: 'Năm sau',
      clear: 'Xóa',
      today: 'Hôm nay'
    },
    eng: {
      months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
      days: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
      prevYear: 'Previous year',
      prevMonth: 'Previous month',
      nextMonth: 'Next month',
      nextYear: 'Next year',
      clear: 'Clear',
      today: 'Today'
    }
  };

  // Get current language texts
  function getTexts() {
    var lang = getLang();
    return texts[lang] || texts.vn;
  }

  var currentTexts = getTexts();

  var pickerEl = null, currentInput = null, currentDate = new Date();
  var wheelHandler = null, clickOutsideHandler = null, scrollHandler = null, resizeHandler = null, rafId = null;

  function createPicker(){
    var texts = getTexts();
    var el = document.createElement('div');
    el.className = 'luna-date-picker';
    el.innerHTML = '\
      <div class="luna-date-picker-header">\
        <div class="luna-date-picker-month-year"></div>\
        <div class="luna-date-picker-nav">\
          <button type="button" class="luna-date-picker-nav-btn prev-year" title="' + texts.prevYear + '"><svg viewBox="0 0 24 24"><polyline points="11 17 6 12 11 7"/><polyline points="18 17 13 12 18 7"/></svg></button>\
          <button type="button" class="luna-date-picker-nav-btn prev-month" title="' + texts.prevMonth + '"><svg viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg></button>\
          <button type="button" class="luna-date-picker-nav-btn next-month" title="' + texts.nextMonth + '"><svg viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></svg></button>\
          <button type="button" class="luna-date-picker-nav-btn next-year" title="' + texts.nextYear + '"><svg viewBox="0 0 24 24"><polyline points="13 17 18 12 13 7"/><polyline points="6 17 11 12 6 7"/></svg></button>\
        </div>\
      </div>\
      <div class="luna-date-picker-weekdays"></div>\
      <div class="luna-date-picker-days"></div>\
      <div class="luna-date-picker-footer">\
        <button type="button" class="luna-date-picker-footer-btn clear-btn">' + texts.clear + '</button>\
        <button type="button" class="luna-date-picker-footer-btn today-btn">' + texts.today + '</button>\
      </div>';
    document.body.appendChild(el);
    return el;
  }

  function getPicker(){ if (!pickerEl) pickerEl = createPicker(); return pickerEl; }

  function updatePickerPosition(){
    if (!pickerEl || !currentInput || !pickerEl.classList.contains('show')) return;
    var rect = currentInput.getBoundingClientRect();
    var wrap = currentInput.closest('.input-wrap');
    var box = wrap ? wrap.getBoundingClientRect() : rect;
    var left = box.left; var top = box.bottom + 6;
    var pickerW = 230, pickerH = 280;
    if (left + pickerW > window.innerWidth) left = window.innerWidth - pickerW - 10;
    if (left < 10) left = 10;
    if (top + pickerH > window.innerHeight) top = box.top - pickerH - 6;
    if (top < 10) top = 10;
    pickerEl.style.left = left + 'px';
    pickerEl.style.top = top + 'px';
  }
  function updatePickerPositionRAF(){ if (rafId) cancelAnimationFrame(rafId); rafId = requestAnimationFrame(function(){ updatePickerPosition(); rafId = null; }); }

  function render(){
    var el = getPicker(); if (!el || !currentInput) return;
    var texts = getTexts();
    var y = currentDate.getFullYear(), m = currentDate.getMonth();
    el.querySelector('.luna-date-picker-month-year').innerHTML = '<span class="month">' + texts.months[m] + '</span><span class="year">' + y + '</span>';
    
    // Update navigation button titles
    el.querySelector('.prev-year').setAttribute('title', texts.prevYear);
    el.querySelector('.prev-month').setAttribute('title', texts.prevMonth);
    el.querySelector('.next-month').setAttribute('title', texts.nextMonth);
    el.querySelector('.next-year').setAttribute('title', texts.nextYear);
    
    // Update footer buttons
    el.querySelector('.clear-btn').textContent = texts.clear;
    el.querySelector('.today-btn').textContent = texts.today;
    
    var weekdays = el.querySelector('.luna-date-picker-weekdays'); weekdays.innerHTML='';
    texts.days.forEach(function(d){ var div=document.createElement('div'); div.className='luna-date-picker-weekday'; div.textContent=d; weekdays.appendChild(div); });
    var days = el.querySelector('.luna-date-picker-days'); days.innerHTML='';
    var first = new Date(y, m, 1), start = new Date(first); start.setDate(start.getDate() - start.getDay());
    var lastSelected=null; if (currentInput.value){ var p=currentInput.value.split('-'); if(p.length===3){ lastSelected=new Date(+p[0], +p[1]-1, +p[2]); lastSelected.setHours(0,0,0,0);} }
    var today=new Date(); today.setHours(0,0,0,0);
    for (var i=0;i<42;i++){
      var d=new Date(start); d.setDate(start.getDate()+i);
      var btn=document.createElement('button'); btn.type='button'; btn.className='luna-date-picker-day'; btn.textContent=d.getDate();
      if (d.getMonth()!==m) btn.classList.add('other-month');
      if (d.getTime()===today.getTime()) btn.classList.add('today');
      if (lastSelected && d.getTime()===lastSelected.getTime()) btn.classList.add('selected');
      (function(date){ btn.addEventListener('click', function(){ select(date); }); })(new Date(d));
      days.appendChild(btn);
    }
  }

  function select(date){ if(!currentInput) return; var y=date.getFullYear(), mo=('0'+(date.getMonth()+1)).slice(-2), da=('0'+date.getDate()).slice(-2); currentInput.value = y+'-'+mo+'-'+da; currentInput.dispatchEvent(new Event('change',{bubbles:true})); hide(); }

  function show(input){ if(!input||input.type!=='date' || input.disabled) return; currentInput=input; if(input.value){ var p=input.value.split('-'); if(p.length===3){ currentDate=new Date(+p[0],+p[1]-1,+p[2]); } else { currentDate=new Date(); } } else { currentDate=new Date(); }
    var el=getPicker(); render(); updatePickerPosition(); el.classList.add('show');
    // events
    // cleanup old
    if (wheelHandler) { el.removeEventListener('wheel', wheelHandler); }
    if (clickOutsideHandler) { document.removeEventListener('click', clickOutsideHandler); }
    if (scrollHandler) { window.removeEventListener('scroll', scrollHandler, true); }
    if (resizeHandler) { window.removeEventListener('resize', resizeHandler); }
    // nav
    el.querySelector('.prev-year').onclick=function(){ currentDate.setMonth(currentDate.getMonth()-12); render(); };
    el.querySelector('.prev-month').onclick=function(){ currentDate.setMonth(currentDate.getMonth()-1); render(); };
    el.querySelector('.next-month').onclick=function(){ currentDate.setMonth(currentDate.getMonth()+1); render(); };
    el.querySelector('.next-year').onclick=function(){ currentDate.setMonth(currentDate.getMonth()+12); render(); };
    el.querySelector('.clear-btn').onclick=function(){ if(currentInput){ currentInput.value=''; hide(); } };
    el.querySelector('.today-btn').onclick=function(){ select(new Date()); };
    // wheel throttle
    var lastWheel=0; wheelHandler=function(e){ if(!el.classList.contains('show')) return; e.preventDefault(); var now=Date.now(); if(now-lastWheel<150) return; lastWheel=now; var delta=e.deltaY||e.detail||-e.wheelDelta; if(delta>0) currentDate.setMonth(currentDate.getMonth()+1); else if(delta<0) currentDate.setMonth(currentDate.getMonth()-1); render(); };
    el.addEventListener('wheel', wheelHandler, {passive:false});
    scrollHandler=function(){ if(el.classList.contains('show')) updatePickerPositionRAF(); };
    resizeHandler=function(){ if(el.classList.contains('show')) updatePickerPositionRAF(); };
    window.addEventListener('scroll', scrollHandler, true);
    window.addEventListener('resize', resizeHandler);
    clickOutsideHandler=function(e){ if(!el.classList.contains('show')) return; var inside=el.contains(e.target); var onInput=(e.target===currentInput||currentInput.contains(e.target)); var onIcon=!!e.target.closest('.date-icon'); if(!inside && !onInput && !onIcon){ hide(); } };
    document.addEventListener('click', clickOutsideHandler);
  }
  function hide(){ if(!pickerEl) return; pickerEl.classList.remove('show'); if (wheelHandler){ pickerEl.removeEventListener('wheel', wheelHandler); wheelHandler=null; } if(clickOutsideHandler){ document.removeEventListener('click', clickOutsideHandler); clickOutsideHandler=null; } if(scrollHandler){ window.removeEventListener('scroll', scrollHandler, true); scrollHandler=null; } if(resizeHandler){ window.removeEventListener('resize', resizeHandler); resizeHandler=null; } currentInput=null; }

  // Bind icon and input - att-date
  var icon = attendanceModal.querySelector('.date-icon[data-target="att-date"]');
  if (icon){ icon.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); var input=document.getElementById('att-date'); if(input) show(input); }); }
  var input = document.getElementById('att-date');
  if (input){ input.addEventListener('click', function(e){ e.preventDefault(); show(input); }); input.addEventListener('focus', function(e){ e.preventDefault(); show(input); }); }
  
  // Bind icon and input - att-edit-date
  var iconEdit = attendanceModal.querySelector('.date-icon[data-target="att-edit-date"]');
  if (iconEdit){ iconEdit.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); var input=document.getElementById('att-edit-date'); if(input) show(input); }); }
  var inputEdit = document.getElementById('att-edit-date');
  if (inputEdit){ inputEdit.addEventListener('click', function(e){ e.preventDefault(); show(inputEdit); }); inputEdit.addEventListener('focus', function(e){ e.preventDefault(); show(inputEdit); }); }

  // Bind icon and input - fetch range: att-fetch-from
  var iconFrom = attendanceModal.querySelector('.date-icon[data-target="att-fetch-from"]');
  if (iconFrom){ iconFrom.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); var input=document.getElementById('att-fetch-from'); if(input) show(input); }); }
  var inputFrom = document.getElementById('att-fetch-from');
  if (inputFrom){ inputFrom.addEventListener('click', function(e){ e.preventDefault(); show(inputFrom); }); inputFrom.addEventListener('focus', function(e){ e.preventDefault(); show(inputFrom); }); }

  // Bind icon and input - fetch range: att-fetch-to
  var iconTo = attendanceModal.querySelector('.date-icon[data-target="att-fetch-to"]');
  if (iconTo){ iconTo.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); var input=document.getElementById('att-fetch-to'); if(input) show(input); }); }
  var inputTo = document.getElementById('att-fetch-to');
  if (inputTo){ inputTo.addEventListener('click', function(e){ e.preventDefault(); show(inputTo); }); inputTo.addEventListener('focus', function(e){ e.preventDefault(); show(inputTo); }); }

  // Bind icon and input - update modal: att-update-date
  var updateModal = document.getElementById('attendance-update-modal');
  if (updateModal) {
    var iconUpdate = updateModal.querySelector('.date-icon[data-target="att-update-date"]');
    if (iconUpdate){ iconUpdate.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); var input=document.getElementById('att-update-date'); if(input) show(input); }); }
    var inputUpdate = document.getElementById('att-update-date');
    if (inputUpdate){ inputUpdate.addEventListener('click', function(e){ e.preventDefault(); show(inputUpdate); }); inputUpdate.addEventListener('focus', function(e){ e.preventDefault(); show(inputUpdate); }); }
  }
}
</script>

<script>
// Custom Time Picker for Attendance modal
document.addEventListener('DOMContentLoaded', function(){
  var attendanceModal = document.getElementById('attendance-modal');
  if (!attendanceModal) return;

  // Get current language texts for time picker
  function getTimePickerTexts() {
    var lang = window.getCurrentLanguage ? window.getCurrentLanguage() : (window.APP_LANG || 'vn');
    var texts = {
      vn: {
        now: 'Bây giờ',
        clear: 'Xóa',
        hour: 'GIỜ',
        minute: 'PHÚT',
        second: 'GIÂY'
      },
      eng: {
        now: 'Now',
        clear: 'Clear',
        hour: 'HOUR',
        minute: 'MINUTE',
        second: 'SECOND'
      }
    };
    return texts[lang] || texts.vn;
  }

  var picker = null, currentInput = null;
  var selectedH = 0, selectedM = 0, selectedS = 0;
  var closeHandlers = { scroll:null, resize:null, outside:null };
  var suppressClose = false;

  function createTimePicker(){
    var texts = getTimePickerTexts();
    var el = document.createElement('div');
    el.className = 'luna-time-picker';
    el.innerHTML = '\
      <div class="luna-time-header">\
        <div class="luna-time-display" id="tp-display">00:00:00</div>\
        <div class="luna-time-actions">\
          <button type="button" class="now-btn">' + texts.now + '</button>\
          <button type="button" class="clear-btn">' + texts.clear + '</button>\
          <button type="button" class="ok-btn-header">OK</button>\
        </div>\
      </div>\
      <div class="luna-time-columns">\
        <div class="time-col hours"></div>\
        <div class="time-sep">:</div>\
        <div class="time-col minutes"></div>\
        <div class="time-sep">:</div>\
        <div class="time-col seconds"></div>\
      </div>\
      <div class="time-labels">\
        <div class="lbl">' + texts.hour + '</div><div class="spacer"></div><div class="lbl">' + texts.minute + '</div><div class="spacer"></div><div class="lbl">' + texts.second + '</div>\
      </div>';
    document.body.appendChild(el);
    return el;
  }

  function getPicker(){ if(!picker) picker = createTimePicker(); return picker; }

  function updateDisplay(){
    var d = document.getElementById('tp-display');
    if (d) d.textContent = String(selectedH).padStart(2,'0') + ':' + String(selectedM).padStart(2,'0') + ':' + String(selectedS).padStart(2,'0');
  }

  function renderColumns(){
    var el = getPicker();
    var hCol = el.querySelector('.hours');
    var mCol = el.querySelector('.minutes');
    var sCol = el.querySelector('.seconds');
    hCol.innerHTML = ''; mCol.innerHTML=''; sCol.innerHTML='';
    for (var h=0; h<24; h++){
      var b=document.createElement('div'); b.className='time-item'+(h===selectedH?' selected':''); b.textContent=String(h).padStart(2,'0'); b.dataset.h=h;
      b.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); selectedH = parseInt(e.target.dataset.h,10); renderColumns(); updateDisplay(); });
      hCol.appendChild(b);
    }
    for (var m=0; m<60; m+=1){
      var c=document.createElement('div'); c.className='time-item'+(m===selectedM?' selected':''); c.textContent=String(m).padStart(2,'0'); c.dataset.m=m;
      c.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); selectedM = parseInt(e.target.dataset.m,10); renderColumns(); updateDisplay(); });
      mCol.appendChild(c);
    }
    for (var s=0; s<60; s+=1){
      var d=document.createElement('div'); d.className='time-item'+(s===selectedS?' selected':''); d.textContent=String(s).padStart(2,'0'); d.dataset.s=s;
      d.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); selectedS = parseInt(e.target.dataset.s,10); renderColumns(); updateDisplay(); });
      sCol.appendChild(d);
    }
    updateDisplay();
  }

  function position(){
    var el = getPicker(); if(!currentInput) return;
    var rect = currentInput.getBoundingClientRect();
    var wrap = currentInput.closest('.input-wrap');
    var box = wrap ? wrap.getBoundingClientRect() : rect;
    var left = box.left; var top = box.bottom + 6;
    var w = 220, h = 240;
    if (left + w > window.innerWidth) left = window.innerWidth - w - 10;
    if (left < 10) left = 10;
    if (top + h > window.innerHeight) top = box.top - h - 6;
    if (top < 10) top = 10;
    el.style.left = left + 'px'; el.style.top = top + 'px';
  }
  function show(input){
    currentInput = input;
    // Parse current value (HH:MM[:SS])
    var h=0,m=0,s=0;
    if (input && input.value){
      var parts = input.value.split(':');
      if (parts.length>=2){ h = parseInt(parts[0]||'0',10)||0; m = parseInt(parts[1]||'0',10)||0; }
      if (parts.length>=3){ s = parseInt(parts[2]||'0',10)||0; }
    } else {
      var now = new Date(); h = now.getHours(); m = now.getMinutes(); s = now.getSeconds();
    }
    selectedH = Math.max(0, Math.min(23, h));
    selectedM = Math.max(0, Math.min(59, m));
    selectedS = Math.max(0, Math.min(59, s));

    var el = getPicker(); renderColumns(); position(); el.classList.add('show');

    // Bind actions
    el.querySelector('.now-btn').onclick = function(){ var n=new Date(); var v = String(n.getHours()).padStart(2,'0') + ':' + String(n.getMinutes()).padStart(2,'0') + ':' + String(n.getSeconds()).padStart(2,'0'); if (currentInput){ currentInput.value = v; currentInput.dispatchEvent(new Event('change',{bubbles:true})); } hide(); };
    el.querySelector('.clear-btn').onclick = function(){ if(currentInput){ currentInput.value = ''; } hide(); };
    var okHeader = el.querySelector('.ok-btn-header');
    if (okHeader) {
      okHeader.onclick = function(){
        if (currentInput) {
          var v = String(selectedH).padStart(2,'0') + ':' + String(selectedM).padStart(2,'0') + ':' + String(selectedS).padStart(2,'0');
          currentInput.value = v;
          currentInput.dispatchEvent(new Event('change',{bubbles:true}));
        }
        hide();
      };
    }

    // Outside/scroll/resize close
    closeHandlers.outside = function(e){ if (!el.contains(e.target) && e.target !== currentInput && !e.target.closest('.time-icon')) hide(); };
    closeHandlers.scroll = function(){ if (el.classList.contains('show')) position(); };
    closeHandlers.resize = function(){ if (el.classList.contains('show')) position(); };
    document.addEventListener('click', closeHandlers.outside);
    window.addEventListener('scroll', closeHandlers.scroll, true);
    window.addEventListener('resize', closeHandlers.resize);
  }
  function hide(){ if(!picker) return; picker.classList.remove('show'); document.removeEventListener('click', closeHandlers.outside); window.removeEventListener('scroll', closeHandlers.scroll, true); window.removeEventListener('resize', closeHandlers.resize); currentInput=null; }

  // Bind icon & input
  var timeIcon = attendanceModal.querySelector('.time-icon[data-target="att-time"]');
  if (timeIcon){ timeIcon.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); var t=document.getElementById('att-time'); if(t) show(t); }); }
  var timeInput = document.getElementById('att-time');
  if (timeInput){ timeInput.addEventListener('click', function(e){ e.preventDefault(); show(timeInput); }); timeInput.addEventListener('focus', function(e){ e.preventDefault(); show(timeInput); }); }
  // Expose a global opener for inline handlers
  window.openTimePickerAtt = function(){ var t=document.getElementById('att-time'); if (t) show(t); };
  // Delegated fallback (in case elements are re-rendered)
  document.addEventListener('click', function(e){
    var icon = e.target.closest('.time-icon[data-target="att-time"]');
    if (icon){ e.preventDefault(); e.stopPropagation(); var t = document.getElementById('att-time'); if(t) show(t); return; }
    var inp = e.target.closest('#att-time');
    if (inp){ e.preventDefault(); show(inp); }
  }, true);
});

// Custom Time Picker for Attendance Edit modal
document.addEventListener('DOMContentLoaded', function(){
  var editModal = document.getElementById('attendance-edit-modal');
  if (!editModal) return;

  // Get current language texts for time picker
  function getTimePickerTexts() {
    var lang = window.getCurrentLanguage ? window.getCurrentLanguage() : (window.APP_LANG || 'vn');
    var texts = {
      vn: {
        now: 'Bây giờ',
        clear: 'Xóa',
        hour: 'GIỜ',
        minute: 'PHÚT',
        second: 'GIÂY'
      },
      eng: {
        now: 'Now',
        clear: 'Clear',
        hour: 'HOUR',
        minute: 'MINUTE',
        second: 'SECOND'
      }
    };
    return texts[lang] || texts.vn;
  }

  var picker = null, currentInput = null;
  var selectedH = 0, selectedM = 0, selectedS = 0;
  var closeHandlers = { scroll:null, resize:null, outside:null };

  function createTimePicker(){
    var texts = getTimePickerTexts();
    var el = document.createElement('div');
    el.className = 'luna-time-picker';
    el.id = 'luna-time-picker-edit';
    el.innerHTML = '\
      <div class="luna-time-header">\
        <div class="luna-time-display" id="tp-display-edit">00:00:00</div>\
        <div class="luna-time-actions">\
          <button type="button" class="now-btn">' + texts.now + '</button>\
          <button type="button" class="clear-btn">' + texts.clear + '</button>\
          <button type="button" class="ok-btn-header">OK</button>\
        </div>\
      </div>\
      <div class="luna-time-columns">\
        <div class="time-col hours"></div>\
        <div class="time-sep">:</div>\
        <div class="time-col minutes"></div>\
        <div class="time-sep">:</div>\
        <div class="time-col seconds"></div>\
      </div>\
      <div class="time-labels">\
        <div class="lbl">' + texts.hour + '</div><div class="spacer"></div><div class="lbl">' + texts.minute + '</div><div class="spacer"></div><div class="lbl">' + texts.second + '</div>\
      </div>';
    document.body.appendChild(el);
    return el;
  }

  function getPicker(){ if(!picker) picker = createTimePicker(); return picker; }

  function updateDisplay(){
    var d = document.getElementById('tp-display-edit');
    if (d) d.textContent = String(selectedH).padStart(2,'0') + ':' + String(selectedM).padStart(2,'0') + ':' + String(selectedS).padStart(2,'0');
  }

  function renderColumns(){
    var el = getPicker();
    var hCol = el.querySelector('.hours');
    var mCol = el.querySelector('.minutes');
    var sCol = el.querySelector('.seconds');
    hCol.innerHTML = ''; mCol.innerHTML=''; sCol.innerHTML='';
    for (var h=0; h<24; h++){
      var b=document.createElement('div'); b.className='time-item'+(h===selectedH?' selected':''); b.textContent=String(h).padStart(2,'0'); b.dataset.h=h;
      b.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); selectedH = parseInt(e.target.dataset.h,10); renderColumns(); updateDisplay(); });
      hCol.appendChild(b);
    }
    for (var m=0; m<60; m+=1){
      var c=document.createElement('div'); c.className='time-item'+(m===selectedM?' selected':''); c.textContent=String(m).padStart(2,'0'); c.dataset.m=m;
      c.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); selectedM = parseInt(e.target.dataset.m,10); renderColumns(); updateDisplay(); });
      mCol.appendChild(c);
    }
    for (var s=0; s<60; s+=1){
      var d=document.createElement('div'); d.className='time-item'+(s===selectedS?' selected':''); d.textContent=String(s).padStart(2,'0'); d.dataset.s=s;
      d.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); selectedS = parseInt(e.target.dataset.s,10); renderColumns(); updateDisplay(); });
      sCol.appendChild(d);
    }
    updateDisplay();
  }

  function position(){
    var el = getPicker(); if(!currentInput) return;
    var rect = currentInput.getBoundingClientRect();
    var wrap = currentInput.closest('.input-wrap');
    var box = wrap ? wrap.getBoundingClientRect() : rect;
    var left = box.left; var top = box.bottom + 6;
    var w = 220, h = 240;
    if (left + w > window.innerWidth) left = window.innerWidth - w - 10;
    if (left < 10) left = 10;
    if (top + h > window.innerHeight) top = box.top - h - 6;
    if (top < 10) top = 10;
    el.style.left = left + 'px'; el.style.top = top + 'px';
  }
  
  function show(input){
    currentInput = input;
    // Parse current value (HH:MM[:SS])
    var h=0,m=0,s=0;
    if (input && input.value){
      var parts = input.value.split(':');
      if (parts.length>=2){ h = parseInt(parts[0]||'0',10)||0; m = parseInt(parts[1]||'0',10)||0; }
      if (parts.length>=3){ s = parseInt(parts[2]||'0',10)||0; }
    } else {
      var now = new Date(); h = now.getHours(); m = now.getMinutes(); s = now.getSeconds();
    }
    selectedH = Math.max(0, Math.min(23, h));
    selectedM = Math.max(0, Math.min(59, m));
    selectedS = Math.max(0, Math.min(59, s));

    var el = getPicker(); renderColumns(); position(); el.classList.add('show');

    // Bind actions
    el.querySelector('.now-btn').onclick = function(){ var n=new Date(); var v = String(n.getHours()).padStart(2,'0') + ':' + String(n.getMinutes()).padStart(2,'0') + ':' + String(n.getSeconds()).padStart(2,'0'); if (currentInput){ currentInput.value = v; currentInput.dispatchEvent(new Event('change',{bubbles:true})); } hide(); };
    el.querySelector('.clear-btn').onclick = function(){ if(currentInput){ currentInput.value = ''; } hide(); };
    var okHeader = el.querySelector('.ok-btn-header');
    if (okHeader) {
      okHeader.onclick = function(){
        if (currentInput) {
          var v = String(selectedH).padStart(2,'0') + ':' + String(selectedM).padStart(2,'0') + ':' + String(selectedS).padStart(2,'0');
          currentInput.value = v;
          currentInput.dispatchEvent(new Event('change',{bubbles:true}));
        }
        hide();
      };
    }

    // Outside/scroll/resize close
    closeHandlers.outside = function(e){ if (!el.contains(e.target) && e.target !== currentInput && !e.target.closest('.time-icon')) hide(); };
    closeHandlers.scroll = function(){ if (el.classList.contains('show')) position(); };
    closeHandlers.resize = function(){ if (el.classList.contains('show')) position(); };
    document.addEventListener('click', closeHandlers.outside);
    window.addEventListener('scroll', closeHandlers.scroll, true);
    window.addEventListener('resize', closeHandlers.resize);
  }
  
  function hide(){ if(!picker) return; picker.classList.remove('show'); document.removeEventListener('click', closeHandlers.outside); window.removeEventListener('scroll', closeHandlers.scroll, true); window.removeEventListener('resize', closeHandlers.resize); currentInput=null; }

  // Bind icon & input
  var timeIcon = editModal.querySelector('.time-icon[data-target="att-edit-time"]');
  if (timeIcon){ timeIcon.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); var t=document.getElementById('att-edit-time'); if(t) show(t); }); }
  var timeInput = document.getElementById('att-edit-time');
  if (timeInput){ timeInput.addEventListener('click', function(e){ e.preventDefault(); show(timeInput); }); timeInput.addEventListener('focus', function(e){ e.preventDefault(); show(timeInput); }); }
  // Expose a global opener for inline handlers
  window.openTimePickerAttEdit = function(){ var t=document.getElementById('att-edit-time'); if (t) show(t); };
  // Delegated fallback
  document.addEventListener('click', function(e){
    var icon = e.target.closest('.time-icon[data-target="att-edit-time"]');
    if (icon){ e.preventDefault(); e.stopPropagation(); var t = document.getElementById('att-edit-time'); if(t) show(t); return; }
    var inp = e.target.closest('#att-edit-time');
    if (inp){ e.preventDefault(); show(inp); }
  }, true);
});

// Custom Time Picker for Attendance Update modal
document.addEventListener('DOMContentLoaded', function(){
  var updateModal = document.getElementById('attendance-update-modal');
  if (!updateModal) return;

  // Get current language texts for time picker
  function getTimePickerTexts() {
    var lang = window.getCurrentLanguage ? window.getCurrentLanguage() : (window.APP_LANG || 'vn');
    var texts = {
      vn: {
        now: 'Bây giờ',
        clear: 'Xóa',
        hour: 'GIỜ',
        minute: 'PHÚT',
        second: 'GIÂY'
      },
      eng: {
        now: 'Now',
        clear: 'Clear',
        hour: 'HOUR',
        minute: 'MINUTE',
        second: 'SECOND'
      }
    };
    return texts[lang] || texts.vn;
  }

  var picker = null, currentInput = null;
  var selectedH = 0, selectedM = 0, selectedS = 0;
  var closeHandlers = { scroll:null, resize:null, outside:null };

  function createTimePicker(){
    var texts = getTimePickerTexts();
    var el = document.createElement('div');
    el.className = 'luna-time-picker';
    el.id = 'luna-time-picker-update';
    el.innerHTML = '\
      <div class="luna-time-header">\
        <div class="luna-time-display" id="tp-display-update">00:00:00</div>\
        <div class="luna-time-actions">\
          <button type="button" class="now-btn">' + texts.now + '</button>\
          <button type="button" class="clear-btn">' + texts.clear + '</button>\
          <button type="button" class="ok-btn-header">OK</button>\
        </div>\
      </div>\
      <div class="luna-time-columns">\
        <div class="time-col hours"></div>\
        <div class="time-sep">:</div>\
        <div class="time-col minutes"></div>\
        <div class="time-sep">:</div>\
        <div class="time-col seconds"></div>\
      </div>\
      <div class="time-labels">\
        <div class="lbl">' + texts.hour + '</div><div class="spacer"></div><div class="lbl">' + texts.minute + '</div><div class="spacer"></div><div class="lbl">' + texts.second + '</div>\
      </div>';
    document.body.appendChild(el);
    return el;
  }

  function getPicker(){ if(!picker) picker = createTimePicker(); return picker; }

  function updateDisplay(){
    var d = document.getElementById('tp-display-update');
    if (d) d.textContent = String(selectedH).padStart(2,'0') + ':' + String(selectedM).padStart(2,'0') + ':' + String(selectedS).padStart(2,'0');
  }

  function renderColumns(){
    var el = getPicker();
    var hCol = el.querySelector('.hours');
    var mCol = el.querySelector('.minutes');
    var sCol = el.querySelector('.seconds');
    hCol.innerHTML = ''; mCol.innerHTML=''; sCol.innerHTML='';
    for (var h=0; h<24; h++){
      var b=document.createElement('div'); b.className='time-item'+(h===selectedH?' selected':''); b.textContent=String(h).padStart(2,'0'); b.dataset.h=h;
      b.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); selectedH = parseInt(e.target.dataset.h,10); renderColumns(); updateDisplay(); });
      hCol.appendChild(b);
    }
    for (var m=0; m<60; m+=1){
      var c=document.createElement('div'); c.className='time-item'+(m===selectedM?' selected':''); c.textContent=String(m).padStart(2,'0'); c.dataset.m=m;
      c.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); selectedM = parseInt(e.target.dataset.m,10); renderColumns(); updateDisplay(); });
      mCol.appendChild(c);
    }
    for (var s=0; s<60; s+=1){
      var d=document.createElement('div'); d.className='time-item'+(s===selectedS?' selected':''); d.textContent=String(s).padStart(2,'0'); d.dataset.s=s;
      d.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); selectedS = parseInt(e.target.dataset.s,10); renderColumns(); updateDisplay(); });
      sCol.appendChild(d);
    }
    updateDisplay();
  }

  function position(){
    var el = getPicker(); if(!currentInput) return;
    var rect = currentInput.getBoundingClientRect();
    var wrap = currentInput.closest('.input-wrap');
    var box = wrap ? wrap.getBoundingClientRect() : rect;
    var left = box.left; var top = box.bottom + 6;
    var w = 220, h = 240;
    if (left + w > window.innerWidth) left = window.innerWidth - w - 10;
    if (left < 10) left = 10;
    if (top + h > window.innerHeight) top = box.top - h - 6;
    if (top < 10) top = 10;
    el.style.left = left + 'px'; el.style.top = top + 'px';
  }
  
  function show(input){
    currentInput = input;
    // Parse current value (HH:MM[:SS])
    var h=0,m=0,s=0;
    if (input && input.value){
      var parts = input.value.split(':');
      if (parts.length>=2){ h = parseInt(parts[0]||'0',10)||0; m = parseInt(parts[1]||'0',10)||0; }
      if (parts.length>=3){ s = parseInt(parts[2]||'0',10)||0; }
    } else {
      var now = new Date(); h = now.getHours(); m = now.getMinutes(); s = now.getSeconds();
    }
    selectedH = Math.max(0, Math.min(23, h));
    selectedM = Math.max(0, Math.min(59, m));
    selectedS = Math.max(0, Math.min(59, s));

    var el = getPicker(); renderColumns(); position(); el.classList.add('show');

    // Bind actions
    el.querySelector('.now-btn').onclick = function(){ var n=new Date(); var v = String(n.getHours()).padStart(2,'0') + ':' + String(n.getMinutes()).padStart(2,'0') + ':' + String(n.getSeconds()).padStart(2,'0'); if (currentInput){ currentInput.value = v; currentInput.dispatchEvent(new Event('change',{bubbles:true})); } hide(); };
    el.querySelector('.clear-btn').onclick = function(){ if(currentInput){ currentInput.value = ''; } hide(); };
    var okHeader = el.querySelector('.ok-btn-header');
    if (okHeader) {
      okHeader.onclick = function(){
        if (currentInput) {
          var v = String(selectedH).padStart(2,'0') + ':' + String(selectedM).padStart(2,'0') + ':' + String(selectedS).padStart(2,'0');
          currentInput.value = v;
          currentInput.dispatchEvent(new Event('change',{bubbles:true}));
        }
        hide();
      };
    }

    // Outside/scroll/resize close
    closeHandlers.outside = function(e){ if (!el.contains(e.target) && e.target !== currentInput && !e.target.closest('.time-icon')) hide(); };
    closeHandlers.scroll = function(){ if (el.classList.contains('show')) position(); };
    closeHandlers.resize = function(){ if (el.classList.contains('show')) position(); };
    document.addEventListener('click', closeHandlers.outside);
    window.addEventListener('scroll', closeHandlers.scroll, true);
    window.addEventListener('resize', closeHandlers.resize);
  }
  
  function hide(){ if(!picker) return; picker.classList.remove('show'); document.removeEventListener('click', closeHandlers.outside); window.removeEventListener('scroll', closeHandlers.scroll, true); window.removeEventListener('resize', closeHandlers.resize); currentInput=null; }

  // Bind icon & input
  var timeIcon = updateModal.querySelector('.time-icon[data-target="att-update-time"]');
  if (timeIcon){ timeIcon.addEventListener('click', function(e){ e.preventDefault(); e.stopPropagation(); var t=document.getElementById('att-update-time'); if(t) show(t); }); }
  function preventManualTyping(input){
    if (!input) return;
    var allowKeys = ['Tab','Shift','ArrowLeft','ArrowRight','Home','End'];
    input.addEventListener('keydown', function(e){
      if (e.ctrlKey || e.metaKey) return;
      if (allowKeys.indexOf(e.key) !== -1) return;
      if (/^\d$/.test(e.key)){
        e.preventDefault();
        show(input);
        return;
      }
      e.preventDefault();
      if (e.key === 'Enter' || e.key === ' '){
        show(input);
      }
    }, true);
    input.addEventListener('beforeinput', function(e){
      e.preventDefault();
      show(input);
    }, true);
    input.addEventListener('paste', function(e){
      e.preventDefault();
      show(input);
    }, true);
  }

  var timeInput = document.getElementById('att-update-time');
  if (timeInput){
    preventManualTyping(timeInput);
    timeInput.addEventListener('click', function(e){ e.preventDefault(); show(timeInput); });
    timeInput.addEventListener('focus', function(e){ e.preventDefault(); show(timeInput); });
  }
  // Expose a global opener for inline handlers
  window.openTimePickerAttUpdate = function(){ var t=document.getElementById('att-update-time'); if (t) show(t); };
  // Delegated fallback
  document.addEventListener('click', function(e){
    var icon = e.target.closest('.time-icon[data-target="att-update-time"]');
    if (icon){ e.preventDefault(); e.stopPropagation(); var t = document.getElementById('att-update-time'); if(t) show(t); return; }
    var inp = e.target.closest('#att-update-time');
    if (inp){ e.preventDefault(); show(inp); }
  }, true);
});
</script>

<script>
// Client-side validation for Attendance form - keep page and show toast on error
(function(){
  var form = document.getElementById('attendance-form');
  if (!form) return;
  form.addEventListener('submit', function(ev){
    var pinEl = document.getElementById('att-pin');
    var nameEl = document.getElementById('att-name');
    var dateEl = document.getElementById('att-date');
    var pin  = pinEl ? String(pinEl.value).trim()  : '';
    var name = nameEl ? String(nameEl.value).trim() : '';
    var date = dateEl ? String(dateEl.value).trim() : '';

    // reset decorations
    [pinEl,nameEl,dateEl].forEach(function(el){ if(el){ el.style.borderColor=''; el.style.boxShadow=''; }});

    var errs = [];
    var msgEmpId = (window.__MESSAGES__ && window.__MESSAGES__['attendance_validation_employee_id_required']) ? window.__MESSAGES__['attendance_validation_employee_id_required'] : '* Mã nhân viên không được để trống.';
    var msgFullName = (window.__MESSAGES__ && window.__MESSAGES__['attendance_validation_full_name_required']) ? window.__MESSAGES__['attendance_validation_full_name_required'] : '* Họ tên không được để trống.';
    var msgDate = (window.__MESSAGES__ && window.__MESSAGES__['attendance_validation_date_required']) ? window.__MESSAGES__['attendance_validation_date_required'] : '* Ngày không được để trống.';
    if (!pin)  errs.push('* ' + msgEmpId);
    if (!name) errs.push('* ' + msgFullName);
    if (!date) errs.push('* ' + msgDate);

    if (errs.length){
      ev.preventDefault();
      // highlight fields

      var title = (window.__MESSAGES__ && window.__MESSAGES__['error_notification_title']) ? window.__MESSAGES__['error_notification_title'] : 'THÔNG BÁO';
      var body  = errs.join('<br>');
      if (typeof window.showToast === 'function'){
        window.showToast('error', '<div class="error-header">'+title+'</div>'+body);
      } else {
        alert(errs.join('\n'));
      }
    }
  });
})();

// Client-side validation for Attendance Edit form
(function(){
  var form = document.getElementById('attendance-edit-form');
  if (!form) return;
  form.addEventListener('submit', function(ev){
    var dateEl = document.getElementById('att-edit-date');
    var date = dateEl ? String(dateEl.value).trim() : '';

    // reset decorations
    if(dateEl){ dateEl.style.borderColor=''; dateEl.style.boxShadow=''; }

    var errs = [];
    var msgDate = (window.__MESSAGES__ && window.__MESSAGES__['attendance_validation_date_required']) ? window.__MESSAGES__['attendance_validation_date_required'] : '* Ngày không được để trống.';
    if (!date) errs.push('* ' + msgDate);

    if (errs.length){
      ev.preventDefault();
      var title = (window.__MESSAGES__ && window.__MESSAGES__['error_notification_title']) ? window.__MESSAGES__['error_notification_title'] : 'THÔNG BÁO';
      var body  = errs.join('<br>');
      if (typeof window.showToast === 'function'){
        window.showToast('error', '<div class="error-header">'+title+'</div>'+body);
      } else {
        alert(errs.join('\n'));
      }
    }
  });
})();
</script>

<?php if ($__att_created): ?>
<script>
  document.addEventListener('DOMContentLoaded', function(){
    try {
      var title = (window.__MESSAGES__ && window.__MESSAGES__['success_notification_title']) ? window.__MESSAGES__['success_notification_title'] : 'THÔNG BÁO';
      var body = <?= json_encode($__att_created_msg, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
      if (typeof window.showToast === 'function') {
        window.showToast('success', '<div class="success-header">' + title + '</div>' + body);
      }
    } catch(e) {}
  });
</script>
<?php endif; ?>

<?php if ($__att_edited ?? false): ?>
<script>
  document.addEventListener('DOMContentLoaded', function(){
    try {
      var title = (window.__MESSAGES__ && window.__MESSAGES__['success_notification_title']) ? window.__MESSAGES__['success_notification_title'] : 'THÔNG BÁO';
      var body = <?= json_encode($__att_edited_msg ?? '', JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
      if (typeof window.showToast === 'function') {
        window.showToast('success', '<div class="success-header">' + title + '</div>' + body);
      }
    } catch(e) {}
  });
</script>
<?php endif; ?>
