<?php
// dashboard.php - v17.1: Enhanced Security & Performance
// Security Headers
header('X-Frame-Options: SAMEORIGIN');
header('X-Content-Type-Options: nosniff');
header('X-XSS-Protection: 1; mode=block');
header('Referrer-Policy: strict-origin-when-cross-origin');

session_name('FONFIX_SYSTEM_ID');
session_start();
require 'db.php'; 

if (!isset($_SESSION['_dashboard_migrations_done'])) {
    $newColumns = [
        'can_add_cross_branch_stock',
        'can_view_stock_logs',
        'can_merge_stock',
        'can_bulk_ops',
        'can_bulk_print',
        'can_bulk_import',
        'can_convert_uppercase'
    ];
    foreach ($newColumns as $col) {
        try {
            $checkColumn = $pdo->query("SHOW COLUMNS FROM users LIKE '$col'");
            if ($checkColumn->rowCount() == 0) {
                $pdo->exec("ALTER TABLE users ADD COLUMN $col TINYINT(1) DEFAULT 0");
            }
        } catch (Exception $e) {}
    }
    $_SESSION['_dashboard_migrations_done'] = true;
}

if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
    header('Location: index.php');
    exit;
}

$user_role  = $_SESSION['role'] ?? ''; 
$username   = strtolower($_SESSION['user'] ?? '');
$is_endie   = ($username === 'endie');
$is_master  = ($user_role === 'master');
$can_admin  = ($is_master || $is_endie);

// --- FETCH LIVE PERMISSIONS ---
$stmt = $pdo->prepare("SELECT can_edit, can_delete, can_transfer, can_refund, can_restore, can_add_cross_branch_stock, can_view_stock_logs, can_merge_stock, can_bulk_ops, can_bulk_print, can_bulk_import, can_convert_uppercase FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$perms = $stmt->fetch(PDO::FETCH_ASSOC);

$can_edit_bool     = ($is_endie || $is_master || ($perms['can_edit'] ?? 0) == 1);
$can_delete_bool   = ($is_endie || $is_master || ($perms['can_delete'] ?? 0) == 1);
$can_transfer_bool = ($is_endie || $is_master || ($perms['can_transfer'] ?? 0) == 1);
$can_refund_bool   = ($is_endie || $is_master || ($perms['can_refund'] ?? 0) == 1);
$can_restore_bool  = ($is_endie || $is_master || ($perms['can_restore'] ?? 0) == 1);
$can_cross_branch_stock = ($is_endie || $is_master || ($perms['can_add_cross_branch_stock'] ?? 0) == 1);
$can_view_stock_logs = ($is_endie || $is_master || ($perms['can_view_stock_logs'] ?? 0) == 1);
$can_merge_stock = ($is_endie || $is_master || ($perms['can_merge_stock'] ?? 0) == 1);
$can_bulk_ops = ($is_endie || $is_master || ($perms['can_bulk_ops'] ?? 0) == 1);
$can_bulk_print = ($is_endie || $is_master || ($perms['can_bulk_print'] ?? 0) == 1);
$can_bulk_import = ($is_endie || $is_master || ($perms['can_bulk_import'] ?? 0) == 1);
$can_convert_uppercase = ($is_endie || $is_master || ($perms['can_convert_uppercase'] ?? 0) == 1);

$can_edit     = $can_edit_bool ? 'true' : 'false';
$can_delete   = $can_delete_bool ? 'true' : 'false';
$can_transfer = $can_transfer_bool ? 'true' : 'false';
$can_refund   = $can_refund_bool ? 'true' : 'false';
$can_restore  = $can_restore_bool ? 'true' : 'false';
$can_cross_stock = $can_cross_branch_stock ? 'true' : 'false';

// Generate CSRF token if it doesn't exist
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
$csrf_token = $_SESSION['csrf_token'];

$my_branch = $_SESSION['assigned_branch'] ?? '';
$is_restricted = !($is_master || $is_endie) && !empty($my_branch);
if (!$is_restricted) { $my_branch = $my_branch ?: 'Gombak'; }

function renderBranchOptions($selected = '', $allowAll = false) {
    global $is_restricted, $my_branch;
    if (!$is_restricted) {
        if ($allowAll) echo '<option value="all">All Branches</option>';
        echo '<option value="Gombak" '.($selected=='Gombak'?'selected':'').'>Gombak</option>';
        echo '<option value="Sri Rampai" '.($selected=='Sri Rampai'?'selected':'').'>Sri Rampai</option>';
    } else {
        echo '<option value="'.$my_branch.'">'.$my_branch.'</option>';
    }
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>Fon2Fix :: DASHBOARD</title>
    <link rel="icon" type="image/png" href="logo.png">
    <link rel="shortcut icon" type="image/png" href="logo.png">
    <link rel="apple-touch-icon" href="logo.png">
    <!-- Warm the TLS handshake for cdnjs before the SRI-pinned scripts below run. -->
    <link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
    <link rel="dns-prefetch" href="https://cdnjs.cloudflare.com">
    <!-- Pinned + SRI (was floating: chart.js, html5-qrcode). All hashes from cdnjs. -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.0/chart.umd.min.js"
            integrity="sha512-Y51n9mtKTVBh3Jbx5pZSJNDDMyY+yGe77DGtBPzRlgsf/YLCh13kSZ3JmfHGzYFCmOndraf0sQgfM654b7dJ3w=="
            crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/qrious/4.0.2/qrious.min.js"
            integrity="sha512-pUhApVQtLbnpLtJn6DuzDD5o2xtmLJnJ7oBoMsBnzOkVkpqofGLGPaBJ6ayD2zQe3lCgCibhJBi4cj5wAxwVKA=="
            crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html5-qrcode/2.3.8/html5-qrcode.min.js"
            integrity="sha512-r6rDA7W6ZeQhvl8S7yRVQUKVHdexq+GAlNkNNqVC7YyIV+NwqCTJe2hDWCiffTyRNOeGEzRRJ9ifvRm/HCzGYg=="
            crossorigin="anonymous" referrerpolicy="no-referrer" type="text/javascript"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"
            integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg=="
            crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jsbarcode/3.11.5/JsBarcode.all.min.js"
            integrity="sha512-QEAheCz+x/VkKtxeGoDq6nsGyzTx/0LMINTgQjqZ0h3+NjP+bCsPYz3hn0HnBkGmkIFSr7QcEZT+KyEM7lbLPQ=="
            crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    
    <style>
        /* ROS DESIGN SYSTEM */
        :root {
            --primary: hsl(245 58% 51%);
            --secondary: hsl(245 58% 45%);
            --accent: hsl(350 72% 54%);
            --success: hsl(151 55% 41%);
            --bg: hsl(220 20% 97%);
            --text: hsl(220 26% 12%);
            --card-bg: #ffffff;
            --border: hsl(220 16% 88%);
            --input-bg: #ffffff;
            --muted: hsl(220 12% 46%);
            --focus-ring: hsl(245 58% 70% / 0.2);
            --danger: hsl(350 72% 54%);
            --warn: hsl(38 92% 48%);
        }
        * { box-sizing: border-box; }
        body {
            font-family: Inter, 'Segoe UI', Roboto, sans-serif;
            background:
                radial-gradient(circle at 12% 8%, hsl(245 90% 74% / 0.16), transparent 38%),
                radial-gradient(circle at 84% 14%, hsl(197 92% 70% / 0.14), transparent 40%),
                linear-gradient(180deg, hsl(220 34% 98%) 0%, var(--bg) 34%, hsl(220 24% 95%) 100%);
            color: var(--text);
            margin: 0;
            padding: 14px;
            min-height: 100vh;
            font-size: 14px;
            letter-spacing: -0.01em;
        }
        .container { max-width: 1200px; margin: 0 auto; padding-bottom: 50px; }
        
        .card {
            background: linear-gradient(180deg, hsl(0 0% 100% / 0.92) 0%, hsl(0 0% 100% / 0.86) 100%);
            border: 1px solid hsl(220 14% 88% / 0.65);
            padding: 20px;
            border-radius: 16px;
            box-shadow: 0 1px 2px hsl(220 20% 20% / 0.05), 0 12px 30px hsl(220 22% 16% / 0.06);
            backdrop-filter: blur(10px);
            margin-bottom: 20px;
            transition: box-shadow 0.2s ease, transform 0.2s ease;
        }
        .card:hover {
            box-shadow: 0 1px 2px hsl(220 20% 20% / 0.05), 0 16px 36px hsl(220 26% 20% / 0.1);
            transform: translateY(-1px);
        }
        .form-row { display: flex; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
        .form-group { flex: 1; min-width: 140px; }
        .d-none { display: none !important; }

        h1 { text-align: center; margin: 10px 0 25px 0; font-weight: 800; color: var(--secondary); font-size: 1.8rem; letter-spacing: -0.5px; }
        .section-title { font-size: 0.8rem; text-transform: uppercase; color: var(--primary); font-weight: 700; margin: 10px 0 15px 0; border-bottom: 2px solid hsl(220 14% 92%); padding-bottom: 5px; }

        label { display: block; font-size: 0.75rem; font-weight: 700; margin-bottom: 5px; color: var(--muted); text-transform: uppercase; }
        input, select, textarea {
            width: 100%;
            padding: 11px 13px;
            background: var(--input-bg);
            border: 1px solid hsl(220 14% 84%);
            border-radius: 12px;
            color: var(--text);
            font-size: 15px;
            transition: border-color 0.2s ease, box-shadow 0.2s ease;
        }
        input:focus, select:focus, textarea:focus {
            outline: none;
            border-color: hsl(245 58% 60%);
            box-shadow: 0 0 0 4px var(--focus-ring);
        }
        
        .btn {
            padding: 10px 13px;
            border: 1px solid hsl(220 14% 84%);
            border-radius: 12px;
            cursor: pointer;
            font-weight: 700;
            text-transform: uppercase;
            color: var(--text);
            background: #fff;
            width: 100%;
            margin-top: 10px;
            transition: transform 0.15s ease, box-shadow 0.2s ease, border-color 0.2s ease;
        }
        .btn:hover {
            border-color: hsl(245 58% 70%);
            box-shadow: 0 8px 24px hsl(220 24% 20% / 0.08), 0 2px 8px hsl(220 20% 16% / 0.07);
            transform: translateY(-1px);
        }
        .btn-primary {
            background: linear-gradient(180deg, var(--primary) 0%, var(--secondary) 100%);
            color: #fff;
            border: 0;
        }
        .btn-accent { background: #9b59b6; }
        .btn-danger {
            background: linear-gradient(180deg, hsl(350 84% 60%) 0%, hsl(350 72% 54%) 100%);
            border: 0;
            color: #fff;
        }
        .btn-success { background: var(--success); }
        .btn-edit { background: #f39c12; color: white; }
        .btn-action { padding: 6px 10px; width: auto; margin:0; background: #fff; border:1px solid hsl(220 14% 84%); color:#555; margin-right: 4px; border-radius: 10px; font-size: 1.1rem; }
        .btn-action:hover { background: hsl(245 100% 98%); color: var(--primary); border-color: hsl(245 58% 70%); }

        /* BUTTON ICONS */
        .btn-icon { width: 32px; height: 32px; border: none; border-radius: 6px; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: 1rem; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-left: 3px; color: white; }
        .btn-icon:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.15); }
        .btn-transfer { background: #3498db; }
        .btn-qr-sg { background: #2ecc71; font-weight: 800; font-size: 0.7rem; }
        .btn-qr-sr { background: #9b59b6; font-weight: 800; font-size: 0.7rem; }
        .btn-edit-item { background: #f39c12; }
        .btn-delete-item { background: #e74c3c; }

        .mode-switch { display: flex; background: #ffffffc7; border-radius: 14px; padding: 7px; margin-bottom: 20px; border: 1px solid hsl(220 16% 88% / 0.85); box-shadow: 0 6px 18px hsl(220 24% 16% / 0.06); backdrop-filter: blur(8px); }
        .mode-btn { flex: 1; background: transparent; color: #7f8c8d; border: none; padding: 12px; font-weight: 600; cursor: pointer; border-radius: 8px; transition: 0.2s; }
        .mode-btn:hover { background: hsl(245 100% 97%); color: var(--primary); }
        .mode-btn.active { background: linear-gradient(180deg, var(--primary) 0%, var(--secondary) 100%); color: white; box-shadow: 0 8px 20px hsl(245 58% 40% / 0.2); }
        
        .table-container { overflow-x: auto; border-radius: 12px; border: 1px solid var(--border); background: #fff; }
        table { width: 100%; border-collapse: collapse; min-width: 800px; }
        th { background: hsl(220 22% 97%); color: #555; padding: 12px 15px; font-size: 0.8rem; text-align: left; border-bottom: 2px solid #e9ecef; font-weight: 800; }
        td { padding: 12px 15px; border-bottom: 1px solid hsl(220 20% 94%); font-size: 0.9rem; vertical-align: top; color: #333; }
        .job-id { background: hsl(245 100% 97%); color: var(--primary); padding: 2px 8px; border-radius: 8px; font-family: monospace; font-weight: bold; border: 1px solid hsl(245 72% 88%); }
        .payment-badge { font-size: 0.8rem; background: hsl(220 20% 96%); padding: 2px 6px; border-radius: 8px; border:1px solid hsl(220 14% 88%); }
        
        #toast-container { position: fixed; top: 20px; right: 20px; z-index: 99999; display: flex; flex-direction: column; gap: 10px; }
        .toast { background: #fff; color: #333; padding: 15px 20px; border-radius: 8px; box-shadow: 0 5px 20px rgba(0,0,0,0.15); display: flex; align-items: center; gap: 12px; min-width: 250px; animation: slideIn 0.3s ease-out, fadeOut 0.5s ease-in 3.5s forwards; border-left: 5px solid #ccc; font-weight: 600; }
        .toast.success { border-left-color: #2ecc71; }
        .toast.error { border-left-color: #e74c3c; }
        
        @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
        @keyframes fadeOut { to { opacity: 0; transform: translateY(-20px); } }

        .modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); backdrop-filter: blur(3px); justify-content: center; align-items: center; z-index: 1000; padding: 10px; }
        .modal-content { background: linear-gradient(180deg, hsl(0 0% 100% / 0.9) 0%, hsl(0 0% 100% / 0.84) 100%); border: 1px solid hsl(220 16% 88% / 0.7); color: #333; padding: 30px; border-radius: 16px; width: 100%; max-width: 500px; max-height: 90vh; overflow-y: auto; box-shadow: 0 20px 50px rgba(0,0,0,0.2); backdrop-filter: blur(10px); }
        
        .pattern-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; width: 180px; margin: 20px auto; user-select: none; }
        .pattern-dot { width: 20px; height: 20px; background: #ddd; border-radius: 50%; cursor: pointer; position: relative; transition: 0.2s; margin: auto; border: 2px solid #ccc; }
        .pattern-dot.active { background: var(--primary); box-shadow: 0 0 10px var(--primary); transform: scale(1.3); border-color: #fff; }
        #patternModal { z-index: 10001; } 

        .charts-row { display: flex; gap: 20px; margin-bottom: 20px; flex-wrap: wrap; }
        .chart-box { flex: 1; min-width: 300px; background: linear-gradient(180deg, hsl(0 0% 100% / 0.92) 0%, hsl(0 0% 100% / 0.86) 100%); padding: 15px; border-radius: 16px; border: 1px solid hsl(220 14% 88% / 0.65); }
        .chart-wrapper { position: relative; height: 300px; width: 100%; }
        .summary-stats { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }
        .stat-card { flex: 1; background: linear-gradient(180deg, #fff 0%, hsl(220 30% 99%) 100%); padding: 15px; border-radius: 14px; text-align: center; border: 1px solid hsl(220 16% 88%); box-shadow: 0 2px 5px rgba(0,0,0,0.05); }
        
        .stock-columns { display: flex; gap: 20px; flex-wrap: wrap; }
        .stock-col { flex: 1; min-width: 300px; background: linear-gradient(180deg, #fff 0%, hsl(220 30% 99%) 100%); padding: 15px; border-radius: 16px; border: 1px solid var(--border); }
        .stock-part-row { display: flex; gap: 10px; padding: 10px; background: #fff; border: 1px solid hsl(220 16% 91%); border-radius: 12px; margin-bottom: 6px; align-items: center; transition: 0.1s; }
        .stock-part-row:hover { background: hsl(245 100% 98%); border-color: hsl(245 72% 85%); }
        .stock-input { padding: 6px; background: hsl(220 28% 98%); border: 1px solid hsl(220 14% 86%); text-align: center; width: 60px; font-weight: bold; border-radius: 10px; color:#333; }
        
        #qrOverlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: #fff; z-index: 9999; display: none; flex-direction: column; justify-content: center; align-items: center; color: #333; }
        @media print {
            @page {
                size: 40mm 30mm;
                margin: 0;
                padding: 0;
            }
            * {
                margin: 0 !important;
                padding: 0 !important;
                box-sizing: border-box !important;
            }
            html {
                width: 40mm !important;
                height: 30mm !important;
                margin: 0 !important;
                padding: 0 !important;
                overflow: hidden !important;
            }
            body {
                width: 40mm !important;
                height: 30mm !important;
                margin: 0 !important;
                padding: 0 !important;
                overflow: hidden !important;
                page-break-after: avoid !important;
                page-break-before: avoid !important;
                page-break-inside: avoid !important;
            }
            body > *:not(#qrOverlay) {
                display: none !important;
                visibility: hidden !important;
            }
            #qrOverlay {
                display: flex !important;
                position: absolute !important;
                top: 0 !important;
                left: 0 !important;
                width: 40mm !important;
                height: 30mm !important;
                max-width: 40mm !important;
                max-height: 30mm !important;
                min-width: 40mm !important;
                min-height: 30mm !important;
                background: white !important;
                color: black !important;
                flex-direction: column !important;
                justify-content: flex-start !important;
                align-items: center !important;
                margin: 0 !important;
                padding: 0.5mm !important;
                box-sizing: border-box !important;
                page-break-after: avoid !important;
                page-break-inside: avoid !important;
                page-break-before: avoid !important;
                break-inside: avoid !important;
                break-after: avoid !important;
                break-before: avoid !important;
                overflow: hidden !important;
            }
            #qrOverlay > div {
                width: 100% !important;
                max-width: 100% !important;
                height: 100% !important;
                max-height: 100% !important;
                display: flex !important;
                flex-direction: column !important;
                align-items: center !important;
                justify-content: flex-start !important;
                overflow: hidden !important;
                padding: 0.5mm !important;
            }
            #qrOverlay * {
                visibility: visible !important;
            }
            #qrOverlay .no-print {
                display: none !important;
                visibility: hidden !important;
            }
            .no-print {
                display: none !important;
                visibility: hidden !important;
            }
            button {
                display: none !important;
                visibility: hidden !important;
            }
            #qrBranch {
                display: none !important;
            }
            /* Text on TOP - Order 1 - Match Top Label Style */
            #qrTitle {
                display: block !important;
                order: 1 !important;
                font-size: 7pt !important;
                font-weight: normal !important;
                margin: 0.8mm 0 0.4mm 0 !important;
                padding: 0 1.5mm !important;
                color: black !important;
                text-align: center !important;
                line-height: 1.3 !important;
                font-family: 'Arial', 'Helvetica', sans-serif !important;
                text-transform: uppercase !important;
                letter-spacing: 0.3px !important;
                page-break-after: avoid !important;
                page-break-inside: avoid !important;
                page-break-before: avoid !important;
                break-after: avoid !important;
                break-inside: avoid !important;
                break-before: avoid !important;
                word-wrap: break-word !important;
                overflow-wrap: break-word !important;
                max-height: 7mm !important;
                overflow: hidden !important;
                width: 100% !important;
            }
            /* Price/Additional Info - Order 2 - Match Top Label Style */
            #qrPrice {
                display: block !important;
                order: 2 !important;
                font-size: 7pt !important;
                font-weight: normal !important;
                margin: 0.2mm 0 0.6mm 0 !important;
                padding: 0 1.5mm !important;
                color: black !important;
                background: transparent !important;
                border: none !important;
                text-align: center !important;
                font-family: 'Arial', 'Helvetica', sans-serif !important;
                text-transform: uppercase !important;
                letter-spacing: 0.2px !important;
                page-break-after: avoid !important;
                page-break-inside: avoid !important;
                page-break-before: avoid !important;
                break-after: avoid !important;
                break-inside: avoid !important;
                break-before: avoid !important;
                max-height: 3mm !important;
                overflow: hidden !important;
                width: 100% !important;
            }
            /* QR Code on BOTTOM - Order 3 - Match Top Label Style */
            #qrCanvas {
                display: block !important;
                order: 3 !important;
                width: 18mm !important;
                height: 18mm !important;
                max-width: 18mm !important;
                max-height: 18mm !important;
                min-width: 18mm !important;
                min-height: 18mm !important;
                border: none !important;
                margin: 0.3mm auto 0 !important;
                padding: 0 !important;
                image-rendering: -webkit-optimize-contrast !important;
                image-rendering: crisp-edges !important;
                page-break-after: avoid !important;
                page-break-inside: avoid !important;
                page-break-before: avoid !important;
                break-after: avoid !important;
                break-inside: avoid !important;
                break-before: avoid !important;
            }
        }
        
        /* EDIT TABLE STYLES */
        .edit-table-input { border: 1px solid #ccc; padding: 6px; border-radius: 4px; width: 100%; font-size: 13px; }
        .edit-table-input:focus { border-color: var(--primary); outline: none; box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2); }

        /* BEGINNER-FRIENDLY UI IMPROVEMENTS */
        
        /* Tooltips */
        .tooltip-wrapper { position: relative; display: inline-block; }
        .tooltip-icon { display: inline-block; width: 16px; height: 16px; background: var(--primary); color: white; border-radius: 50%; text-align: center; font-size: 11px; line-height: 16px; cursor: help; margin-left: 5px; font-weight: bold; }
        .tooltip-text { visibility: hidden; position: absolute; bottom: 125%; left: 50%; transform: translateX(-50%); background: #333; color: #fff; padding: 8px 12px; border-radius: 6px; font-size: 12px; white-space: nowrap; z-index: 1000; opacity: 0; transition: opacity 0.3s; box-shadow: 0 4px 12px rgba(0,0,0,0.2); }
        .tooltip-text::after { content: ""; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); border: 5px solid transparent; border-top-color: #333; }
        .tooltip-wrapper:hover .tooltip-text { visibility: visible; opacity: 1; }

        /* Help Text & Hints */
        .help-text { font-size: 0.75rem; color: #7f8c8d; margin-top: 4px; font-style: italic; line-height: 1.4; }
        .help-text::before { content: "💡 "; }
        .help-box { background: #e8f4f8; border-left: 4px solid var(--primary); padding: 12px 15px; border-radius: 6px; margin: 10px 0; font-size: 0.85rem; color: #2c3e50; }
        .help-box strong { color: var(--primary); }
        .quick-tip { background: #fff3cd; border-left: 4px solid #ffc107; padding: 10px 15px; border-radius: 6px; margin-top: 10px; font-size: 0.85rem; color: #856404; }
        
        /* Required Field Indicator */
        .required-field::after { content: " *"; color: #e74c3c; font-weight: bold; }
        
        /* Status Badges */
        .status-badge { display: inline-block; padding: 4px 10px; border-radius: 12px; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; }
        .status-pending { background: #fff3cd; color: #856404; border: 1px solid #ffc107; }
        .status-completed { background: #d4edda; color: #155724; border: 1px solid #28a745; }
        .status-paid { background: #d1ecf1; color: #0c5460; border: 1px solid #17a2b8; }
        .status-unpaid { background: #f8d7da; color: #721c24; border: 1px solid #dc3545; }
        .status-partial { background: #ffeaa7; color: #d63031; border: 1px solid #fdcb6e; }
        
        /* Better Button Labels */
        .btn-label { display: flex; align-items: center; justify-content: center; gap: 8px; }
        .btn-label-icon { font-size: 1.1em; }
        
        /* Section Headers with Help */
        .section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
        .section-header .section-title { margin: 0; border: none; padding: 0; }
        .section-help-btn { background: transparent; border: 1px solid var(--border); color: #7f8c8d; padding: 4px 10px; border-radius: 4px; font-size: 0.7rem; cursor: help; }
        .section-help-btn:hover { background: #f8f9fa; color: var(--primary); border-color: var(--primary); }
        
        /* Form Field Groups */
        .field-group { margin-bottom: 15px; }
        .field-group label { display: flex; align-items: center; gap: 5px; }
        
        /* Visual Separators */
        .section-divider { height: 2px; background: linear-gradient(to right, transparent, var(--border), transparent); margin: 20px 0; }
        
        /* Info Cards */
        .info-card { background: #f8f9fa; border: 1px solid var(--border); border-radius: 8px; padding: 12px; margin: 10px 0; }
        .info-card-title { font-weight: 700; color: var(--primary); font-size: 0.85rem; margin-bottom: 5px; }
        .info-card-content { font-size: 0.8rem; color: #555; line-height: 1.5; }
        
        /* Better Mobile Responsiveness */
        @media (max-width: 768px) {
            .mode-switch { flex-wrap: wrap; }
            .mode-btn { min-width: calc(50% - 5px); font-size: 0.75rem; padding: 10px 8px; }
            .tooltip-text { font-size: 11px; padding: 6px 10px; max-width: 200px; white-space: normal; }
            .help-box, .quick-tip { font-size: 0.8rem; padding: 10px; }
        }
        
        /* Loading States */
        .btn.loading { opacity: 0.6; cursor: not-allowed; position: relative; }
        .btn.loading::after { content: "..."; animation: dots 1.5s steps(4, end) infinite; }
        @keyframes dots { 0%, 20% { content: "."; } 40% { content: ".."; } 60%, 100% { content: "..."; } }
        
        /* Empty State Messages */
        .empty-state { text-align: center; padding: 40px 20px; color: #95a5a6; }
        .empty-state-icon { font-size: 3rem; margin-bottom: 10px; opacity: 0.5; }
        .empty-state-text { font-size: 0.9rem; }

        /* ===== UI POLISH ===== */

        .main-tab { animation: fadeSlideIn 0.25s ease-out; }
        @keyframes fadeSlideIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }

        .modal { transition: background 0.2s ease; }
        .modal-content { animation: modalPop 0.2s ease-out; }
        @keyframes modalPop { from { opacity: 0; transform: scale(0.95) translateY(10px); } to { opacity: 1; transform: scale(1) translateY(0); } }

        .mode-switch { gap: 4px; background: #f0f2f5; border: none; box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
        .mode-btn { border-radius: 8px; transition: all 0.2s ease; font-size: 0.82rem; position: relative; }
        .mode-btn:hover { background: #e8edf2; color: var(--primary); transform: translateY(-1px); }
        .mode-btn.active { box-shadow: 0 3px 12px rgba(52, 152, 219, 0.35); transform: translateY(-1px); }

        .card { transition: box-shadow 0.2s ease; }
        .card:hover { box-shadow: 0 4px 16px rgba(0,0,0,0.07); }

        .stock-part-row { transition: all 0.15s ease; border-left: 3px solid transparent; }
        .stock-part-row:hover { border-left-color: var(--primary); transform: translateX(2px); box-shadow: 0 2px 8px rgba(0,0,0,0.05); }

        .btn-icon { transition: all 0.15s ease; margin: 1px; }
        .btn-icon:active { transform: scale(0.92); }

        input, select, textarea { transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease; }

        .btn-label:hover { box-shadow: 0 6px 20px rgba(0,0,0,0.15); }
        .btn-label:active { transform: translateY(0); box-shadow: 0 2px 6px rgba(0,0,0,0.1); }

        #stockListContainer::-webkit-scrollbar { width: 6px; }
        #stockListContainer::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 3px; }
        #stockListContainer::-webkit-scrollbar-thumb { background: #c0c0c0; border-radius: 3px; }
        #stockListContainer::-webkit-scrollbar-thumb:hover { background: #999; }

        .toast { font-size: 0.9rem; border-radius: 10px; }
        .toast.success { background: linear-gradient(135deg, #fff 90%, #e8f8f0); }
        .toast.error { background: linear-gradient(135deg, #fff 90%, #fdecea); }

        tbody tr { transition: background 0.15s ease; }
        tbody tr:hover { background: #f7faff; }

        .section-title { border-bottom: none; position: relative; padding-left: 10px; padding-bottom: 8px; border-left: 3px solid currentColor; }

        .stat-card { transition: all 0.2s ease; cursor: default; }
        .stat-card:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,0,0,0.08); }

        .form-group:focus-within label { color: var(--primary); }

        input:disabled, select:disabled { opacity: 0.6; cursor: not-allowed; background: #eef0f2; }

        @keyframes subtlePulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(52,152,219,0.3); } 50% { box-shadow: 0 0 0 6px rgba(52,152,219,0); } }

        .stat-card > div:first-child { transition: color 0.3s ease; }

        /* ===== STOCK ROW COMPONENT CLASSES ===== */
        .stock-checkbox-cell { width: 30px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
        .stock-checkbox { width: 18px; height: 18px; cursor: pointer; accent-color: var(--primary); }
        .stock-name-cell { flex: 1 1 180px; display: flex; flex-direction: column; justify-content: center; }
        .stock-name { font-weight: 700; font-size: 0.95em; line-height: 1.3; }
        .stock-model { color: #999; font-size: 0.78em; margin-top: 1px; }
        .stock-qty-cell { text-align: center; margin-right: 5px; flex-shrink: 0; }
        .stock-qty-label-sg { color: #2980b9; display: block; margin-bottom: 3px; font-size: 0.7em; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; }
        .stock-qty-label-sr { color: #8e44ad; display: block; margin-bottom: 3px; font-size: 0.7em; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; }
        .stock-qty-badge { padding: 4px 12px; border-radius: 6px; font-weight: 800; font-size: 1.05em; border: 1px solid; display: inline-block; min-width: 36px; }
        .stock-qty-ok { background: #e8f8f0; border-color: #2ecc71; color: #27ae60; }
        .stock-qty-warn { background: #fff3cd; border-color: #f39c12; color: #e67e22; }
        .stock-qty-danger { background: #fdecea; border-color: #e74c3c; color: #c0392b; }
        .stock-actions { display: flex; gap: 2px; align-items: center; flex-wrap: wrap; flex-shrink: 0; }
        .stock-cost-cell { font-size: 0.85em; flex-shrink: 0; text-align: center; }
        .stock-cost-label { color: #999; font-size: 0.7em; display: block; margin-bottom: 2px; }
        .stock-cost-value { font-weight: 700; color: #333; }
        .stock-sell-value { font-weight: 600; color: #27ae60; }

        /* ===== REPORT TABLE CLASSES ===== */
        .rpt-tr { border-bottom: 1px solid #eee; page-break-inside: avoid !important; break-inside: avoid !important; }
        .rpt-td { padding: 6px 4px; border-right: 1px solid #eee; font-size: 8pt; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .rpt-td-id { font-family: monospace; font-weight: bold; color: #2980b9; }
        .rpt-td-center { text-align: center; }
        .rpt-td-right { text-align: right; font-weight: 600; }
        .rpt-td-last { border-right: none; }
        .rpt-type-retail { display: inline-block; padding: 2px 5px; background: #e8f5e9; border-radius: 2px; font-size: 7pt; font-weight: 600; }
        .rpt-type-repair { display: inline-block; padding: 2px 5px; background: #e3f2fd; border-radius: 2px; font-size: 7pt; font-weight: 600; }
        .exp-td { padding: 8px; border-right: 1px solid #eee; }

        /* ===== MOBILE RESPONSIVENESS ===== */
        @media (max-width: 768px) {
            .mode-switch { flex-wrap: wrap; }
            .mode-btn { min-width: calc(50% - 5px); font-size: 0.72rem; padding: 10px 6px; }
            .summary-stats { flex-direction: column; }
            .stat-card { min-width: 100%; }
            .charts-row { flex-direction: column; }
            .chart-box { min-width: 100%; }
            .stock-columns { flex-direction: column; }
            .stock-col { min-width: 100%; }
            .modal-content { max-width: 95vw; padding: 18px; margin: 8px; }
            .form-row { flex-direction: column; }
            .form-group { min-width: 100%; }
            h1 { font-size: 1.3rem; }
            .stock-part-row { flex-wrap: wrap; padding: 8px; }
            .stock-part-row > div:last-child { width: 100%; justify-content: flex-end; margin-top: 6px; margin-left: 0; }
            .tooltip-text { font-size: 11px; padding: 6px 10px; max-width: 200px; white-space: normal; }
            .help-box, .quick-tip { font-size: 0.8rem; padding: 10px; }
        }
        @media (max-width: 480px) {
            body { padding: 5px; font-size: 13px; }
            .btn { padding: 10px 12px; font-size: 0.8rem; }
            .stat-card { padding: 10px; }
            .card { padding: 12px; }
            .stock-name { font-size: 0.85em; }
            .stock-qty-badge { padding: 3px 8px; font-size: 0.9em; min-width: 30px; }
        }
    </style>
</head>
<body>

<div id="toast-container"></div>

<datalist id="retailStockList"></datalist>
<datalist id="repairStockList"></datalist>

<div id="qrOverlay">
    <div style="text-align: center; max-width: 40mm; margin: 0 auto; display: flex; flex-direction: column;">
        <h1 id="qrBranch" style="font-size:40px; margin-bottom:20px; color:#000; display:none;">FON2FIX</h1>
        <h2 id="qrTitle" style="font-size:20px; margin-bottom:5px; color:#000; font-weight:normal; text-align:center; line-height:1.3; padding:0 5px; word-wrap:break-word; max-width:100%; order: 1; text-transform: uppercase; font-family: Arial, Helvetica, sans-serif; letter-spacing: 0.5px;"></h2>
        <div id="qrPrice" style="font-size:16px; font-weight:normal; margin-bottom:8px; color:#000; text-align:center; order: 2; text-transform: uppercase; font-family: Arial, Helvetica, sans-serif;"></div>
        <canvas id="qrCanvas" style="width: 200px; height: 200px; display: block; margin: 0 auto; order: 3;"></canvas>
    </div>
    <div style="margin-top: 30px; display:flex; gap:20px; justify-content:center;" class="no-print">
        <button class="btn" style="background:#333; color:#fff; width:auto; padding: 15px 30px;" onclick="window.print()">🖨 PRINT</button>
        <button class="btn btn-danger" style="width:auto; padding: 15px 30px;" onclick="closeQR()">❌ CLOSE</button>
    </div>
</div>

<div class="container">
    <div class="card" style="display:flex; justify-content:space-between; align-items:center; padding: 15px 20px; border-left: 4px solid var(--primary);">
        <div style="display:flex; align-items:center; gap:14px;">
            <div style="width:42px; height:42px; background:linear-gradient(135deg, var(--primary), var(--secondary)); border-radius:10px; display:flex; align-items:center; justify-content:center; color:white; font-weight:800; font-size:1.1rem;"><?php echo strtoupper(substr($_SESSION['user'], 0, 1)); ?></div>
            <div>
                <div style="font-size: 0.7rem; color:#aaa; letter-spacing:1.5px; font-weight:600; text-transform:uppercase;">Logged in as</div>
                <div style="font-weight:800; font-size: 1.15rem; color: var(--secondary); line-height:1.3;">
                    <?php echo $_SESSION['user']; ?> 
                    <span style="font-size:0.75rem; color:#b0b0b0; font-weight:500; margin-left:2px;"><?php echo $my_branch . ($is_restricted ? ' &middot; Locked' : ''); ?></span>
                </div>
            </div>
        </div>
        <div style="display:flex; gap:8px;">
            <a href="backup.php" class="btn" style="background:#f39c12; color:white; width:auto; padding:8px 15px; margin:0; box-shadow:none; font-size:0.8rem;">💾 BACKUP</a>
            <button
                id="syncBackupBtn"
                class="btn btn-primary"
                style="width:auto; padding:8px 15px; margin:0; box-shadow:none; font-size:0.8rem;"
                onclick="sendBackupToServer()"
            >☁️ SEND BACKUP TO SERVER</button>
            <button class="btn" style="background:#7f8c8d; color:white; width:auto; padding:8px 15px; margin:0; box-shadow:none; font-size:0.8rem;" onclick="openChangePassword()">🔑 PASS</button>
            <a href="logout.php" class="btn btn-danger" style="padding:8px 15px; width:auto; margin:0; box-shadow:none; font-size:0.8rem;">🚪</a>
        </div>
    </div>

    <h1 style="letter-spacing:-0.5px;">FON2FIX DASHBOARD <small id="f2fVersionBadge" style="font-size:0.45em; color:#8e44ad; vertical-align:middle; background:#f4ecf7; padding:3px 8px; border-radius:10px; margin-left:8px; font-weight:normal;" title="Build identifier. If this doesn't say v18.2 after upload, do a hard refresh (Ctrl+Shift+R).">v18.2</small></h1>

    <!-- TODAY'S SUMMARY DASHBOARD -->
    <div id="todaySummary" class="card" style="border-top: 4px solid #3498db; margin-bottom: 20px;">
        <div class="section-header">
            <div class="section-title" style="color: #3498db;">📊 TODAY'S SUMMARY</div>
            <span class="tooltip-wrapper">
                <span class="tooltip-icon">?</span>
                <span class="tooltip-text">Real-time statistics for today's business performance</span>
            </span>
        </div>
        <div class="summary-stats" id="todayStats">
            <div class="stat-card">
                <div style="font-size: 2rem; font-weight: bold; color: #3498db;" id="todaySales">RM 0.00</div>
                <div style="font-size: 0.75rem; color: #777; margin-top: 5px;">Today's Sales</div>
                <div class="help-text" style="margin-top: 3px; font-size: 0.7rem;">Total revenue today</div>
            </div>
            <div class="stat-card">
                <div style="font-size: 2rem; font-weight: bold; color: #2ecc71;" id="todayJobs">0</div>
                <div style="font-size: 0.75rem; color: #777; margin-top: 5px;">Jobs Completed</div>
                <div class="help-text" style="margin-top: 3px; font-size: 0.7rem;">Finished repairs/sales</div>
            </div>
            <div class="stat-card">
                <div style="font-size: 2rem; font-weight: bold; color: #e67e22;" id="pendingJobs">0</div>
                <div style="font-size: 0.75rem; color: #777; margin-top: 5px;">Pending Jobs</div>
                <div class="help-text" style="margin-top: 3px; font-size: 0.7rem;">In progress</div>
            </div>
            <div class="stat-card">
                <div style="font-size: 2rem; font-weight: bold; color: #e74c3c;" id="lowStock">0</div>
                <div style="font-size: 0.75rem; color: #777; margin-top: 5px;">Low Stock Items</div>
                <div class="help-text" style="margin-top: 3px; font-size: 0.7rem;">Needs restocking</div>
            </div>
        </div>
    </div>
    
    <!-- BEGINNER GUIDE INFO CARD (Can be dismissed) -->
    <div id="beginnerGuide" class="card" style="border-top: 4px solid #f1c40f; background: linear-gradient(135deg, #fff9e6 0%, #ffffff 100%); margin-bottom: 20px; display: none;">
        <div style="display: flex; justify-content: space-between; align-items: start;">
            <div style="flex: 1;">
                <div class="section-title" style="color: #f39c12; margin-bottom: 10px;">👋 WELCOME! QUICK START GUIDE</div>
                <div class="info-card" style="background: transparent; border: none; padding: 0; margin: 0;">
                    <div class="info-card-content">
                        <strong>📌 Getting Started:</strong><br>
                        • <strong>Daily Repairs/Sales</strong> - For quick walk-in sales and same-day repairs<br>
                        • <strong>Drop Off Repairs</strong> - For repairs that take longer (customer drops off device)<br>
                        • <strong>Billing</strong> - View completed jobs ready for customer pickup<br>
                        • <strong>Stock</strong> - Manage inventory, scan QR codes, transfer items between stores<br>
                        • <strong>Report</strong> - View sales analytics and generate reports<br><br>
                        <strong>💡 Pro Tips:</strong> Use QR scanner for quick item lookup, press number keys (1-7) to switch tabs, and hover over <span class="tooltip-icon" style="margin: 0 2px;">?</span> icons for help!
                    </div>
                </div>
            </div>
            <button onclick="document.getElementById('beginnerGuide').style.display='none'; localStorage.setItem('hideBeginnerGuide', 'true');" style="background: transparent; border: none; font-size: 1.5rem; cursor: pointer; color: #999; padding: 0 10px;">×</button>
        </div>
    </div>

    <div class="mode-switch">
        <button class="mode-btn" id="tabRepair" onclick="switchMainTab('repair')" title="For repairs that take longer - customer drops off device">
            <span style="display:block; font-size:0.7rem; opacity:0.8; margin-bottom:2px;">1</span>
            🔧 DROP OFF REPAIRS
        </button>
        <button class="mode-btn" id="tabBilling" onclick="switchMainTab('billing')" style="color:var(--success); font-weight:bold;" title="View completed jobs ready for customer pickup and payment">
            <span style="display:block; font-size:0.7rem; opacity:0.8; margin-bottom:2px;">2</span>
            ✅ BILLING
        </button>
        <button class="mode-btn active" id="tabRetail" onclick="switchMainTab('retail')" title="Quick sales and same-day repairs - perfect for walk-in customers">
            <span style="display:block; font-size:0.7rem; opacity:0.8; margin-bottom:2px;">3</span>
            🛒 DAILY REPAIRS/SALES
        </button>
        <button class="mode-btn" id="tabStock" onclick="switchMainTab('stock')" title="Manage inventory, add items, transfer stock between stores">
            <span style="display:block; font-size:0.7rem; opacity:0.8; margin-bottom:2px;">4</span>
            📦 STOCK
        </button>
        <button class="mode-btn" id="tabReport" onclick="switchMainTab('report')" title="View sales reports, analytics, and business insights">
            <span style="display:block; font-size:0.7rem; opacity:0.8; margin-bottom:2px;">5</span>
            📈 REPORT
        </button>
        <?php if($can_restore_bool) { ?>
        <button class="mode-btn" id="tabTrash" onclick="switchMainTab('trash')" style="color:#e74c3c;" title="Recover deleted items - restore or permanently delete">
            <span style="display:block; font-size:0.7rem; opacity:0.8; margin-bottom:2px;">6</span>
            🗑️ TRASH
        </button>
        <?php } ?>
        <?php if($can_admin) { ?>
        <button class="mode-btn" id="tabArchive" onclick="switchMainTab('archive')" style="color:#8e44ad;" title="View archived records (1+ year old) and move old rows out of live tables">
            <span style="display:block; font-size:0.7rem; opacity:0.8; margin-bottom:2px;">7</span>
            📦 ARCHIVE
        </button>
        <button class="mode-btn" id="tabUsers" onclick="switchMainTab('users')" title="Manage staff accounts and permissions">
            <span style="display:block; font-size:0.7rem; opacity:0.8; margin-bottom:2px;">8</span>
            👥 STAFF
        </button>
        <?php } ?>
    </div>

    <div id="trashMode" class="main-tab d-none">
        <div class="card" style="border-top: 4px solid #e74c3c;">
            <div class="section-title" style="color:#e74c3c;">🗑️ DELETED ITEMS RECOVERY</div>
            <div class="table-container">
                <table>
                    <thead><tr><th>Type</th><th>ID</th><th>Original Date</th><th>Deleted Date</th><th>Customer</th><th>Info</th><th>Reason</th><th>Actions</th></tr></thead>
                    <tbody id="trashTableBody"></tbody>
                </table>
            </div>
        </div>
    </div>

    <div id="repairMode" class="main-tab d-none">
        <div class="form-row">
            <input type="text" id="searchInput" placeholder="🔍 Search Name, Phone, IMEI, or Job ID..." style="flex: 2;">
            <div style="flex: 1; min-width: 120px;">
                <select id="branchFilter" onchange="fetchJobs(this.value)">
                    <?php renderBranchOptions('all', true); ?>
                </select>
            </div>
        </div>
        <div class="card" style="border-top: 4px solid var(--primary);">
            <div class="section-header">
                <div class="section-title">📍 REPAIR LOGISTICS</div>
            </div>
            <div class="form-row">
                <div class="form-group">
                    <label>Branch
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Select which store location this repair is for</span>
                        </span>
                    </label>
                    <?php if ($can_admin && !$is_restricted): ?>
                        <select id="rep_branch">
                            <option value="Gombak">Gombak</option>
                            <option value="Sri Rampai">Sri Rampai</option>
                        </select>
                    <?php else: ?>
                        <input type="text" id="rep_branch" value="<?php echo $my_branch; ?>" readonly style="background: #e9ecef; cursor: not-allowed; color: #777;">
                    <?php endif; ?>
                </div>
                <div class="form-group">
                    <label>Date In
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">When did the customer drop off the device?</span>
                        </span>
                    </label>
                    <input type="date" id="rep_date" value="<?php echo date('Y-m-d'); ?>">
                </div>
                <div class="form-group">
                    <label>Pickup Date
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">When should the customer come back to collect?</span>
                        </span>
                    </label>
                    <input type="date" id="rep_pickup" value="<?php echo date('Y-m-d'); ?>">
                </div>
            </div>
            
            <div class="section-divider"></div>
            
            <div class="section-header">
                <div class="section-title">👤 CUSTOMER & DEVICE</div>
            </div>
            <div class="form-row">
                <div class="form-group">
                    <label class="required-field">Customer Name</label>
                    <input type="text" id="rep_cust" placeholder="Enter customer's full name" required>
                </div>
                <div class="form-group">
                    <label>Phone Number
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Type phone number to see customer's previous repairs</span>
                        </span>
                    </label>
                    <input type="tel" id="rep_phone" placeholder="e.g. 012-3456789" list="repCustList">
                    <datalist id="repCustList"></datalist>
                    <div id="repCustomerHistory"></div>
                </div>
            </div>
            <div class="form-row">
                <div class="form-group">
                    <label class="required-field">Device Model</label>
                    <input type="text" id="rep_model" placeholder="e.g. iPhone 13 Pro, Samsung Galaxy S21" required>
                </div>
                <div class="form-group">
                    <label>IMEI/Serial Number
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Unique device identifier (optional but recommended)</span>
                        </span>
                    </label>
                    <input type="text" id="rep_imei" placeholder="Optional - for device tracking" onkeyup="cleanInput(this)">
                </div>
                <div class="form-group">
                    <label>Device Passcode
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Password, PIN, or pattern lock to unlock the device</span>
                        </span>
                    </label>
                    <div style="display:flex; gap:5px;">
                        <input type="text" id="rep_pass" placeholder="Enter password or PIN" style="flex:1;">
                        <button type="button" class="btn" style="width:auto; padding:0 12px; background:#9b59b6; margin:0;" onclick="openPatternModal('rep_pass')" title="Click to draw pattern lock">::: </button>
                    </div>
                </div>
            </div>
            
            <div class="section-divider"></div>
            
            <div class="section-header">
                <div class="section-title">🔧 REPAIR DETAILS & PARTS</div>
            </div>
            <div class="form-group">
                <label>Problem / Repair Description
                    <span class="tooltip-wrapper">
                        <span class="tooltip-icon">?</span>
                        <span class="tooltip-text">Describe what's wrong with the device and what needs to be fixed</span>
                    </span>
                </label>
                <div style="display:flex; gap:10px;">
                    <select id="rep_quick_fix" class="quick-select" onchange="applyQuickFix(this, 'rep_desc')" style="border: 2px solid #f1c40f; background: #fffcf5; color: #d35400; font-weight: bold; cursor: pointer;">
                        <option value="">-- Select Common Fix --</option>
                        <option value="LCD Replacement">LCD Replacement</option>
                        <option value="Battery Replacement">Battery Replacement</option>
                        <option value="Charging Port Replacement">Charging Port Replacement</option>
                        <option value="Back Glass Replacement">Back Glass Replacement</option>
                        <option value="Housing Replacement">Housing Replacement</option>
                        <option value="Camera Replacement">Camera Replacement</option>
                        <option value="Motherboard Repair">Motherboard Repair</option>
                        <option value="Software Issue">Software Issue</option>
                        <option value="Water Damage Treatment">Water Damage Treatment</option>
                    </select>
                    <input type="text" id="rep_desc" placeholder="Or type your own repair description..." style="flex:2;">
                </div>
            </div>
            
            <div class="form-group">
                <label>Internal Remarks
                    <span class="tooltip-wrapper">
                        <span class="tooltip-icon">?</span>
                        <span class="tooltip-text">Private notes about device condition, customer requests, or special instructions</span>
                    </span>
                </label>
                <textarea id="rep_remarks" placeholder="e.g. Screen has scratches, customer wants data backup, device is under warranty..." style="height:60px;"></textarea>
            </div>
            <div class="section-divider"></div>
            
            <div class="section-header">
                <div class="section-title">💰 PRICING & STATUS</div>
            </div>
            <div class="form-row" style="margin-top:15px;">
                <div class="form-group">
                    <label>Repair Price (RM)
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Total amount the customer will pay for this repair</span>
                        </span>
                    </label>
                    <input type="number" id="rep_price" placeholder="0.00" step="0.01" onchange="calcRepairTotal()">
                </div>
                <div class="form-group">
                    <label>Deposit Amount (RM)
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Amount customer paid upfront (if any)</span>
                        </span>
                    </label>
                    <input type="number" id="rep_deposit" placeholder="0.00" step="0.01" onchange="calcRepairTotal()">
                </div>
                <div class="form-group">
                    <label>Warranty Period
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">How long is the repair covered by warranty?</span>
                        </span>
                    </label>
                    <select id="rep_war">
                        <option>No Warranty</option>
                        <option>1 Week</option>
                        <option>2 Weeks</option>
                        <option>1 Month</option>
                        <option>3 Months</option>
                        <option>1 Year</option>
                    </select>
                </div>
                <div class="form-group">
                    <label>Job Status
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Current status of this repair job</span>
                        </span>
                    </label>
                    <select id="rep_stat">
                        <option>Pending</option>
                        <option>Completed</option>
                        <option>Return</option>
                    </select>
                </div>
            </div>
            <div class="section-divider"></div>
            
            <div class="section-header">
                <div class="section-title">💳 PAYMENT INFORMATION</div>
            </div>
            <div class="form-row" style="margin-top:10px;">
                <div class="form-group">
                    <label>Primary Payment Method
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">How did the customer pay? Select the main payment method</span>
                        </span>
                    </label>
                    <select id="rep_pay" onchange="updatePaymentAmounts('rep')">
                        <option value="">-- Select Payment Method --</option>
                        <option>Cash</option>
                        <option>Bank Transfer/QR</option>
                        <option>SPayLater</option>
                        <option>TnG Ewallet</option>
                    </select>
                    <input type="number" id="rep_pay_amt1" placeholder="Amount paid (RM)" step="0.01" style="margin-top:5px; background:#f0f0f0;" onchange="validatePaymentAmounts('rep')" disabled>
                </div>
                <div class="form-group">
                    <label>Secondary Payment Method (Optional)
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">If customer used 2 payment methods (e.g., Cash + QR), select the second one here</span>
                        </span>
                    </label>
                    <div style="display:flex; gap:5px; align-items:flex-start;">
                        <div style="flex:1;">
                            <select id="rep_pay2" onchange="updatePaymentAmounts('rep')" style="margin-bottom:5px;">
                                <option value="">-- None (Single Payment) --</option>
                                <option>Cash</option>
                                <option>Bank Transfer/QR</option>
                                <option>SPayLater</option>
                                <option>TnG Ewallet</option>
                            </select>
                            <input type="number" id="rep_pay_amt2" placeholder="Amount (RM)" step="0.01" onchange="validatePaymentAmounts('rep')" disabled style="background:#f0f0f0;">
                        </div>
                        <label style="margin:0; font-size:0.75rem; white-space:nowrap; cursor:pointer; padding-top:8px;">
                            <input type="checkbox" id="rep_sync_pay" onchange="syncPaymentMethods('rep')" style="margin-right:3px;"> Enable Amount Entry
                        </label>
                    </div>
                </div>
                <div class="form-group">
                    <label>Payment Status
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Has the customer fully paid, partially paid, or not paid yet?</span>
                        </span>
                    </label>
                    <select id="rep_pay_status" style="border: 2px solid var(--primary);">
                        <option value="Unpaid">🔴 Unpaid - No payment received</option>
                        <option value="Partial">🟠 Partial - Deposit or partial payment received</option>
                        <option value="Paid">🟢 Paid - Fully paid</option>
                    </select>
                </div>
                <div class="form-group" style="text-align:right;">
                    <label style="font-size:0.9rem; color:var(--primary);">TOTAL AMOUNT (RM)</label>
                    <input type="number" id="totalRepairPrice" placeholder="0.00" readonly style="font-weight:bold; font-size:1.8rem; text-align:right; border:none; background:transparent; color:var(--primary);">
                </div>
            </div>
            <button id="repSubmitBtn" class="btn btn-primary btn-label" onclick="submitRepair()" title="Press Enter or Ctrl+Enter to submit">
                <span class="btn-label-icon">✅</span>
                <span>CREATE REPAIR TICKET</span>
            </button>
        </div>
        <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
            <div class="section-title">📋 REPAIR JOBS LIST</div>
            <button class="btn" style="width:auto; padding:8px 15px; margin:0; background:#3498db; font-size:0.85rem;" onclick="fetchJobs()" title="Refresh Job List">🔄 REFRESH</button>
        </div>
        <div id="jobTableBody_pgCtrl" class="f2f-pager-bar" style="display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:8px 4px;"></div>
        <div class="table-container"><table><thead><tr><th>Job ID</th><th>Customer</th><th>Device/Issue</th><th>Price</th><th>Method</th><th>Status</th><th>Actions</th></tr></thead><tbody id="jobTableBody"></tbody></table></div>
    </div>

    <div id="billingMode" class="main-tab d-none">
        <div class="card" style="border-top: 4px solid var(--success);">
            <div class="section-header">
                <div class="section-title" style="color: var(--success);">✅ READY FOR BILLING & COLLECTION</div>
            </div>
            
            <div class="form-row">
                 <input type="text" id="billingSearch" placeholder="🔍 Search by Job ID, Customer Name, Phone, or Device..." style="flex: 2;">
                 <button id="batchPrintBtn" class="btn" style="background:#16a085; color:white; width:auto; margin:0; flex:1;" onclick="batchPrintReceipts()" disabled>🖨️ BATCH PRINT</button>
                 <span class="tooltip-wrapper" style="align-self: center;">
                     <span class="tooltip-icon">?</span>
                     <span class="tooltip-text">Search for completed jobs by any detail</span>
                 </span>
            </div>

            <div id="billingTableBody_pgCtrl" class="f2f-pager-bar" style="display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:8px 4px;"></div>
            <div class="table-container">
                <table id="billingTable">
                    <thead>
                        <tr>
                            <th style="width:40px;"><input type="checkbox" id="selectAllBilling" onchange="toggleAllBillingJobs(this.checked)" title="Select All"></th>
                            <th>Job ID</th>
                            <th>Date</th>
                            <th>Customer</th>
                            <th>Device</th>
                            <th>Total</th>
                            <th>Payment</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody id="billingTableBody"></tbody>
                </table>
            </div>
        </div>
    </div>

    <div id="retailMode" class="main-tab">
        <div class="card" style="border-top: 4px solid #9b59b6;">
            <div class="section-header">
                <div class="section-title" style="color:#9b59b6;">📍 RETAIL LOGISTICS</div>
            </div>
            <div class="form-row">
                <div class="form-group">
                    <label>Branch
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Which store location is this sale for?</span>
                        </span>
                    </label>
                    <?php if ($can_admin && !$is_restricted): ?>
                        <select id="ret_branch">
                            <option value="Gombak">Gombak</option>
                            <option value="Sri Rampai">Sri Rampai</option>
                        </select>
                    <?php else: ?>
                        <input type="text" id="ret_branch" value="<?php echo $my_branch; ?>" readonly style="background: #e9ecef; cursor: not-allowed; color: #777;">
                    <?php endif; ?>
                </div>
                <div class="form-group">
                    <label>Sale Date
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Date of this sale/repair</span>
                        </span>
                    </label>
                    <input type="date" id="ret_date" value="<?php echo date('Y-m-d'); ?>">
                </div>
                <div class="form-group">
                    <label>Pickup Date
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">When will customer collect? (Usually same day for retail)</span>
                        </span>
                    </label>
                    <input type="date" id="ret_pickup" value="<?php echo date('Y-m-d'); ?>">
                </div>
            </div>
            
            <div class="section-divider"></div>
            
            <div class="section-header">
                <div class="section-title" style="color:#9b59b6;">👤 CUSTOMER INFORMATION</div>
            </div>
            <div class="form-row">
                <div class="form-group">
                    <label class="required-field">Customer Name</label>
                    <input type="text" id="ret_cust" value="Walk-in Customer" placeholder="Enter customer name" required>
                </div>
                <div class="form-group">
                    <label>Phone Number
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Enter phone to see customer's previous orders</span>
                        </span>
                    </label>
                    <input type="tel" id="ret_phone" placeholder="e.g. 012-3456789" list="retCustList">
                    <datalist id="retCustList"></datalist>
                    <div id="retCustomerHistory"></div>
                </div>
            </div>
            <div class="form-row">
                <div class="form-group">
                    <label>IMEI/Serial Number
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">Device serial number (optional, for tracking)</span>
                        </span>
                    </label>
                    <input type="text" id="ret_imei" placeholder="Optional - for device tracking" onkeyup="cleanInput(this)">
                </div>
            </div>
            
            <div class="section-divider"></div>
            
            <input type="hidden" id="ret_desc" value="">
            <div class="section-header" style="margin-top:20px;">
                <div class="section-title" style="color:#9b59b6;">🛒 SHOPPING CART</div>
                <button class="btn-action" style="background:#9b59b6; color:white; border:none;" onclick="startCameraScanner('retail')" title="Open camera to scan QR codes">📷 SCAN QR</button>
            </div>
            <input type="text" id="retailScannerInput" placeholder="📷 SCAN QR CODE HERE - Item will be added automatically!" onkeyup="handleRetailScan(this)" style="border: 2px dashed #9b59b6; background: #fbf5fc; color: #555; text-align:center; margin-bottom: 15px; font-weight:bold; padding: 12px;">
            <div class="form-row" style="background:#f8f9fa; padding:8px; border-bottom:2px solid #ddd; font-weight:bold; font-size:0.85rem; margin-bottom:5px;">
                <div style="flex:2;">Item Name</div>
                <div style="flex:1; min-width:120px;">Compatible Model</div>
                <div style="width:60px; text-align:center;">Qty</div>
                <div style="width:80px; text-align:center;">Price</div>
                <div style="width:110px; text-align:center;">Warranty</div>
                <div style="width:auto;"></div>
            </div>
            <div id="itemsContainer" style="margin-bottom: 10px;"></div>
            <button class="btn" style="background:#ecf0f1; border:1px solid #bdc3c7; color:#333; width:100%; margin: 10px 0;" onclick="addRetailItem()">+ MANUAL ADD ITEM</button>
            <div class="form-group">
                <label>Internal Remarks
                    <span class="tooltip-wrapper">
                        <span class="tooltip-icon">?</span>
                        <span class="tooltip-text">Private notes about this sale (not shown on receipt)</span>
                    </span>
                </label>
                <textarea id="ret_remarks" placeholder="e.g. Customer requested warranty, special discount applied..." style="height:60px;"></textarea>
            </div>
            
            <div class="section-divider"></div>
            
            <div class="section-header">
                <div class="section-title" style="color:#9b59b6;">💳 PAYMENT INFORMATION</div>
            </div>
            <div class="form-row" style="margin-top:10px;">
                <div class="form-group">
                    <label>Primary Payment Method
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">How did the customer pay? Select the main payment method</span>
                        </span>
                    </label>
                    <select id="ret_pay" onchange="updatePaymentAmounts('ret')">
                        <option value="">-- Select Payment Method --</option>
                        <option>Cash</option>
                        <option>Bank Transfer/QR</option>
                        <option>SPayLater</option>
                        <option>TnG Ewallet</option>
                    </select>
                    <input type="number" id="ret_pay_amt1" placeholder="Amount paid (RM)" step="0.01" style="margin-top:5px; background:#f0f0f0;" onchange="validatePaymentAmounts('ret')" disabled>
                </div>
                <div class="form-group">
                    <label>Secondary Payment Method (Optional)
                        <span class="tooltip-wrapper">
                            <span class="tooltip-icon">?</span>
                            <span class="tooltip-text">If customer used 2 payment methods, select the second one here</span>
                        </span>
                    </label>
                    <div style="display:flex; gap:5px; align-items:flex-start;">
                        <div style="flex:1;">
                            <select id="ret_pay2" onchange="updatePaymentAmounts('ret')" style="margin-bottom:5px;">
                                <option value="">-- None (Single Payment) --</option>
                                <option>Cash</option>
                                <option>Bank Transfer/QR</option>
                                <option>SPayLater</option>
                                <option>TnG Ewallet</option>
                            </select>
                            <input type="number" id="ret_pay_amt2" placeholder="Amount (RM)" step="0.01" onchange="validatePaymentAmounts('ret')" disabled style="background:#f0f0f0;">
                        </div>
                        <label style="margin:0; font-size:0.75rem; white-space:nowrap; cursor:pointer; padding-top:8px;">
                            <input type="checkbox" id="ret_sync_pay" onchange="syncPaymentMethods('ret')" style="margin-right:3px;"> Enable Amount Entry
                        </label>
                    </div>
                </div>
                <div class="form-group" style="text-align:right;">
                    <label style="font-size:0.9rem; color:#9b59b6;">TOTAL AMOUNT (RM)</label>
                    <input type="number" id="totalRetailPrice" placeholder="0.00" readonly style="font-weight:bold; font-size:1.8rem; text-align:right; border:none; background:transparent; color:#9b59b6;">
                </div>
            </div>
            <button id="retSubmitBtn" class="btn btn-accent btn-label" onclick="submitRetail()" title="Press Enter or Ctrl+Enter to submit">
                <span class="btn-label-icon">✅</span>
                <span>COMPLETE SALE</span>
            </button>
        </div>
        
        <div class="card" style="margin-top: 20px;">
            <div class="form-row" style="margin-bottom:15px;">
                <input type="text" id="retailSearchInput" placeholder="🔍 Search Sale ID, Customer, Phone, or Items..." style="flex: 2;">
                <div style="flex: 1; min-width: 120px;">
                    <select id="retailBranchFilter" onchange="filterRetailHistory()">
                        <?php renderBranchOptions('all', true); ?>
                    </select>
                </div>
            </div>
            <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
                <div class="section-title" style="color:#9b59b6; margin:0;">📋 RETAIL SALES HISTORY</div>
                <div style="display:flex; gap:6px;">
                    <button class="btn" style="width:auto; background:#f1c40f; padding:6px 14px; margin:0; color:#333; font-size:0.82rem;" onclick="viewActivityLogs()">📜 LOGS</button>
                    <button class="btn" style="width:auto; padding:6px 14px; margin:0; background:#9b59b6; font-size:0.82rem;" onclick="fetchRetailHistory()" title="Refresh Retail Sales">🔄 REFRESH</button>
                </div>
            </div>
            <div id="retailTableBody_pgCtrl" class="f2f-pager-bar" style="display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:8px 4px;"></div>
            <div class="table-container"><table><thead><tr><th>Sale ID</th><th>Date</th><th>Customer</th><th>Items</th><th>Total</th><th>Payment</th><th>Actions</th></tr></thead><tbody id="retailTableBody"></tbody></table></div>
        </div>
    </div>

    <div id="stockMode" class="main-tab d-none">
        <div class="form-row">
            <div class="form-group" style="flex:2">
                <div class="card" style="border-top: 3px solid #f39c12; margin-bottom: 20px;">
    <div class="section-title" style="color:#f39c12;">🔧 ADD REPAIR PART</div>

    <div class="form-row">
        <div class="form-group" style="flex:1">
            <label>Category <span style="color:#e67e22;">*</span></label>
            <?php if ($is_master): ?><input type="text" id="np_cat" placeholder="e.g. LCD, Battery" list="np_cat_list" onchange="handleCategoryChange()" oninput="handleCategoryChange()" style="border: 2px solid #f39c12; background:#fffcf5; width:100%;"><datalist id="np_cat_list"></datalist><?php else: ?><select id="np_cat" onchange="handleCategoryChange()" style="border: 2px solid #f39c12; background:#fffcf5;"><option value="">-- Select Category First --</option></select><?php endif; ?>
        </div>
        <div class="form-group" style="flex:2">
            <label>Device Model <span style="color:#e67e22;">*</span></label>
            <?php if ($is_master || $is_endie): ?>
            <div style="position:relative;">
                <input type="text" id="np_device_search" placeholder="Search or type new device model..." 
                       oninput="handleDeviceSearchInput()" 
                       onfocus="showDeviceDropdown()" 
                       onblur="setTimeout(() => hideDeviceDropdown(), 200)"
                       onkeydown="handleDeviceSearchKeydown(event)"
                       disabled
                       style="width:100%; padding:8px; border:2px solid #ddd; border-radius:4px; background:#f5f5f5; cursor:not-allowed;">
                <div id="np_device_dropdown" style="display:none; position:absolute; top:100%; left:0; right:0; background:white; border:1px solid #ddd; border-radius:4px; max-height:200px; overflow-y:auto; z-index:1000; box-shadow:0 2px 8px rgba(0,0,0,0.1); margin-top:2px;">
                    <div id="np_device_list" style="padding:0;"></div>
                    <div style="border-top:1px solid #eee; padding:8px; background:#f8f9fa;">
                        <button type="button" onclick="addNewDeviceModel()" style="width:100%; padding:6px; background:#f39c12; color:white; border:none; border-radius:4px; cursor:pointer; font-weight:bold;">
                            ➕ Add "<span id="new_device_name_preview"></span>"
                        </button>
                    </div>
                </div>
            </div>
            <input type="hidden" id="np_device" value="">
            <?php else: ?>
            <select id="np_device" disabled style="width:100%; padding:8px; border:2px solid #ddd; border-radius:4px; background:#f5f5f5;" onchange="generatePartName()"><option value="">-- Select Device Model --</option></select>
            <?php endif; ?>
        </div>
    </div>

    <div class="form-group">
        <label>Full Part Name <span id="np_name_label" style="color:#999;">(Manual Entry)</span></label>
        <input type="text" id="np_name" placeholder="Device Model + Category" style="background:#fff; color:#333; font-weight:normal;" oninput="updatePartNameLabel()">
    </div>

    <div class="form-row">
        <div class="form-group"><label>Brand <span style="color:#e67e22;">*</span></label><?php if ($is_master): ?><input type="text" id="np_brand" placeholder="e.g. OEM, Original, Grade A (supplier brand)" onchange="prependBrandToPartName()"><?php else: ?><select id="np_brand" style="border:2px solid #f39c12; background:#fffcf5;" onchange="prependBrandToPartName()"><option value="">-- Select Brand --</option></select><?php endif; ?></div>
        <div class="form-group"><label>Cost (RM)</label><input type="number" id="np_cost" placeholder="0.00"></div>
        <div class="form-group"><label>Supplier <span style="color:#e67e22;">*</span></label><?php if ($is_master): ?><input type="text" id="np_supp" placeholder="e.g. CME, HWT"><?php else: ?><select id="np_supp" style="border:2px solid #f39c12; background:#fffcf5;"><option value="">-- Select Supplier --</option></select><?php endif; ?></div>
    </div>
    <div class="form-row" style="background: #fdf6e7; padding: 10px; border-radius: 8px;">
        <div class="form-group" id="np_qty_g_container"><label style="color:#e67e22">Gombak Qty</label><input type="number" id="np_qty_g" value="0" style="background:#fff;"></div>
        <div class="form-group" id="np_qty_s_container"><label style="color:#d35400">Sri Rampai Qty</label><input type="number" id="np_qty_s" value="0" style="background:#fff;"></div>
    </div>
    <button class="btn" style="background: linear-gradient(135deg, #f39c12, #e67e22);" onclick="addNewStockItem('Part')">ADD PART</button>
</div>

                <div class="card" style="border-top: 3px solid #e74c3c;">
                    <div class="section-title" style="color:#e74c3c;">🛒 ADD RETAIL ITEM</div>
                    <div class="form-row">
                        <div class="form-group" style="flex:2"><label>Item Name <span style="color:#e67e22;">*</span></label><?php if ($is_master): ?><input type="text" id="nr_name" placeholder="e.g. Cable USB-C" oninput="cleanInput(this)" onkeyup="cleanInput(this)"><?php else: ?><select id="nr_name" style="border:2px solid #e74c3c; background:#fffcf5;"><option value="">-- Select Item Name --</option></select><?php endif; ?></div>
                        <div class="form-group"><label>Category <span style="color:#e67e22;">*</span></label><?php if ($is_master): ?><input type="text" id="nr_cat" placeholder="e.g. Cable, Charger" list="nr_cat_list" style="border:2px solid #e74c3c; background:#fffcf5;"><datalist id="nr_cat_list"></datalist><?php else: ?><select id="nr_cat" style="border:2px solid #e74c3c; background:#fffcf5;"><option value="">-- Select Category --</option></select><?php endif; ?></div>
                    </div>
                    <div class="form-row">
                        <div class="form-group"><label>Cost (RM)</label><input type="number" id="nr_cost" placeholder="0.00"></div>
                        <div class="form-group"><label style="color:#e74c3c;">Selling Price (RM)</label><input type="number" id="nr_sell" placeholder="0.00"></div>
                        <div class="form-group"><label>Supplier <span style="color:#e67e22;">*</span></label><?php if ($is_master): ?><input type="text" id="nr_supp" placeholder="e.g. CME, HWT"><?php else: ?><select id="nr_supp" style="border:2px solid #e74c3c; background:#fffcf5;"><option value="">-- Select Supplier --</option></select><?php endif; ?></div>
                    </div>
                    <div class="form-row" style="background: #fdeaea; padding: 10px; border-radius: 8px; border:1px solid #fadbd8;">
                        <div class="form-group" id="nr_qty_g_container"><label style="color:#c0392b">Gombak Qty</label><input type="number" id="nr_qty_g" value="0" style="background:#fff;"></div>
                        <div class="form-group" id="nr_qty_s_container"><label style="color:#922b21">Sri Rampai Qty</label><input type="number" id="nr_qty_s" value="0" style="background:#fff;"></div>
                    </div>
                    <button class="btn" style="background: linear-gradient(135deg, #e74c3c, #c0392b);" onclick="addNewStockItem('Retail')">ADD RETAIL ITEM</button>
                </div>
            </div>
            
            <div class="form-group" style="flex:3; min-width: 400px;">
                <div class="card" style="height: 100%;">
                    <div class="form-row"><input type="text" id="stockSearchInput" placeholder="🔍 Search Stock (Name, Model, Category, Supplier)..." style="flex:2;"><button class="btn" style="flex:0.5; background:#27ae60; margin-top:0; font-size:0.8rem;" onclick="fetchStock()" title="Refresh Stock List">🔄</button></div>
                    <div class="form-row" style="margin-top:5px; flex-wrap:wrap; gap:5px;">
                        <?php if($can_transfer_bool): ?><button class="btn" style="flex:1; background:#95a5a6; margin-top:0; font-size:0.78rem; padding:8px 10px;" onclick="viewTransferLog()" title="Transfer Logs">🚚 TRANSFER</button><?php endif; ?>
                        <?php if($can_view_stock_logs): ?><button class="btn" style="flex:1; background:#3498db; margin-top:0; font-size:0.78rem; padding:8px 10px;" onclick="viewStockLogs()" title="Stock Activity Logs">📜 ACTIVITY</button><?php endif; ?>
                        <?php if($can_merge_stock): ?><button class="btn" style="flex:1; background:#e67e22; margin-top:0; font-size:0.78rem; padding:8px 10px;" onclick="mergeDuplicateStocks()" title="Merge Duplicate Stock Items">🔄 MERGE</button><?php endif; ?>
                        <?php if($can_bulk_ops): ?><button class="btn" style="flex:1; background:#9b59b6; margin-top:0; font-size:0.78rem; padding:8px 10px;" onclick="openBulkOperations()" title="Bulk Operations">⚡ BULK OPS</button><?php endif; ?>
                        <?php if($can_bulk_print): ?><button class="btn" style="flex:1; background:#16a085; margin-top:0; font-size:0.78rem; padding:8px 10px;" onclick="openBulkPrint()" title="Bulk Print">🖨️ PRINT</button><?php endif; ?>
                        <?php if($can_bulk_import): ?><button class="btn" style="flex:1; background:#27ae60; margin-top:0; font-size:0.78rem; padding:8px 10px;" onclick="openBulkImport()" title="Bulk Import Stock">📥 IMPORT</button><?php endif; ?>
                        <?php if($can_convert_uppercase): ?><button class="btn" style="flex:1; background:#c0392b; margin-top:0; font-size:0.78rem; padding:8px 10px;" onclick="convertStockToUppercase()" title="Convert All Stock to Uppercase">🔤 UPPERCASE</button><?php endif; ?>
                    </div>
                    <div id="stockListContainer" style="max-height: 800px; overflow-y: auto;">
                        <div class="section-title">🔧 REPAIR PARTS</div><div id="stockListPart">Loading...</div>
                        <div class="section-title" style="color:#e74c3c; margin-top:20px;">🛒 RETAIL ITEMS</div><div id="stockListRetail">Loading...</div>
                    </div>
                    <?php if($is_master || $is_endie): ?>
                    <div style="margin-top:30px; padding-top:20px; border-top:2px solid #e0e0e0;">
                        <div class="section-title" style="color:#e67e22;">📋 CREDIT NOTE RETURN HISTORY</div>
                        <div style="margin-bottom:10px;">
                            <button class="btn" style="width:auto; padding:8px 15px; margin:0; background:#e67e22; font-size:0.85rem;" onclick="fetchCreditNoteHistory()">🔄 REFRESH HISTORY</button>
                        </div>
                        <div class="table-container" style="max-height:400px; overflow-y:auto;">
                            <table id="creditNoteHistoryTable" style="width:100%; border-collapse:collapse;">
                                <thead>
                                    <tr style="background:#f8f9fa; position:sticky; top:0; z-index:10;">
                                        <th style="padding:10px; text-align:left; border-bottom:2px solid #ddd; font-size:0.75rem; text-transform:uppercase; color:#555;">Date</th>
                                        <th style="padding:10px; text-align:left; border-bottom:2px solid #ddd; font-size:0.75rem; text-transform:uppercase; color:#555;">Item</th>
                                        <th style="padding:10px; text-align:center; border-bottom:2px solid #ddd; font-size:0.75rem; text-transform:uppercase; color:#555;">Branch</th>
                                        <th style="padding:10px; text-align:center; border-bottom:2px solid #ddd; font-size:0.75rem; text-transform:uppercase; color:#555;">Qty</th>
                                        <th style="padding:10px; text-align:left; border-bottom:2px solid #ddd; font-size:0.75rem; text-transform:uppercase; color:#555;">Supplier</th>
                                        <th style="padding:10px; text-align:left; border-bottom:2px solid #ddd; font-size:0.75rem; text-transform:uppercase; color:#555;">Reason</th>
                                        <th style="padding:10px; text-align:left; border-bottom:2px solid #ddd; font-size:0.75rem; text-transform:uppercase; color:#555;">Processed By</th>
                                    </tr>
                                </thead>
                                <tbody id="creditNoteHistoryBody">
                                    <tr><td colspan="7" style="text-align:center; padding:20px; color:#999;">Click "REFRESH HISTORY" to load credit note returns</td></tr>
                                </tbody>
                            </table>
                        </div>
                    </div>
                    <?php endif; ?>
                </div>
            </div>
        </div>
    </div>

    <div id="reportMode" class="main-tab d-none">
        <div class="card">
            <div class="form-row">
                <div class="form-group"><label>Start</label><input type="date" id="reportStart" value="<?php echo date('Y-m-01'); ?>"></div>
                <div class="form-group"><label>End</label><input type="date" id="reportEnd" value="<?php echo date('Y-m-d'); ?>"></div>
                <div class="form-group">
                    <label>Branch</label>
                    <select id="reportBranch"><?php renderBranchOptions('all', true); ?></select>
                </div>
            </div>
            <div style="display:flex; gap:10px; margin-top:10px;">
                <button class="btn btn-primary" onclick="generateReport()" style="flex:2; margin:0;">GENERATE ANALYTICS</button>
                <button class="btn" onclick="downloadPDF()" style="flex:1; margin:0; background:#e74c3c; color:white;">💾 SAVE PDF</button>
                <button class="btn" onclick="shareWhatsApp()" style="flex:1; margin:0; background:#2ecc71; color:white;">💬 WHATSAPP</button>
            </div>
        </div>

        <div id="reportDisplay" class="d-none" style="max-width: 100%; background: #fff;">
            <!-- Professional Report Header -->
            <div id="reportHeader" style="text-align: center; padding: 15px 0 10px 0; border-bottom: 3px solid #3498db; margin-bottom: 20px;">
                <h1 style="margin: 0; font-size: 28px; color: #2c3e50; font-weight: bold; line-height: 1.1;">FON2FIX</h1>
                <h2 style="margin: 3px 0 8px 0; font-size: 14px; color: #7f8c8d; font-weight: normal; line-height: 1.2;">SALES & PERFORMANCE REPORT</h2>
                <div id="reportDateRange" style="font-size: 10px; color: #95a5a6; margin-top: 5px;"></div>
            </div>
            
            <!-- Summary Cards -->
            <div class="summary-stats" style="margin-bottom: 20px;">
                <div class="stat-card"><h2 style="color:var(--primary)" id="totalSalesDisplay">0</h2><small>SALES (RM)</small></div>
                <div class="stat-card"><h2 style="color:#e74c3c" id="totalCostDisplay">0</h2><small>STOCK COST</small></div>
                <div class="stat-card"><h2 style="color:#c0392b" id="totalExpDisplay">0</h2><small>RIDER/EXPENSES</small></div>
                <div class="stat-card" style="border: 2px solid #2ecc71;"><h2 style="color:#2ecc71" id="totalProfitDisplay">0</h2><small>NET PROFIT</small></div>
            </div>

            <div class="card" style="border-left: 5px solid #c0392b;">
                <div class="section-title" style="color:#c0392b;">🛵 RIDER / DISPATCH EXPENSES</div>
                <div class="form-row" style="align-items: flex-end;">
                    <div class="form-group" style="flex:2">
                        <label>Description</label>
                        <input type="text" id="exp_desc" placeholder="e.g. Stock Transfer to Gombak">
                    </div>
                    <div class="form-group">
                        <label>Type</label>
                        <select id="exp_type" onchange="updateExpAmt(this)">
                            <option value="5">Rider (RM 5)</option>
                            <option value="10">Rider (RM 10)</option>
                            <option value="custom">Custom Amount</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label>Amount (RM)</label>
                        <input type="number" id="exp_amt" value="5.00">
                    </div>
                    <button class="btn" style="background:#c0392b; width:auto; margin-bottom:0;" onclick="submitExpense()">ADD EXPENSE</button>
                </div>
                <div id="expenseTableContainer" style="margin-top:10px;"></div>
            </div>
            
            <div class="charts-row">
                <div class="chart-box"><div class="section-title">💳 PAYMENTS</div><div class="chart-wrapper"><canvas id="paymentChart"></canvas></div></div>
                <div class="chart-box"><div class="section-title">🏢 BRANCHES</div><div class="chart-wrapper"><canvas id="branchChart"></canvas></div></div>
            </div>
            <div class="card"><div class="section-title">📈 SALES TREND (DAILY)</div><div class="chart-wrapper" style="height:300px;"><canvas id="trendChart"></canvas></div></div>
            
            <!-- Advanced Analytics Tables -->
            <div class="charts-row" style="margin-top:20px;">
                <div class="card" style="flex:1;">
                    <div class="section-title">🏆 TOP SELLING ITEMS</div>
                    <div class="table-container" style="max-height:300px; overflow-y:auto;">
                        <table style="width:100%; font-size:0.85rem;">
                            <thead><tr style="background:#f8f9fa;"><th style="padding:8px;">Item</th><th style="padding:8px; text-align:right;">Qty Sold</th></tr></thead>
                            <tbody id="topItemsTable"></tbody>
                        </table>
                    </div>
                </div>
                <div class="card" style="flex:1;">
                    <div class="section-title">💰 PROFIT BY CATEGORY</div>
                    <div class="table-container" style="max-height:300px; overflow-y:auto;">
                        <table style="width:100%; font-size:0.85rem;">
                            <thead><tr style="background:#f8f9fa;"><th style="padding:8px;">Category</th><th style="padding:8px; text-align:right;">Profit (RM)</th></tr></thead>
                            <tbody id="categoryProfitTable"></tbody>
                        </table>
                    </div>
                </div>
            </div>
            
            <div class="card" style="page-break-inside: auto;">
                <div class="section-title">📊 DETAILED BREAKDOWN</div>
                <div class="table-container">
                    <table id="detailedReportTable" style="width: 100%; border-collapse: collapse; table-layout: fixed;">
                        <colgroup>
                            <col style="width: 9%;">
                            <col style="width: 7%;">
                            <col style="width: 5%;">
                            <col style="width: 11%;">
                            <col style="width: 19%;">
                            <col style="width: 7%;">
                            <col style="width: 8%;">
                            <col style="width: 10%;">
                            <col style="width: 8%;">
                            <col style="width: 8%;">
                        </colgroup>
                        <thead>
                            <tr>
                                <th style="text-align: left; padding: 6px 2px; font-size: 7pt;">Job ID</th>
                                <th style="text-align: left; padding: 6px 2px; font-size: 7pt;">Date</th>
                                <th style="text-align: center; padding: 6px 2px; font-size: 7pt;">Type</th>
                                <th style="text-align: left; padding: 6px 2px; font-size: 7pt;">Customer</th>
                                <th style="text-align: left; padding: 6px 2px; font-size: 7pt;">Payment</th>
                                <th style="text-align: left; padding: 6px 2px; font-size: 7pt;">Branch</th>
                                <th style="text-align: center; padding: 6px 2px; font-size: 7pt;">Status</th>
                                <th style="text-align:right; padding: 6px 2px; font-size: 7pt;">Price</th>
                                <th style="text-align:right; padding: 6px 2px; font-size: 7pt;">Cost</th>
                                <th style="text-align:right; padding: 6px 2px; font-size: 7pt;">Profit</th>
                            </tr>
                        </thead>
                        <tbody id="reportTableBody"></tbody>
                        <tfoot id="reportTableFoot"></tfoot>
                    </table>
                </div>
            </div>
        </div>
    </div>

    <!-- ============================================== -->
    <!-- v18.0 ARCHIVE CONSOLE (master-only)            -->
    <!-- ============================================== -->
    <div id="archiveMode" class="main-tab d-none">
        <div class="card" style="border-top:4px solid #8e44ad;">
            <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:14px; flex-wrap:wrap; gap:10px;">
                <div class="section-title" style="margin:0; color:#8e44ad;">📦 ARCHIVE CONSOLE</div>
                <div style="font-size:0.8rem; color:#666; max-width:560px;">Rows older than ~1 year live here. Live tables stay fast. All operations are reversible via Restore. Master-only.</div>
            </div>

            <!-- Sub-tab nav -->
            <div style="display:flex; flex-wrap:wrap; gap:6px; border-bottom:2px solid #ecf0f1; margin-bottom:14px;">
                <button class="arch-subtab active" data-scope="dropoff" onclick="archSwitchSubtab('dropoff')" style="padding:8px 14px; border:none; background:transparent; border-bottom:3px solid #8e44ad; cursor:pointer; font-weight:bold;">🔧 Drop-off Repairs</button>
                <button class="arch-subtab" data-scope="retail" onclick="archSwitchSubtab('retail')" style="padding:8px 14px; border:none; background:transparent; border-bottom:3px solid transparent; cursor:pointer;">🛒 Daily Repairs / Sales</button>
                <button class="arch-subtab" data-scope="retail-billing" onclick="archSwitchSubtab('retail-billing')" style="padding:8px 14px; border:none; background:transparent; border-bottom:3px solid transparent; cursor:pointer;">✅ Billing</button>
                <button class="arch-subtab" data-scope="expenses" onclick="archSwitchSubtab('expenses')" style="padding:8px 14px; border:none; background:transparent; border-bottom:3px solid transparent; cursor:pointer;">💸 Expenses</button>
                <button class="arch-subtab" data-scope="activity_logs" onclick="archSwitchSubtab('activity_logs')" style="padding:8px 14px; border:none; background:transparent; border-bottom:3px solid transparent; cursor:pointer;">📜 Activity Logs</button>
            </div>

            <!-- Toolbar -->
            <div style="display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin-bottom:12px;">
                <input id="archSearch" type="text" placeholder="🔍 Search archive (job_id, customer, phone, IMEI)..." style="flex:1; min-width:240px; padding:8px; border:1px solid #ccc; border-radius:6px;" oninput="archDebouncedReload()">
                <input id="archDateFrom" type="date" style="padding:8px; border:1px solid #ccc; border-radius:6px;" onchange="archReload()" title="From date">
                <span>→</span>
                <input id="archDateTo" type="date" style="padding:8px; border:1px solid #ccc; border-radius:6px;" onchange="archReload()" title="To date">
                <button class="btn" style="width:auto; padding:8px 14px; margin:0; background:#8e44ad;" onclick="archOpenMoveDialog()">📥 Archive new rows…</button>
                <button class="btn" style="width:auto; padding:8px 14px; margin:0; background:#34495e;" onclick="archReload()" title="Refresh list">🔄 Refresh</button>
            </div>

            <!-- Stat strip -->
            <div id="archStatStrip" style="display:flex; gap:10px; flex-wrap:wrap; margin-bottom:12px; font-size:0.85rem;"></div>

            <!-- Table -->
            <div class="table-container">
                <table style="width:100%;">
                    <thead id="archTableHead"></thead>
                    <tbody id="archTableBody"></tbody>
                </table>
            </div>

            <!-- Pager -->
            <div id="archPager" style="display:flex; justify-content:space-between; align-items:center; margin-top:12px; flex-wrap:wrap; gap:10px;"></div>
        </div>
    </div>

    <!-- v18.0 Archive Move dialog -->
    <div id="archMoveModal" class="modal" style="display:none;"><div class="modal-content" style="max-width:560px; border-top:4px solid #8e44ad;">
        <h3 style="color:#8e44ad; margin-top:0;">📥 Archive Old Rows</h3>
        <p id="archMoveScopeLabel" style="font-weight:bold; color:#34495e;"></p>
        <div style="background:#fff3cd; border-left:4px solid #ffc107; padding:10px; border-radius:4px; margin:10px 0; font-size:0.85rem;">
            Rows older than the selected age are <b>moved</b> from the live table into the archive table. Nothing is deleted; everything is restorable.
        </div>
        <div style="display:grid; grid-template-columns:140px 1fr; gap:10px; align-items:center; margin-bottom:10px;">
            <label>Older than (days):</label>
            <input id="archMoveDays" type="number" min="30" max="7300" value="365" style="padding:6px; border:1px solid #ccc; border-radius:4px;">
            <label id="archMoveStatusLabel">Status filter:</label>
            <select id="archMoveStatus" style="padding:6px; border:1px solid #ccc; border-radius:4px;">
                <option value="all">All statuses</option>
                <option value="Completed">Completed</option>
                <option value="Pending">Pending</option>
                <option value="In Progress">In Progress</option>
                <option value="Cancelled">Cancelled</option>
                <option value="Refund">Refund</option>
            </select>
            <label>Branch:</label>
            <select id="archMoveBranch" style="padding:6px; border:1px solid #ccc; border-radius:4px;">
                <option value="all">Both branches</option>
                <option value="Gombak">Gombak</option>
                <option value="Sri Rampai">Sri Rampai</option>
            </select>
        </div>
        <div style="margin:10px 0;">
            <button class="btn" style="width:auto; padding:8px 14px; margin:0; background:#3498db;" onclick="archPreview()">🔍 Preview count</button>
            <span id="archPreviewResult" style="margin-left:10px; font-weight:bold;"></span>
        </div>
        <div id="archConfirmTokenBox" style="display:none; margin:10px 0; padding:10px; background:#fef5e7; border-radius:6px;">
            <small>Large batch — type the confirmation exactly:</small><br>
            <code id="archConfirmTokenExpected" style="background:#fff; padding:2px 6px; border-radius:3px;"></code>
            <input id="archConfirmToken" type="text" placeholder="Type confirmation here" style="display:block; margin-top:6px; padding:6px; width:100%; border:1px solid #ccc; border-radius:4px;">
        </div>
        <div style="text-align:right; margin-top:14px;">
            <button class="btn" style="width:auto; padding:8px 14px; margin:0 8px 0 0; background:#bdc3c7;" onclick="archCloseMoveDialog()">Cancel</button>
            <button class="btn" style="width:auto; padding:8px 14px; margin:0; background:#8e44ad;" onclick="archDoMove()">📥 Archive Now</button>
        </div>
    </div></div>

    <div id="usersMode" class="main-tab d-none">
        <div class="card">
            <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;">
                <div class="section-title" style="margin:0;">👥 STAFF MANAGEMENT</div>
                <div style="display:flex; gap:10px;">
                    <button class="btn" style="width:auto; padding:8px 15px; margin:0; background:#f1c40f; color:#333;" onclick="viewActivityLogs()">📜 LOGS</button>
                    <button class="btn" style="width:auto; padding:8px 15px; margin:0; background:#2ecc71;" onclick="openCreateUserModal()">➕ ADD STAFF</button>
                </div>
            </div>
            <div class="table-container" style="overflow-x:auto;">
                <table id="userTable" style="width:100%; border-collapse:collapse; font-size:0.85rem;">
                    <thead>
                        <tr style="background:#f8f9fa; position:sticky; top:0; z-index:10;">
                            <th style="padding:12px; text-align:left; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:120px;">Username</th>
                            <th style="padding:12px; text-align:left; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:80px;">Role</th>
                            <th style="padding:12px; text-align:left; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:100px;">Branch</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:80px; font-size:0.75rem;">✏️ Edit</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:80px; font-size:0.75rem;">🗑️ Delete</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:80px; font-size:0.75rem;">🚚 Transfer</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:80px; font-size:0.75rem;">↩️ Refund</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:80px; font-size:0.75rem;">♻️ Restore</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:90px; font-size:0.75rem;">🔒 Restrict</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:100px; font-size:0.75rem;">📦 Cross-Branch</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:90px; font-size:0.75rem;">📜 Logs</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:90px; font-size:0.75rem;">🔄 Merge</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:80px; font-size:0.75rem;">⚡ Bulk Ops</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:90px; font-size:0.75rem;">🖨️ Print</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:90px; font-size:0.75rem;">📥 Import</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:100px; font-size:0.75rem;">🔤 Uppercase</th>
                            <th style="padding:12px; text-align:center; border-bottom:2px solid #ddd; font-weight:bold; color:#555; min-width:100px;">Actions</th>
                        </tr>
                    </thead>
                    <tbody id="userListBody"></tbody>
                </table>
            </div>
        </div>
    </div>
</div>

<div id="editJobModal" class="modal">
    <div class="modal-content" style="max-width:850px;">
        <h3 style="color:#3498db;text-align:center;">EDIT ENTRY</h3>
        <input type="hidden" id="edit_db_id">
        <input type="hidden" id="edit_job_type"> 
        <div class="form-row">
            <div class="form-group"><label>Customer</label><input type="text" id="edit_customer"></div>
            <div class="form-group"><label style="color:#2980b9;">Phone</label><input type="text" id="edit_phone"></div>
            <div class="form-group"><label>Date</label><input type="date" id="edit_date"></div>
        </div>

        <div id="editRepairFields">
            <div class="form-group"><label>Device/Model</label><input type="text" id="edit_model"></div>
            <div class="form-row">
                <div class="form-group"><label>IMEI/SN</label><input type="text" id="edit_imei" onkeyup="cleanInput(this)"></div>
                <div class="form-group">
                    <label>Passcode</label>
                    <div style="display:flex; gap:5px;">
                        <input type="text" id="edit_passcode" style="flex:1;">
                        <button type="button" class="btn" style="width:auto; padding:0 12px; background:#9b59b6; margin:0;" onclick="openPatternModal('edit_passcode')" title="Draw Pattern">::: </button>
                    </div>
                </div>
            </div>
            <div class="form-group"><label>Description</label><textarea id="edit_repair"></textarea></div>
            
            <div style="background:#f8f9fa; padding:10px; border:1px solid #e0e0e0; border-radius:8px; margin-top:10px;">
                <label style="color:#2c3e50;">Parts Used (Stock Deducted)</label>
                <div id="editRepairPartsTable"></div>
                <div style="display:flex; gap:5px; margin-top:5px; flex-wrap:wrap;">
                    <select id="edit_repair_part_input" style="flex:2; padding:8px; min-width:150px;">
                        <option value="">-- Select Part --</option>
                    </select>
                    <input type="text" id="edit_repair_part_alt" placeholder="Compatible model (optional)" style="flex:1; padding:8px; min-width:120px;">
                    <input type="number" id="edit_repair_part_qty" value="1" style="width:60px; text-align:center;">
                    <button class="btn" style="width:auto; margin:0; background:#7f8c8d;" onclick="addEditRepairPart()">ADD</button>
                </div>
            </div>
        </div>

        <div id="editRetailFields" style="display:none; background:#f8f9fa; padding:15px; border:1px solid #e0e0e0; border-radius:8px; margin-bottom:10px;">
            <label style="color:#2c3e50; font-weight:bold; margin-bottom:10px;">🛒 RETAIL ITEMS</label>
            <div id="editRetailTable" style="margin-bottom:15px;"></div>
            <div style="display:flex; gap:10px; align-items:center;">
                <input type="text" id="edit_scan_input" list="retailStockList" placeholder="Scan Barcode or Search Item to Add..." onchange="handleEditScan(this)" style="flex:1; border:2px solid #2ecc71; padding:10px;">
                <button class="btn" style="width:auto; margin:0; background:#2ecc71; padding:10px 20px;" onclick="handleEditScan(document.getElementById('edit_scan_input'))">ADD</button>
            </div>
        </div>

        <div class="form-group"><label>Remarks</label><textarea id="edit_remarks" style="height:60px;"></textarea></div>
        
        <div class="form-row">
            <div class="form-group"><label>Price (Total)</label><input type="number" id="edit_price"></div>
            <div class="form-group"><label style="color:#e67e22;">Job Cost (RM)</label><input type="number" id="edit_job_cost" placeholder="0.00" oninput="markCostAsManual()"></div>
            <div class="form-group"><label>Deposit</label><input type="number" id="edit_deposit"></div>
        </div>

        <div class="form-row" style="background:#f8f9fa; border:1px solid #eee; padding:10px; border-radius:8px;">
            <div class="form-group"><label>Payment Method 1</label>
                <select id="edit_payment" onchange="updatePaymentAmounts('edit')"><option value="">-- None --</option><option value="Cash">Cash</option><option value="Bank Transfer/QR">Bank Transfer/QR</option><option value="SPayLater">SPayLater</option><option value="TnG Ewallet">TnG Ewallet</option></select>
                <input type="number" id="edit_pay_amt1" placeholder="Amount (RM)" step="0.01" style="margin-top:5px; background:#f0f0f0;" onchange="validatePaymentAmounts('edit')" disabled>
            </div>
            <div class="form-group"><label>Payment Method 2</label>
                <div style="display:flex; gap:5px; align-items:flex-start;">
                    <div style="flex:1;">
                        <select id="edit_payment2" onchange="updatePaymentAmounts('edit')" style="margin-bottom:5px;"><option value="">-- None --</option><option value="Cash">Cash</option><option value="Bank Transfer/QR">Bank Transfer/QR</option><option value="SPayLater">SPayLater</option><option value="TnG Ewallet">TnG Ewallet</option></select>
                        <input type="number" id="edit_pay_amt2" placeholder="Amount (RM)" step="0.01" onchange="validatePaymentAmounts('edit')" disabled style="background:#f0f0f0;">
                    </div>
                    <label style="margin:0; font-size:0.75rem; white-space:nowrap; cursor:pointer; padding-top:8px;">
                        <input type="checkbox" id="edit_sync_pay" onchange="syncPaymentMethods('edit')" style="margin-right:3px;"> Enable Amount Entry
                    </label>
                </div>
            </div>
            <div class="form-group"><label>Payment Status</label><select id="edit_pay_status"><option value="Unpaid">Unpaid</option><option value="Partial">Partial (Depo)</option><option value="Paid">Paid</option></select></div>
        </div>
        
        <div class="form-row">
            <div class="form-group"><label>Status</label><select id="edit_status"><option value="Pending">Pending</option><option value="Completed">Completed</option><option value="Return">Return</option></select></div>
            <div class="form-group"><label>Status Date</label><input type="date" id="edit_completed_at"></div>
        </div>
        
        <button class="btn btn-edit" onclick="saveEditJob()">SAVE CHANGES</button>
        <button class="btn" style="background:transparent;border:1px solid #ccc;color:#555;margin-top:10px;" onclick="document.getElementById('editJobModal').style.display='none'">CANCEL</button>
    </div>
</div>

<div id="deleteModal" class="modal">
    <div class="modal-content" style="text-align:center; border:1px solid #e74c3c;">
        <h3 style="color:#e74c3c;">⚠️ DELETE RECORD?</h3>
        <p>This action will release the ID for reuse.</p>
        <div style="margin: 15px 0;">
            <label style="text-align:left; font-size:12px;">Reason for Deletion (Required):</label>
            <textarea id="deleteReason" style="width:100%; height:60px; padding:10px; margin-top:5px; border:1px solid #ccc;"></textarea>
        </div>
        <button id="finalDeleteBtn" class="btn btn-danger" onclick="executeDelete()">YES, DELETE IT</button>
        <button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="closeDeleteModal()">CANCEL</button>
    </div>
</div>

<div id="editStockModal" class="modal"><div class="modal-content" style="border-top:4px solid #f39c12;"><h3 style="color:#f39c12;text-align:center;">EDIT STOCK ITEM</h3><input type="hidden" id="es_id"><div class="form-group"><label>Type</label><select id="es_type"><option value="Part">Repair Part</option><option value="Retail">Retail Item</option></select></div><div class="form-row"><div class="form-group"><label>Group</label><input type="text" id="es_group"></div><div class="form-group"><label>Model</label><?php if ($is_master || $is_endie): ?><input type="text" id="es_model"><?php else: ?><select id="es_model" style="border:1px solid #ddd; background:#fff;"><option value="">-- Select Device Model --</option></select><?php endif; ?></div></div><div class="form-group"><label>Part Name</label><input type="text" id="es_name"></div><div class="form-row"><div class="form-group" id="es_brand_container"><label>Brand</label><?php if ($is_master || $is_endie): ?><input type="text" id="es_brand" placeholder="e.g. OEM, Original, Grade A (supplier brand)"><?php else: ?><select id="es_brand" style="border:1px solid #ddd; background:#fff;"><option value="">-- Select Brand --</option></select><?php endif; ?></div><div class="form-group"><label>Category</label><select id="es_category"><option value="Other">Other</option><option value="LCD">LCD</option><option value="Battery">Battery</option><option value="Housing">Housing</option><option value="Back Glass">Back Glass</option><option value="Charging Port">Charging Port</option><option value="Camera">Camera</option><option value="Face ID">Face ID</option><option value="Motherboard">Motherboard</option><option value="Speaker">Speaker</option><option value="Unlock/Flash">Unlock/Flash</option><option value="Phone">Phone</option><option value="Tablet">Tablet</option><option value="Tempered Glass">Tempered Glass</option><option value="Cable">Cable</option><option value="Charger">Charger</option><option value="Earphone">Earphone</option><option value="Car holder">Car holder</option></select></div></div><div class="form-row"><div class="form-group"><label>Cost (RM)</label><input type="number" id="es_cost" step="0.01"></div><div class="form-group"><label>Selling Price</label><input type="number" id="es_sell" step="0.01"></div></div><div class="form-group"><label>Supplier</label><input type="text" id="es_supp"></div><div class="form-row" style="background:#f8f9fa; border:1px solid #eee; padding:10px; border-radius:8px; margin-top:10px;"><div class="form-group"><label style="color:#2980b9;">Gombak Qty</label><input type="number" id="es_stock_g"></div><div class="form-group"><label style="color:#8e44ad;">Sri Rampai Qty</label><input type="number" id="es_stock_s"></div></div><button class="btn btn-edit" onclick="saveEditStock()">UPDATE STOCK</button><button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="document.getElementById('editStockModal').style.display='none'">CANCEL</button></div></div>
<div id="patternModal" class="modal"><div class="modal-content" style="width: 300px; text-align: center;"><h3>Draw Pattern</h3><p style="font-size:12px; color:#aaa;">Click dots in order</p><div class="pattern-grid" id="patternGrid"></div><div style="margin-top:20px; display:flex; gap:10px;"><button class="btn btn-danger" onclick="resetPattern()">CLEAR</button><button class="btn btn-primary" onclick="savePattern()">USE THIS</button></div><button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="closePatternModal()">CANCEL</button></div></div>
<div id="createUserModal" class="modal"><div class="modal-content"><h3>Add New Staff</h3><label>Username</label><input type="text" id="new_user_name"><label>Password</label><input type="password" id="new_user_pass" value="123456"><label>Assigned Branch</label><select id="new_user_branch" style="margin-bottom:15px;"><option value="Gombak">Gombak</option><option value="Sri Rampai">Sri Rampai</option></select><button class="btn btn-primary" onclick="submitNewUser()">CREATE USER</button><button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="document.getElementById('createUserModal').style.display='none'">CANCEL</button></div></div>
<div id="passwordModal" class="modal"><div class="modal-content"><h3>Change Password</h3><input type="hidden" id="pass_user_id"><div id="oldPassField"><label>Old Password</label><input type="password" id="old_pass"></div><label>New Password</label><input type="password" id="new_pass"><button class="btn btn-primary" onclick="submitPassChange()">UPDATE</button><button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="document.getElementById('passwordModal').style.display='none'">CANCEL</button></div></div>
<div id="cameraModal" class="modal"><div class="modal-content" style="text-align:center;"><h3>📷 Scan QR</h3><div id="reader"></div><button class="btn btn-danger" onclick="stopCameraScanner()">CLOSE</button></div></div>
<div id="transferModal" class="modal"><div class="modal-content"><h3>Transfer Stock</h3><input type="hidden" id="transferId"><p id="transferItemName"></p><div class="form-row"><select id="transferFrom"><option value="Gombak">Gombak</option><option value="Sri Rampai">Sri Rampai</option></select><select id="transferTo"><option value="Sri Rampai">Sri Rampai</option><option value="Gombak">Gombak</option></select></div><input type="number" id="transferQty" value="1"><button class="btn btn-primary" onclick="submitTransfer()">CONFIRM</button><button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="document.getElementById('transferModal').style.display='none'">CANCEL</button></div></div>
<div id="deleteStockModal" class="modal"><div class="modal-content" style="border-top:4px solid #e74c3c;"><h3 style="color:#e74c3c;text-align:center;">🗑️ DELETE STOCK</h3><input type="hidden" id="deleteStockId"><input type="hidden" id="deleteStockLocation"><p id="deleteStockItemName" style="font-weight:bold; font-size:1.1em; margin:10px 0;"></p><div class="form-group"><label>Location</label><div style="display:flex; gap:10px; align-items:center; padding:10px; background:#f8f9fa; border-radius:6px;"><span id="deleteStockLocationDisplay" style="font-weight:bold; font-size:1.2em;"></span></div></div><div class="form-group"><label>Current Stock</label><div style="display:flex; gap:10px; align-items:center; padding:10px; background:#ecf0f1; border-radius:6px;"><span id="deleteStockCurrentQty" style="font-weight:bold; font-size:1.3em; color:#2980b9;"></span></div></div><div class="form-group"><label>Delete Option</label><select id="deleteStockOption" onchange="toggleDeleteStockQty()" style="margin-bottom:10px;"><option value="all">Delete All Stock</option><option value="qty">Delete Specific Quantity</option></select></div><div id="deleteStockQtyContainer" class="form-group" style="display:none;"><label>Quantity to Delete</label><input type="number" id="deleteStockQty" min="1" value="1" placeholder="Enter quantity"></div><button class="btn btn-danger" onclick="executeDeleteStock()">DELETE</button><button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="closeDeleteStockModal()">CANCEL</button></div></div>
<div id="creditNoteModal" class="modal"><div class="modal-content" style="border-top:4px solid #e67e22;"><h3 style="color:#e67e22;text-align:center;">📝 CREDIT NOTE - RETURN TO SUPPLIER</h3><input type="hidden" id="cnStockId"><p id="cnItemName" style="font-weight:bold; font-size:1.1em; margin:10px 0; color:#333;"></p><div class="form-group"><label>Supplier</label><input type="text" id="cnSupplier" readonly style="background:#f8f9fa; color:#777;"></div><div class="form-row"><div class="form-group"><label>Branch</label><select id="cnBranch" onchange="updateCNMaxQty()"><option value="Gombak">Gombak</option><option value="Sri Rampai">Sri Rampai</option></select></div><div class="form-group"><label>Current Stock</label><div style="padding:10px; background:#ecf0f1; border-radius:6px; text-align:center;"><span id="cnCurrentStock" style="font-weight:bold; font-size:1.2em; color:#2980b9;">0</span></div></div><div class="form-group"><label>Quantity to Return</label><input type="number" id="cnQuantity" min="1" value="1" placeholder="Enter quantity" onchange="validateCNQty()"></div></div><div class="form-group"><label>Return Date</label><input type="date" id="cnDate" value="<?php echo date('Y-m-d'); ?>"></div><div class="form-group"><label>Reason for Return</label><textarea id="cnReason" placeholder="Enter reason for returning stock to supplier..." style="min-height:80px; resize:vertical;"></textarea></div><button class="btn" style="background:#e67e22; color:white;" onclick="submitCreditNote()">SUBMIT CREDIT NOTE</button><button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="closeCreditNoteModal()">CANCEL</button></div></div>
<div id="historyModal" class="modal"><div class="modal-content"><h3>Logs</h3><div class="table-container"><table id="historyTableBody"></table></div><button class="btn" style="background:#eee; color:#333; border:1px solid #ccc;" onclick="document.getElementById('historyModal').style.display='none'">CLOSE</button></div></div>
<div id="activityModal" class="modal"><div class="modal-content"><h3>Activity Logs</h3><div class="table-container"><table id="activityTableBody"></table></div><button class="btn" style="background:#eee; color:#333; border:1px solid #ccc;" onclick="document.getElementById('activityModal').style.display='none'">CLOSE</button></div></div>
<div id="stockLogModal" class="modal"><div class="modal-content" style="border-top:4px solid #3498db;"><h3 style="color:#3498db;text-align:center;">📜 STOCK ACTIVITY LOGS</h3><div class="table-container"><table id="stockLogTableBody"></table></div><button class="btn" style="background:#eee; color:#333; border:1px solid #ccc;" onclick="document.getElementById('stockLogModal').style.display='none'">CLOSE</button></div></div>

<div id="stockMovementsModal" class="modal"><div class="modal-content" style="border-top:4px solid #16a085; max-width:900px; max-height:85vh; overflow-y:auto;"><h3 style="color:#16a085;text-align:center;">📋 DATE IN / DATE OUT / REFUND</h3><p id="stockMovementsItemName" style="font-weight:bold; margin:10px 0; color:#333;"></p><div class="table-container"><table id="stockMovementsTableBody"></table></div><button class="btn" style="background:#eee; color:#333; border:1px solid #ccc; margin-top:15px;" onclick="document.getElementById('stockMovementsModal').style.display='none'">CLOSE</button></div></div>
<div id="categoryBreakdownModal" class="modal"><div class="modal-content" style="border-top:4px solid #27ae60;"><h3 style="color:#27ae60;text-align:center;" id="categoryBreakdownTitle">💰 CATEGORY BREAKDOWN</h3><div style="padding:20px;"><table style="width:100%; border-collapse:collapse; margin:20px 0;"><tr style="border-bottom:2px solid #ecf0f1;"><td style="padding:12px; font-weight:bold; color:#555;">Category</td><td id="categoryBreakdownName" style="padding:12px; font-weight:bold; color:#27ae60;"></td></tr><tr style="border-bottom:1px solid #ecf0f1;"><td style="padding:12px;">Total Sales</td><td id="categoryBreakdownSales" style="padding:12px; text-align:right; font-weight:bold; color:#2ecc71;"></td></tr><tr style="border-bottom:1px solid #ecf0f1;"><td style="padding:12px;">Total Cost</td><td id="categoryBreakdownCost" style="padding:12px; text-align:right; font-weight:bold; color:#e74c3c;"></td></tr><tr style="background:#f8f9fa; border-top:2px solid #27ae60;"><td style="padding:12px; font-weight:bold;">Profit</td><td id="categoryBreakdownProfit" style="padding:12px; text-align:right; font-weight:bold; font-size:1.2em;"></td></tr></table></div><button class="btn" style="background:#eee; color:#333; border:1px solid #ccc;" onclick="document.getElementById('categoryBreakdownModal').style.display='none'">CLOSE</button></div></div>
<div id="bulkOperationsModal" class="modal"><div class="modal-content" style="border-top:4px solid #9b59b6;"><h3 style="color:#9b59b6;text-align:center;">⚡ BULK OPERATIONS</h3><p style="color:#777; font-size:0.9em; margin-bottom:15px;">Select items from stock list (checkboxes), then choose operation below.</p><div class="form-group"><label>Operation Type</label><select id="bulkOperationType" onchange="toggleBulkFields()"><option value="">-- Select Operation --</option><option value="price">Update Price</option><option value="stock_gombak">Update Gombak Stock</option><option value="stock_sr">Update Sri Rampai Stock</option><option value="cost">Update Cost</option><option value="category">Change Category</option><option value="supplier">Update Supplier</option></select></div><div id="bulkValueContainer" class="form-group" style="display:none;"><label id="bulkValueLabel">Value</label><input type="text" id="bulkValue" placeholder="Enter value"></div><div id="bulkCategoryContainer" class="form-group" style="display:none;"><label>Category</label><select id="bulkCategory"><option value="Other">Other</option><option value="LCD">LCD</option><option value="Battery">Battery</option><option value="Housing">Housing</option><option value="Back Glass">Back Glass</option><option value="Charging Port">Charging Port</option><option value="Camera">Camera</option><option value="Face ID">Face ID</option><option value="Motherboard">Motherboard</option><option value="Speaker">Speaker</option><option value="Unlock/Flash">Unlock/Flash</option><option value="Tempered Glass">Tempered Glass</option><option value="Cable">Cable</option><option value="Charger">Charger</option></select></div><button class="btn btn-primary" onclick="executeBulkOperation()">APPLY TO SELECTED</button><button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="document.getElementById('bulkOperationsModal').style.display='none'">CANCEL</button></div></div>
<div id="bulkPrintModal" class="modal"><div class="modal-content" style="border-top:4px solid #16a085;"><h3 style="color:#16a085;text-align:center;">🖨️ BULK PRINT</h3><p style="color:#777; font-size:0.9em; margin-bottom:15px;">Select items from stock list (checkboxes), then choose print type.</p><div class="form-group"><label>Print Type</label><select id="bulkPrintType"><option value="qr">QR Codes</option><option value="labels">Labels</option><option value="barcode">Barcodes</option></select></div><div class="form-group"><label>Branch Prefix</label><select id="bulkPrintBranch"><option value="both">Both (SG & SR)</option><option value="gombak">Gombak (SG) Only</option><option value="srirampai">Sri Rampai (SR) Only</option></select></div><button class="btn btn-primary" onclick="executeBulkPrint()">PRINT SELECTED</button><button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="document.getElementById('bulkPrintModal').style.display='none'">CANCEL</button></div></div>

<div id="lowStockAlertsModal" class="modal"><div class="modal-content" style="border-top:4px solid #e74c3c; max-width:900px; max-height:80vh; overflow-y:auto;"><h3 style="color:#e74c3c;text-align:center;">⚠️ LOW STOCK ALERTS</h3><div style="margin-bottom:15px;"><label>Filter by Branch:</label><select id="lowStockBranchFilter" onchange="loadLowStockAlerts()" style="margin-left:10px; padding:5px;"><option value="all">All Branches</option><option value="Gombak">Gombak Only</option><option value="Sri Rampai">Sri Rampai Only</option></select></div><div id="lowStockAlertsContent"></div><button class="btn" style="background:#eee; color:#333; border:1px solid #ccc; margin-top:20px;" onclick="document.getElementById('lowStockAlertsModal').style.display='none'">CLOSE</button></div></div>

<div id="stockValuationModal" class="modal"><div class="modal-content" style="border-top:4px solid #3498db; max-width:1000px; max-height:80vh; overflow-y:auto;"><h3 style="color:#3498db;text-align:center;">💰 STOCK VALUATION</h3><div class="summary-stats" style="margin:20px 0;"><div class="stat-card"><h2 style="color:#2980b9;" id="valGombak">RM 0</h2><small>Gombak Value</small></div><div class="stat-card"><h2 style="color:#8e44ad;" id="valSR">RM 0</h2><small>Sri Rampai Value</small></div><div class="stat-card" style="border:2px solid #2ecc71;"><h2 style="color:#2ecc71;" id="valTotal">RM 0</h2><small>Total Value</small></div></div><div id="stockValuationContent"></div><button class="btn" style="background:#eee; color:#333; border:1px solid #ccc; margin-top:20px;" onclick="document.getElementById('stockValuationModal').style.display='none'">CLOSE</button></div></div>

<div id="purchaseOrdersModal" class="modal"><div class="modal-content" style="border-top:4px solid #9b59b6; max-width:1000px; max-height:80vh; overflow-y:auto;"><h3 style="color:#9b59b6;text-align:center;">📋 PURCHASE ORDERS</h3><div style="display:flex; gap:10px; margin-bottom:15px;"><select id="poStatusFilter" onchange="loadPurchaseOrders()" style="flex:1; padding:5px;"><option value="all">All Status</option><option value="Pending">Pending</option><option value="Received">Received</option><option value="Cancelled">Cancelled</option></select><button class="btn" style="background:#9b59b6; width:auto; padding:8px 15px; margin:0;" onclick="createPurchaseOrder()">➕ NEW PURCHASE ORDER</button></div><div id="purchaseOrdersContent"></div><button class="btn" style="background:#eee; color:#333; border:1px solid #ccc; margin-top:20px;" onclick="document.getElementById('purchaseOrdersModal').style.display='none'">CLOSE</button></div></div>

<div id="inventoryAnalyticsModal" class="modal"><div class="modal-content" style="border-top:4px solid #16a085; max-width:1200px; max-height:80vh; overflow-y:auto;"><h3 style="color:#16a085;text-align:center;">📊 INVENTORY ANALYTICS</h3><div style="margin-bottom:15px;"><label>Analysis Period:</label><select id="analyticsDays" onchange="loadInventoryAnalytics()" style="margin-left:10px; padding:5px;"><option value="30">Last 30 Days</option><option value="60">Last 60 Days</option><option value="90" selected>Last 90 Days</option><option value="180">Last 180 Days</option></select></div><div id="inventoryAnalyticsContent"></div><button class="btn" style="background:#eee; color:#333; border:1px solid #ccc; margin-top:20px;" onclick="document.getElementById('inventoryAnalyticsModal').style.display='none'">CLOSE</button></div></div>

<div id="bulkImportModal" class="modal"><div class="modal-content" style="border-top:4px solid #27ae60; max-width:900px;"><h3 style="color:#27ae60;text-align:center;">📥 BULK STOCK IMPORT</h3><p style="color:#777; font-size:0.9em; margin-bottom:15px;">Paste your stock list below. Each entry should be on a new line with the following format:</p><div style="background:#f8f9fa; padding:15px; border-radius:8px; margin-bottom:15px; border-left:4px solid #27ae60;"><strong style="color:#27ae60;">Format Example:</strong><pre style="margin:10px 0; padding:10px; background:#fff; border:1px solid #ddd; border-radius:4px; font-size:0.85em; white-space:pre-wrap;">Iphone 13 PRO MAX SS HIGH CAPACITY BATTERY
Stock SG : 1
Stock SR : 1
Cost : RM59
Supplier : HWT</pre><p style="margin:0; font-size:0.85em; color:#555;">Each item should be separated by a blank line. Fields are case-insensitive.</p></div><div class="form-group"><label>Stock Type</label><select id="bulkImportType" style="margin-bottom:10px;"><option value="Part">Repair Part</option><option value="Retail">Retail Item</option></select></div><div class="form-group"><label>Paste Stock Data</label><textarea id="bulkImportData" placeholder="Paste your stock list here..." style="width:100%; min-height:300px; padding:10px; border:2px solid #27ae60; border-radius:6px; font-family:monospace; font-size:0.9em; line-height:1.5;"></textarea></div><div id="bulkImportProgress" style="display:none; margin:15px 0; padding:10px; background:#e8f5e9; border-radius:6px;"><div style="display:flex; align-items:center; gap:10px;"><div style="flex:1; background:#fff; height:20px; border-radius:10px; overflow:hidden;"><div id="bulkImportProgressBar" style="background:#27ae60; height:100%; width:0%; transition:width 0.3s;"></div></div><span id="bulkImportProgressText">0%</span></div><div id="bulkImportStatus" style="margin-top:10px; font-size:0.9em; color:#555;"></div></div><div id="bulkImportResults" style="display:none; margin-top:15px; max-height:300px; overflow-y:auto; padding:10px; background:#f8f9fa; border-radius:6px;"><h4 style="margin:0 0 10px 0; color:#27ae60;">Import Results:</h4><div id="bulkImportResultsContent"></div></div><button class="btn btn-primary" style="background:#27ae60;" onclick="executeBulkImport()">IMPORT STOCK</button><button class="btn" style="background:transparent; margin-top:5px; border:1px solid #ccc; color:#555;" onclick="closeBulkImportModal()">CANCEL</button></div></div>

<script>
    const CSRF = "<?php echo $csrf_token; ?>";
    const HEADERS = { 'Content-Type': 'application/json', 'X-CSRF-Token': CSRF };
    
    // --- USER PERMISSIONS & CONSTANTS ---
    const IS_MASTER = <?php echo ($is_master || $is_endie) ? 'true' : 'false'; ?>;
    const IS_ENDIE = <?php echo $is_endie ? 'true' : 'false'; ?>;
    const MY_ID = <?php echo $_SESSION['user_id']; ?>;
    const MY_USERNAME = "<?php echo addslashes($_SESSION['user'] ?? ''); ?>";
    
    let liveCanEdit = <?php echo $can_edit; ?>;
    let liveCanDelete = <?php echo $can_delete; ?>;
    let liveCanTransfer = <?php echo $can_transfer; ?>;
    let liveCanRefund = <?php echo $can_refund; ?>;
    let liveCanRestore = <?php echo $can_restore; ?>;
    let liveCanCrossBranchStock = <?php echo $can_cross_stock; ?>;
    let liveCanViewStockLogs = <?php echo $can_view_stock_logs ? 'true' : 'false'; ?>;
    
    const IS_RESTRICTED = <?php echo $is_restricted ? 'true' : 'false'; ?>;
    const MY_BRANCH_NAME = "<?php echo addslashes($my_branch); ?>";
    const MY_BRANCH_LOWER = "<?php echo addslashes(strtolower($my_branch)); ?>";
    let isSubmittingRepair = false;
    let isSubmittingRetail = false;
    let isSendingBackupToServer = false;

    function setSubmitButtonState(buttonId, loading, loadingText) {
        const btn = document.getElementById(buttonId);
        if (!btn) return;
        const labelNode = btn.querySelector('span:last-child');
        if (!btn.dataset.originalText && labelNode) {
            btn.dataset.originalText = labelNode.textContent;
        }
        btn.disabled = loading;
        btn.classList.toggle('loading', loading);
        if (labelNode) {
            labelNode.textContent = loading ? loadingText : (btn.dataset.originalText || labelNode.textContent);
        }
    }

    function generateRequestId(prefix = 'REQ') {
        const rand = Math.random().toString(36).slice(2, 10);
        return `${prefix}-${Date.now()}-${rand}`.toUpperCase();
    }

    function getItemBranchStock(partName) {
        if (!partName || !allStock) return null;
        const nameLower = partName.toLowerCase().trim();
        const isGombak = MY_BRANCH_LOWER.includes('gombak');
        for (const type of ['Part', 'Retail']) {
            if (!allStock[type]) continue;
            for (const cat in allStock[type]) {
                for (const item of allStock[type][cat]) {
                    if ((item.part_name || '').toLowerCase().trim() === nameLower) {
                        const branchQty = parseInt(isGombak ? item.stock_gombak : item.stock_sr) || 0;
                        const totalQty = (parseInt(item.stock_gombak) || 0) + (parseInt(item.stock_sr) || 0);
                        return { branchQty, totalQty, branchName: isGombak ? 'Gombak' : 'Sri Rampai', item };
                    }
                }
            }
        }
        return null;
    }

    function checkStockBeforeAdd(partName, qty = 1) {
        const stock = getItemBranchStock(partName);
        if (!stock) return true;
        if (stock.branchQty <= 0) {
            showToast(`❌ No stock for "${partName}" at ${stock.branchName} (Stock: 0)`, 'error');
            return false;
        }
        if (qty > stock.branchQty) {
            showToast(`⚠️ Only ${stock.branchQty} left for "${partName}" at ${stock.branchName}`, 'error');
            return false;
        }
        return true;
    }

    // Restrict stock input fields based on permission
    function restrictStockFields() {
        const isGombak = MY_BRANCH_LOWER.includes('gombak');
        
        // Get container elements for hiding/showing
        const gombakQtyPartContainer = document.getElementById('np_qty_g_container');
        const srQtyPartContainer = document.getElementById('np_qty_s_container');
        const gombakQtyRetailContainer = document.getElementById('nr_qty_g_container');
        const srQtyRetailContainer = document.getElementById('nr_qty_s_container');
        
        // Get input elements for disabling/enabling
        const gombakQtyPart = document.getElementById('np_qty_g');
        const srQtyPart = document.getElementById('np_qty_s');
        const gombakQtyRetail = document.getElementById('nr_qty_g');
        const srQtyRetail = document.getElementById('nr_qty_s');
        const editGombak = document.getElementById('es_stock_g');
        const editSr = document.getElementById('es_stock_s');
        
        // If master or has cross-branch permission, show all fields
        if (IS_MASTER || liveCanCrossBranchStock) {
            // Show all containers
            if (gombakQtyPartContainer) gombakQtyPartContainer.style.display = '';
            if (srQtyPartContainer) srQtyPartContainer.style.display = '';
            if (gombakQtyRetailContainer) gombakQtyRetailContainer.style.display = '';
            if (srQtyRetailContainer) srQtyRetailContainer.style.display = '';
            // Enable all inputs
            if (gombakQtyPart) { gombakQtyPart.disabled = false; gombakQtyPart.value = gombakQtyPart.value || 0; }
            if (srQtyPart) { srQtyPart.disabled = false; srQtyPart.value = srQtyPart.value || 0; }
            if (gombakQtyRetail) { gombakQtyRetail.disabled = false; gombakQtyRetail.value = gombakQtyRetail.value || 0; }
            if (srQtyRetail) { srQtyRetail.disabled = false; srQtyRetail.value = srQtyRetail.value || 0; }
            if (editGombak) editGombak.disabled = false;
            if (editSr) editSr.disabled = false;
            return;
        }
        
        // Restricted users - hide the other branch's fields
        if (isGombak) {
            // User is Gombak - hide Sri Rampai fields
            if (srQtyPartContainer) srQtyPartContainer.style.display = 'none';
            if (srQtyRetailContainer) srQtyRetailContainer.style.display = 'none';
            // Show Gombak fields
            if (gombakQtyPartContainer) gombakQtyPartContainer.style.display = '';
            if (gombakQtyRetailContainer) gombakQtyRetailContainer.style.display = '';
            // Ensure Sri Rampai values are 0 and disabled
            if (srQtyPart) { srQtyPart.disabled = true; srQtyPart.value = 0; }
            if (srQtyRetail) { srQtyRetail.disabled = true; srQtyRetail.value = 0; }
            if (editSr) { editSr.disabled = true; editSr.title = 'Only Gombak staff can edit this'; }
            // Enable Gombak fields
            if (gombakQtyPart) gombakQtyPart.disabled = false;
            if (gombakQtyRetail) gombakQtyRetail.disabled = false;
        } else {
            // User is Sri Rampai - hide Gombak fields
            if (gombakQtyPartContainer) gombakQtyPartContainer.style.display = 'none';
            if (gombakQtyRetailContainer) gombakQtyRetailContainer.style.display = 'none';
            // Show Sri Rampai fields
            if (srQtyPartContainer) srQtyPartContainer.style.display = '';
            if (srQtyRetailContainer) srQtyRetailContainer.style.display = '';
            // Ensure Gombak values are 0 and disabled
            if (gombakQtyPart) { gombakQtyPart.disabled = true; gombakQtyPart.value = 0; }
            if (gombakQtyRetail) { gombakQtyRetail.disabled = true; gombakQtyRetail.value = 0; }
            if (editGombak) { editGombak.disabled = true; editGombak.title = 'Only Sri Rampai staff can edit this'; }
            // Enable Sri Rampai fields
            if (srQtyPart) srQtyPart.disabled = false;
            if (srQtyRetail) srQtyRetail.disabled = false;
        }
    }
    
    // Call on page load and when modals open
    document.addEventListener('DOMContentLoaded', restrictStockFields);

    // --- GLOBAL VARIABLES ---
    let allJobs = [];
    let allRetailJobs = [];
    let allStock = [];
    let jobToDeleteId = null;
    let currentEditItems = [];
    let currentEditRepairParts = [];
    let isCostManuallyEdited = false; // Flag to track if user manually edited the cost

    // --- UTILITY FUNCTIONS ---
    function formatDate(dateString) {
        if (!dateString) return '';
        const date = new Date(dateString + 'T00:00:00');
        const options = { year: 'numeric', month: 'long', day: 'numeric' };
        return date.toLocaleDateString('en-US', options);
    }
    function escapeHtml(text) {
        if (!text) return '';
        return text.toString()
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }

    function showToast(msg, type = 'success') {
        const container = document.getElementById('toast-container');
        const div = document.createElement('div');
        div.className = `toast ${type}`;
        div.innerHTML = `<span class="toast-icon">${type === 'success' ? '✅' : '⚠️'}</span> <span class="toast-msg">${msg}</span>`;
        container.appendChild(div);
        setTimeout(() => div.remove(), 4000);
    }

    async function sendBackupToServer() {
        if (isSendingBackupToServer) {
            showToast('Backup sync is already running. Please wait...', 'error');
            return;
        }
        if (!confirm('Send backup to backup server now? This may take a while.')) return;

        const btn = document.getElementById('syncBackupBtn');
        const originalText = btn ? btn.textContent : '';
        isSendingBackupToServer = true;
        if (btn) {
            btn.disabled = true;
            btn.textContent = '⏳ SENDING...';
        }
        showToast('Starting backup sync...', 'success');

        try {
            const response = await fetch('sync_to_backup.php?ajax=1', {
                method: 'POST',
                headers: { 'X-CSRF-Token': CSRF },
                credentials: 'same-origin'
            });
            const result = await response.json();

            if (response.ok && result.success) {
                showToast(`Backup sent successfully (HTTP ${result.http_code ?? 200})`, 'success');
            } else {
                const errorMsg = result.error || `Backup sync failed (HTTP ${result.http_code || response.status})`;
                showToast(errorMsg, 'error');
            }
        } catch (error) {
            showToast(`Network error during backup sync: ${error.message}`, 'error');
        } finally {
            isSendingBackupToServer = false;
            if (btn) {
                btn.disabled = false;
                btn.textContent = originalText || '☁️ SEND BACKUP TO SERVER';
            }
        }
    }

    function cleanInput(el) {
        if (el.value.includes('|')) {
            el.value = el.value.replace(/(Gombak\||Sri Rampai\|)/g, '').trim();
        }
    }

    document.getElementById('rep_date').valueAsDate = new Date();
    document.getElementById('ret_date').valueAsDate = new Date();
    document.getElementById('ret_pickup').valueAsDate = new Date();
    
    // Show beginner guide if not dismissed
    if (!localStorage.getItem('hideBeginnerGuide')) {
        document.getElementById('beginnerGuide').style.display = 'block';
    }
    
    // Initialize repair total calculation
    if (typeof calcRepairTotal === 'function') {
        calcRepairTotal();
    }

    (function enforceBranchSelects() {
        try {
            if (!IS_MASTER && IS_RESTRICTED && MY_BRANCH_NAME) {
                const ids = ['branchFilter', 'rep_branch', 'ret_branch', 'reportBranch', 'new_user_branch'];
                ids.forEach(id => {
                    const el = document.getElementById(id);
                    if (!el) return;
                    el.innerHTML = `<option value="${MY_BRANCH_NAME}">${MY_BRANCH_NAME}</option>`;
                    el.value = MY_BRANCH_NAME;
                    el.disabled = true;
                });
            }
        } catch (e) {
        }
    })();

    // --- PATTERN LOCK MODAL LOGIC ---
    let currentPatternTargetId = '';
    let patternSequence = [];

    function openPatternModal(targetInputId) {
        currentPatternTargetId = targetInputId;
        patternSequence = [];
        renderPatternGrid();
        document.getElementById('patternModal').style.display = 'flex';
    }

    function closePatternModal() {
        document.getElementById('patternModal').style.display = 'none';
    }

    function renderPatternGrid() {
        const grid = document.getElementById('patternGrid');
        grid.innerHTML = '';
        for (let i = 1; i <= 9; i++) {
            let dot = document.createElement('div');
            dot.className = 'pattern-dot ' + (patternSequence.includes(i) ? 'active' : '');
            dot.dataset.val = i;
            dot.onclick = function() {
                if (!patternSequence.includes(i)) {
                    patternSequence.push(i);
                    this.classList.add('active');
                }
            };
            grid.appendChild(dot);
        }
    }

    function resetPattern() {
        patternSequence = [];
        renderPatternGrid();
    }

    function savePattern() {
        if (patternSequence.length > 0) {
            document.getElementById(currentPatternTargetId).value = "Pattern: " + patternSequence.join('-');
        }
        closePatternModal();
    }

    document.getElementById('edit_status').addEventListener('change', function() {
        if (this.value === 'Completed') {
            document.getElementById('edit_pay_status').value = 'Paid';
        }
    });

    // --- PAYMENT METHOD SYNC & COMBINE ---
    function syncPaymentMethods(prefix) {
        // Handle different ID naming conventions: 'edit' uses 'edit_payment', others use 'rep_pay'/'ret_pay'
        const method1Id = prefix === 'edit' ? prefix + '_payment' : prefix + '_pay';
        const method2Id = prefix === 'edit' ? prefix + '_payment2' : prefix + '_pay2';
        
        const checkbox = document.getElementById(prefix + '_sync_pay');
        const method1 = document.getElementById(method1Id);
        const method2 = document.getElementById(method2Id);
        const amt1 = document.getElementById(prefix + '_pay_amt1');
        const amt2 = document.getElementById(prefix + '_pay_amt2');
        
        if (!checkbox || !method1 || !method2) return; // Safety check
        
        // Payment method dropdowns are always enabled - only amount inputs are controlled by checkbox
        if (checkbox.checked) {
            // When checked: Enable amount inputs for both methods
            if (amt1) {
                amt1.disabled = false;
                amt1.style.background = '';
            }
            if (amt2) {
                amt2.disabled = false;
                amt2.style.background = '';
                // Sync amount 2 to amount 1 if method 2 is synced
                if (method2.value === method1.value && amt1) {
                    amt2.value = amt1.value;
                }
            }
        } else {
            // When unchecked: Disable amount inputs and clear values
            if (amt1) {
                amt1.disabled = true;
                amt1.style.background = '#f0f0f0';
                amt1.value = '';
            }
            if (amt2) {
                amt2.disabled = true;
                amt2.style.background = '#f0f0f0';
                amt2.value = '';
            }
        }
    }

    function updatePaymentAmounts(prefix) {
        const checkbox = document.getElementById(prefix + '_sync_pay');
        if (checkbox && checkbox.checked) {
            const amt1 = document.getElementById(prefix + '_pay_amt1');
            const amt2 = document.getElementById(prefix + '_pay_amt2');
            if (amt1 && amt2) {
                amt2.value = amt1.value;
            }
        }
    }

    function validatePaymentAmounts(prefix) {
        const amt1 = parseFloat(document.getElementById(prefix + '_pay_amt1')?.value || 0);
        const amt2 = parseFloat(document.getElementById(prefix + '_pay_amt2')?.value || 0);
        const totalField = prefix === 'rep' ? document.getElementById('totalRepairPrice') : 
                          prefix === 'ret' ? document.getElementById('totalRetailPrice') : null;
        
        if (totalField) {
            const total = parseFloat(totalField.value || 0);
            const sum = amt1 + amt2;
            if (sum > total && total > 0) {
                showToast(`Payment amounts (RM ${sum.toFixed(2)}) exceed total (RM ${total.toFixed(2)})`, 'error');
            }
        }
    }

    function combinePaymentMethods(prefix) {
        // Handle different ID naming conventions: 'edit' uses 'edit_payment', others use 'rep_pay'/'ret_pay'
        const method1Id = prefix === 'edit' ? prefix + '_payment' : prefix + '_pay';
        const method2Id = prefix === 'edit' ? prefix + '_payment2' : prefix + '_pay2';
        
        const method1El = document.getElementById(method1Id);
        const method2El = document.getElementById(method2Id);
        const amt1El = document.getElementById(prefix + '_pay_amt1');
        const amt2El = document.getElementById(prefix + '_pay_amt2');
        
        const method1 = method1El ? method1El.value : '';
        // Only include method2 if it's enabled (checkbox is checked)
        const method2 = (method2El && !method2El.disabled) ? method2El.value : '';
        const amt1 = amt1El ? parseFloat(amt1El.value || 0) : 0;
        const amt2 = (amt2El && !amt2El.disabled) ? parseFloat(amt2El.value || 0) : 0;
        
        if (!method1 && !method2) {
            return 'Cash'; // Default
        }
        
        let result = '';
        if (method1) {
            result = amt1 > 0 ? `${method1} (RM ${amt1.toFixed(2)})` : method1;
        }
        if (method2) {
            const part2 = amt2 > 0 ? `${method2} (RM ${amt2.toFixed(2)})` : method2;
            if (result) {
                result += ' + ' + part2;
            } else {
                result = part2;
            }
        }
        
        return result || 'Cash';
    }

    // Auto-sync when method 1 changes (if checkbox is checked)
    document.getElementById('rep_pay').addEventListener('change', function() {
        if (document.getElementById('rep_sync_pay').checked) {
            document.getElementById('rep_pay2').value = this.value;
            updatePaymentAmounts('rep');
        }
    });

    document.getElementById('ret_pay').addEventListener('change', function() {
        if (document.getElementById('ret_sync_pay').checked) {
            document.getElementById('ret_pay2').value = this.value;
            updatePaymentAmounts('ret');
        }
    });

    // Also handle edit modal
    const editPay1 = document.getElementById('edit_payment');
    if (editPay1) {
        editPay1.addEventListener('change', function() {
            if (document.getElementById('edit_sync_pay').checked) {
                document.getElementById('edit_payment2').value = this.value;
            }
        });
    }

    // --- TAB SWITCHING ---
    let _stockLoaded = false;
    function switchMainTab(tab) {
        document.querySelectorAll('.main-tab').forEach(el => el.classList.add('d-none'));
        document.querySelectorAll('.mode-btn').forEach(el => el.classList.remove('active'));

        document.getElementById(tab + 'Mode').classList.remove('d-none');
        document.getElementById('tab' + tab.charAt(0).toUpperCase() + tab.slice(1)).classList.add('active');

        if (!_stockLoaded) {
            fetchStock().then(() => { _stockLoaded = true; });
        }

        if (tab === 'repair') {
            fetchJobs();
            setTimeout(() => {
                const firstInput = document.querySelector('#repairMode input:not([type="hidden"]), #repairMode select');
                if (firstInput) firstInput.focus();
            }, 100);
        }
        if (tab === 'retail') {
            fetchRetailHistory();
            setTimeout(() => {
                const scannerInput = document.getElementById('retailScannerInput');
                if (scannerInput) scannerInput.focus();
            }, 100);
        }
        if (tab === 'stock') {
            if (IS_MASTER) {
                fetchCreditNoteHistory();
            }
            fetchStock();
            setTimeout(() => {
                const firstInput = document.querySelector('#stockMode input:not([type="hidden"])');
                if (firstInput) firstInput.focus();
                restrictStockFields();
            }, 100);
        }
        if (tab === 'trash') fetchDeletedJobs();
        if (tab === 'users') fetchUsers();
        if (tab === 'archive') { archInitIfNeeded(); archReload(); }
        if (tab === 'billing') {
            const retailPromise = fetchRetailHistory();
            if (retailPromise && retailPromise.then) {
                retailPromise.then(() => {
                    fetchBilling();
                    const searchInput = document.getElementById('billingSearch');
                    if (searchInput) searchInput.focus();
                });
            } else {
                fetchBilling();
            }
        }
        
        updateTodaysSummary(); 
    }

    async function apiRequest(body) {
        try {
            const isFormData = body instanceof FormData;
            const opts = {
                method: 'POST',
                headers: isFormData ? { 'X-CSRF-Token': CSRF } : HEADERS,
                body: isFormData ? body : JSON.stringify(body)
            };
            const r = await fetch('api.php', opts);
            return await r.json();
        } catch (e) {
            return { success: false, error: 'Network Error' };
        }
    }

    // --- JOB MANAGEMENT ---
    function refreshPage() {
        if (confirm('Reload the entire page? All unsaved changes will be lost.')) {
            window.location.reload();
        }
    }
    
    let _fetchJobsInFlight = null;
    function fetchJobs(retryCount = 0) {
        if (_fetchJobsInFlight && retryCount === 0) return _fetchJobsInFlight;
        const maxRetries = 3;
        _fetchJobsInFlight = fetch('api.php?action=fetch_jobs&t=' + new Date().getTime())
            .then(r => {
                if (!r.ok) {
                    throw new Error(`HTTP ${r.status}: ${r.statusText}`);
                }
                return r.json();
            })
            .then(d => {
                if (d.success) {
                    if (d.permissions) {
                        liveCanEdit = d.permissions.can_edit;
                        liveCanDelete = d.permissions.can_delete;
                    }
                    allJobs = d.jobs;
                    renderJobs();
                    if (retryCount === 0) {
                        showToast('✅ Jobs list refreshed', 'success');
                    }
                } else {
                    throw new Error(d.error || 'Failed to fetch jobs');
                }
            })
            .catch(err => {
                console.error('Error fetching jobs:', err);
                if (retryCount < maxRetries) {
                    showToast(`⚠️ Retrying... (${retryCount + 1}/${maxRetries})`, 'error');
                    setTimeout(() => fetchJobs(retryCount + 1), 1000 * (retryCount + 1));
                } else {
                    showToast('❌ Failed to load jobs. Click REFRESH to try again.', 'error');
                    const reloadBtn = document.createElement('button');
                    reloadBtn.className = 'btn';
                    reloadBtn.style.cssText = 'width:auto; padding:8px 15px; margin:5px 0 0 0; background:#e74c3c; font-size:0.85rem;';
                    reloadBtn.textContent = '🔄 Retry Now';
                    reloadBtn.onclick = () => { reloadBtn.remove(); fetchJobs(); };
                    const errorEl = document.querySelector('#jobTableBody')?.parentElement?.previousElementSibling;
                    if (errorEl) {
                        errorEl.appendChild(reloadBtn);
                    }
                }
            })
            .finally(() => { _fetchJobsInFlight = null; });
        return _fetchJobsInFlight;
    }

    function renderJobs() {
        const tbody = document.getElementById('jobTableBody');
        if (!tbody) return;
        tbody.innerHTML = allJobs.map(j => {
            let btns = '';
            if (liveCanEdit) btns += `<button class="btn-action" onclick="openEditModal('${j.job_id}')" title="Edit Job">✏️</button>`;
            btns += `<button class="btn-action" onclick="window.open('invoice.php?id=${j.job_id}&token=${j.token||''}')" title="Print Invoice">📄</button>`;
            btns += `<button class="btn-action" onclick="sendWhatsapp('${j.job_id}')" style="color:#2ecc71;" title="Send WhatsApp">💬</button>`;
            if (j.status !== 'Completed' && liveCanEdit) {
                btns += `<button class="btn-action" onclick="quickComplete('${j.job_id}')" style="color:#2ecc71;" title="Mark as Completed">✅</button>`;
            }
            if (liveCanDelete) btns += `<button class="btn-action" onclick="confirmDelete(${j.id})" style="color:#e74c3c;" title="Delete">🗑</button>`;

            let repairText = (j.repair || '').substring(0,40);
            let payBadgeClass = j.payment_status === 'Paid' ? 'status-paid' : (j.payment_status === 'Partial' ? 'status-partial' : 'status-unpaid');
            let statusBadgeClass = j.status === 'Completed' ? 'status-completed' : 'status-pending';
            const searchData = `${j.job_id} ${j.customer} ${j.phone} ${j.model} ${j.imei}`.toLowerCase();

            return `<tr data-search="${escapeHtml(searchData)}" data-branch="${escapeHtml(j.branch)}">
                <td><span class="job-id">${escapeHtml(j.job_id)}</span><br><small style="color:#999">${escapeHtml(j.date)}</small></td>
                <td><b>${escapeHtml(j.customer)}</b><br><small style="color:#2980b9">${escapeHtml(j.phone)}</small></td>
                <td>${escapeHtml(j.model)}<br><small style="color:#777">${escapeHtml(repairText)}</small></td>
                <td style="white-space:nowrap;"><span style="font-weight:700;">RM ${j.price}</span><br><span class="status-badge ${payBadgeClass}" style="margin-top:4px;">${j.payment_status ? j.payment_status.toUpperCase() : 'UNPAID'}</span></td>
                <td><span class="payment-badge">${j.payment_method||'-'}</span></td>
                <td><span class="status-badge ${statusBadgeClass}">${j.status}</span>${j.completed_at && j.completed_at !== '0000-00-00' ? `<br><small style="color:#7f8c8d; font-size:0.7rem;">${escapeHtml(j.completed_at)}</small>` : ''}</td>
                <td style="white-space:nowrap;">${btns}</td>
            </tr>`;
        }).join('');
        filterJobs();
    }

    function filterJobs() {
        const term = document.getElementById('searchInput').value.toLowerCase();
        const br = document.getElementById('branchFilter').value;
        const rows = document.querySelectorAll('#jobTableBody tr[data-search]');
        rows.forEach(row => {
            const matchBranch = br === 'all' || row.dataset.branch === br;
            const matchSearch = !term || row.dataset.search.includes(term);
            // Flag for the paginator (it decides final visibility).
            row.dataset.filterHidden = (matchBranch && matchSearch) ? '0' : '1';
        });
        if (typeof f2fResetPagerPage === 'function') f2fResetPagerPage('jobTableBody');
        if (typeof f2fApplyPagination === 'function') f2fApplyPagination('jobTableBody');
    }

    function submitRepair() {
        if (isSubmittingRepair) {
            showToast("Repair submit in progress. Please wait...", 'error');
            return;
        }
        let repairDesc = document.getElementById('rep_desc').value;
        
        const parts = [];
        const repairParts = document.querySelectorAll('#repairPartsContainer .form-row');
        repairParts.forEach(row => {
            const nameEl = row.querySelector('.r-name');
            const qtyInput = row.querySelector('.r-qty');
            const altModelEl = row.querySelector('.r-alt-model');
            
            let partName = '';
            if (nameEl && nameEl.tagName === 'SELECT') {
                partName = nameEl.value || '';
            } else if (nameEl) {
                partName = nameEl.value || '';
            }
            
            if (partName.trim() && qtyInput) {
                const qty = parseInt(qtyInput.value) || 1;
                const altModel = altModelEl ? altModelEl.value.trim() : '';
                let entry = partName.trim();
                if (altModel) {
                    entry += ` [Alt: ${altModel}]`;
                }
                parts.push(`${entry} (x${qty})`);
            }
        });
        
        if (parts.length > 0) {
            for (const p of parts) {
                const cleanName = p.replace(/\s*\[Alt:.*?\]/, '').replace(/\s*\(x\d+\)$/, '').trim();
                const qtyMatch = p.match(/\(x(\d+)\)$/);
                const qty = qtyMatch ? parseInt(qtyMatch[1]) : 1;
                if (!checkStockBeforeAdd(cleanName, qty)) return;
            }
            const partsString = parts.join(' || ');
            repairDesc = repairDesc ? `${repairDesc} || ${partsString}` : partsString;
        }
        
        // Get calculated job cost (from calcRepairJobCost)
        const calculatedCost = window.repairJobCost || 0;

        const data = {
            action: 'CREATE_JOB',
            request_id: generateRequestId('JOB'),
            branch: document.getElementById('rep_branch').value,
            date: document.getElementById('rep_date').value,
            pickup_date: document.getElementById('rep_pickup').value,
            customer: document.getElementById('rep_cust').value,
            phone: document.getElementById('rep_phone').value,
            model: document.getElementById('rep_model').value,
            imei: document.getElementById('rep_imei').value,
            passcode: document.getElementById('rep_pass').value,
            repair: repairDesc,
            remarks: document.getElementById('rep_remarks').value,
            price: document.getElementById('rep_price').value,
            deposit: document.getElementById('rep_deposit').value,
            warranty: document.getElementById('rep_war').value,
            status: document.getElementById('rep_stat').value,
            paymentMethod: combinePaymentMethods('rep'),
            payment_status: document.getElementById('rep_pay_status').value,
            job_cost: calculatedCost // Include calculated job cost
        };

        if (!data.customer || data.customer.trim() === '') {
            document.getElementById('rep_cust').focus();
            return showToast("⚠️ Customer name is required", 'error');
        }
        if (!data.model || data.model.trim() === '') {
            document.getElementById('rep_model').focus();
            return showToast("⚠️ Device model is required", 'error');
        }
        if (!data.price || parseFloat(data.price) <= 0) {
            document.getElementById('rep_price').focus();
            return showToast("⚠️ Price must be greater than 0", 'error');
        }

        isSubmittingRepair = true;
        setSubmitButtonState('repSubmitBtn', true, 'CREATING...');
        apiRequest(data)
            .then(d => {
                if (d.success) {
                    showToast("Repair Created");
                    if (d.newJobId) {
                        showToast(`Created ID: ${d.newJobId}`, 'success');
                    }
                    fetchJobs();
                    fetchStock();
                    ['rep_cust', 'rep_phone', 'rep_model', 'rep_imei', 'rep_pass', 'rep_desc', 'rep_remarks', 'rep_price', 'rep_deposit', 'totalRepairPrice', 'rep_pay_amt1', 'rep_pay_amt2'].forEach(id => {
                        const el = document.getElementById(id);
                        if (el) el.value = '';
                    });
                    document.getElementById('rep_pay').value = '';
                    document.getElementById('rep_pay2').value = '';
                    document.getElementById('rep_sync_pay').checked = false;
                    syncPaymentMethods('rep'); // This will disable method 2
                    // Clear repair parts container
                    document.getElementById('repairPartsContainer').innerHTML = '';
                    window.repairJobCost = 0; // Reset job cost
                    calcRepairTotal();
                    // Clear draft after successful submission
                    clearDraft('repair');
                } else {
                    showToast(d.error || "Failed to create repair", 'error');
                }
            })
            .finally(() => {
                isSubmittingRepair = false;
                setSubmitButtonState('repSubmitBtn', false, '');
            });
    }

    function addRepairPart(name = '') {
        const div = document.createElement('div');
        div.className = 'form-row';
        div.style.alignItems = 'center';
        
        const select = document.createElement('select');
        select.style.flex = '2';
        select.className = 'r-name';
        select.innerHTML = '<option value="">-- Select Part --</option>';
        
        if (allStock['Part']) {
            for (let g in allStock['Part']) {
                allStock['Part'][g].forEach(item => {
                    const option = document.createElement('option');
                    option.value = item.part_name;
                    option.textContent = item.part_name;
                    option.dataset.cost = item.cost || 0;
                    if (name && item.part_name.toLowerCase() === name.toLowerCase()) {
                        option.selected = true;
                    }
                    select.appendChild(option);
                });
            }
        }
        
        if (allStock['Retail']) {
            for (let g in allStock['Retail']) {
                allStock['Retail'][g].forEach(item => {
                    const existing = Array.from(select.options).find(opt => opt.value === item.part_name);
                    if (!existing) {
                        const option = document.createElement('option');
                        option.value = item.part_name;
                        option.textContent = item.part_name;
                        option.dataset.cost = item.cost || 0;
                        if (name && item.part_name.toLowerCase() === name.toLowerCase()) {
                            option.selected = true;
                        }
                        select.appendChild(option);
                    }
                });
            }
        }
        
        select.onchange = function() {
            const partName = this.value;
            if (partName && !checkStockBeforeAdd(partName)) {
                this.selectedIndex = 0;
                return;
            }
            calcRepairJobCost();
        };
        
        const altModelInput = document.createElement('input');
        altModelInput.type = 'text';
        altModelInput.style.flex = '1';
        altModelInput.className = 'r-alt-model';
        altModelInput.placeholder = 'Compatible model (optional)';
        altModelInput.style.minWidth = '120px';
        
        const qtyInput = document.createElement('input');
        qtyInput.type = 'number';
        qtyInput.style.width = '60px';
        qtyInput.className = 'r-qty';
        qtyInput.value = '1';
        qtyInput.onchange = function() {
            const row = this.closest('.form-row');
            const nameEl = row?.querySelector('.r-name');
            if (nameEl && nameEl.value) {
                const qty = parseInt(this.value) || 1;
                if (!checkStockBeforeAdd(nameEl.value, qty)) {
                    const stock = getItemBranchStock(nameEl.value);
                    if (stock) this.value = Math.max(1, stock.branchQty);
                }
            }
            calcRepairJobCost();
        };
        
        const removeBtn = document.createElement('button');
        removeBtn.className = 'btn-danger';
        removeBtn.style.width = 'auto';
        removeBtn.style.margin = '0';
        removeBtn.innerHTML = 'X';
        removeBtn.onclick = function() { 
            div.remove(); 
            calcRepairJobCost();
        };
        
        div.appendChild(select);
        div.appendChild(altModelInput);
        div.appendChild(qtyInput);
        div.appendChild(removeBtn);
        document.getElementById('repairPartsContainer').appendChild(div);
        
        if (name) {
            if (!checkStockBeforeAdd(name)) {
                div.remove();
                return;
            }
            const nameLower = name.toLowerCase().trim();
            for (let i = 0; i < select.options.length; i++) {
                if (select.options[i].value.toLowerCase() === nameLower) {
                    select.selectedIndex = i;
                    calcRepairJobCost();
                    break;
                }
            }
        }
    }
    
    function detectRepairPartStock(selectEl) {
        const val = selectEl.value;
        if (!val) {
            calcRepairJobCost();
            return;
        }
        // Part is already selected from dropdown, just recalculate cost
        calcRepairJobCost();
    }
    
    function calcRepairJobCost() {
        // Calculate total job cost from all repair parts
        let totalCost = 0;
        const repairParts = document.querySelectorAll('#repairPartsContainer .form-row');
        
        repairParts.forEach(row => {
            const nameInput = row.querySelector('.r-name');
            const qtyInput = row.querySelector('.r-qty');
            if (!nameInput || !qtyInput) return;
            
            const itemName = nameInput.value.toLowerCase().trim();
            const qty = parseInt(qtyInput.value) || 1;
            
            if (!itemName) return;
            
            let found = null;
            
            // Search in Part stock first
            if (allStock['Part']) {
                for (let g in allStock['Part']) {
                    let match = allStock['Part'][g].find(i => {
                        const partNameLower = (i.part_name || '').toLowerCase().trim();
                        return partNameLower === itemName;
                    });
                    if (match) {
                        found = match;
                        break;
                    }
                }
            }
            
            // Also check Retail stock if not found
            if (!found && allStock['Retail']) {
                for (let g in allStock['Retail']) {
                    let match = allStock['Retail'][g].find(i => {
                        const partNameLower = (i.part_name || '').toLowerCase().trim();
                        return partNameLower === itemName;
                    });
                    if (match) {
                        found = match;
                        break;
                    }
                }
            }
            
            if (found) {
                const cost = parseFloat(found.cost || 0);
                totalCost += (cost * qty);
            }
        });
        
        // Store calculated cost (can be used later when submitting)
        window.repairJobCost = totalCost;
    }

    function addRetailPart(name = '') {
        const div = document.createElement('div');
        div.className = 'form-row';
        const input = document.createElement('input');
        input.style.flex = '2';
        input.className = 'r-name';
        input.setAttribute('list', 'repairStockList');
        input.value = escapeHtml(name);
        input.placeholder = 'Select Part (Optional)';
        input.onkeyup = function() { cleanInput(this); };
        input.onchange = function() { };
        
        const qtyInput = document.createElement('input');
        qtyInput.type = 'number';
        qtyInput.style.width = '60px';
        qtyInput.className = 'r-qty';
        qtyInput.value = '1';
        
        const removeBtn = document.createElement('button');
        removeBtn.className = 'btn-danger';
        removeBtn.style.width = 'auto';
        removeBtn.style.margin = '0';
        removeBtn.innerHTML = 'X';
        removeBtn.onclick = function() { div.remove(); };
        
        div.appendChild(input);
        div.appendChild(qtyInput);
        div.appendChild(removeBtn);
        document.getElementById('retailPartsContainer').appendChild(div);
    }

    // --- BILLING LOGIC ---
    let _billingData = [];
    function fetchBilling() {
        if (!allRetailJobs || allRetailJobs.length === 0) {
            const p = fetchRetailHistory();
            if (p && p.then) { p.then(() => fetchBilling()); }
            return;
        }
        
        const cacheBuster = '&t=' + Date.now();
        fetch('api.php?action=fetch_jobs' + cacheBuster)
            .then(r => r.json())
            .then(jobsData => {
                if (jobsData.success) { allJobs = jobsData.jobs || []; }
                renderBilling();
            })
            .catch(() => { renderBilling(); });
    }

    function renderBilling() {
        const combinedJobs = [...(allJobs || []), ...(allRetailJobs || [])];
        _billingData = combinedJobs.filter(j => {
            if (j.date && j.date.startsWith('2025-')) return false;
            const isRetail = (j.model === 'Retail Sale' || j.remarks === 'Retail Order');
            if (!isRetail) return false;
            if (j.status === 'Cancelled' || j.status === 'Refund' || j.is_deleted === 1 || j.is_deleted === '1') return false;
            return true;
        });
        _billingData.sort((a, b) => {
            const dateA = a.date || '', dateB = b.date || '';
            if (dateB > dateA) return 1;
            if (dateB < dateA) return -1;
            return (b.job_id || '').localeCompare(a.job_id || '');
        });

        const tableBody = document.getElementById('billingTableBody');
        if (!tableBody) return;
        if (_billingData.length === 0) {
            tableBody.innerHTML = '<tr><td colspan="8" style="text-align:center; padding:20px; color:#999;">No completed retail sales found.</td></tr>';
            return;
        }

        tableBody.innerHTML = _billingData.map(j => {
            let useInvoice = (j.invoice_id && j.invoice_id !== '');
            let displayId = useInvoice ? j.invoice_id : j.job_id;
            let linkId = displayId;
            let badgeStyle = useInvoice 
                ? 'background:#eafaf1; color:#2ecc71; border:1px solid #2ecc71; font-weight:bold;' 
                : 'background:#e3f2fd; color:#1565c0; border:1px solid #bbdefb; font-weight:bold;';
            const receiptFile = 'receipt.php';
            let btns = '';
            btns += `<button class="btn-action" onclick="window.open('${receiptFile}?id=${linkId}&token=${j.token||''}')" title="Print Receipt">📄</button>`;
            btns += `<button class="btn-action" onclick="printThermalReceipt('${linkId}')" style="color:#e67e22;" title="Thermal Print">🖨️</button>`;
            btns += `<button class="btn-action" onclick="sendWhatsapp('${linkId}')" style="color:#2ecc71;" title="WhatsApp">💬</button>`;
            const searchData = `${j.job_id || ''} ${j.invoice_id || ''} ${j.customer || ''} ${j.phone || ''} ${j.model || ''}`.toLowerCase();

            return `<tr data-search="${escapeHtml(searchData)}">
                <td style="text-align:center;"><input type="checkbox" onchange="toggleJobSelection('${linkId}')" ${selectedJobsForPrint.has(linkId) ? 'checked' : ''}></td>
                <td><span class="job-id" style="${badgeStyle}; padding: 2px 8px; border-radius: 4px; font-family:monospace;">${escapeHtml(displayId)}</span></td>
                <td>${escapeHtml(j.date)}</td>
                <td><b style="cursor:pointer; color:#3498db; text-decoration:underline;" onclick="showFullCustomerHistory('${escapeHtml(j.phone || '')}', '${escapeHtml(j.customer || '')}')" title="Click to view order history">${escapeHtml(j.customer)}</b></td>
                <td>${escapeHtml(j.model)}</td>
                <td>RM ${j.price}${j.deposit > 0 && j.payment_status === 'Partial' ? `<br><small style="color:#999;">(Dep: RM ${parseFloat(j.deposit).toFixed(2)})</small>` : ''}</td>
                <td><span class="payment-badge">${j.payment_method||'-'}${j.payment_status === 'Partial' && j.deposit > 0 ? `<br><small style="color:#e67e22; font-weight:bold;">Balance: RM ${(parseFloat(j.price) - parseFloat(j.deposit)).toFixed(2)}</small>` : j.payment_status === 'Unpaid' ? `<br><small style="color:#e74c3c; font-weight:bold;">Unpaid</small>` : ''}</span></td>
                <td>${btns}</td>
            </tr>`;
        }).join('');
        filterBilling();
    }

    function filterBilling() {
        const input = document.getElementById('billingSearch');
        const term = input ? input.value.toLowerCase() : '';
        const rows = document.querySelectorAll('#billingTableBody tr[data-search]');
        rows.forEach(row => {
            row.dataset.filterHidden = (!term || row.dataset.search.includes(term)) ? '0' : '1';
        });
        if (typeof f2fResetPagerPage === 'function') f2fResetPagerPage('billingTableBody');
        if (typeof f2fApplyPagination === 'function') f2fApplyPagination('billingTableBody');
    }

    // --- RETAIL & STOCK ---
    let _fetchRetailInFlight = null;
    function fetchRetailHistory(retryCount = 0) {
        if (_fetchRetailInFlight && retryCount === 0) return _fetchRetailInFlight;
        const maxRetries = 3;
        _fetchRetailInFlight = fetch('api.php?action=fetch_retail_history&t=' + new Date().getTime())
            .then(r => {
                if (!r.ok) {
                    throw new Error(`HTTP ${r.status}: ${r.statusText}`);
                }
                return r.json();
            })
            .then(d => {
                if (d.success) {
                    if (d.permissions) {
                        liveCanEdit = d.permissions.can_edit;
                        liveCanDelete = d.permissions.can_delete;
                        liveCanRefund = d.permissions.can_refund;
                    }
                    allRetailJobs = d.jobs;
                    renderRetailHistory();
                    if (retryCount === 0) {
                        showToast('✅ Retail sales refreshed', 'success');
                    }
                } else {
                    throw new Error(d.error || 'Failed to fetch retail history');
                }
            })
            .catch(err => {
                console.error('Error fetching retail history:', err);
                if (retryCount < maxRetries) {
                    showToast(`⚠️ Retrying... (${retryCount + 1}/${maxRetries})`, 'error');
                    setTimeout(() => fetchRetailHistory(retryCount + 1), 1000 * (retryCount + 1));
                } else {
                    showToast('❌ Failed to load retail sales. Click REFRESH to try again.', 'error');
                    const reloadBtn = document.createElement('button');
                    reloadBtn.className = 'btn';
                    reloadBtn.style.cssText = 'width:auto; padding:8px 15px; margin:5px 0 0 0; background:#e74c3c; font-size:0.85rem;';
                    reloadBtn.textContent = '🔄 Retry Now';
                    reloadBtn.onclick = () => { reloadBtn.remove(); fetchRetailHistory(); };
                    const errorEl = document.querySelector('#retailTableBody')?.parentElement?.previousElementSibling;
                    if (errorEl) {
                        errorEl.appendChild(reloadBtn);
                    }
                }
            })
            .finally(() => { _fetchRetailInFlight = null; });
        return _fetchRetailInFlight;
    }

    function renderRetailHistory() {
        if (!allRetailJobs || allRetailJobs.length === 0) return;
        const tbody = document.getElementById('retailTableBody');
        if (!tbody) return;
        const ivJobs = allRetailJobs.filter(j => j.job_id && (j.job_id.startsWith('IV-SG') || j.job_id.startsWith('IV-SR')));
        tbody.innerHTML = ivJobs.map(j => {
            let btns = '';
            let isARefund = (j.status === 'Refund' || (j.repair && j.repair.indexOf('REFUND FOR:') === 0));
            if (isARefund) {
                if (liveCanEdit) btns += `<button class="btn-action" onclick="openEditModal('${j.job_id}')">✏️</button>`;
                if (liveCanDelete) btns += `<button class="btn-action" onclick="confirmDelete(${j.id})" style="color:#ef473a;">🗑</button>`;
            } else {
                if (j.refund_info) {
                    let staffName = escapeHtml(j.refund_info.by);
                    let refundDate = escapeHtml(j.refund_info.date);
                    btns += `<button class="btn-action" onclick="alert('Error this item has been refunded by : ${staffName}\\nOn the date : ${refundDate}')" title="Already Refunded" style="color:#bbb; cursor:not-allowed; border-color:#eee;">↩️</button>`;
                } else if (liveCanRefund) {
                    btns += `<button class="btn-action" onclick="confirmRefund(${j.id}, '${j.job_id}')" title="Refund Sale" style="color:#e67e22;">↩️</button>`;
                }
                if (liveCanEdit) btns += `<button class="btn-action" onclick="openEditModal('${j.job_id}')">✏️</button>`;
                btns += `<button class="btn-action" onclick="window.open('receipt.php?id=${j.job_id}&token=${j.token||''}')">🧾</button>`;
                btns += `<button class="btn-action" onclick="sendWhatsapp('${j.job_id}')" style="color:#2ecc71;">💬</button>`;
                if (liveCanDelete) btns += `<button class="btn-action" onclick="confirmDelete(${j.id})" style="color:#ef473a;">🗑</button>`;
            }
            let rowStyle = j.refund_info ? 'color:#999; text-decoration:line-through;' : '';
            let statusBadge = j.refund_info ? '<span style="color:red; font-weight:bold; font-size:10px; margin-left:5px;">(REFUNDED)</span>' : '';
            const searchData = `${j.job_id} ${j.customer} ${j.phone || ''} ${j.repair || ''} ${j.date}`.toLowerCase();

            return `<tr data-search="${escapeHtml(searchData)}" data-branch="${escapeHtml(j.branch)}" style="${rowStyle}">
                <td><span class="job-id">${escapeHtml(j.job_id)}</span>${statusBadge}</td>
                <td>${escapeHtml(j.date)}</td>
                <td>${escapeHtml(j.customer)}</td>
                <td><small>${escapeHtml((j.repair || '').substring(0, 50))}</small></td>
                <td>RM ${j.price}</td>
                <td><span class="payment-badge">${j.payment_method||'-'}</span></td>
                <td>${btns}</td>
            </tr>`;
        }).join('');
        filterRetailHistory();
    }

    function filterRetailHistory() {
        const term = document.getElementById('retailSearchInput')?.value.toLowerCase() || '';
        const br = document.getElementById('retailBranchFilter')?.value || 'all';
        const rows = document.querySelectorAll('#retailTableBody tr[data-search]');
        rows.forEach(row => {
            const matchBranch = br === 'all' || row.dataset.branch === br;
            const matchSearch = !term || row.dataset.search.includes(term);
            row.dataset.filterHidden = (matchBranch && matchSearch) ? '0' : '1';
        });
        if (typeof f2fResetPagerPage === 'function') f2fResetPagerPage('retailTableBody');
        if (typeof f2fApplyPagination === 'function') f2fApplyPagination('retailTableBody');
    }

    function confirmRefund(dbId, jobId) {
        if (confirm("⚠️ PROCESS REFUND?\n\nThis will duplicate Sale " + jobId + " as a NEGATIVE refund entry.\n\nAre you sure?")) {
            apiRequest({ action: 'refund_retail', id: dbId }).then(d => {
                if (d.success) {
                    showToast("Refund Processed");
                    fetchRetailHistory();
                } else {
                    alert(d.error);
                }
            });
        }
    }

    function submitRetail() {
        if (isSubmittingRetail) {
            showToast("Sale submit in progress. Please wait...", 'error');
            return;
        }
        const items = [];
        document.querySelectorAll('#itemsContainer .form-row').forEach(r => {
            const nameEl = r.querySelector('.r-name');
            const qtyEl = r.querySelector('.r-qty');
            const priceEl = r.querySelector('.r-price');
            const warrantySelect = r.querySelector('.r-warranty');
            const altModelEl = r.querySelector('.r-alt-model');
            
            let itemName = '';
            if (nameEl.tagName === 'SELECT') {
                itemName = nameEl.value || '';
            } else {
                itemName = nameEl.value || '';
            }
            
            itemName = itemName.replace(/(Gombak\||Sri Rampai\|)/gi, '').trim();
            
            if (!itemName) return;
            
            const altModel = altModelEl ? altModelEl.value.trim() : '';
            if (altModel) {
                itemName += ` [Alt: ${altModel}]`;
            }
            
            const warranty = warrantySelect ? warrantySelect.value : 'No Warranty';
            items.push({
                name: itemName,
                qty: qtyEl ? qtyEl.value : 1,
                price: priceEl ? priceEl.value : 0,
                warranty: warranty
            });
        });

        let retailDesc = (document.getElementById('ret_desc')?.value || '').trim();

        if (items.length === 0) return showToast("Cart is Empty", 'error');

        for (const item of items) {
            const cleanName = item.name.replace(/\s*\[Alt:.*?\]/, '').trim();
            const qty = parseInt(item.qty) || 1;
            if (!checkStockBeforeAdd(cleanName, qty)) return;
        }

        // Calculate total from items (for reference only)
        const cartTotal = parseFloat(document.getElementById('totalRetailPrice').value) || 0;
        
        // Get payment amounts - these take priority if entered
        const payAmt1 = parseFloat(document.getElementById('ret_pay_amt1').value) || 0;
        const payAmt2 = parseFloat(document.getElementById('ret_pay_amt2').value) || 0;
        const totalPaymentAmount = payAmt1 + payAmt2;
        
        // Use payment amount if entered, otherwise use cart total
        const finalPrice = (totalPaymentAmount > 0) ? totalPaymentAmount : cartTotal;

        const data = {
            action: 'CREATE_RETAIL',
            request_id: generateRequestId('RTL'),
            branch: document.getElementById('ret_branch').value,
            date: document.getElementById('ret_date').value,
            pickup_date: document.getElementById('ret_pickup').value,
            customer: document.getElementById('ret_cust').value,
            phone: document.getElementById('ret_phone').value,
            imei: document.getElementById('ret_imei').value,
            repair: retailDesc,
            remarks: document.getElementById('ret_remarks').value,
            price: finalPrice.toFixed(2), // Use payment amount if provided, otherwise cart total
            paymentMethod: combinePaymentMethods('ret'),
            cartItems: items,
            totalAmount: finalPrice.toFixed(2)
        };

        if (!data.customer || data.customer.trim() === '') {
            document.getElementById('ret_cust').focus();
            return showToast("⚠️ Customer name is required", 'error');
        }
        if ((!data.price || parseFloat(data.price) <= 0) && items.length === 0) {
            return showToast("⚠️ Please add items to cart or set a price", 'error');
        }

        isSubmittingRetail = true;
        setSubmitButtonState('retSubmitBtn', true, 'PROCESSING...');
        apiRequest(data)
            .then(d => {
                if (d.success) {
                    if (d.duplicate_blocked) {
                        showToast("Duplicate submit blocked. Existing sale kept.", 'error');
                    } else {
                        showToast("Sale Completed");
                    }
                    if (d.newJobId) {
                        showToast(`Sale ID: ${d.newJobId}`, 'success');
                    }
                    // Open receipt with returned token so link works even before refetch
                    if (d.newJobId && d.token) {
                        window.open(`receipt.php?id=${encodeURIComponent(d.newJobId)}&token=${encodeURIComponent(d.token)}`, '_blank');
                    }
                    fetchRetailHistory();
                    fetchStock();
                    document.getElementById('itemsContainer').innerHTML = '';
                    document.getElementById('totalRetailPrice').value = '0.00';
                    const retDescEl = document.getElementById('ret_desc');
                    if (retDescEl) retDescEl.value = '';
                    document.getElementById('ret_remarks').value = '';
                    document.getElementById('ret_pay').value = '';
                    document.getElementById('ret_pay2').value = '';
                    document.getElementById('ret_pay_amt1').value = '';
                    document.getElementById('ret_pay_amt2').value = '';
                    document.getElementById('ret_sync_pay').checked = false;
                    syncPaymentMethods('ret'); // This will disable method 2
                    // Clear draft after successful submission
                    clearDraft('retail');
                } else {
                    showToast(d.error || "Failed to complete sale", 'error');
                }
            })
            .finally(() => {
                isSubmittingRetail = false;
                setSubmitButtonState('retSubmitBtn', false, '');
            });
    }

    function addScannedFallback(select, nameStr) {
        const newOption = document.createElement('option');
        newOption.value = nameStr;
        newOption.textContent = nameStr + ' (Scanned)';
        newOption.dataset.price = '0';
        select.appendChild(newOption);
        select.selectedIndex = select.options.length - 1;
        showToast(`Item "${nameStr}" not found in stock. Please set price manually.`, 'error');
    }

    // Parse barcode to stock ID: EAN-13 has 13 digits (12 data + check digit), use first 12
    function parseBarcodeToId(barcodeStr) {
        const digits = String(barcodeStr || '').replace(/\D/g, '');
        if (digits.length >= 8 && digits.length <= 13) {
            const idStr = digits.length === 13 ? digits.substring(0, 12) : digits;
            const id = parseInt(idStr, 10);
            return isNaN(id) ? null : id;
        }
        return null;
    }

    function addRetailItem(name = '') {
        if (name && !checkStockBeforeAdd(String(name).trim())) {
            return;
        }

        const div = document.createElement('div');
        div.className = 'form-row';
        div.style.alignItems = 'center';
        
        const select = document.createElement('select');
        select.style.flex = '2';
        select.className = 'r-name';
        select.innerHTML = '<option value="">-- Select Item --</option>';
        
        // Populate dropdown with stock items (Retail first, then Part)
        if (allStock['Retail']) {
            for (let g in allStock['Retail']) {
                allStock['Retail'][g].forEach(item => {
                    const option = document.createElement('option');
                    option.value = item.part_name;
                    option.textContent = item.part_name;
                    option.dataset.price = item.selling_price || item.cost || 0;
                    if (item.id) option.dataset.stockId = item.id;
                    if (name && item.part_name.toLowerCase() === name.toLowerCase()) {
                        option.selected = true;
                    }
                    select.appendChild(option);
                });
            }
        }
        
        // Also add Part items
        if (allStock['Part']) {
            for (let g in allStock['Part']) {
                allStock['Part'][g].forEach(item => {
                    // Check if already added
                    const existing = Array.from(select.options).find(opt => opt.value === item.part_name);
                    if (!existing) {
                        const option = document.createElement('option');
                        option.value = item.part_name;
                        option.textContent = item.part_name;
                        option.dataset.price = item.selling_price || item.cost || 0;
                        if (item.id) option.dataset.stockId = item.id;
                        if (name && item.part_name.toLowerCase() === name.toLowerCase()) {
                            option.selected = true;
                        }
                        select.appendChild(option);
                    }
                });
            }
        }
        
        select.onchange = function() {
            const partName = this.value;
            if (partName && !checkStockBeforeAdd(partName)) {
                this.selectedIndex = 0;
                return;
            }
            autoFillPriceFromSelect(this);
        };
        
        const qtyInput = document.createElement('input');
        qtyInput.type = 'number';
        qtyInput.style.width = '60px';
        qtyInput.className = 'r-qty';
        qtyInput.value = '1';
        qtyInput.onchange = function() {
            const row = this.closest('.form-row');
            const nameEl = row?.querySelector('.r-name');
            if (nameEl && nameEl.value) {
                const qty = parseInt(this.value) || 1;
                if (!checkStockBeforeAdd(nameEl.value, qty)) {
                    const stock = getItemBranchStock(nameEl.value);
                    if (stock) this.value = Math.max(1, stock.branchQty);
                }
            }
            calcTotal();
        };
        
        const priceInput = document.createElement('input');
        priceInput.type = 'number';
        priceInput.style.width = '80px';
        priceInput.className = 'r-price';
        priceInput.placeholder = '0.00';
        priceInput.onchange = function() { calcTotal(); };
        
        const warrantySelect = document.createElement('select');
        warrantySelect.className = 'r-warranty';
        warrantySelect.style.width = '110px';
        warrantySelect.style.padding = '5px';
        warrantySelect.style.fontSize = '0.85rem';
        warrantySelect.innerHTML = `
            <option value="No Warranty">No Warranty</option>
            <option value="1 Week">1 Week</option>
            <option value="2 Weeks">2 Weeks</option>
            <option value="1 Month" selected>1 Month</option>
            <option value="3 Months">3 Months</option>
            <option value="1 Year">1 Year</option>
        `;
        
        const removeBtn = document.createElement('button');
        removeBtn.className = 'btn-danger';
        removeBtn.style.width = 'auto';
        removeBtn.style.margin = '0';
        removeBtn.innerHTML = 'X';
        removeBtn.onclick = function() { 
            div.remove(); 
            calcTotal(); 
        };
        
        const altModelInput = document.createElement('input');
        altModelInput.type = 'text';
        altModelInput.className = 'r-alt-model';
        altModelInput.placeholder = 'Compatible model (optional)';
        altModelInput.style.flex = '1';
        altModelInput.style.minWidth = '120px';

        div.appendChild(select);
        div.appendChild(altModelInput);
        div.appendChild(qtyInput);
        div.appendChild(priceInput);
        div.appendChild(warrantySelect);
        div.appendChild(removeBtn);
        
        document.getElementById('itemsContainer').appendChild(div);
        
        // Auto-select if name is provided (e.g., from QR scan or barcode)
        if (name) {
            const nameStr = String(name).trim();
            const nameLower = nameStr.toLowerCase();
            let found = false;
            
            // If barcode (8-13 digits) - lookup by stock item ID (barcode = padded ID)
            const barcodeId = parseBarcodeToId(nameStr);
            if (barcodeId !== null) {
                for (let i = 0; i < select.options.length; i++) {
                    const opt = select.options[i];
                    if (opt.dataset.stockId && parseInt(opt.dataset.stockId, 10) === barcodeId) {
                        select.selectedIndex = i;
                        select.dispatchEvent(new Event('change'));
                        found = true;
                        break;
                    }
                }
            }
            
            // Try exact match on part name
            if (!found) {
                for (let i = 0; i < select.options.length; i++) {
                    if (select.options[i].value.toLowerCase() === nameLower) {
                        select.selectedIndex = i;
                        select.dispatchEvent(new Event('change'));
                        found = true;
                        break;
                    }
                }
            }
            
            // Try partial match (contains)
            if (!found) {
                for (let i = 0; i < select.options.length; i++) {
                    const optionValue = select.options[i].value.toLowerCase();
                    if (optionValue.includes(nameLower) || nameLower.includes(optionValue)) {
                        select.selectedIndex = i;
                        select.dispatchEvent(new Event('change'));
                        found = true;
                        break;
                    }
                }
            }
            
            // If still not found - for barcode (8-13 digits) try API lookup (handles newly added items)
            if (!found && nameStr) {
                const barcodeId = parseBarcodeToId(nameStr);
                if (barcodeId !== null) {
                    apiRequest({ action: 'get_stock_item', id: barcodeId }).then(d => {
                        if (d.success && d.item) {
                            const item = d.item;
                            const newOption = document.createElement('option');
                            newOption.value = item.part_name;
                            newOption.textContent = item.part_name;
                            newOption.dataset.price = item.selling_price || item.cost || 0;
                            newOption.dataset.stockId = item.id;
                            select.appendChild(newOption);
                            select.selectedIndex = select.options.length - 1;
                            select.dispatchEvent(new Event('change'));
                            // Add to allStock so future rows have it
                            const t = ((item.type || 'Part') + '').toLowerCase() === 'retail' ? 'Retail' : 'Part';
                            const cat = (item.category || item.model_group || 'Other') || 'Other';
                            if (!allStock[t]) allStock[t] = {};
                            if (!allStock[t][cat]) allStock[t][cat] = [];
                            if (!allStock[t][cat].find(x => x.id == item.id)) allStock[t][cat].push(item);
                        } else {
                            addScannedFallback(select, nameStr);
                        }
                    }).catch(() => addScannedFallback(select, nameStr));
                } else {
                    addScannedFallback(select, nameStr);
                }
            }
        }
        
        priceInput.focus();
    }
    
    function autoFillPriceFromSelect(selectEl) {
        const selectedOption = selectEl.options[selectEl.selectedIndex];
        if (selectedOption && selectedOption.dataset.price) {
            const row = selectEl.closest('.form-row');
            if (row) {
                const priceInput = row.querySelector('.r-price');
                if (priceInput) {
                    priceInput.value = parseFloat(selectedOption.dataset.price).toFixed(2);
                    calcTotal();
                    // Focus quantity field for quick editing
                    const qtyInput = row.querySelector('.r-qty');
                    if (qtyInput) {
                        qtyInput.focus();
                        qtyInput.select();
                    }
                }
            }
        }
    }

    function autoFillPrice(el) {
        // Legacy function - kept for compatibility but should use autoFillPriceFromSelect instead
        // This handles input fields if they still exist
        const val = el.value.trim();
        if (!val) return;
        
        // Check if it's a select element
        if (el.tagName === 'SELECT') {
            autoFillPriceFromSelect(el);
            return;
        }
    }

    function calcTotal() {
        let t = 0;
        document.querySelectorAll('#itemsContainer .form-row').forEach(r => {
            const qtyEl = r.querySelector('.r-qty');
            const priceEl = r.querySelector('.r-price');
            if (qtyEl && priceEl) {
                t += (parseFloat(qtyEl.value || 0) * parseFloat(priceEl.value || 0));
            }
        });
        document.getElementById('totalRetailPrice').value = t.toFixed(2);
    }

    function handleRetailScan(el) {
        if (event.key === 'Enter') {
            let val = el.value;
            const originalVal = val; // Keep original for logging
            
            // Handle both old format (Branch|Part Name) and new format (Part Name only)
            // Old QR codes may have "Gombak|" or "Sri Rampai|" prefix - strip it
            // New QR codes are branch-agnostic (no prefix)
            const hadBranchPrefix = /^(Gombak|Sri Rampai)\|/i.test(val);
            val = val.replace(/(Gombak\||Sri Rampai\|)/gi, '').trim();
            // Also remove any leading/trailing pipes or spaces
            val = val.replace(/^\||\|$/g, '').trim();
            
            if (val) {
                addRetailItem(val);
                el.value = '';
            }
        }
    }

    // --- SCANNER FUNCTIONS ---
    let html5QrcodeScanner = null;

    function handleGlobalScan(val) {
        // Remove branch prefixes (Gombak| or Sri Rampai|)
        val = val.replace(/(Gombak\||Sri Rampai\|)/gi, '').trim();
        // Also remove any leading/trailing pipes or spaces
        val = val.replace(/^\||\|$/g, '').trim();
        switchMainTab('retail');
        if (val) {
            addRetailItem(val);
        }
    }

    function startCameraScanner(mode) {
        document.getElementById('cameraModal').style.display = 'flex';
        html5QrcodeScanner = new Html5QrcodeScanner("reader", {
            fps: 10,
            qrbox: 250
        });
        html5QrcodeScanner.render((txt) => {
            let val = txt;
            const originalVal = val; // Keep original for logging
            
            // Handle both old format (Branch|Part Name) and new format (Part Name only)
            // Old QR codes may have "Gombak|" or "Sri Rampai|" prefix - strip it
            // New QR codes are branch-agnostic (no prefix)
            const hadBranchPrefix = /^(Gombak|Sri Rampai)\|/i.test(val);
            val = val.replace(/(Gombak\||Sri Rampai\|)/gi, '').trim();
            // Also remove any leading/trailing pipes or spaces
            val = val.replace(/^\||\|$/g, '').trim();
            
            // Check if it's a barcode (numeric, 8-13 digits) or QR code
            if (/^\d{8,13}$/.test(val)) {
                // It's a barcode - try to find item by barcode or treat as search
                if (mode === 'retail') {
                    // For barcodes, try to find item in stock by searching
                    // If not found, add as scanned item
                    addRetailItem(val);
                }
            } else {
                // It's a QR code or text
                if (mode === 'retail') {
                    addRetailItem(val);
                }
            }
            stopCameraScanner();
        });
    }

    function stopCameraScanner() {
        document.getElementById('cameraModal').style.display = 'none';
        if (html5QrcodeScanner) html5QrcodeScanner.clear();
    }

    let scanBuffer = "";
    let scanTimeout;
    document.addEventListener('keydown', function(e) {
        if (['INPUT', 'TEXTAREA', 'SELECT'].includes(document.activeElement.tagName)) return;
        if (e.key === 'Enter') {
            if (scanBuffer.length > 1) {
                handleGlobalScan(scanBuffer);
            }
            scanBuffer = "";
            return;
        }
        if (e.key.length > 1) return;
        scanBuffer += e.key;
        clearTimeout(scanTimeout);
        scanTimeout = setTimeout(() => {
            scanBuffer = "";
        }, 200);
    });

    // --- EDIT MODAL LOGIC ---
    function openEditModal(jobId) {
        let job = allJobs.find(j => j.job_id === jobId) || allRetailJobs.find(j => j.job_id === jobId);
        if (!job) return;

        document.getElementById('edit_db_id').value = job.id;
        document.getElementById('edit_customer').value = job.customer;
        document.getElementById('edit_phone').value = job.phone;
        document.getElementById('edit_date').value = job.date || '';
        document.getElementById('edit_model').value = job.model;
        document.getElementById('edit_imei').value = job.imei || '';
        document.getElementById('edit_passcode').value = job.passcode || '';
        document.getElementById('edit_remarks').value = job.remarks || '';
        document.getElementById('edit_price').value = job.price;
        const savedCost = job.job_cost || 0;
        document.getElementById('edit_job_cost').value = savedCost;
        // If there's a saved cost, mark it as manually edited to prevent auto-calculation from overwriting it
        isCostManuallyEdited = (savedCost > 0);
        document.getElementById('edit_deposit').value = job.deposit || 0;
        // Parse payment method (could be "Method1 (RM X) + Method2 (RM Y)" or single method)
        const paymentMethod = job.payment_method || 'Cash';
        const paymentParts = paymentMethod.split(' + ').map(p => p.trim());
        
        // Parse first payment method and amount
        const part1 = paymentParts[0] || 'Cash';
        const match1 = part1.match(/^(.+?)\s*\(RM\s*([\d.]+)\)$/);
        const method1 = match1 ? match1[1].trim() : part1;
        const amt1 = match1 ? parseFloat(match1[2]) : 0;
        document.getElementById('edit_payment').value = method1;
        document.getElementById('edit_pay_amt1').value = amt1 > 0 ? amt1 : '';
        
        // Parse second payment method and amount
        if (paymentParts[1]) {
            const part2 = paymentParts[1];
            const match2 = part2.match(/^(.+?)\s*\(RM\s*([\d.]+)\)$/);
            const method2 = match2 ? match2[1].trim() : part2;
            const amt2 = match2 ? parseFloat(match2[2]) : 0;
            document.getElementById('edit_payment2').value = method2;
            document.getElementById('edit_pay_amt2').value = amt2 > 0 ? amt2 : '';
            // Enable amount fields and check the checkbox since there's payment amount data
            document.getElementById('edit_sync_pay').checked = true;
            syncPaymentMethods('edit');
        } else {
            // Check if there's payment amount data
            const hasPaymentAmount = amt1 > 0;
            if (hasPaymentAmount) {
                // There's payment amount data, enable amount fields
                document.getElementById('edit_payment2').value = '';
                document.getElementById('edit_pay_amt2').value = '';
                document.getElementById('edit_sync_pay').checked = true;
                syncPaymentMethods('edit');
            } else {
                document.getElementById('edit_payment2').value = '';
                document.getElementById('edit_pay_amt2').value = '';
                // No payment amount data, disable amount fields and uncheck the checkbox
                document.getElementById('edit_sync_pay').checked = false;
                syncPaymentMethods('edit');
            }
        }
        document.getElementById('edit_status').value = job.status;
        document.getElementById('edit_completed_at').value = job.completed_at || '';
        document.getElementById('edit_pay_status').value = job.payment_status || 'Unpaid';
        
        // Set warranty if field exists
        const editWarrantyField = document.getElementById('edit_warranty');
        if (editWarrantyField) {
            editWarrantyField.value = job.warranty || 'No Warranty';
        }

        const isRetail = (job.model === 'Retail Sale' || job.remarks === 'Retail Order');
        document.getElementById('edit_job_type').value = isRetail ? 'Retail' : 'Repair';

        // Check if user is master/admin
        const isMaster = <?php echo $is_master ? 'true' : 'false'; ?>;
        const isEndie = <?php echo $is_endie ? 'true' : 'false'; ?>;
        const isAdminUser = isMaster || isEndie;
        
        // For retail sales (daily repair), non-master users can only edit customer name and phone
        const restrictRetailEdit = isRetail && !isAdminUser;

        if (isRetail) {
            document.getElementById('editRepairFields').style.display = 'none';
            document.getElementById('editRetailFields').style.display = 'block';
            document.getElementById('edit_model').closest('.form-group').style.display = 'none';

            currentEditItems = parseRepairString(job.repair);
            renderEditRetailTable();
            // Calculate job cost after loading items
            updateEditJobCost();
        } else {
            document.getElementById('editRepairFields').style.display = 'block';
            document.getElementById('editRetailFields').style.display = 'none';
            document.getElementById('edit_model').closest('.form-group').style.display = 'block';

            parseRepairJobString(job.repair);
            renderEditRepairPartsTable();
            // Calculate job cost after loading parts
            updateEditRepairJobCost();
            populateEditRepairPartDropdown();
        }

        // Apply restrictions for non-master users editing retail sales
        if (restrictRetailEdit) {
            // Disable all fields except customer name and phone
            document.getElementById('edit_remarks').disabled = true;
            document.getElementById('edit_price').disabled = true;
            document.getElementById('edit_job_cost').disabled = true;
            document.getElementById('edit_deposit').disabled = true;
            document.getElementById('edit_payment').disabled = true;
            document.getElementById('edit_payment2').disabled = true;
            document.getElementById('edit_pay_amt1').disabled = true;
            document.getElementById('edit_pay_amt2').disabled = true;
            document.getElementById('edit_sync_pay').disabled = true;
            document.getElementById('edit_pay_status').disabled = true;
            document.getElementById('edit_status').disabled = true;
            document.getElementById('edit_completed_at').disabled = true;
            document.getElementById('edit_scan_input').disabled = true;
            document.querySelector('#editRetailFields button').disabled = true;
            
            // Hide the retail items section (can't modify items)
            document.getElementById('editRetailFields').style.opacity = '0.5';
            document.getElementById('editRetailFields').style.pointerEvents = 'none';
            
            // Show warning message
            let warningMsg = document.getElementById('editRetailRestrictionWarning');
            if (!warningMsg) {
                warningMsg = document.createElement('div');
                warningMsg.id = 'editRetailRestrictionWarning';
                warningMsg.style.cssText = 'background: #fff3cd; border-left: 4px solid #ffc107; padding: 10px; margin: 10px 0; border-radius: 4px; color: #856404;';
                warningMsg.innerHTML = '<strong>⚠️ Restricted:</strong> Only customer name and phone can be edited. Master user required for other changes.';
                document.getElementById('editRetailFields').parentNode.insertBefore(warningMsg, document.getElementById('editRetailFields'));
            }
            warningMsg.style.display = 'block';
        } else {
            // Enable all fields for master users or non-retail jobs
            document.getElementById('edit_remarks').disabled = false;
            document.getElementById('edit_price').disabled = false;
            document.getElementById('edit_job_cost').disabled = false;
            document.getElementById('edit_deposit').disabled = false;
            document.getElementById('edit_payment').disabled = false;
            document.getElementById('edit_payment2').disabled = false;
            document.getElementById('edit_pay_amt1').disabled = false;
            document.getElementById('edit_pay_amt2').disabled = false;
            document.getElementById('edit_sync_pay').disabled = false;
            document.getElementById('edit_pay_status').disabled = false;
            document.getElementById('edit_status').disabled = false;
            document.getElementById('edit_completed_at').disabled = false;
            document.getElementById('edit_scan_input').disabled = false;
            const addBtn = document.querySelector('#editRetailFields button');
            if (addBtn) addBtn.disabled = false;
            
            document.getElementById('editRetailFields').style.opacity = '1';
            document.getElementById('editRetailFields').style.pointerEvents = 'auto';
            
            const warningMsg = document.getElementById('editRetailRestrictionWarning');
            if (warningMsg) warningMsg.style.display = 'none';
        }

        document.getElementById('editJobModal').style.display = 'flex';
        
        // Auto-focus first input in edit modal
        setTimeout(() => {
            const firstInput = document.querySelector('#editJobModal input:not([type="hidden"]), #editJobModal select');
            if (firstInput) firstInput.focus();
        }, 100);
    }

    function saveEditJob() {
        const compDate = document.getElementById('edit_completed_at').value;
        const jobType = document.getElementById('edit_job_type').value;
        // Get manual cost - preserve the value as-is (empty string means not set, '0' means manually set to 0)
        const manualCost = document.getElementById('edit_job_cost').value;
        
        // Check if this is a restricted retail edit (non-master user editing retail sale)
        const isMaster = <?php echo $is_master ? 'true' : 'false'; ?>;
        const isEndie = <?php echo $is_endie ? 'true' : 'false'; ?>;
        const isAdminUser = isMaster || isEndie;
        const isRetail = (jobType === 'Retail');
        const restrictRetailEdit = isRetail && !isAdminUser;
        
        // For restricted retail edits, only send customer and phone
        if (restrictRetailEdit) {
            const customer = document.getElementById('edit_customer').value;
            const phone = document.getElementById('edit_phone').value;
            
            if (!customer || customer.trim() === '') {
                return showToast("Customer name is required", "error");
            }
            
            const data = {
                action: 'update_full_job',
                id: document.getElementById('edit_db_id').value,
                customer: customer,
                phone: phone
            };
            
            apiRequest(data).then(d => {
                if (d.success) {
                    showToast("Customer information updated");
                    document.getElementById('editJobModal').style.display = 'none';
                    fetchJobs();
                    fetchRetailHistory();
                } else {
                    console.error("Save error:", d);
                    showToast(d.error || "Failed to update", "error");
                }
            });
            return;
        }
        
        // Full edit for master users or non-retail jobs
        let finalRepairStr = "";

        if (jobType === 'Retail') {
            let parts = [];
            currentEditItems.forEach(i => {
                let snTag = i.sn ? ` [SN: ${i.sn}]` : '';
                let warrantyTag = i.warranty ? ` [W: ${i.warranty}]` : '';
                parts.push(`${i.name}${snTag} (x${i.qty}) @ ${parseFloat(i.price).toFixed(2)}${warrantyTag}`);
            });
            finalRepairStr = parts.join(' || ');
        } else {
            let desc = document.getElementById('edit_repair').value;
            let parts = [];
            currentEditRepairParts.forEach(p => {
                parts.push(`${p.name} (x${p.qty})`);
            });

            if (parts.length > 0) {
                finalRepairStr = desc + " || " + parts.join(" || ");
            } else {
                finalRepairStr = desc;
            }
        }

        // Get warranty - for retail, get from items; for repair, use default or field if exists
        let warranty = 'No Warranty';
        if (jobType === 'Retail' && currentEditItems.length > 0) {
            // For retail, warranty is per item, use first item's warranty or default
            warranty = currentEditItems[0].warranty || 'No Warranty';
        } else {
            const editWarrantyField = document.getElementById('edit_warranty');
            if (editWarrantyField) {
                warranty = editWarrantyField.value || 'No Warranty';
            }
        }

        const data = {
            action: 'update_full_job',
            id: document.getElementById('edit_db_id').value,
            customer: document.getElementById('edit_customer').value,
            phone: document.getElementById('edit_phone').value,
            date: document.getElementById('edit_date').value,
            model: document.getElementById('edit_model').value,
            imei: document.getElementById('edit_imei').value,
            passcode: document.getElementById('edit_passcode').value,
            repair: finalRepairStr,
            remarks: document.getElementById('edit_remarks').value,
            price: document.getElementById('edit_price').value,
            job_cost: manualCost,
            deposit: document.getElementById('edit_deposit').value,
            status: document.getElementById('edit_status').value,
            paymentMethod: combinePaymentMethods('edit'),
            payment_status: document.getElementById('edit_pay_status').value,
            completed_at: compDate,
            warranty: warranty
        };

        // Validate required fields (allow price 0.00 for credit/trade-in)
        if (!data.customer || (data.customer && data.customer.trim() === '')) {
            return showToast("Customer name is required", "error");
        }
        const priceNum = parseFloat(data.price);
        if (isNaN(priceNum) || priceNum < 0) {
            return showToast("Price is required (use 0.00 for credit/trade-in)", "error");
        }
        
        // For repair jobs, model is required
        if (jobType === 'Repair' && !data.model) {
            return showToast("Device Model is required for repair jobs", "error");
        }

        apiRequest(data).then(d => {
            if (d.success) {
                showToast("Job Updated");
                document.getElementById('editJobModal').style.display = 'none';
                fetchJobs();
                fetchRetailHistory();
            } else {
                console.error("Save error:", d);
                showToast("Error Saving: " + (d.error || "Unknown error. Check console."), "error");
            }
        }).catch(err => {
            console.error("Save request failed:", err);
            showToast("Network error. Please try again.", "error");
        });
    }

    // --- REPAIR PARTS LOGIC (EDIT MODE) ---
    function parseRepairJobString(str) {
        currentEditRepairParts = [];
        let descriptionParts = [];
        let parts = (str || '').split(' || ');

        parts.forEach(part => {
            let match = part.match(/^(.*?) \(x(\d+)\)$/);
            if (match) {
                currentEditRepairParts.push({
                    name: match[1],
                    qty: parseInt(match[2])
                });
            } else {
                descriptionParts.push(part);
            }
        });

        document.getElementById('edit_repair').value = descriptionParts.join(' || ');
    }

    function renderEditRepairPartsTable() {
        const container = document.getElementById('editRepairPartsTable');
        if (currentEditRepairParts.length === 0) {
            container.innerHTML = '<small style="color:#777;">No parts used.</small>';
            return;
        }

        let html = '<table style="width:100%; font-size:0.9rem; border-collapse:collapse;">';
        currentEditRepairParts.forEach((part, index) => {
            let displayName = escapeHtml(part.name);
            const altMatch = part.name.match(/\[Alt:\s*(.+?)\]/);
            if (altMatch) {
                const baseName = escapeHtml(part.name.replace(/\s*\[Alt:.*?\]/, ''));
                displayName = `${baseName} <span style="color:#8e44ad; font-size:0.8em; font-weight:normal;">[${escapeHtml(altMatch[1])}]</span>`;
            }
            html += `
                <tr style="border-bottom:1px solid #eee;">
                    <td><b style="color:#333;">${displayName}</b></td>
                    <td style="width:50px; text-align:right;">x${part.qty}</td>
                    <td style="width:30px; text-align:right;"><button style="color:red; background:none; border:none; cursor:pointer;" onclick="removeEditRepairPart(${index})">X</button></td>
                </tr>
            `;
        });
        html += '</table>';
        container.innerHTML = html;
    }

    function addEditRepairPart() {
        const nameSelect = document.getElementById('edit_repair_part_input');
        const qtyInput = document.getElementById('edit_repair_part_qty');
        const altInput = document.getElementById('edit_repair_part_alt');
        let name = nameSelect.value.trim();
        const qty = parseInt(qtyInput.value) || 1;
        const altModel = altInput ? altInput.value.trim() : '';

        if (!name) return;

        let fullName = name;
        if (altModel) {
            fullName += ` [Alt: ${altModel}]`;
        }

        currentEditRepairParts.push({
            name: fullName,
            qty: qty
        });
        
        nameSelect.value = '';
        qtyInput.value = 1;
        if (altInput) altInput.value = '';
        renderEditRepairPartsTable();
        updateEditRepairJobCost();
    }
    
    function populateEditRepairPartDropdown() {
        const select = document.getElementById('edit_repair_part_input');
        if (!select) return;
        
        // Clear existing options except the first one
        while (select.options.length > 1) {
            select.remove(1);
        }
        
        // Populate with stock items (Part first, then Retail)
        if (allStock['Part']) {
            for (let g in allStock['Part']) {
                allStock['Part'][g].forEach(item => {
                    const option = document.createElement('option');
                    option.value = item.part_name;
                    option.textContent = item.part_name;
                    select.appendChild(option);
                });
            }
        }
        
        // Also add Retail items
        if (allStock['Retail']) {
            for (let g in allStock['Retail']) {
                allStock['Retail'][g].forEach(item => {
                    // Check if already added
                    const existing = Array.from(select.options).find(opt => opt.value === item.part_name);
                    if (!existing) {
                        const option = document.createElement('option');
                        option.value = item.part_name;
                        option.textContent = item.part_name;
                        select.appendChild(option);
                    }
                });
            }
        }
    }
    
    function updateEditRepairJobCost() {
        // Only auto-calculate if cost hasn't been manually edited
        if (isCostManuallyEdited) {
            return; // Don't overwrite manually entered cost
        }
        
        // Calculate total job cost from all repair parts
        let totalCost = 0;
        
        currentEditRepairParts.forEach(part => {
            const itemName = part.name.toLowerCase().trim();
            const qty = parseInt(part.qty) || 1;
            
            let found = null;
            
            // Search in Part stock first
            if (allStock['Part']) {
                for (let g in allStock['Part']) {
                    let match = allStock['Part'][g].find(i => {
                        const partNameLower = (i.part_name || '').toLowerCase().trim();
                        return partNameLower === itemName;
                    });
                    if (match) {
                        found = match;
                        break;
                    }
                }
            }
            
            // Also check Retail stock if not found
            if (!found && allStock['Retail']) {
                for (let g in allStock['Retail']) {
                    let match = allStock['Retail'][g].find(i => {
                        const partNameLower = (i.part_name || '').toLowerCase().trim();
                        return partNameLower === itemName;
                    });
                    if (match) {
                        found = match;
                        break;
                    }
                }
            }
            
            if (found) {
                const cost = parseFloat(found.cost || 0);
                totalCost += (cost * qty);
            }
        });
        
        document.getElementById('edit_job_cost').value = totalCost.toFixed(2);
    }

    function removeEditRepairPart(index) {
        currentEditRepairParts.splice(index, 1);
        renderEditRepairPartsTable();
        updateEditRepairJobCost(); // Recalculate job cost when part is removed
    }

    // --- RETAIL TABLE LOGIC (EDIT MODE) ---
    function parseRepairString(str) {
        let items = [];
        let rawItems = (str || '').split(' || ');

        rawItems.forEach(raw => {
            let item = {
                name: '',
                qty: 1,
                price: 0,
                sn: '',
                warranty: '1 Month'
            };

            let clean = raw;
            let snMatch = clean.match(/\[SN: (.*?)\]/);
            if (snMatch) {
                item.sn = snMatch[1];
                clean = clean.replace(snMatch[0], '');
            }
            let wMatch = clean.match(/\[W: (.*?)\]/);
            if (wMatch) {
                item.warranty = wMatch[1];
                clean = clean.replace(wMatch[0], '');
            }

            clean = clean.trim();

            // Accept (x1) or (X1) and optional spaces around @ so prices parse correctly
            let matches = clean.match(/^(.*?) \([xX](\d+)\)\s*@\s*([0-9.]+)/);
            if (matches) {
                item.name = matches[1].trim();
                item.qty = parseInt(matches[2]);
                item.price = parseFloat(matches[3]);
            } else {
                item.name = clean;
            }
            if (item.name) items.push(item);
        });
        return items;
    }

    function renderEditRetailTable() {
        const container = document.getElementById('editRetailTable');
        let html = '<table style="width:100%; border-collapse:collapse; font-size:0.9rem;">';
        html += '<tr style="background:#eee; text-align:left;"><th>Item</th><th>SN</th><th>Warranty</th><th style="width:80px;">Qty</th><th style="width:80px;">Price</th><th>Action</th></tr>';

        currentEditItems.forEach((item, index) => {
            html += `<tr>
                <td><input class="edit-table-input" type="text" list="retailStockList" value="${escapeHtml(item.name)}" onchange="updateEditItem(${index}, 'name', this.value)"></td>
                <td><input class="edit-table-input" type="text" value="${escapeHtml(item.sn)}" onchange="updateEditItem(${index}, 'sn', this.value)"></td>
                <td>
                    <select class="edit-table-input" onchange="updateEditItem(${index}, 'warranty', this.value)">
                        <option value="No Warranty" ${item.warranty==='No Warranty'?'selected':''}>No Warranty</option>
                        <option value="1 Week" ${item.warranty==='1 Week'?'selected':''}>1 Week</option>
                        <option value="2 Weeks" ${item.warranty==='2 Weeks'?'selected':''}>2 Weeks</option>
                        <option value="1 Month" ${item.warranty==='1 Month'?'selected':''}>1 Month</option>
                        <option value="3 Months" ${item.warranty==='3 Months'?'selected':''}>3 Months</option>
                        <option value="1 Year" ${item.warranty==='1 Year'?'selected':''}>1 Year</option>
                    </select>
                </td>
                <td><input class="edit-table-input" type="number" value="${item.qty}" onchange="updateEditItem(${index}, 'qty', this.value)" style="text-align:center; padding-right:0;"></td>
                <td><input class="edit-table-input" type="number" value="${item.price}" onchange="updateEditItem(${index}, 'price', this.value)"></td>
                <td><button onclick="removeEditItem(${index})" style="color:red; background:none; border:none; cursor:pointer; font-weight:bold;">X</button></td>
            </tr>`;
        });
        html += '</table>';
        container.innerHTML = html;
        updateEditTotal();
    }

    function updateEditItem(index, field, value) {
        if (field === 'name') {
            currentEditItems[index].name = value;
            let found = null;
            const valLower = value.toLowerCase().trim();
            if (allStock['Retail']) {
                for (let g in allStock['Retail']) {
                    // Case-insensitive match
                    let match = allStock['Retail'][g].find(i => {
                        const partNameLower = (i.part_name || '').toLowerCase().trim();
                        return partNameLower === valLower;
                    });
                    if (match) {
                        found = match;
                        break;
                    }
                }
            }
            // Also check Repair Parts stock
            if (!found && allStock['Part']) {
                for (let g in allStock['Part']) {
                    let match = allStock['Part'][g].find(i => {
                        const partNameLower = (i.part_name || '').toLowerCase().trim();
                        return partNameLower === valLower;
                    });
                    if (match) {
                        found = match;
                        break;
                    }
                }
            }
            if (found) {
                currentEditItems[index].price = parseFloat(found.selling_price || found.cost || 0);
            }
            renderEditRetailTable();
            updateEditJobCost(); // Recalculate job cost when item name changes
            return;
        }

        if (field === 'qty' || field === 'price') value = parseFloat(value) || 0;
        currentEditItems[index][field] = value;
        updateEditTotal();
        if (field === 'qty') updateEditJobCost(); // Recalculate job cost when quantity changes
    }

    function removeEditItem(index) {
        currentEditItems.splice(index, 1);
        renderEditRetailTable();
        updateEditJobCost(); // Recalculate job cost when item is removed
    }

    function updateEditTotal() {
        let total = 0;
        currentEditItems.forEach(i => total += (i.qty * i.price));
        document.getElementById('edit_price').value = total.toFixed(2);
    }
    
    function updateEditJobCost() {
        // Only auto-calculate if cost hasn't been manually edited
        if (isCostManuallyEdited) {
            return; // Don't overwrite manually entered cost
        }
        
        // Calculate total job cost from all items
        let totalCost = 0;
        currentEditItems.forEach(item => {
            const itemName = item.name.toLowerCase().trim();
            let found = null;
            
            // Search in Retail stock
            if (allStock['Retail']) {
                for (let g in allStock['Retail']) {
                    let match = allStock['Retail'][g].find(i => {
                        const partNameLower = (i.part_name || '').toLowerCase().trim();
                        return partNameLower === itemName;
                    });
                    if (match) {
                        found = match;
                        break;
                    }
                }
            }
            
            // Search in Part stock if not found
            if (!found && allStock['Part']) {
                for (let g in allStock['Part']) {
                    let match = allStock['Part'][g].find(i => {
                        const partNameLower = (i.part_name || '').toLowerCase().trim();
                        return partNameLower === itemName;
                    });
                    if (match) {
                        found = match;
                        break;
                    }
                }
            }
            
            if (found) {
                const cost = parseFloat(found.cost || 0);
                totalCost += (cost * (parseInt(item.qty) || 1));
            }
        });
        
        document.getElementById('edit_job_cost').value = totalCost.toFixed(2);
    }

    function markCostAsManual() {
        isCostManuallyEdited = true;
    }

    function handleEditScan(el) {
        const val = el.value.replace(/(Gombak\||Sri Rampai\|)/g, '').trim();
        if (!val) return;

        let found = null;
        const valLower = val.toLowerCase().trim();
        
        // Search in Retail stock (case-insensitive)
        if (allStock['Retail']) {
            for (let g in allStock['Retail']) {
                let match = allStock['Retail'][g].find(i => {
                    const partNameLower = (i.part_name || '').toLowerCase().trim();
                    return partNameLower === valLower;
                });
                if (match) {
                    found = match;
                    break;
                }
            }
        }
        
        // Also check Repair Parts stock
        if (!found && allStock['Part']) {
            for (let g in allStock['Part']) {
                let match = allStock['Part'][g].find(i => {
                    const partNameLower = (i.part_name || '').toLowerCase().trim();
                    return partNameLower === valLower;
                });
                if (match) {
                    found = match;
                    break;
                }
            }
        }

        if (found) {
            currentEditItems.push({
                name: found.part_name,
                qty: 1,
                price: parseFloat(found.selling_price || found.cost || 0),
                sn: '',
                warranty: '1 Month'
            });
            renderEditRetailTable();
            updateEditJobCost(); // Recalculate job cost when item is added
            el.value = '';
        } else {
            currentEditItems.push({
                name: val,
                qty: 1,
                price: 0,
                sn: '',
                warranty: 'No Warranty'
            });
        }
        el.value = '';
        renderEditRetailTable();
    }

    // --- DELETION LOGIC ---
    function fetchDeletedJobs() {
        fetch('api.php?action=fetch_deleted_jobs').then(r => r.json()).then(d => {
            if (d.success) {
                const rows = d.jobs.map(j => {
                    let reasonDisplay = '-';
                    if (j.delete_reason && String(j.delete_reason).trim() !== '') {
                        reasonDisplay = j.delete_reason;
                    } else if (j.remarks && j.remarks.includes('| Deleted:')) {
                        let parts = j.remarks.split('| Deleted:');
                        reasonDisplay = parts[1].trim();
                    } else {
                        reasonDisplay = j.remarks;
                    }

                    const deletedDate = j.deleted_at ? new Date(j.deleted_at).toLocaleString('en-MY', {year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit'}) : (j.created_at ? new Date(j.created_at).toLocaleDateString('en-MY') : '-');
                    const originalDate = j.date || j.created_at ? (j.date || j.created_at) : '-';
                    
                    return `<tr style="opacity:0.7">
                            <td>${j.model === 'Retail Sale' ? '🛒 Retail' : '🔧 Repair'}</td>
                            <td><span class="job-id">${escapeHtml(j.job_id)}</span></td>
                            <td>${escapeHtml(originalDate)}</td>
                            <td style="color:#e74c3c; font-weight:bold;">${escapeHtml(deletedDate)}</td>
                            <td>${escapeHtml(j.customer)}</td>
                            <td>${escapeHtml(j.model)} - ${escapeHtml(j.repair)}</td>
                            <td style="color:#c0392b; font-style:italic;">${escapeHtml(reasonDisplay)}${j.deleted_by ? `<br><small style="color:#7f8c8d;">by ${escapeHtml(j.deleted_by)}</small>` : ''}</td>
                            <td>
                                <button class="btn-action" onclick="restoreJob(${j.id})" title="Restore">♻️</button>
                                ${liveCanDelete ? `<button class="btn-action" onclick="forceDelete(${j.id})" style="color:red" title="Permanent Delete">❌</button>` : ''}
                            </td>
                        </tr>`;
                }).join('');
                document.getElementById('trashTableBody').innerHTML = rows || '<tr><td colspan="8" style="text-align:center">Trash is empty</td></tr>';
            } else {
                alert(d.error);
            }
        });
    }

    function confirmDelete(dbId) {
        jobToDeleteId = dbId;
        document.getElementById('deleteReason').value = '';
        document.getElementById('deleteModal').style.display = 'flex';
    }

    function closeDeleteModal() {
        document.getElementById('deleteModal').style.display = 'none';
        jobToDeleteId = null;
    }

    function executeDelete() {
        if (!jobToDeleteId) return;
        const reason = document.getElementById('deleteReason').value.trim();
        if (!reason) {
            alert("Please enter a reason for deletion.");
            return;
        }
        const btn = document.getElementById('finalDeleteBtn');
        btn.disabled = true;
        btn.innerText = "DELETING...";

        apiRequest({
            action: 'delete_job',
            request_id: generateRequestId('DEL'),
            id: jobToDeleteId,
            reason: reason
        }).then(d => {
            if (d.success) {
                showToast("Deleted Successfully");
                document.getElementById('deleteModal').style.display = 'none';
                fetchJobs();
                fetchRetailHistory();
            } else {
                alert("Error: " + (d.error || "Delete failed"));
            }
            btn.disabled = false;
            btn.innerText = "YES, DELETE IT";
        });
    }
    
    function forceDelete(id) {
        if (!confirm('⚠️ PERMANENT DELETE\n\nThis will permanently delete this job from the database. This action CANNOT be undone.\n\nAre you absolutely sure?')) {
            return;
        }
        apiRequest({
            action: 'force_delete_job',
            id: id
        }).then(d => {
            if (d.success) {
                showToast("Permanently Deleted", 'success');
                fetchDeletedJobs();
            } else {
                showToast(d.error || "Delete Failed", 'error');
            }
        });
    }

    function restoreJob(id) {
        if(confirm("♻️ RESTORE ITEM?\n\nThis will move the item back to the main list.")) {
            apiRequest({action:'restore_job', id:id}).then(d=>{
                if(d.success) { showToast("Item Restored"); fetchDeletedJobs(); }
                else { alert(d.error); }
            });
        }
    }

    // --- STOCK & REPORTS ---
    let _fetchStockInFlight = null;
    function fetchStock(retryCount = 0) {
        if (_fetchStockInFlight && retryCount === 0) return _fetchStockInFlight;
        const maxRetries = 3;
        const cacheBuster = '&t=' + new Date().getTime();
        _fetchStockInFlight = fetch('api.php?action=fetch_stock' + cacheBuster)
            .then(r => {
                if (!r.ok) {
                    throw new Error(`HTTP ${r.status}: ${r.statusText}`);
                }
                return r.json();
            })
            .then(d => {
                if (d.success) {
                    allStock = d.stock;
                    renderStock();

                    const list = document.getElementById('retailStockList');
                    const repList = document.getElementById('repairStockList');
                    const retailFrag = document.createDocumentFragment();
                    const repairFrag = document.createDocumentFragment();

                    ['Part', 'Retail'].forEach(type => {
                        if (allStock[type]) {
                            for (let g in allStock[type]) {
                                allStock[type][g].forEach(i => {
                                    let opt = document.createElement('option');
                                    opt.value = i.part_name;
                                    if (type === 'Retail') {
                                        opt.dataset.price = i.selling_price;
                                        retailFrag.appendChild(opt.cloneNode(true));
                                    }
                                    repairFrag.appendChild(opt);
                                });
                            }
                        }
                    });

                    list.innerHTML = '';
                    repList.innerHTML = '';
                    list.appendChild(retailFrag);
                    repList.appendChild(repairFrag);

                    populateAllDropdowns();
                    
                    if (retryCount === 0) {
                        showToast('✅ Stock list refreshed', 'success');
                    }
                } else {
                    throw new Error(d.error || 'Failed to fetch stock');
                }
            })
            .catch(err => {
                console.error('Error fetching stock:', err);
                if (retryCount < maxRetries) {
                    showToast(`⚠️ Retrying... (${retryCount + 1}/${maxRetries})`, 'error');
                    setTimeout(() => fetchStock(retryCount + 1), 1000 * (retryCount + 1));
                } else {
                    showToast('❌ Failed to load stock. Click REFRESH to try again.', 'error');
                    document.getElementById('stockListPart').innerHTML = '<div style="padding:20px; text-align:center; color:#e74c3c;">⚠️ Failed to load stock. <button class="btn" style="width:auto; padding:8px 15px; margin:10px 0 0 0; background:#e74c3c; font-size:0.85rem;" onclick="fetchStock()">🔄 Retry Now</button></div>';
                    document.getElementById('stockListRetail').innerHTML = '';
                }
            })
            .finally(() => { _fetchStockInFlight = null; });
        return _fetchStockInFlight;
    }

    function populateAllDropdowns() {
        const brands = new Set();
        const suppliers = new Set();
        const partCategories = new Set();
        const retailCategories = new Set();
        const retailNames = new Set();
        const deviceModels = new Set();

        ['Part', 'Retail'].forEach(type => {
            if (!allStock || !allStock[type]) return;
            for (let g in allStock[type]) {
                allStock[type][g].forEach(i => {
                    const b = (i.brand || '').trim();
                    const s = (i.supplier || '').trim();
                    const c = (i.category || '').trim();
                    if (b) brands.add(b);
                    if (s && s !== 'Unknown') suppliers.add(s);
                    if (type === 'Part') {
                        if (c) partCategories.add(c);
                        const m = (i.device_model || '').trim();
                        if (m && m !== 'Universal') deviceModels.add(m);
                    } else {
                        if (c) retailCategories.add(c);
                        const n = (i.part_name || '').trim();
                        if (n) retailNames.add(n);
                    }
                });
            }
        });

        const sortedBrands = Array.from(brands).sort((a, b) => a.localeCompare(b));
        const brandHtml = '<option value="">-- Select Brand --</option>' + sortedBrands.map(b => `<option value="${escapeHtml(b)}">${escapeHtml(b)}</option>`).join('');
        const npBrand = document.getElementById('np_brand');
        const esBrand = document.getElementById('es_brand');
        if (npBrand && npBrand.tagName === 'SELECT') npBrand.innerHTML = brandHtml;
        if (esBrand && esBrand.tagName === 'SELECT') esBrand.innerHTML = brandHtml;

        const sortedSuppliers = Array.from(suppliers).sort((a, b) => a.localeCompare(b));
        const suppHtml = '<option value="">-- Select Supplier --</option>' + sortedSuppliers.map(s => `<option value="${escapeHtml(s)}">${escapeHtml(s)}</option>`).join('');
        const npSupp = document.getElementById('np_supp');
        const nrSupp = document.getElementById('nr_supp');
        if (npSupp && npSupp.tagName === 'SELECT') npSupp.innerHTML = suppHtml;
        if (nrSupp && nrSupp.tagName === 'SELECT') nrSupp.innerHTML = suppHtml;

        const sortedPartCats = Array.from(partCategories).sort((a, b) => a.localeCompare(b));
        const partCatHtml = '<option value="">-- Select Category First --</option>' + sortedPartCats.map(c => `<option value="${escapeHtml(c)}">${escapeHtml(c)}</option>`).join('');
        const npCat = document.getElementById('np_cat');
        const npCatList = document.getElementById('np_cat_list');
        if (npCat && npCat.tagName === 'SELECT') npCat.innerHTML = partCatHtml;
        if (npCatList) npCatList.innerHTML = sortedPartCats.map(c => `<option value="${escapeHtml(c)}">`).join('');

        const sortedRetailNames = Array.from(retailNames).sort((a, b) => a.localeCompare(b));
        const retailNameHtml = '<option value="">-- Select Item Name --</option>' + sortedRetailNames.map(n => `<option value="${escapeHtml(n)}">${escapeHtml(n)}</option>`).join('');
        const nrName = document.getElementById('nr_name');
        if (nrName && nrName.tagName === 'SELECT') nrName.innerHTML = retailNameHtml;

        const sortedRetailCats = Array.from(retailCategories).sort((a, b) => a.localeCompare(b));
        const retailCatHtml = '<option value="">-- Select Category --</option>' + sortedRetailCats.map(c => `<option value="${escapeHtml(c)}">${escapeHtml(c)}</option>`).join('');
        const nrCat = document.getElementById('nr_cat');
        const nrCatList = document.getElementById('nr_cat_list');
        if (nrCat && nrCat.tagName === 'SELECT') nrCat.innerHTML = retailCatHtml;
        if (nrCatList) nrCatList.innerHTML = sortedRetailCats.map(c => `<option value="${escapeHtml(c)}">`).join('');

        const sortedModels = Array.from(deviceModels).sort((a, b) => a.localeCompare(b));
        const modelHtml = '<option value="">-- Select Device Model --</option>' + sortedModels.map(m => `<option value="${escapeHtml(m)}">${escapeHtml(m)}</option>`).join('');
        const npDevice = document.getElementById('np_device');
        const esModel = document.getElementById('es_model');
        if (npDevice && npDevice.tagName === 'SELECT') {
            npDevice.innerHTML = modelHtml;
            const cat = document.getElementById('np_cat')?.value;
            npDevice.disabled = !cat;
        }
        if (esModel && esModel.tagName === 'SELECT') esModel.innerHTML = modelHtml;
    }

    function populateBrandOptions() { populateAllDropdowns(); }
    function populateSupplierOptions() {}
    function populatePartCategoryOptions() { populateAllDropdowns(); }
    function populateRetailItemNamesOptions() {}
    function populateRetailCategoryOptions() {}
    function populateDeviceModelOptions() {}

    function addNewStockItem(type){ 
        const data = { action: 'insert_stock_item', type: type };
        if (type === 'Part') {
            data.model_group = document.getElementById('np_device').value || 'General';
            data.device_model = document.getElementById('np_device').value || '';
            data.part_name = document.getElementById('np_name').value;
            data.category = document.getElementById('np_cat').value || 'Other';
            data.brand = (document.getElementById('np_brand')?.value || '').trim();
            data.cost = document.getElementById('np_cost').value;
            data.supplier = document.getElementById('np_supp').value;
            // Get values safely - use 0 if element doesn't exist or is disabled
            // Convert to number and ensure it's not NaN or empty
            const npGombak = document.getElementById('np_qty_g');
            const npSr = document.getElementById('np_qty_s');
            const gombakVal = (npGombak && !npGombak.disabled) ? npGombak.value : '0';
            const srVal = (npSr && !npSr.disabled) ? npSr.value : '0';
            data.stock_gombak = parseInt(gombakVal) || 0;
            data.stock_sr = parseInt(srVal) || 0;
        } else {
            // Retail
            data.part_name = document.getElementById('nr_name').value;
            data.category = document.getElementById('nr_cat').value || 'Other';
            data.cost = document.getElementById('nr_cost').value;
            data.selling_price = document.getElementById('nr_sell').value;
            data.supplier = document.getElementById('nr_supp').value;
            // Get values safely - use 0 if element doesn't exist or is disabled
            // Convert to number and ensure it's not NaN or empty
            const nrGombak = document.getElementById('nr_qty_g');
            const nrSr = document.getElementById('nr_qty_s');
            const gombakVal = (nrGombak && !nrGombak.disabled) ? nrGombak.value : '0';
            const srVal = (nrSr && !nrSr.disabled) ? nrSr.value : '0';
            data.stock_gombak = parseInt(gombakVal) || 0;
            data.stock_sr = parseInt(srVal) || 0;
        }
        if(!data.part_name) return showToast("Name required", 'error');
        if (type === 'Part') {
            const npCat = document.getElementById('np_cat');
            const npBrand = document.getElementById('np_brand');
            const npSupp = document.getElementById('np_supp');
            if (npCat && npCat.tagName === 'SELECT' && !(npCat.value || '').trim()) return showToast("Please select Category", 'error');
            if (npBrand && npBrand.tagName === 'SELECT' && !(npBrand.value || '').trim()) return showToast("Please select Brand", 'error');
            if (npSupp && npSupp.tagName === 'SELECT' && !(npSupp.value || '').trim()) return showToast("Please select Supplier", 'error');
        } else {
            const nrName = document.getElementById('nr_name');
            const nrCat = document.getElementById('nr_cat');
            const nrSupp = document.getElementById('nr_supp');
            if (nrName && nrName.tagName === 'SELECT' && !(nrName.value || '').trim()) return showToast("Please select Item Name", 'error');
            if (nrCat && nrCat.tagName === 'SELECT' && !(nrCat.value || '').trim()) return showToast("Please select Category", 'error');
            if (nrSupp && nrSupp.tagName === 'SELECT' && !(nrSupp.value || '').trim()) return showToast("Please select Supplier", 'error');
        }
        
        apiRequest(data).then(d=>{
            if(d.success){
                // Show appropriate message based on whether it was merged or added new
                if (d.message && d.message.includes('combined')) {
                    const combined = d.combined_stock || {};
                    const gombak = combined.gombak || 0;
                    const sr = combined.sr || 0;
                    showToast(`✅ Stock merged! Gombak: ${gombak}, Sri Rampai: ${sr}`, 'success');
                } else {
                    showToast("✅ Stock Added Successfully"); 
                }
                fetchStock();
                // Switch to Retail tab so user can immediately scan the new item's barcode
                switchMainTab('retail');
                setTimeout(() => {
                    const si = document.getElementById('retailScannerInput');
                    if (si) si.focus();
                }, 150);
                if(type === 'Part') { 
                    ['np_name','np_brand','np_cost','np_supp','np_qty_g','np_qty_s','np_device','np_cat'].forEach(id=>{
                        const el = document.getElementById(id);
                        if(el) {
                            el.value = (id === 'np_qty_g' || id === 'np_qty_s') ? '0' : '';
                            // Clear dataset tracking for name field
                            if (id === 'np_name') {
                                el.dataset.lastDev = '';
                                el.dataset.lastCat = '';
                                el.dataset.isManualEdit = 'false';
                            }
                        }
                    });
                    // Clear device search field and reset state
                    const deviceSearch = document.getElementById('np_device_search');
                    const npDevice = document.getElementById('np_device');
                    if (deviceSearch) {
                        deviceSearch.value = '';
                        deviceSearch.disabled = true;
                        deviceSearch.style.background = '#f5f5f5';
                        deviceSearch.style.cursor = 'not-allowed';
                    }
                    if (npDevice) {
                        npDevice.value = '';
                        if (npDevice.tagName === 'SELECT') npDevice.disabled = true;
                    }
                    hideDeviceDropdown();
                    // Regenerate part name after clearing
                    generatePartName();
                } else { 
                    ['nr_name','nr_cost','nr_sell','nr_supp','nr_qty_g','nr_qty_s','nr_cat'].forEach(id=>{
                        const el = document.getElementById(id);
                        if(el) el.value = (id === 'nr_qty_g' || id === 'nr_qty_s') ? '0' : '';
                    });
                }
            } else {
                showToast("❌ Error: " + (d.error || "Failed to add stock"), 'error');
                console.error("Stock add error:", d);
            }
        }).catch(err => {
            showToast("❌ Network error: " + err.message, 'error');
            console.error("Stock add request failed:", err);
        }); 
    }

    function convertStockToUppercase() {
        if (!confirm('⚠️ UPPERCASE CONVERSION\n\n' +
                    'This will convert text fields to UPPERCASE:\n' +
                    '• Part Name\n' +
                    '• Device Model\n' +
                    '• Category\n' +
                    '• Supplier\n' +
                    '• Type\n\n' +
                    '✅ SAFE OPERATION:\n' +
                    '• NO data will be deleted\n' +
                    '• NO numeric fields changed (cost, stock quantities)\n' +
                    '• NO NULL values modified\n' +
                    '• Only text case is changed\n\n' +
                    'Continue?')) {
            return;
        }
        
        showToast('🔄 Converting stock to uppercase (safe operation - no data loss)...', 'success');
        
        apiRequest({ action: 'convert_stock_to_uppercase' }).then(d => {
            if (d.success) {
                const updated = d.updated || 0;
                const skipped = d.skipped || 0;
                const total = d.total || 0;
                const errors = d.errors || [];
                
                let message = `✅ Conversion complete!\n\n` +
                             `Updated: ${updated} items\n` +
                             `Skipped: ${skipped} items (already uppercase)\n` +
                             `Total: ${total} items`;
                
                if (errors.length > 0) {
                    message += `\n\n⚠️ ${errors.length} error(s) occurred (see console for details)`;
                    console.error('Conversion errors:', errors);
                }
                
                showToast(message, 'success');
                fetchStock(); // Refresh the stock list
            } else {
                const errorMsg = d.message || d.error || 'Failed to convert stock. No data was changed.';
                console.error('Conversion failed:', d);
                showToast('❌ Error: ' + errorMsg, 'error');
            }
        }).catch(err => {
            console.error('Conversion exception:', err);
            showToast('❌ Error: ' + (err.message || 'Unknown error') + '\n\nNo data was changed. Check console for details.', 'error');
        });
    }

    function mergeDuplicateStocks() {
        if (!confirm('This will merge all duplicate stock items with similar names. Continue?')) {
            return;
        }
        
        showToast('🔍 Scanning for duplicates...', 'success');
        
        apiRequest({ action: 'merge_duplicate_stocks' }).then(d => {
            if (d.success) {
                const merged = d.merged || [];
                const totalMerged = d.total_merged || 0;
                
                if (totalMerged === 0) {
                    showToast('✅ No duplicates found! All stock items are unique.', 'success');
                } else {
                    // Show summary toast first
                    showToast(`✅ Merged ${totalMerged} duplicate item(s) into ${merged.length} base item(s)`, 'success');
                    
                    // Show individual merge notifications (limit to first 5 to avoid spam)
                    const maxNotifications = 5;
                    merged.slice(0, maxNotifications).forEach((merge, index) => {
                        setTimeout(() => {
                            const names = merge.merged_names.slice(0, 2).join(', ');
                            const more = merge.merged_count > 2 ? ` +${merge.merged_count - 2} more` : '';
                            showToast(
                                `Merged into "${merge.base_name}": ${names}${more}`,
                                'success'
                            );
                        }, (index + 1) * 800); // Stagger notifications
                    });
                    
                    // If there are more merges, show a final summary
                    if (merged.length > maxNotifications) {
                        setTimeout(() => {
                            showToast(`...and ${merged.length - maxNotifications} more merge(s) completed`, 'success');
                        }, (maxNotifications + 1) * 800);
                    }
                    
                    // Refresh stock list after all notifications
                    setTimeout(() => {
                        fetchStock();
                        showToast('📦 Stock list refreshed', 'success');
                    }, (Math.min(merged.length, maxNotifications) + 2) * 800);
                }
            } else {
                showToast('❌ Error: ' + (d.error || 'Failed to merge duplicates'), 'error');
            }
        }).catch(err => {
            showToast('❌ Error merging duplicates: ' + err.message, 'error');
        });
    }

    function openEditStock(id) {
        let item = null;
        if(allStock['Part']) for(let g in allStock['Part']) { const f=allStock['Part'][g].find(x=>x.id==id); if(f) item=f; }
        if(!item && allStock['Retail']) for(let g in allStock['Retail']) { const f=allStock['Retail'][g].find(x=>x.id==id); if(f) item=f; }
        
        if(!item) return;
        
        document.getElementById('es_id').value = item.id;
        document.getElementById('es_type').value = item.type;
        document.getElementById('es_group').value = item.model_group || '';
        const esModel = document.getElementById('es_model');
        if (esModel) {
            if (esModel.tagName === 'SELECT') {
                const itemModel = (item.device_model || '').trim();
                if (itemModel) {
                    const hasOption = Array.from(esModel.options).some(o => o.value === itemModel);
                    if (!hasOption) {
                        const opt = document.createElement('option');
                        opt.value = itemModel;
                        opt.textContent = itemModel;
                        esModel.appendChild(opt);
                    }
                }
                esModel.value = item.device_model || '';
            } else {
                esModel.value = item.device_model || '';
            }
        }
        document.getElementById('es_name').value = item.part_name;
        const esBrand = document.getElementById('es_brand');
        if (esBrand) {
            if (esBrand.tagName === 'SELECT') {
                const itemBrand = (item.brand || '').trim();
                if (itemBrand) {
                    const hasOption = Array.from(esBrand.options).some(o => o.value === itemBrand);
                    if (!hasOption) {
                        const opt = document.createElement('option');
                        opt.value = itemBrand;
                        opt.textContent = itemBrand;
                        esBrand.appendChild(opt);
                    }
                }
                esBrand.value = item.brand || '';
            } else {
                esBrand.value = item.brand || '';
            }
        }
        document.getElementById('es_category').value = item.category || 'Other';
        document.getElementById('es_cost').value = item.cost;
        document.getElementById('es_sell').value = item.selling_price || 0;
        document.getElementById('es_supp').value = item.supplier || '';
        document.getElementById('es_stock_g').value = item.stock_gombak;
        document.getElementById('es_stock_s').value = item.stock_sr;
        
        document.getElementById('editStockModal').style.display='flex';
        // Apply restrictions after modal opens
        setTimeout(restrictStockFields, 100);
    }

    function saveEditStock() {
        const data = {
            action: 'update_full_stock',
            id: document.getElementById('es_id').value,
            type: document.getElementById('es_type').value,
            model_group: document.getElementById('es_group').value,
            device_model: document.getElementById('es_model').value,
            part_name: document.getElementById('es_name').value,
            brand: (document.getElementById('es_brand')?.value || '').trim(),
            category: document.getElementById('es_category').value,
            cost: document.getElementById('es_cost').value,
            selling_price: document.getElementById('es_sell').value,
            supplier: document.getElementById('es_supp').value,
            stock_gombak: document.getElementById('es_stock_g').value,
            stock_sr: document.getElementById('es_stock_s').value
        };
        apiRequest(data).then(d => {
            if(d.success) { showToast("Stock Updated"); document.getElementById('editStockModal').style.display='none'; fetchStock(); } 
            else { alert("Error: " + d.error); }
        });
    }

    function filterStockList() {
        const term = document.getElementById('stockSearchInput').value.toLowerCase().trim();
        ['Part', 'Retail'].forEach(t => {
            const container = document.getElementById('stockList' + t);
            if (!container) return;
            const rows = container.querySelectorAll('.stock-part-row');
            const headers = container.querySelectorAll('.section-title');
            rows.forEach(row => {
                row.style.display = (!term || row.dataset.search.includes(term)) ? '' : 'none';
            });
            headers.forEach(hdr => {
                let next = hdr.nextElementSibling;
                let anyVisible = false;
                while (next && !next.classList.contains('section-title')) {
                    if (next.classList.contains('stock-part-row') && next.style.display !== 'none') anyVisible = true;
                    next = next.nextElementSibling;
                }
                hdr.style.display = anyVisible ? '' : 'none';
            });
        });
    }

    function renderStock() {
        ['Part', 'Retail'].forEach(t => {
            let h = '';
            if (allStock[t])
                for (let g in allStock[t]) {
                    let categoryItems = allStock[t][g];
                    
                    if (categoryItems.length === 0) continue;
                    
                    h += `<div class="section-title">${escapeHtml(g)}</div>`;
                    categoryItems.forEach(i => {
                        const supplierName = (i.supplier && i.supplier !== 'Unknown' && i.supplier.trim()) ? escapeHtml(i.supplier) : '';
                        let costDisplay = '';
                        const costVal = parseFloat(i.cost) || 0;
                        const sellVal = parseFloat(i.selling_price) || 0;
                        if (IS_MASTER) {
                            costDisplay = `<div class="stock-cost-cell" style="width:80px; margin-right:10px;"><small class="stock-cost-label">Cost</small><span class="stock-cost-value">RM ${costVal.toFixed(2)}</span>${supplierName ? `<small class="stock-model">${supplierName}</small>` : ''}</div>`;
                        } else {
                            if (t === 'Retail') {
                                costDisplay = `<div class="stock-cost-cell" style="width:100px; margin-right:10px;"><small class="stock-cost-label">Cost</small><span class="stock-cost-value">RM ${costVal.toFixed(2)}</span>${sellVal > 0 ? `<small class="stock-sell-value">Sell: RM ${sellVal.toFixed(2)}</small>` : ''}${supplierName ? `<small class="stock-model">${supplierName}</small>` : ''}</div>`;
                            } else {
                                costDisplay = `<div class="stock-cost-cell" style="width:80px; margin-right:10px;"><small class="stock-cost-label">Cost</small><span class="stock-cost-value">RM ${costVal.toFixed(2)}</span>${supplierName ? `<small class="stock-model">${supplierName}</small>` : ''}</div>`;
                            }
                        }

                        const editBtn = IS_MASTER ? `<button class="btn-icon btn-edit-item" onclick="openEditStock(${i.id})">✏️</button>` : '';
                        const delBtn = IS_ENDIE ? `<button class="btn-icon btn-delete-item" onclick="deleteStockItem(${i.id}, '${escapeHtml(i.part_name)}')">🗑</button>` : '';
                        const transferBtn = liveCanTransfer ? `<button class="btn-icon btn-transfer" onclick="openQuickTransferModal(${i.id})" title="Quick Transfer Stock">🚚</button>` : '';
                        const deleteSgBtn = liveCanDelete ? `<button class="btn-icon btn-delete-item" onclick="openDeleteStockModal(${i.id}, 'SG', '${escapeHtml(i.part_name)}', ${i.stock_gombak})" title="Delete SG Stock" style="background:#e74c3c; font-size:0.7rem;">SG🗑</button>` : '';
                        const deleteSrBtn = liveCanDelete ? `<button class="btn-icon btn-delete-item" onclick="openDeleteStockModal(${i.id}, 'SR', '${escapeHtml(i.part_name)}', ${i.stock_sr})" title="Delete SR Stock" style="background:#c0392b; font-size:0.7rem;">SR🗑</button>` : '';
                        const barcodeBtn = IS_MASTER ? `<button class="btn-icon" onclick="generateBarcode(${i.id}, '${escapeHtml(i.part_name)}')" title="Generate Barcode" style="background:#8e44ad; font-size:0.7rem;">📊</button>` : '';
                        const cnBtn = IS_MASTER ? `<button class="btn-icon" onclick="openCreditNoteModal(${i.id}, '${escapeHtml(i.part_name)}', ${i.stock_gombak}, ${i.stock_sr}, '${escapeHtml(i.supplier || '')}')" title="Credit Note - Return to Supplier" style="background:#e67e22; font-size:0.7rem;">CN</button>` : '';
                        const historyBtn = liveCanViewStockLogs ? `<button class="btn-icon" onclick="viewStockMovements(${i.id}, '${escapeHtml(i.part_name)}')" title="Date In / Date Out / Refund History" style="background:#16a085; font-size:0.7rem;">📋</button>` : '';
                        const isGombakBranch = MY_BRANCH_LOWER.includes('gombak');
                        const isSriRampaiBranch = MY_BRANCH_LOWER.includes('sri') || MY_BRANCH_LOWER.includes('rampai');
                        const showSgQr = !IS_RESTRICTED || isGombakBranch;
                        const showSrQr = !IS_RESTRICTED || isSriRampaiBranch;
                        const qrSgBtn = showSgQr ? `<button class="btn-icon btn-qr-sg" onclick="generateStockQR('${escapeHtml(i.part_name)}', ${i.selling_price || 0})" title="Generate QR - Gombak">SG</button>` : '';
                        const qrSrBtn = showSrQr ? `<button class="btn-icon btn-qr-sr" onclick="generateStockQR('${escapeHtml(i.part_name)}', ${i.selling_price || 0})" title="Generate QR - Sri Rampai">SR</button>` : '';

                        const sgQty = parseInt(i.stock_gombak) || 0;
                        const srQty = parseInt(i.stock_sr) || 0;
                        const sgClass = sgQty <= 0 ? 'stock-qty-danger' : (sgQty <= 2 ? 'stock-qty-warn' : 'stock-qty-ok');
                        const srClass = srQty <= 0 ? 'stock-qty-danger' : (srQty <= 2 ? 'stock-qty-warn' : 'stock-qty-ok');

                        const searchText = [i.part_name, i.device_model, g, i.supplier].filter(Boolean).join(' ').toLowerCase();
                        h += `<div class="stock-part-row" style="flex-wrap:wrap;" data-search="${escapeHtml(searchText)}">
                        <div class="stock-checkbox-cell">
                            <input type="checkbox" class="stock-checkbox" data-stock-id="${i.id}">
                        </div>
                        <div class="stock-name-cell">
                            <span class="stock-name">${escapeHtml(i.part_name)}</span>
                            ${i.device_model ? `<small class="stock-model">${escapeHtml(i.device_model)}</small>` : ''}
                        </div>
                        ${costDisplay}
                        <div class="stock-qty-cell">
                            <small class="stock-qty-label-sg">Gombak</small>
                            <span class="stock-qty-badge ${sgClass}">${i.stock_gombak}</span>
                        </div>
                        <div class="stock-qty-cell" style="margin-right:0;">
                            <small class="stock-qty-label-sr">Sri Rampai</small>
                            <span class="stock-qty-badge ${srClass}">${i.stock_sr}</span>
                        </div>
                        <div class="stock-actions">
                             ${historyBtn}
                             ${transferBtn}
                             ${qrSgBtn}
                             ${qrSrBtn}
                             ${barcodeBtn}
                             ${cnBtn}
                             ${deleteSgBtn}
                             ${deleteSrBtn}
                             ${editBtn}
                             ${delBtn}
                        </div>
                    </div>`;
                    });
                }
            document.getElementById('stockList' + t).innerHTML = h;
        });
        const currentTerm = document.getElementById('stockSearchInput')?.value?.toLowerCase()?.trim();
        if (currentTerm) filterStockList();
    }

    function updateStock(id,f,v){ apiRequest({action:'update_stock_field', id:id, field:f, value:v}); }
    
    function deleteStockItem(id, name) {
        if(confirm("⚠️ PERMANENTLY DELETE?\n\nItem: " + name + "\n\nThis cannot be undone.")) {
            apiRequest({action:'delete_stock_item', id:id}).then(d=>{
                if(d.success) { showToast("Item Deleted"); fetchStock(); }
                else { alert(d.error); }
            });
        }
    }

    // --- REPORT GENERATION (EXPANDED) ---
    async function generateReport() {
        const d = await apiRequest({
            action: 'get_report',
            start: document.getElementById('reportStart').value,
            end: document.getElementById('reportEnd').value,
            branch: document.getElementById('reportBranch').value
        });

        if (d.success) {
            document.getElementById('reportDisplay').classList.remove('d-none');
            const allRows = d.details;
            // Filter to only show IV orders (retail/invoice), exclude JS orders (repair jobs)
            const rows = allRows.filter(r => r.job_id && r.job_id.startsWith('IV-'));
            const expenses = d.expenses || [];

            // Render Jobs (FIXED: Customer Column)
            const tableBody = rows.map(r => {
                const price = parseFloat(r.price) || 0;
                const cost = parseFloat(r.job_cost) || 0;
                const profit = price - cost;

                let statusColor = '#333';
                if (r.status === 'Completed') statusColor = '#2ecc71';
                else if (r.status === 'Refund') statusColor = '#e74c3c';
                else if (r.status === 'Return') statusColor = '#e67e22';

                const paymentText = (r.payment_method || '-').length > 30 ? (r.payment_method || '-').substring(0, 27) + '...' : (r.payment_method || '-');
                return `<tr class="rpt-tr">
                    <td class="rpt-td rpt-td-id">${r.job_id}</td>
                    <td class="rpt-td">${r.date}</td>
                    <td class="rpt-td rpt-td-center"><span class="${r.model === 'Retail Sale' ? 'rpt-type-retail' : 'rpt-type-repair'}">${r.model === 'Retail Sale' ? 'Retail' : 'Repair'}</span></td>
                    <td class="rpt-td">${escapeHtml(r.customer)}</td>
                    <td class="rpt-td" style="font-size:7.5pt;" title="${r.payment_method || '-'}">${paymentText}</td>
                    <td class="rpt-td">${r.branch}</td>
                    <td class="rpt-td rpt-td-center" style="color:${statusColor}; font-weight:bold;">${r.status}</td>
                    <td class="rpt-td rpt-td-right" style="color:${price < 0 ? '#e74c3c' : 'inherit'};">RM ${price.toFixed(2)}</td>
                    <td class="rpt-td rpt-td-right" style="color:#e67e22;">RM ${cost.toFixed(2)}</td>
                    <td class="rpt-td rpt-td-right rpt-td-last" style="font-weight:bold; color:${profit < 0 ? '#e74c3c' : '#2ecc71'};">RM ${profit.toFixed(2)}</td>
                </tr>`;
            }).join('');
            document.getElementById('reportTableBody').innerHTML = tableBody;

            // Render Expenses with better formatting
            const expRows = expenses.map(e => `
                <tr class="rpt-tr">
                    <td class="exp-td">${e.date}</td>
                    <td class="exp-td"><strong>${escapeHtml(e.description)}</strong></td>
                    <td class="exp-td">${e.branch}</td>
                    <td class="exp-td rpt-td-right">RM ${parseFloat(e.amount).toFixed(2)}</td>
                    <td class="exp-td rpt-td-center"><button onclick="deleteExpense(${e.id})" style="color:red; border:none; background:none; cursor:pointer; font-size:14px;">✕</button></td>
                </tr>
            `).join('');
            document.getElementById('expenseTableContainer').innerHTML = expenses.length > 0 ? `
                <table style="width: 100%; border-collapse: collapse; margin-top: 10px;">
                    <thead>
                        <tr style="background: #f8f9fa; border-bottom: 2px solid #dee2e6;">
                            <th style="padding: 10px; text-align: left; border-right: 1px solid #dee2e6;">Date</th>
                            <th style="padding: 10px; text-align: left; border-right: 1px solid #dee2e6;">Description</th>
                            <th style="padding: 10px; text-align: left; border-right: 1px solid #dee2e6;">Branch</th>
                            <th style="padding: 10px; text-align: right; border-right: 1px solid #dee2e6;">Amount</th>
                            <th style="padding: 10px; text-align: center;">Action</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${expRows}
                    </tbody>
                </table>
            ` : '<div style="padding: 15px; text-align: center; color: #999; font-style: italic;">No expenses recorded for this period.</div>';

            // Totals - Recalculate based on filtered IV orders only
            const totalSales = rows.reduce((sum, r) => sum + (parseFloat(r.price) || 0), 0);
            const totalStockCost = rows.reduce((sum, r) => sum + (parseFloat(r.job_cost) || 0), 0);
            const totalExpenses = parseFloat(d.summary.total_expenses || 0);
            const netProfit = totalSales - totalStockCost - totalExpenses;

            document.getElementById('reportTableFoot').innerHTML = `
                <tr style="background: #f8f9fa; border-top: 3px solid #dee2e6; font-size: 14px;">
                    <td colspan="7" style="padding: 12px 8px; text-align:right; font-weight: bold; border-right: 1px solid #dee2e6;">TOTALS:</td>
                    <td style="padding: 12px 8px; text-align:right; font-weight: bold; border-right: 1px solid #dee2e6;">RM ${totalSales.toFixed(2)}</td>
                    <td style="padding: 12px 8px; text-align:right; color:#e67e22; font-weight: bold; border-right: 1px solid #dee2e6;">RM ${totalStockCost.toFixed(2)}</td>
                    <td style="padding: 12px 8px; text-align:right; color:#2ecc71; font-weight: bold;">RM ${(totalSales - totalStockCost).toFixed(2)}</td>
                </tr>
            `;

            document.getElementById('totalSalesDisplay').innerText = "RM " + totalSales.toFixed(2);
            document.getElementById('totalCostDisplay').innerText = "RM " + totalStockCost.toFixed(2);
            document.getElementById('totalExpDisplay').innerText = "RM " + totalExpenses.toFixed(2);
            document.getElementById('totalProfitDisplay').innerText = "RM " + netProfit.toFixed(2);

            // Helper function to parse combined payment methods
            function parsePaymentMethod(paymentMethodStr, totalPrice) {
                const results = [];
                if (!paymentMethodStr) {
                    results.push({ method: 'Cash', amount: totalPrice });
                    return results;
                }
                
                // Check if it's a combined payment (contains " + ")
                if (paymentMethodStr.includes(' + ')) {
                    // Split by " + " to get individual methods
                    const parts = paymentMethodStr.split(' + ');
                    let totalExtractedAmount = 0;
                    
                    parts.forEach((part, index) => {
                        part = part.trim();
                        // Extract method name and amount
                        // Format: "Cash (RM 200.00)" or "Bank Transfer/QR (RM 150.00)"
                        // Handle truncated strings (missing closing parenthesis)
                        const amountMatch = part.match(/\(RM\s+([\d,]+\.?\d*)/);
                        let amount = 0;
                        let method = '';
                        
                        if (amountMatch) {
                            // Found amount pattern
                            amount = parseFloat(amountMatch[1].replace(/,/g, ''));
                            // Extract method name by removing the amount part
                            method = part.replace(/\s*\(RM\s+[\d,]+\.?\d*.*$/, '').trim();
                        } else {
                            // No amount found - might be truncated or just method name
                            // Check if it looks like a method name (common payment methods)
                            const commonMethods = ['Cash', 'Bank Transfer/QR', 'SPayLater', 'TnG Ewallet'];
                            for (let m of commonMethods) {
                                // Check if part matches or is a prefix of the method name
                                if (part.includes(m) || m.toLowerCase().startsWith(part.toLowerCase().trim())) {
                                    method = m;
                                    break;
                                }
                            }
                            // If no match found but part contains method keywords, try to reconstruct
                            if (!method) {
                                const partLower = part.toLowerCase();
                                if (partLower.includes('bank') || partLower.includes('transfer') || partLower.includes('qr')) {
                                    method = 'Bank Transfer/QR';
                                } else if (partLower.includes('spay') || partLower.includes('later')) {
                                    method = 'SPayLater';
                                } else if (partLower.includes('tng') || partLower.includes('ewallet')) {
                                    method = 'TnG Ewallet';
                                } else if (partLower.includes('cash')) {
                                    method = 'Cash';
                                } else {
                                    // Use the part as-is (might be truncated method name)
                                    method = part;
                                }
                            }
                        }
                        
                        if (method) {
                            results.push({ method: method, amount: amount });
                            totalExtractedAmount += amount;
                        }
                    });
                    
                    // If amounts were extracted but don't sum to total, adjust the last one
                    // Or if no amounts were extracted, distribute evenly
                    if (results.length > 0) {
                        if (totalExtractedAmount === 0) {
                            // No amounts extracted - distribute evenly
                            const perMethod = totalPrice / results.length;
                            results.forEach(r => r.amount = perMethod);
                        } else if (totalExtractedAmount !== totalPrice && totalExtractedAmount > 0) {
                            // Adjust last method to make total match
                            const diff = totalPrice - totalExtractedAmount;
                            if (results.length > 0) {
                                results[results.length - 1].amount += diff;
                            }
                        }
                    }
                } else {
                    // Single payment method - extract amount if present
                    const amountMatch = paymentMethodStr.match(/\(RM\s+([\d,]+\.?\d*)/);
                    const amount = amountMatch ? parseFloat(amountMatch[1].replace(/,/g, '')) : totalPrice;
                    const method = paymentMethodStr.replace(/\s*\(RM\s+[\d,]+\.?\d*.*$/, '').trim() || 'Cash';
                    
                    results.push({ method: method, amount: amount });
                }
                
                // Fallback if no results
                if (results.length === 0) {
                    results.push({ method: 'Cash', amount: totalPrice });
                }
                
                return results;
            }

            // Charts
            let payments = {}, branches = {}, dates = {};
            rows.forEach(r => {
                const price = parseFloat(r.price);
                if (!(r.status === 'Return' && price > 0)) {
                    // Parse payment method(s) and split into individual methods
                    const paymentMethods = parsePaymentMethod(r.payment_method, price);
                    paymentMethods.forEach(pm => {
                        payments[pm.method] = (payments[pm.method] || 0) + pm.amount;
                    });
                    
                    branches[r.branch] = (branches[r.branch] || 0) + price;
                    dates[r.date] = (dates[r.date] || 0) + price;
                }
            });
            
            renderChart('paymentChart', 'doughnut', Object.keys(payments), Object.values(payments), ['#3498db', '#2980b9', '#9b59b6', '#f1c40f']);
            renderChart('branchChart', 'pie', Object.keys(branches), Object.values(branches), ['#2980b9', '#9b59b6']);
            renderChart('trendChart', 'line', Object.keys(dates).sort(), Object.values(dates), '#3498db');
            
            // Advanced Analytics Charts
            if (d.analytics) {
                // Top Items Table
                if (d.analytics.top_items) {
                    const topItemsRows = Object.entries(d.analytics.top_items).map(([item, qty]) => 
                        `<tr><td>${escapeHtml(item)}</td><td style="text-align:right; font-weight:bold;">${qty}</td></tr>`
                    ).join('');
                    document.getElementById('topItemsTable').innerHTML = topItemsRows || '<tr><td colspan="2" style="text-align:center; padding:20px; color:#999;">No data</td></tr>';
                }
                
                // Category Profit Table - Make rows clickable
                if (d.analytics.category_profits) {
                    const categoryDetails = d.analytics.category_profit_details || {};
                    const categoryRows = Object.entries(d.analytics.category_profits).map(([cat, profit]) => {
                        const details = categoryDetails[cat] || {sales: 0, cost: 0, profit: 0};
                        return `<tr style="cursor:pointer; transition:background 0.2s;" onclick="showCategoryBreakdown('${escapeHtml(cat)}', ${details.sales}, ${details.cost}, ${details.profit})" onmouseover="this.style.background='#f0f0f0'" onmouseout="this.style.background=''"><td style="padding:8px;">${escapeHtml(cat)}</td><td style="text-align:right; font-weight:bold; color:${profit >= 0 ? '#2ecc71' : '#e74c3c'}">RM ${profit.toFixed(2)}</td></tr>`;
                    }).join('');
                    document.getElementById('categoryProfitTable').innerHTML = categoryRows || '<tr><td colspan="2" style="text-align:center; padding:20px; color:#999;">No data</td></tr>';
                }
            }
        }
    }

    // --- OTHER CORE FUNCTIONS (Minified/Standard) ---
    // (Included for completeness but kept succinct to not exceed response limits while maintaining readability)
    function openTransfer(id,name) { document.getElementById('transferId').value=id; document.getElementById('transferItemName').innerText=name; document.getElementById('transferModal').style.display='flex'; }
    function submitTransfer() { const d = { action:'transfer_stock', id:document.getElementById('transferId').value, name:document.getElementById('transferItemName').innerText, from:document.getElementById('transferFrom').value, to:document.getElementById('transferTo').value, qty:document.getElementById('transferQty').value, staff:'<?php echo $_SESSION['user']; ?>' }; apiRequest(d).then(res=>{ if(res.success){ showToast("Transfer Complete"); document.getElementById('transferModal').style.display='none'; fetchStock(); } }); }
    function viewTransferLog() { fetch('api.php?action=get_transfers').then(r => r.json()).then(d => { const rows = d.logs.map(l => `<tr><td>${l.date}</td><td>${escapeHtml(l.item_name)}</td><td><b>${l.qty}</b></td><td>${l.from_branch} ➝ ${l.to_branch}</td><td style="color:var(--primary); font-weight:bold;">${escapeHtml(l.user)}</td></tr>`).join(''); document.getElementById('historyTableBody').innerHTML = `<thead><tr><th style="background:#f8f9fa;">Date</th><th style="background:#f8f9fa;">Item</th><th style="background:#f8f9fa;">Qty</th><th style="background:#f8f9fa;">Route</th><th style="background:#f8f9fa; color:#2980b9;">User</th></tr></thead><tbody>${rows}</tbody>`; document.getElementById('historyModal').style.display='flex'; }); }
    
    function viewStockLogs() {
        fetch('api.php?action=get_stock_logs')
        .then(r => r.json())
        .then(d => {
            if (d.success) {
                const rows = d.logs.map(l => {
                    const dateTime = new Date(l.created_at).toLocaleString('en-MY', {
                        year: 'numeric',
                        month: '2-digit',
                        day: '2-digit',
                        hour: '2-digit',
                        minute: '2-digit',
                        second: '2-digit'
                    });
                    let actionBadge = '';
                    switch(l.action) {
                        case 'ADD_STOCK':
                            actionBadge = '<span style="background:#2ecc71; color:white; padding:2px 8px; border-radius:4px; font-size:0.8em; font-weight:bold;">ADD</span>';
                            break;
                        case 'UPDATE_STOCK':
                        case 'EDIT_STOCK':
                            actionBadge = '<span style="background:#f39c12; color:white; padding:2px 8px; border-radius:4px; font-size:0.8em; font-weight:bold;">UPDATE</span>';
                            break;
                        case 'DELETE_STOCK':
                        case 'DELETE_STOCK_LOCATION':
                            actionBadge = '<span style="background:#e74c3c; color:white; padding:2px 8px; border-radius:4px; font-size:0.8em; font-weight:bold;">DELETE</span>';
                            break;
                        case 'TRANSFER_STOCK':
                            actionBadge = '<span style="background:#3498db; color:white; padding:2px 8px; border-radius:4px; font-size:0.8em; font-weight:bold;">TRANSFER</span>';
                            break;
                        default:
                            actionBadge = l.action;
                    }
                    return `<tr style="border-bottom:1px solid #eee;">
                        <td style="padding:8px; font-size:0.85em; color:#666;">${dateTime}</td>
                        <td style="padding:8px;">${actionBadge}</td>
                        <td style="padding:8px; font-weight:bold; color:#2980b9;">${escapeHtml(l.user)}</td>
                        <td style="padding:8px; font-size:0.9em;">${escapeHtml(l.description)}</td>
                    </tr>`;
                }).join('');
                document.getElementById('stockLogTableBody').innerHTML = `
                    <thead>
                        <tr style="background:#f8f9fa; border-bottom:2px solid #ddd;">
                            <th style="padding:10px; text-align:left;">Date & Time</th>
                            <th style="padding:10px; text-align:left;">Action</th>
                            <th style="padding:10px; text-align:left;">User ID</th>
                            <th style="padding:10px; text-align:left;">Details</th>
                        </tr>
                    </thead>
                    <tbody>${rows || '<tr><td colspan="4" style="text-align:center; padding:20px; color:#999;">No stock activity logs found</td></tr>'}</tbody>
                `;
                document.getElementById('stockLogModal').style.display = 'flex';
            } else {
                alert('Error loading stock logs: ' + (d.error || 'Unknown error'));
            }
        })
        .catch(err => {
            console.error('Stock logs fetch error:', err);
            alert('Error loading stock logs');
        });
    }

    function viewStockMovements(stockId, partName) {
        apiRequest({ action: 'get_stock_movements', stock_id: stockId })
            .then(d => {
                if (d.success) {
                    document.getElementById('stockMovementsItemName').textContent = partName;
                    const movements = d.movements || [];
                    const typeLabels = {
                        'IN': { label: 'Date In', color: '#2ecc71', bg: '#e8f5e9' },
                        'OUT': { label: 'Date Out', color: '#e74c3c', bg: '#ffebee' },
                        'REFUND': { label: 'Refund (Circle Back)', color: '#3498db', bg: '#e3f2fd' },
                        'TRANSFER_IN': { label: 'Transfer In', color: '#8e44ad', bg: '#f3e5f5' },
                        'TRANSFER_OUT': { label: 'Transfer Out', color: '#e67e22', bg: '#fff3e0' },
                        'DELETE': { label: 'Deleted', color: '#95a5a6', bg: '#eceff1' }
                    };
                    const rows = movements.map(m => {
                        const dt = m.movement_date ? new Date(m.movement_date).toLocaleString('en-MY', { year:'numeric', month:'2-digit', day:'2-digit', hour:'2-digit', minute:'2-digit' }) : '-';
                        const info = typeLabels[m.movement_type] || { label: m.movement_type, color: '#999', bg: '#f5f5f5' };
                        return `<tr style="border-bottom:1px solid #eee;">
                            <td style="padding:8px; font-size:0.85em;">${dt}</td>
                            <td style="padding:8px;"><span style="background:${info.bg}; color:${info.color}; padding:2px 8px; border-radius:4px; font-size:0.8em; font-weight:bold;">${info.label}</span></td>
                            <td style="padding:8px; font-weight:bold;">${m.qty}</td>
                            <td style="padding:8px;"><span style="color:#2980b9;">${escapeHtml(m.branch || '-')}</span></td>
                            <td style="padding:8px; font-size:0.85em;">${escapeHtml(m.job_id || '-')}</td>
                            <td style="padding:8px; font-size:0.85em; color:#666;">${escapeHtml(m.staff || '-')}</td>
                            <td style="padding:8px; font-size:0.8em; color:#777;">${escapeHtml(m.reference || '')}</td>
                        </tr>`;
                    }).join('');
                    document.getElementById('stockMovementsTableBody').innerHTML = `
                        <thead><tr style="background:#f8f9fa; border-bottom:2px solid #ddd;">
                            <th style="padding:10px;">Date</th> <th style="padding:10px;">Type</th> <th style="padding:10px;">Qty</th> <th style="padding:10px;">Branch</th> <th style="padding:10px;">Job ID</th> <th style="padding:10px;">Staff</th> <th style="padding:10px;">Reference</th>
                        </tr></thead>
                        <tbody>${rows || '<tr><td colspan="7" style="text-align:center; padding:20px; color:#999;">No movements yet. Stock entries will appear here when added.</td></tr>'}</tbody>`;
                    document.getElementById('stockMovementsModal').style.display = 'flex';
                } else {
                    showToast('Error: ' + (d.error || 'Failed to load'), 'error');
                }
            })
            .catch(err => {
                console.error('Stock movements fetch error:', err);
                showToast('Error loading stock movements', 'error');
            });
    }
    
    function showCategoryBreakdown(category, sales, cost, profit) {
        document.getElementById('categoryBreakdownName').textContent = category;
        document.getElementById('categoryBreakdownSales').textContent = 'RM ' + parseFloat(sales).toFixed(2);
        document.getElementById('categoryBreakdownCost').textContent = 'RM ' + parseFloat(cost).toFixed(2);
        const profitEl = document.getElementById('categoryBreakdownProfit');
        profitEl.textContent = 'RM ' + parseFloat(profit).toFixed(2);
        profitEl.style.color = profit >= 0 ? '#2ecc71' : '#e74c3c';
        document.getElementById('categoryBreakdownModal').style.display = 'flex';
    }

    // --- BULK OPERATIONS FUNCTIONS ---
    function openBulkOperations() {
        const checked = getSelectedStockItems();
        if (checked.length === 0) {
            showToast('Please select items from stock list first', 'error');
            return;
        }
        document.getElementById('bulkOperationsModal').style.display = 'flex';
        document.getElementById('bulkOperationType').value = '';
        document.getElementById('bulkValue').value = '';
        document.getElementById('bulkValueContainer').style.display = 'none';
        document.getElementById('bulkCategoryContainer').style.display = 'none';
    }
    
    function toggleBulkFields() {
        const opType = document.getElementById('bulkOperationType').value;
        const valueContainer = document.getElementById('bulkValueContainer');
        const categoryContainer = document.getElementById('bulkCategoryContainer');
        const valueLabel = document.getElementById('bulkValueLabel');
        
        valueContainer.style.display = 'none';
        categoryContainer.style.display = 'none';
        
        if (opType === 'category') {
            categoryContainer.style.display = 'block';
        } else if (opType) {
            valueContainer.style.display = 'block';
            const labels = {
                'price': 'New Selling Price (RM)',
                'stock_gombak': 'Gombak Stock Qty',
                'stock_sr': 'Sri Rampai Stock Qty',
                'cost': 'Cost (RM)',
                'supplier': 'Supplier Name'
            };
            valueLabel.innerText = labels[opType] || 'Value';
            document.getElementById('bulkValue').type = (opType === 'stock_gombak' || opType === 'stock_sr') ? 'number' : 
                                                         (opType === 'price' || opType === 'cost') ? 'number' : 'text';
        }
    }
    
    function executeBulkOperation() {
        const checked = getSelectedStockItems();
        if (checked.length === 0) {
            showToast('Please select items first', 'error');
            return;
        }
        
        const opType = document.getElementById('bulkOperationType').value;
        if (!opType) {
            showToast('Please select an operation type', 'error');
            return;
        }
        
        let value = '';
        if (opType === 'category') {
            value = document.getElementById('bulkCategory').value;
        } else {
            value = document.getElementById('bulkValue').value;
            if (!value) {
                showToast('Please enter a value', 'error');
                return;
            }
        }
        
        if (!confirm(`Apply this operation to ${checked.length} selected item(s)?`)) return;
        
        apiRequest({
            action: 'bulk_update_stock',
            ids: checked,
            field: opType,
            value: value
        }).then(d => {
            if (d.success) {
                showToast(`Updated ${d.updated} items successfully`);
                document.getElementById('bulkOperationsModal').style.display = 'none';
                fetchStock();
            } else {
                alert('Error: ' + (d.error || 'Operation failed'));
            }
        });
    }
    
    function getSelectedStockItems() {
        const checkboxes = document.querySelectorAll('.stock-checkbox:checked');
        return Array.from(checkboxes).map(cb => parseInt(cb.dataset.stockId));
    }
    
    // --- BULK PRINT FUNCTIONS ---
    function openBulkPrint() {
        const checked = getSelectedStockItems();
        if (checked.length === 0) {
            showToast('Please select items from stock list first', 'error');
            return;
        }
        document.getElementById('bulkPrintModal').style.display = 'flex';
    }
    
    function executeBulkPrint() {
        const checked = getSelectedStockItems();
        if (checked.length === 0) {
            showToast('Please select items first', 'error');
            return;
        }
        
        const printType = document.getElementById('bulkPrintType').value;
        const branch = document.getElementById('bulkPrintBranch').value;
        
        // Get selected items data
        const items = [];
        checked.forEach(id => {
            let item = null;
            if(allStock['Part']) for(let g in allStock['Part']) { const f=allStock['Part'][g].find(x=>x.id==id); if(f) item=f; }
            if(!item && allStock['Retail']) for(let g in allStock['Retail']) { const f=allStock['Retail'][g].find(x=>x.id==id); if(f) item=f; }
            if (item) items.push(item);
        });
        
        if (items.length === 0) {
            showToast('No valid items found', 'error');
            return;
        }
        
        if (printType === 'qr') {
            // Print QR codes
            items.forEach(item => {
                if (branch === 'both' || branch === 'gombak') {
                    generateStockQR('Gombak|' + item.part_name, item.selling_price || 0);
                    setTimeout(() => window.print(), 100);
                }
                if (branch === 'both' || branch === 'srirampai') {
                    setTimeout(() => {
                        generateStockQR('Sri Rampai|' + item.part_name, item.selling_price || 0);
                        setTimeout(() => window.print(), 100);
                    }, 500);
                }
            });
            showToast(`Printing ${items.length} QR code(s)`);
        } else if (printType === 'barcode') {
            // Generate and print barcodes
            items.forEach((item, idx) => {
                setTimeout(() => {
                    generateBarcode(item.id, item.part_name, true);
                }, idx * 300);
            });
        } else {
            showToast('Label printing coming soon', 'error');
        }
        
        document.getElementById('bulkPrintModal').style.display = 'none';
    }
    
    // --- BULK IMPORT FUNCTIONS ---
    function openBulkImport() {
        document.getElementById('bulkImportModal').style.display = 'flex';
        document.getElementById('bulkImportData').value = '';
        document.getElementById('bulkImportProgress').style.display = 'none';
        document.getElementById('bulkImportResults').style.display = 'none';
        document.getElementById('bulkImportType').value = 'Part';
        // Focus on textarea
        setTimeout(() => {
            document.getElementById('bulkImportData').focus();
        }, 100);
    }
    
    function closeBulkImportModal() {
        document.getElementById('bulkImportModal').style.display = 'none';
        document.getElementById('bulkImportData').value = '';
        document.getElementById('bulkImportProgress').style.display = 'none';
        document.getElementById('bulkImportResults').style.display = 'none';
    }
    
    function parseBulkImportData(text) {
        const items = [];
        // Remove WhatsApp timestamp patterns like [17:16, 16/01/2026] Endie Boss F2F:
        text = text.replace(/\[\d{1,2}:\d{2},\s*\d{1,2}\/\d{1,2}\/\d{4}\][^\n]*\n?/gi, '');
        // Also handle cases where there might not be blank lines - split by pattern
        // Try splitting by blank lines first
        let blocks = text.split(/\n\s*\n/);
        
        // If no blank lines found, try to detect item boundaries by looking for item name patterns
        if (blocks.length === 1 && blocks[0].trim()) {
            // Try to split by lines that start with uppercase (likely item names)
            const lines = text.split('\n').map(l => l.trim()).filter(l => l);
            blocks = [];
            let currentBlock = [];
            
            for (let i = 0; i < lines.length; i++) {
                const line = lines[i];
                // If line looks like an item name (starts with uppercase, doesn't contain "Stock", "Cost", "Supplier")
                const isItemName = line.length > 5 && 
                                   !line.toLowerCase().includes('stock') && 
                                   !line.toLowerCase().includes('cost') && 
                                   !line.toLowerCase().includes('supplier') &&
                                   !line.toLowerCase().includes('category') &&
                                   !line.match(/^\d+$/) &&
                                   !line.match(/^rm\s*[\d.]+$/i);
                
                if (isItemName && currentBlock.length > 0) {
                    // Start a new block
                    blocks.push(currentBlock.join('\n'));
                    currentBlock = [line];
                } else {
                    currentBlock.push(line);
                }
            }
            
            if (currentBlock.length > 0) {
                blocks.push(currentBlock.join('\n'));
            }
        }
        
        for (let block of blocks) {
            if (!block.trim()) continue;
            
            const lines = block.split('\n').map(l => l.trim()).filter(l => l);
            if (lines.length === 0) continue;
            
            let item = {
                part_name: '',
                stock_gombak: 0,
                stock_sr: 0,
                cost: 0,
                supplier: 'Unknown',
                category: 'Other'
            };
            
            // First line is usually the item name
            item.part_name = lines[0].trim();
            
            // Track which fields we've found
            let foundStockSG = false;
            let foundStockSR = false;
            let foundCost = false;
            let foundSupplier = false;
            
            // Parse remaining lines
            for (let i = 1; i < lines.length; i++) {
                const line = lines[i].trim();
                if (!line) continue;
                
                const lineLower = line.toLowerCase();
                
                // Stock SG / Stock Gombak - more flexible matching
                if (lineLower.includes('stock') && (lineLower.includes('sg') || lineLower.includes('gombak'))) {
                    // Try multiple patterns
                    let match = line.match(/stock\s+(?:sg|gombak)\s*:?\s*(\d+)/i);
                    if (!match) match = line.match(/stock\s*sg\s*:?\s*(\d+)/i);
                    if (!match) match = line.match(/stock\s*gombak\s*:?\s*(\d+)/i);
                    if (match) {
                        item.stock_gombak = parseInt(match[1]) || 0;
                        foundStockSG = true;
                    }
                }
                // Stock SR / Stock Sri Rampai - more flexible matching
                else if (lineLower.includes('stock') && (lineLower.includes('sr') || lineLower.includes('sri'))) {
                    // Try multiple patterns
                    let match = line.match(/stock\s+(?:sr|sri\s*rampai|sri)\s*:?\s*(\d+)/i);
                    if (!match) match = line.match(/stock\s*sr\s*:?\s*(\d+)/i);
                    if (!match) match = line.match(/stock\s*sri\s*rampai\s*:?\s*(\d+)/i);
                    if (match) {
                        item.stock_sr = parseInt(match[1]) || 0;
                        foundStockSR = true;
                    }
                }
                // Cost
                else if (lineLower.includes('cost')) {
                    const match = line.match(/cost\s*:?\s*(?:rm\s*)?([\d.]+)/i);
                    if (match) {
                        item.cost = parseFloat(match[1]) || 0;
                        foundCost = true;
                    }
                }
                // Supplier with "Supplier :" prefix
                else if (lineLower.includes('supplier')) {
                    const match = line.match(/supplier\s*:?\s*(.+)/i);
                    if (match) {
                        item.supplier = match[1].trim() || 'Unknown';
                        foundSupplier = true;
                    }
                }
                // Category (optional)
                else if (lineLower.includes('category')) {
                    const match = line.match(/category\s*:?\s*(.+)/i);
                    if (match) item.category = match[1].trim();
                }
                // If line doesn't match any pattern and we haven't found supplier yet,
                // and it's a short line (likely supplier name), treat it as supplier
                else if (!foundSupplier && line.length > 0 && line.length < 50 && 
                         !line.match(/^\d+$/) && // Not just a number
                         !line.match(/^rm\s*[\d.]+$/i) && // Not a price
                         !line.match(/stock/i)) { // Not stock related
                    item.supplier = line.trim();
                    foundSupplier = true;
                }
            }
            
            // Only add item if it has a name and at least some data
            if (item.part_name && item.part_name.length > 0) {
                items.push(item);
            }
        }
        
        return items;
    }
    
    async function executeBulkImport() {
        const data = document.getElementById('bulkImportData').value.trim();
        const stockType = document.getElementById('bulkImportType').value;
        
        if (!data) {
            showToast('Please paste stock data', 'error');
            return;
        }
        
        // Parse the data
        const items = parseBulkImportData(data);
        
        if (items.length === 0) {
            showToast('No valid items found. Please check the format.', 'error');
            return;
        }
        
        // Show progress
        document.getElementById('bulkImportProgress').style.display = 'block';
        document.getElementById('bulkImportResults').style.display = 'none';
        document.getElementById('bulkImportProgressBar').style.width = '0%';
        document.getElementById('bulkImportProgressText').textContent = '0%';
        document.getElementById('bulkImportStatus').textContent = `Processing ${items.length} items...`;
        
        const results = {
            success: [],
            failed: [],
            merged: []
        };
        
        // Process each item
        for (let i = 0; i < items.length; i++) {
            const item = items[i];
            
            // Update progress
            const progress = Math.round(((i + 1) / items.length) * 100);
            document.getElementById('bulkImportProgressBar').style.width = progress + '%';
            document.getElementById('bulkImportProgressText').textContent = progress + '%';
            document.getElementById('bulkImportStatus').textContent = `Processing ${i + 1} of ${items.length}: ${item.part_name.substring(0, 40)}...`;
            
            try {
                // Auto-detect category from name if not set
                if (item.category === 'Other' && stockType === 'Part') {
                    const nameLower = item.part_name.toLowerCase();
                    if (nameLower.includes('battery')) item.category = 'Battery';
                    else if (nameLower.includes('lcd') || nameLower.includes('screen')) item.category = 'LCD';
                    else if (nameLower.includes('housing')) item.category = 'Housing';
                    else if (nameLower.includes('back glass') || nameLower.includes('backglass')) item.category = 'Back Glass';
                    else if (nameLower.includes('charging port') || nameLower.includes('chargingport')) item.category = 'Charging Port';
                    else if (nameLower.includes('camera')) item.category = 'Camera';
                    else if (nameLower.includes('face id') || nameLower.includes('faceid')) item.category = 'Face ID';
                    else if (nameLower.includes('motherboard')) item.category = 'Motherboard';
                    else if (nameLower.includes('speaker')) item.category = 'Speaker';
                    else if (nameLower.includes('unlock') || nameLower.includes('flash')) item.category = 'Unlock/Flash';
                } else if (item.category === 'Other' && stockType === 'Retail') {
                    const nameLower = item.part_name.toLowerCase();
                    if (nameLower.includes('cable')) item.category = 'Cable';
                    else if (nameLower.includes('charger')) item.category = 'Charger';
                    else if (nameLower.includes('tempered glass') || nameLower.includes('glass')) item.category = 'Tempered Glass';
                    else if (nameLower.includes('earphone') || nameLower.includes('earbud')) item.category = 'Earphone';
                    else if (nameLower.includes('car holder') || nameLower.includes('carholder')) item.category = 'Car holder';
                }
                
                // Ensure numeric values are properly set
                const requestData = {
                    action: 'insert_stock_item',
                    type: stockType,
                    part_name: item.part_name.trim(),
                    category: item.category || 'Other',
                    cost: parseFloat(item.cost) || 0,
                    supplier: (item.supplier && item.supplier !== 'Unknown') ? item.supplier.trim() : 'Unknown',
                    stock_gombak: parseInt(item.stock_gombak) || 0,
                    stock_sr: parseInt(item.stock_sr) || 0,
                    selling_price: 0 // Default to 0, can be updated later
                };
                
                const response = await apiRequest(requestData);
                
                if (response.success) {
                    // Check if it was merged (has combined_stock in response)
                    if (response.combined_stock || (response.message && (response.message.includes('combined') || response.message.includes('Merged') || response.message.includes('Stock combined')))) {
                        const combinedStock = response.combined_stock || { 
                            gombak: requestData.stock_gombak, 
                            sr: requestData.stock_sr 
                        };
                        results.merged.push({
                            name: item.part_name,
                            message: 'Merged with existing item',
                            stock: combinedStock,
                            addedStock: {
                                gombak: requestData.stock_gombak,
                                sr: requestData.stock_sr
                            },
                            cost: response.cost,
                            supplier: response.supplier
                        });
                    } else {
                        results.success.push({
                            name: item.part_name,
                            message: 'Added successfully',
                            stock: {
                                gombak: requestData.stock_gombak,
                                sr: requestData.stock_sr
                            }
                        });
                    }
                } else {
                    results.failed.push({
                        name: item.part_name,
                        error: response.error || 'Unknown error'
                    });
                }
            } catch (error) {
                console.error('Error processing item:', item.part_name, error);
                results.failed.push({
                    name: item.part_name,
                    error: error.message || 'Network error'
                });
            }
            
            // Small delay to prevent overwhelming the server
            await new Promise(resolve => setTimeout(resolve, 100));
        }
        
        // Show results
        document.getElementById('bulkImportProgressBar').style.width = '100%';
        document.getElementById('bulkImportProgressText').textContent = '100%';
        document.getElementById('bulkImportStatus').textContent = `Completed! ${results.success.length + results.merged.length} succeeded, ${results.failed.length} failed.`;
        
        // Display results
        let resultsHtml = '';
        
        if (results.success.length > 0) {
            resultsHtml += `<div style="margin-bottom:15px;"><strong style="color:#27ae60;">✅ Added (${results.success.length}):</strong><ul style="margin:5px 0; padding-left:20px; font-size:0.9em;">`;
            results.success.forEach(r => {
                const g = r.stock?.gombak || 0;
                const s = r.stock?.sr || 0;
                resultsHtml += `<li>${escapeHtml(r.name)} - Stock: Gombak=${g}, SR=${s}</li>`;
            });
            resultsHtml += '</ul></div>';
        }
        
        if (results.merged.length > 0) {
            resultsHtml += `<div style="margin-bottom:15px;"><strong style="color:#f39c12;">🔄 Merged (${results.merged.length}):</strong><ul style="margin:5px 0; padding-left:20px; font-size:0.9em;">`;
            results.merged.forEach(r => {
                const g = r.stock?.gombak || 0;
                const s = r.stock?.sr || 0;
                const addedG = r.addedStock?.gombak || 0;
                const addedS = r.addedStock?.sr || 0;
                let costText = '';
                if (r.cost) {
                    costText = ` | Cost: RM${r.cost}`;
                }
                if (r.supplier && r.supplier !== 'Unknown') {
                    costText += ` | Supplier: ${escapeHtml(r.supplier)}`;
                }
                resultsHtml += `<li>${escapeHtml(r.name)} - Added: Gombak=${addedG}, SR=${addedS} | Total Stock: Gombak=${g}, SR=${s}${costText}</li>`;
            });
            resultsHtml += '</ul></div>';
        }
        
        if (results.failed.length > 0) {
            resultsHtml += `<div style="margin-bottom:15px;"><strong style="color:#e74c3c;">❌ Failed (${results.failed.length}):</strong><ul style="margin:5px 0; padding-left:20px; font-size:0.9em;">`;
            results.failed.forEach(r => {
                resultsHtml += `<li>${escapeHtml(r.name)} - ${escapeHtml(r.error)}</li>`;
            });
            resultsHtml += '</ul></div>';
        }
        
        document.getElementById('bulkImportResultsContent').innerHTML = resultsHtml;
        document.getElementById('bulkImportResults').style.display = 'block';
        
        if (results.success.length > 0 || results.merged.length > 0) {
            setTimeout(() => {
                fetchStock();
            }, 500);
            
            const totalProcessed = results.success.length + results.merged.length;
            const totalFailed = results.failed.length;
            if (totalFailed > 0) {
                showToast(`Bulk import completed! ${totalProcessed} items processed, ${totalFailed} failed. Check results below.`, 'warning');
            } else {
                showToast(`Bulk import completed! ${totalProcessed} items processed successfully. Refreshing stock list...`, 'success');
            }
        } else if (results.failed.length > 0) {
            showToast(`Bulk import failed! All ${results.failed.length} items failed. Check results below.`, 'error');
        }
        
    }
    
    // --- BARCODE GENERATION ---
    function generateBarcode(itemId, itemName, autoPrint = false) {
        apiRequest({
            action: 'generate_barcode',
            id: itemId
        }).then(d => {
            if (d.success) {
                // Create barcode display - NO price/cost on barcode (only on stock list)
                const overlay = document.getElementById('qrOverlay');
                const canvas = document.getElementById('qrCanvas');
                const titleEl = document.getElementById('qrTitle');
                const priceEl = document.getElementById('qrPrice');
                
                const item = d.item || {};
                titleEl.innerText = item.part_name || itemName || '';
                priceEl.style.display = 'none';  // Never show cost/price on barcode print
                
                // Clear canvas first
                const ctx = canvas.getContext('2d');
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                canvas.width = 300;
                canvas.height = 120;
                
                const barcodeNum = d.barcode_number || d.barcode || '';
                // Use JsBarcode library
                if (typeof JsBarcode !== 'undefined') {
                    try {
                        JsBarcode(canvas, barcodeNum, {
                            format: d.format || 'CODE128',
                            width: 2,
                            height: 80,
                            displayValue: true,
                            fontSize: 16,
                            margin: 10
                        });
                    } catch (e) {
                        console.error('Barcode generation error:', e);
                        // Fallback: show barcode number
                        ctx.fillStyle = '#000';
                        ctx.font = '16px monospace';
                        ctx.fillText('Barcode: ' + barcodeNum, 10, 50);
                    }
                } else {
                    // Fallback: show barcode number
                    ctx.fillStyle = '#000';
                    ctx.font = '16px monospace';
                    ctx.fillText('Barcode: ' + barcodeNum, 10, 50);
                }
                
                overlay.style.display = 'flex';
                if (autoPrint) {
                    setTimeout(() => window.print(), 500);
                }
            }
        });
    }
    
    // --- THERMAL PRINTER SUPPORT ---
    function printThermalReceipt(jobId) {
        apiRequest({
            action: 'print_thermal_receipt',
            job_id: jobId
        }).then(d => {
            if (d.success) {
                // Send to thermal printer via WebUSB or print dialog
                // For now, offer download or copy to clipboard
                if (confirm('Thermal receipt ready. Choose method:\n\nOK = Copy ESC/POS commands to clipboard\nCancel = Download as file')) {
                    navigator.clipboard.writeText(d.raw).then(() => {
                        showToast('ESC/POS commands copied to clipboard. Paste into printer software.');
                    });
                } else {
                    const blob = new Blob([d.raw], { type: 'text/plain' });
                    const url = URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = 'receipt_' + jobId + '.txt';
                    a.click();
                    URL.revokeObjectURL(url);
                }
            } else {
                alert('Error: ' + (d.error || 'Print failed'));
            }
        });
    }
    
    // --- ENHANCED BARCODE SCANNING ---
    // Extend existing scanning to support barcodes (EAN-13, UPC, Code 128)
    function handleBarcodeScan(barcode) {
        const cleanBarcode = barcode.trim();
        // Try to find item by barcode in stock (if barcode field exists in future)
        // For now, treat as search term - will be handled by addRetailItem matching logic
        switchMainTab('retail');
        addRetailItem(cleanBarcode);
    }

    // --- DELETE STOCK BY LOCATION FUNCTIONS ---
    function openDeleteStockModal(id, location, itemName, currentStock) {
        document.getElementById('deleteStockId').value = id;
        document.getElementById('deleteStockLocation').value = location;
        document.getElementById('deleteStockItemName').innerText = itemName;
        const locationName = location === 'SG' ? 'Gombak (SG)' : 'Sri Rampai (SR)';
        document.getElementById('deleteStockLocationDisplay').innerText = locationName;
        document.getElementById('deleteStockLocationDisplay').style.color = location === 'SG' ? '#2980b9' : '#8e44ad';
        document.getElementById('deleteStockCurrentQty').innerText = currentStock;
        document.getElementById('deleteStockOption').value = 'all';
        document.getElementById('deleteStockQty').value = '1';
        document.getElementById('deleteStockQtyContainer').style.display = 'none';
        document.getElementById('deleteStockModal').style.display = 'flex';
    }
    
    function toggleDeleteStockQty() {
        const option = document.getElementById('deleteStockOption').value;
        const qtyContainer = document.getElementById('deleteStockQtyContainer');
        if (option === 'qty') {
            qtyContainer.style.display = 'block';
            document.getElementById('deleteStockQty').focus();
        } else {
            qtyContainer.style.display = 'none';
        }
    }
    
    function closeDeleteStockModal() {
        document.getElementById('deleteStockModal').style.display = 'none';
        document.getElementById('deleteStockId').value = '';
        document.getElementById('deleteStockLocation').value = '';
        document.getElementById('deleteStockQty').value = '1';
    }
    
    function executeDeleteStock() {
        const id = document.getElementById('deleteStockId').value;
        const location = document.getElementById('deleteStockLocation').value;
        const option = document.getElementById('deleteStockOption').value;
        const itemName = document.getElementById('deleteStockItemName').innerText;
        const currentStock = parseInt(document.getElementById('deleteStockCurrentQty').innerText);
        
        if (!id || !location) {
            alert('Error: Missing parameters');
            return;
        }
        
        let qty = null; // null means delete all
        if (option === 'qty') {
            qty = parseInt(document.getElementById('deleteStockQty').value);
            if (!qty || qty <= 0) {
                alert('Please enter a valid quantity greater than 0');
                return;
            }
            if (qty > currentStock) {
                alert(`Cannot delete more than available stock (${currentStock})`);
                return;
            }
        }
        
        const confirmMsg = option === 'all' 
            ? `⚠️ DELETE ALL STOCK?\n\nItem: ${itemName}\nLocation: ${location === 'SG' ? 'Gombak (SG)' : 'Sri Rampai (SR)'}\nQuantity: ${currentStock}\n\nThis cannot be undone!`
            : `⚠️ DELETE STOCK?\n\nItem: ${itemName}\nLocation: ${location === 'SG' ? 'Gombak (SG)' : 'Sri Rampai (SR)'}\nQuantity to delete: ${qty}\nRemaining: ${currentStock - qty}\n\nConfirm?`;
        
        if (!confirm(confirmMsg)) {
            return;
        }
        
        const data = {
            action: 'delete_stock_by_location',
            id: id,
            location: location,
            qty: qty
        };
        
        apiRequest(data).then(res => {
            if (res.success) {
                showToast(res.message || 'Stock deleted successfully');
                document.getElementById('deleteStockModal').style.display = 'none';
                fetchStock();
            } else {
                alert('Error: ' + (res.error || 'Delete failed'));
            }
        });
    }

    // --- CREDIT NOTE FUNCTIONS ---
    function openCreditNoteModal(stockId, itemName, stockGombak, stockSr, supplier) {
        if (!IS_MASTER) {
            showToast('Only master users can create credit notes', 'error');
            return;
        }
        document.getElementById('cnStockId').value = stockId;
        document.getElementById('cnItemName').innerText = itemName;
        document.getElementById('cnSupplier').value = supplier || 'Unknown';
        document.getElementById('cnBranch').value = 'Gombak';
        document.getElementById('cnQuantity').value = 1;
        document.getElementById('cnDate').value = new Date().toISOString().split('T')[0];
        document.getElementById('cnReason').value = '';
        // Set initial stock display
        document.getElementById('cnCurrentStock').innerText = stockGombak;
        document.getElementById('cnQuantity').max = stockGombak;
        updateCNMaxQty();
        document.getElementById('creditNoteModal').style.display = 'flex';
    }

    function updateCNMaxQty() {
        const branch = document.getElementById('cnBranch').value;
        const stockId = parseInt(document.getElementById('cnStockId').value);
        let stock = null;
        
        // Search through all categories in Part
        for (let cat in allStock.Part) {
            stock = allStock.Part[cat].find(s => s.id == stockId);
            if (stock) break;
        }
        
        // If not found, search in Retail
        if (!stock) {
            for (let cat in allStock.Retail) {
                stock = allStock.Retail[cat].find(s => s.id == stockId);
                if (stock) break;
            }
        }
        
        if (stock) {
            const currentStock = branch === 'Gombak' ? stock.stock_gombak : stock.stock_sr;
            document.getElementById('cnCurrentStock').innerText = currentStock;
            document.getElementById('cnQuantity').max = currentStock;
            if (parseInt(document.getElementById('cnQuantity').value) > currentStock) {
                document.getElementById('cnQuantity').value = currentStock;
            }
        }
    }

    function validateCNQty() {
        const qty = parseInt(document.getElementById('cnQuantity').value);
        const max = parseInt(document.getElementById('cnCurrentStock').innerText);
        if (qty > max) {
            document.getElementById('cnQuantity').value = max;
            showToast(`Maximum quantity is ${max}`, 'error');
        }
        if (qty < 1) {
            document.getElementById('cnQuantity').value = 1;
        }
    }

    function closeCreditNoteModal() {
        document.getElementById('creditNoteModal').style.display = 'none';
    }

    function submitCreditNote() {
        if (!IS_MASTER) {
            showToast('Only master users can create credit notes', 'error');
            return;
        }
        
        const stockId = document.getElementById('cnStockId').value;
        const branch = document.getElementById('cnBranch').value;
        const quantity = parseInt(document.getElementById('cnQuantity').value);
        const date = document.getElementById('cnDate').value;
        const reason = document.getElementById('cnReason').value.trim();
        const supplier = document.getElementById('cnSupplier').value;
        const itemName = document.getElementById('cnItemName').innerText;
        
        if (!stockId || !quantity || !date) {
            showToast('Please fill in all required fields', 'error');
            return;
        }
        
        if (quantity < 1) {
            showToast('Quantity must be at least 1', 'error');
            return;
        }
        
        if (!reason) {
            showToast('Please enter a reason for the return', 'error');
            return;
        }
        
        const confirmMsg = `⚠️ SUBMIT CREDIT NOTE?\n\nItem: ${itemName}\nBranch: ${branch}\nQuantity: ${quantity}\nSupplier: ${supplier}\nDate: ${date}\nReason: ${reason}\n\nThis will deduct stock from inventory.`;
        
        if (!confirm(confirmMsg)) {
            return;
        }
        
        apiRequest({
            action: 'create_credit_note',
            stock_id: stockId,
            branch: branch,
            quantity: quantity,
            date: date,
            reason: reason,
            supplier: supplier
        }).then(res => {
            if (res.success) {
                showToast('✅ Credit note created successfully', 'success');
                closeCreditNoteModal();
                fetchStock();
                if (IS_MASTER) {
                    fetchCreditNoteHistory();
                }
            } else {
                showToast('Error: ' + (res.error || 'Failed to create credit note'), 'error');
            }
        });
    }

    function fetchCreditNoteHistory() {
        if (!IS_MASTER) return;
        
        apiRequest({ action: 'get_credit_note_history' }).then(res => {
            if (res.success) {
                const tbody = document.getElementById('creditNoteHistoryBody');
                if (res.history && res.history.length > 0) {
                    tbody.innerHTML = res.history.map(cn => `
                        <tr style="border-bottom:1px solid #eee;">
                            <td style="padding:10px; font-size:0.85rem;">${escapeHtml(cn.date)}</td>
                            <td style="padding:10px; font-size:0.85rem; font-weight:bold;">${escapeHtml(cn.item_name)}</td>
                            <td style="padding:10px; text-align:center; font-size:0.85rem;">
                                <span style="padding:4px 8px; border-radius:4px; background:${cn.branch === 'Gombak' ? '#e3f2fd' : '#f3e5f5'}; color:${cn.branch === 'Gombak' ? '#1565c0' : '#7b1fa2'}; font-weight:bold;">${escapeHtml(cn.branch)}</span>
                            </td>
                            <td style="padding:10px; text-align:center; font-size:0.85rem; font-weight:bold; color:#e67e22;">${cn.quantity}</td>
                            <td style="padding:10px; font-size:0.85rem; color:#555;">${escapeHtml(cn.supplier || 'Unknown')}</td>
                            <td style="padding:10px; font-size:0.85rem; color:#666; max-width:300px; word-wrap:break-word;">${escapeHtml(cn.reason)}</td>
                            <td style="padding:10px; font-size:0.85rem; color:#2980b9; font-weight:bold;">${escapeHtml(cn.created_by)}</td>
                        </tr>
                    `).join('');
                } else {
                    tbody.innerHTML = '<tr><td colspan="7" style="text-align:center; padding:20px; color:#999;">No credit note returns found</td></tr>';
                }
            } else {
                showToast('Error loading credit note history', 'error');
            }
        });
    }

    // --- MISSING EXPENSE FUNCTIONS ---

    function updateExpAmt(el) {
        const val = el.value;
        const input = document.getElementById('exp_amt');
        if (val === 'custom') {
            input.value = '';
            input.focus();
        } else {
            input.value = parseFloat(val).toFixed(2);
        }
    }

    function submitExpense() {
        const desc = document.getElementById('exp_desc').value;
        const amt = document.getElementById('exp_amt').value;
        // Use the report end date (usually today) for the expense
        const date = document.getElementById('reportEnd').value || new Date().toISOString().split('T')[0];
        const branch = document.getElementById('reportBranch').value;

        if (!desc || !amt) return showToast("Please enter description and amount", "error");
        if (branch === 'all') return showToast("Please select a specific branch (Gombak/Sri Rampai)", "error");

        const data = {
            action: 'add_expense',
            branch: branch,
            date: date,
            description: desc,
            amount: amt
        };

        apiRequest(data).then(d => {
            if (d.success) {
                showToast("Expense Added");
                document.getElementById('exp_desc').value = '';
                // Refresh the report immediately to show the new item
                generateReport();
            } else {
                alert(d.error || "Failed to add expense");
            }
        });
    }

    function deleteExpense(id) {
        if (confirm("⚠️ Delete this expense record?")) {
            apiRequest({ action: 'delete_expense', id: id }).then(d => {
                if (d.success) {
                    showToast("Expense Deleted");
                    generateReport();
                } else {
                    alert(d.error);
                }
            });
        }
    }

    // --- PDF DOWNLOAD (IMPROVED) ---
    async function downloadPDF() {
        showToast("📄 Generating PDF...", "success");
        
        // Use the original element, don't clone (cloning breaks canvas charts)
        const pdfElement = document.getElementById('reportDisplay');
        
        // Store original display state
        const originalDisplay = pdfElement.style.display;
        pdfElement.style.display = 'block';
        
        // Temporarily hide interactive elements in original element
        const hiddenElements = [];
        pdfElement.querySelectorAll('input, button, select').forEach(el => {
            if (el.style.display !== 'none') {
                hiddenElements.push(el);
                el.style.visibility = 'hidden';
            }
        });
        
        // Hide expense form section for PDF
        const expenseCard = pdfElement.querySelector('.card[style*="border-left: 5px solid #c0392b"]');
        let formRow = null;
        if (expenseCard) {
            formRow = expenseCard.querySelector('.form-row[style*="align-items: flex-end"]');
            if (formRow && formRow.style.display !== 'none') {
                formRow.style.display = 'none';
            }
        }
        
        // Convert canvas charts to images before PDF generation
        const canvasElements = pdfElement.querySelectorAll('canvas');
        const imageReplacements = [];
        
        for (const canvas of canvasElements) {
            try {
                const img = document.createElement('img');
                img.src = canvas.toDataURL('image/png');
                img.style.maxWidth = '100%';
                img.style.height = 'auto';
                img.style.display = 'block';
                
                const parent = canvas.parentElement;
                if (parent) {
                    parent.insertBefore(img, canvas);
                    imageReplacements.push({ img, canvas, parent });
                    canvas.style.display = 'none';
                }
            } catch (e) {
                console.warn('Failed to convert canvas to image:', e);
            }
        }
        
        // Wait a bit for images to load
        await new Promise(resolve => setTimeout(resolve, 300));
        
        // Add professional print styles with A4 scaling
        const printStyle = document.createElement('style');
        printStyle.id = 'pdfPrintStyles';
        printStyle.textContent = `
            #reportDisplay {
                background: #ffffff !important;
                color: #000000 !important;
                font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
                padding: 15px !important;
                width: 100% !important;
                max-width: 100% !important;
                box-sizing: border-box !important;
                transform-origin: top left !important;
            }
            #reportDisplay * {
                box-sizing: border-box !important;
            }
            #reportHeader {
                page-break-after: avoid !important;
                margin-bottom: 20px !important;
                padding: 15px 0 10px 0 !important;
            }
            #reportHeader h1 {
                font-size: 28pt !important;
                margin-bottom: 3px !important;
                line-height: 1.1 !important;
            }
            #reportHeader h2 {
                font-size: 14pt !important;
                margin-bottom: 8px !important;
                line-height: 1.2 !important;
            }
            #reportDateRange {
                font-size: 10pt !important;
                margin-top: 5px !important;
            }
            #reportDisplay .summary-stats {
                display: grid !important;
                grid-template-columns: repeat(4, 1fr) !important;
                gap: 10px !important;
                margin-bottom: 20px !important;
                page-break-inside: avoid !important;
            }
            #reportDisplay .stat-card {
                padding: 12px 10px !important;
                border: 2px solid #e0e0e0 !important;
                border-radius: 6px !important;
                text-align: center !important;
                background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%) !important;
                box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;
            }
            #reportDisplay .stat-card h2 {
                font-size: 20pt !important;
                margin: 5px 0 !important;
                font-weight: bold !important;
                line-height: 1.2 !important;
            }
            #reportDisplay .stat-card small {
                font-size: 8pt !important;
                color: #666 !important;
                text-transform: uppercase !important;
                letter-spacing: 0.5px !important;
            }
            #reportDisplay .card {
                margin-bottom: 20px !important;
                padding: 15px !important;
                border: 1px solid #dee2e6 !important;
                border-radius: 6px !important;
                background: #ffffff !important;
                page-break-inside: avoid !important;
                break-inside: avoid !important;
            }
            #reportDisplay .section-title {
                font-size: 12pt !important;
                font-weight: bold !important;
                margin-bottom: 10px !important;
                color: #2c3e50 !important;
                padding-bottom: 8px !important;
                border-bottom: 2px solid #3498db !important;
                page-break-after: avoid !important;
            }
            #reportDisplay .table-container {
                overflow-x: visible !important;
                margin-top: 10px !important;
                page-break-inside: avoid !important;
                break-inside: avoid !important;
                orphans: 3 !important;
                widows: 3 !important;
            }
            #reportDisplay table {
                width: 100% !important;
                border-collapse: collapse !important;
                font-size: 8pt !important;
                margin-top: 8px !important;
                page-break-before: auto !important;
                page-break-after: auto !important;
                page-break-inside: avoid !important;
                break-inside: avoid !important;
                -webkit-page-break-inside: avoid !important;
                table-layout: fixed !important;
            }
            #reportDisplay table thead {
                background: linear-gradient(135deg, #3498db 0%, #2980b9 100%) !important;
                color: #ffffff !important;
                display: table-header-group !important;
                -webkit-page-break-inside: avoid !important;
                page-break-inside: avoid !important;
            }
            #reportDisplay table thead tr {
                -webkit-page-break-inside: avoid !important;
                page-break-inside: avoid !important;
                page-break-after: avoid !important;
                break-inside: avoid !important;
                break-after: avoid !important;
            }
            #reportDisplay table tbody {
                display: table-row-group !important;
            }
            #reportDisplay table tfoot {
                display: table-footer-group !important;
            }
            #reportDisplay table tfoot tr {
                -webkit-page-break-inside: avoid !important;
                page-break-inside: avoid !important;
                page-break-before: avoid !important;
                break-inside: avoid !important;
                break-before: avoid !important;
            }
            #reportDisplay table th {
                padding: 8px 5px !important;
                text-align: left !important;
                border: 1px solid #2980b9 !important;
                font-weight: bold !important;
                font-size: 8.5pt !important;
                text-transform: uppercase !important;
                letter-spacing: 0.3px !important;
                overflow: hidden !important;
                text-overflow: ellipsis !important;
                white-space: nowrap !important;
            }
            #reportDisplay table th[style*="text-align:right"],
            #reportDisplay table th[style*="text-align: center"] {
                text-align: right !important;
            }
            #reportDisplay table th[style*="center"] {
                text-align: center !important;
            }
            #reportDisplay table td {
                padding: 6px 4px !important;
                border: 1px solid #dee2e6 !important;
                word-wrap: break-word !important;
                overflow: hidden !important;
                text-overflow: ellipsis !important;
                vertical-align: middle !important;
                page-break-inside: avoid !important;
                break-inside: avoid !important;
                font-size: 8pt !important;
            }
            #reportDisplay table tbody tr {
                border-bottom: 1px solid #eee !important;
                -webkit-page-break-inside: avoid !important;
                page-break-inside: avoid !important;
                break-inside: avoid !important;
                display: table-row !important;
            }
            #reportDisplay table tbody tr:last-child {
                border-bottom: none !important;
            }
            #reportDisplay table tbody tr:hover {
                background: #f8f9fa !important;
            }
            #reportDisplay table tfoot {
                background: #f8f9fa !important;
                border-top: 3px solid #dee2e6 !important;
            }
            #reportDisplay .charts-row {
                display: grid !important;
                grid-template-columns: 1fr 1fr !important;
                gap: 20px !important;
                margin-bottom: 25px !important;
                page-break-inside: avoid !important;
            }
            #reportDisplay .chart-box {
                border: 1px solid #dee2e6 !important;
                padding: 15px !important;
                border-radius: 8px !important;
                background: #ffffff !important;
            }
            #reportDisplay .chart-wrapper {
                position: relative !important;
                height: 250px !important;
            }
            #reportDisplay img {
                max-width: 100% !important;
                height: auto !important;
                display: block !important;
            }
        `;
        document.head.appendChild(printStyle);
        
        try {
            const opt = {
                margin: [8, 8, 8, 8],
                filename: 'Fon2Fix_Report_' + document.getElementById('reportStart').value + '_to_' + document.getElementById('reportEnd').value + '.pdf',
                image: { type: 'jpeg', quality: 0.98 },
                html2canvas: { 
                    scale: 1.5,
                    useCORS: true,
                    logging: false,
                    backgroundColor: '#ffffff',
                    removeContainer: false,
                    letterRendering: true
                },
                jsPDF: { 
                    unit: 'mm', 
                    format: 'a4', 
                    orientation: 'portrait',
                    compress: true
                },
                pagebreak: { 
                    mode: ['avoid-all', 'css', 'legacy'],
                    before: '.page-break-before',
                    after: '.page-break-after',
                    avoid: ['table', '.table-container', '.card', 'tr', '.stat-card', '.chart-box']
                }
            };
            
            await html2pdf().set(opt).from(pdfElement).save();
            showToast("✅ PDF saved successfully!", "success");
        } catch (error) {
            console.error('PDF generation error:', error);
            showToast("❌ PDF generation failed. Please try again.", "error");
        } finally {
            // Restore canvas elements
            imageReplacements.forEach(({ img, canvas, parent }) => {
                canvas.style.display = '';
                if (img.parentNode) {
                    img.parentNode.removeChild(img);
                }
            });
            
            // Restore hidden elements
            hiddenElements.forEach(el => {
                el.style.visibility = '';
            });
            
            // Restore form row
            if (formRow) {
                formRow.style.display = '';
            }
            
            // Restore original display state
            pdfElement.style.display = originalDisplay;
            
            // Remove print styles
            const styleEl = document.getElementById('pdfPrintStyles');
            if (styleEl) styleEl.remove();
        }
    }

    // --- WHATSAPP SHARING (IMPROVED) ---
    async function shareWhatsApp() {
        showToast("📄 Generating PDF...", "success");
        
        // Use the original element (same approach as downloadPDF)
        const pdfElement = document.getElementById('reportDisplay');
        
        // Store original display state
        const originalDisplay = pdfElement.style.display;
        pdfElement.style.display = 'block';
        
        // Temporarily hide interactive elements
        const hiddenElements = [];
        pdfElement.querySelectorAll('input, button, select').forEach(el => {
            if (el.style.display !== 'none') {
                hiddenElements.push(el);
                el.style.visibility = 'hidden';
            }
        });
        
        // Hide expense form
        const expenseCard = pdfElement.querySelector('.card[style*="border-left: 5px solid #c0392b"]');
        let formRow = null;
        if (expenseCard) {
            formRow = expenseCard.querySelector('.form-row[style*="align-items: flex-end"]');
            if (formRow && formRow.style.display !== 'none') {
                formRow.style.display = 'none';
            }
        }
        
        // Convert canvas charts to images before PDF generation
        const canvasElements = pdfElement.querySelectorAll('canvas');
        const imageReplacements = [];
        
        for (const canvas of canvasElements) {
            try {
                const img = document.createElement('img');
                img.src = canvas.toDataURL('image/png');
                img.style.maxWidth = '100%';
                img.style.height = 'auto';
                img.style.display = 'block';
                
                const parent = canvas.parentElement;
                if (parent) {
                    parent.insertBefore(img, canvas);
                    imageReplacements.push({ img, canvas, parent });
                    canvas.style.display = 'none';
                }
            } catch (e) {
                console.warn('Failed to convert canvas to image:', e);
            }
        }
        
        // Wait a bit for images to load
        await new Promise(resolve => setTimeout(resolve, 300));
        
        // Apply PDF styles
        const printStyle = document.createElement('style');
        printStyle.id = 'pdfPrintStylesWhatsApp';
        printStyle.textContent = `
            #reportDisplay { background: #ffffff !important; color: #000000 !important; }
            #reportDisplay .summary-stats { display: grid !important; grid-template-columns: repeat(4, 1fr) !important; gap: 10px !important; }
            #reportDisplay .stat-card { padding: 15px !important; border: 1px solid #ddd !important; border-radius: 5px !important; text-align: center !important; }
            #reportDisplay table { border-collapse: collapse !important; }
            #reportDisplay table th, #reportDisplay table td { border: 1px solid #ddd !important; padding: 6px !important; }
        `;
        document.head.appendChild(printStyle);
        
        try {
            const opt = {
                margin: [10, 10, 10, 10],
                image: { type: 'jpeg', quality: 0.95 },
                html2canvas: { scale: 2, useCORS: true, backgroundColor: '#ffffff', logging: false },
                jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait', compress: true }
            };
            
            const pdfBlob = await html2pdf().set(opt).from(pdfElement).output('blob');
            const formData = new FormData();
            formData.append('action', 'upload_report_pdf');
            formData.append('pdf', pdfBlob, 'report.pdf');

            const response = await fetch('api.php', { method: 'POST', body: formData });
            const data = await response.json();

            if(data.success) {
                const url = data.url;
                const choice = prompt("Enter 1 for +60107732919\nEnter 2 for +601129190338", "1");
                
                let phone = '';
                if(choice === '1') phone = '60107732919';
                else if(choice === '2') phone = '601129190338';
                else return; // Cancelled

                // Get today's date and current time
                const today = new Date();
                const reportDate = document.getElementById('reportEnd').value || today.toISOString().split('T')[0];
                const dateStr = new Date(reportDate).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
                const timeStr = today.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true });
                const dateTimeStr = today.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) + ', ' + timeStr;

                const msg = `Report for ${dateStr}

Generated by ${MY_USERNAME} (ID: ${MY_ID}) on ${dateTimeStr}

${url}`;
                window.open(`https://wa.me/${phone}?text=${encodeURIComponent(msg)}`, '_blank');
                showToast("✅ PDF shared via WhatsApp!", "success");
            } else {
                alert("Upload Failed: " + data.error);
            }
        } catch(e) {
            console.error('WhatsApp sharing error:', e);
            alert("Error sending report: " + e);
        } finally {
            // Restore canvas elements
            imageReplacements.forEach(({ img, canvas, parent }) => {
                canvas.style.display = '';
                if (img.parentNode) {
                    img.parentNode.removeChild(img);
                }
            });
            
            // Restore hidden elements
            hiddenElements.forEach(el => {
                el.style.visibility = '';
            });
            
            // Restore form row
            if (formRow) {
                formRow.style.display = '';
            }
            
            // Restore original display state
            pdfElement.style.display = originalDisplay;
            
            // Remove print styles
            const styleEl = document.getElementById('pdfPrintStylesWhatsApp');
            if (styleEl) styleEl.remove();
        }
    }
    
    // --- CHART & LOGS ---
    let chartInstances = {};
    function renderChart(canvasId, type, labels, data, colors) { 
        if(chartInstances[canvasId]) chartInstances[canvasId].destroy(); 
        const ctx = document.getElementById(canvasId).getContext('2d'); 
        const isBar = type === 'bar';
        const chartColors = Array.isArray(colors) ? colors : (isBar ? colors : [colors]);
        chartInstances[canvasId] = new Chart(ctx, { 
            type: type, 
            data: { 
                labels: labels, 
                datasets: [{ 
                    label: 'Sales (RM)', 
                    data: data, 
                    backgroundColor: isBar ? chartColors[0] : chartColors, 
                    borderColor: isBar ? chartColors[0] : (Array.isArray(colors) ? '#111' : colors), 
                    borderWidth: 2, 
                    tension: 0.3 
                }] 
            }, 
            options: { 
                responsive: true, 
                maintainAspectRatio: false, 
                devicePixelRatio: 3, 
                plugins: { 
                    legend: { position: 'bottom', labels: { color: '#333' } } 
                }, 
                scales: (type === 'line' || type === 'bar') ? { 
                    y: { beginAtZero: true, grid:{color:'#eee'}, ticks:{color:'#555', callback: function(value) { return 'RM ' + value.toFixed(0); }} }, 
                    x:{grid:{color:'#eee'}, ticks:{color:'#555', maxRotation: isBar ? 45 : 0, minRotation: isBar ? 45 : 0}} 
                } : {} 
            } 
        }); 
    }
    
    function viewActivityLogs() { 
        fetch('api.php?action=get_activity_logs')
        .then(r=>r.json())
        .then(d=>{ 
            const rows = d.logs.map(l=>`<tr><td>${l.created_at}</td><td>${escapeHtml(l.user)}</td><td>${l.action}</td><td><small>${escapeHtml(l.description)}</small></td></tr>`).join(''); 
            document.getElementById('activityTableBody').innerHTML = `<thead><tr><th>Date</th><th>User</th><th>Action</th><th>Detail</th></tr></thead><tbody>${rows}</tbody>`; 
            document.getElementById('activityModal').style.display='flex'; 
        }); 
    }

    function searchCustomer(val, type) { 
        if(val.length<3) {
            // Hide history panel if search is too short
            const historyPanel = document.getElementById(type + 'CustomerHistory');
            if (historyPanel) historyPanel.style.display = 'none';
            return;
        }
        
        apiRequest({action:'search_customer', term:val})
        .then(d=>{ 
            const list = document.getElementById(type+'CustList'); 
            list.innerHTML=''; 
            d.results.forEach(c=> { 
                let op=document.createElement('option'); 
                op.value=c.phone; 
                op.innerText=c.name; 
                list.appendChild(op); 
            });
            
            // Show customer history if available
            if (d.history && d.history.length > 0) {
                showCustomerHistory(d.history, type);
            }
            
            // Auto-fill customer name if exact match found
            if (d.results.length === 1 && d.results[0].phone === val) {
                const nameField = document.getElementById(type + '_cust');
                if (nameField && !nameField.value || nameField.value === 'Walk-in Customer') {
                    nameField.value = d.results[0].name;
                }
            }
        }); 
    }
    
    function showCustomerHistory(history, type) {
        // Create or update history panel
        let historyPanel = document.getElementById(type + 'CustomerHistory');
        if (!historyPanel) {
            const phoneInput = document.getElementById(type + '_phone');
            if (!phoneInput) return;
            
            historyPanel = document.createElement('div');
            historyPanel.id = type + 'CustomerHistory';
            historyPanel.style.cssText = 'margin-top: 10px; padding: 10px; background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 6px; max-height: 200px; overflow-y: auto;';
            phoneInput.parentElement.appendChild(historyPanel);
        }
        
        historyPanel.style.display = 'block';
        historyPanel.innerHTML = '<div style="font-weight: bold; margin-bottom: 8px; color: #555; font-size: 0.85rem;">📋 Previous Orders (' + history.length + '):</div>' +
            history.map(h => `
                <div style="padding: 8px; margin-bottom: 5px; background: white; border-radius: 4px; border-left: 3px solid #3498db; cursor: pointer;" 
                     onclick="fillFromHistory('${escapeHtml(h.job_id)}', '${type}')"
                     onmouseover="this.style.background='#e3f2fd'" 
                     onmouseout="this.style.background='white'">
                    <div style="font-weight: bold; color: #333;">${escapeHtml(h.customer)} - ${escapeHtml(h.job_id)}</div>
                    <div style="font-size: 0.8rem; color: #666;">
                        ${escapeHtml(h.model)} | ${h.date} | RM ${parseFloat(h.price).toFixed(2)} | ${escapeHtml(h.status)}
                    </div>
                </div>
            `).join('');
    }
    
    function fillFromHistory(jobId, type) {
        const job = allJobs.find(j => j.job_id === jobId) || allRetailJobs.find(j => j.job_id === jobId);
        if (!job) return;
        
        document.getElementById(type + '_cust').value = job.customer || '';
        document.getElementById(type + '_phone').value = job.phone || '';
        document.getElementById(type + '_imei').value = job.imei || '';
        
        // Hide history panel
        const historyPanel = document.getElementById(type + 'CustomerHistory');
        if (historyPanel) historyPanel.style.display = 'none';
        
        showToast('✅ Customer info filled from history');
    }
    
    // Quick action: Mark job as Completed
    function quickComplete(jobId) {
        const job = allJobs.find(j => j.job_id === jobId);
        if (!job) return;
        
        if (confirm(`Mark job ${jobId} as Completed?`)) {
            const data = {
                action: 'update_full_job',
                id: job.id,
                customer: job.customer,
                phone: job.phone,
                model: job.model,
                imei: job.imei || '',
                passcode: job.passcode || '',
                repair: job.repair || '',
                remarks: job.remarks || '',
                price: job.price,
                deposit: job.deposit || 0,
                status: 'Completed',
                payment_status: job.payment_status || 'Unpaid',
                paymentMethod: job.payment_method || 'Cash',
                warranty: job.warranty || 'No Warranty',
                job_cost: job.job_cost || 0
            };
            
            apiRequest(data).then(d => {
                if (d.success) {
                    showToast('✅ Job marked as Completed');
                    fetchJobs();
                    fetchBilling();
                } else {
                    showToast('Error: ' + (d.error || 'Failed to update'), 'error');
                }
            });
        }
    }

    // --- WHATSAPP MESSAGE (SINGLE INVOICE) ---
    function sendWhatsapp(jobId){ 
        const job = allJobs.find(j => j.job_id === jobId) || allRetailJobs.find(j => j.job_id === jobId); 
        if(!job) return; 
        
        let p = job.phone.replace(/\D/g,''); 
        if(p.startsWith('01')) p = '6'+p; 
        
        // Use invoice.php for repair jobs, receipt.php for retail sales
        const isRetail = (job.model === 'Retail Sale' || job.remarks === 'Retail Order');
        const linkFile = isRetail ? 'receipt.php' : 'invoice.php';
        const link = `${window.location.origin}/${linkFile}?id=${job.job_id}&token=${job.token||''}`;
        
        // Use pickup date if available, else date of creation
        let dateDisplay = (job.pickup_date && job.pickup_date !== '0000-00-00') ? job.pickup_date : job.date;
        
        const msg = `Hello ${job.customer}, thank you for visiting Fon2Fix.

Job ID: ${job.job_id}
Pickup Date: ${dateDisplay}
Total: RM ${job.price}

View Invoice:
${link}`;
        
        const url = `https://wa.me/${p}?text=` + encodeURIComponent(msg); 
        window.open(url, '_blank'); 
    }

    // --- USER MANAGEMENT ---
    function fetchUsers() { 
        if(!IS_MASTER) return; 
        fetch('api.php?action=get_users').then(r=>r.json()).then(d=>{ 
            const tbody = document.getElementById('userListBody'); 
            tbody.innerHTML = d.users.map(u => { 
                if(u.username.toLowerCase() === 'endie') {
                    return `<tr style="border-bottom:1px solid #eee; background:#fff3cd;">
                        <td style="padding:10px; font-weight:bold; color:#856404;">${escapeHtml(u.username)} <span style="color:#856404; font-size:0.75rem;">(Master)</span></td>
                        <td style="padding:10px;"><span style="padding:4px 8px; border-radius:4px; background:#ffc107; color:#856404; font-size:0.75rem; font-weight:bold;">Master</span></td>
                        <td style="padding:10px; color:#999;">-</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#999;">-</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center; color:#2ecc71; font-weight:bold;">✅</td>
                        <td style="padding:10px; text-align:center;"><button class="btn-action" onclick="openAdminPass(${u.id})" title="Reset Password">🔑</button></td>
                    </tr>`;
                }
                let delBtn = ''; 
                if(u.id != MY_ID) { 
                    delBtn = `<button class="btn-action" style="background:#e74c3c; color:white; border:none;" onclick="terminateUser(${u.id}, '${escapeHtml(u.username)}')" title="Terminate">❌</button>`; 
                } 
                const isGombak = (u.assigned_branch === 'Gombak') ? 'selected' : ''; 
                const isSri = (u.assigned_branch === 'Sri Rampai') ? 'selected' : ''; 
                const branchSelect = `<select onchange="updateUserBranch(${u.id}, this.value)" style="padding:5px; background:#fff; color:#333; border:1px solid #ccc; border-radius:4px;"><option value="Gombak" ${isGombak}>Gombak</option><option value="Sri Rampai" ${isSri}>Sri Rampai</option></select>`; 
                return `<tr style="border-bottom:1px solid #eee; ${u.id == MY_ID ? 'background:#e8f5e9;' : ''}">
                    <td style="padding:10px; font-weight:bold; color:#333;">${escapeHtml(u.username)}${u.id == MY_ID ? ' <span style="color:#2ecc71; font-size:0.75rem;">(You)</span>' : ''}</td>
                    <td style="padding:10px;"><span style="padding:4px 8px; border-radius:4px; background:#e3f2fd; color:#1565c0; font-size:0.75rem; font-weight:bold;">${escapeHtml(u.role)}</span></td>
                    <td style="padding:10px;">${branchSelect}</td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${u.can_edit==1?'checked':''} onchange="updatePerm(this, ${u.id})" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${u.can_delete==1?'checked':''} onchange="updatePerm(this, ${u.id})" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${u.can_transfer==1?'checked':''} onchange="updatePerm(this, ${u.id})" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${u.can_refund==1?'checked':''} onchange="updatePerm(this, ${u.id})" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${u.can_restore==1?'checked':''} onchange="updatePerm(this, ${u.id})" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${u.restrict_branch==1?'checked':''} onchange="updatePerm(this, ${u.id})" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${(u.can_add_cross_branch_stock==1)?'checked':''} onchange="updatePerm(this, ${u.id})" title="Allow adding stock for other branch" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${(u.can_view_stock_logs==1)?'checked':''} onchange="updatePerm(this, ${u.id})" title="View Stock Activity Logs" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${(u.can_merge_stock==1)?'checked':''} onchange="updatePerm(this, ${u.id})" title="Merge Duplicate Stock" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${(u.can_bulk_ops==1)?'checked':''} onchange="updatePerm(this, ${u.id})" title="Bulk Operations" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${(u.can_bulk_print==1)?'checked':''} onchange="updatePerm(this, ${u.id})" title="Bulk Print" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${(u.can_bulk_import==1)?'checked':''} onchange="updatePerm(this, ${u.id})" title="Bulk Import" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;"><input type="checkbox" ${(u.can_convert_uppercase==1)?'checked':''} onchange="updatePerm(this, ${u.id})" title="Convert Stock to Uppercase" style="width:18px; height:18px; cursor:pointer;"></td>
                    <td style="padding:10px; text-align:center;">
                        <button class="btn-action" onclick="openAdminPass(${u.id})" title="Reset Password" style="margin-right:5px;">🔑</button>${delBtn}
                    </td>
                </tr>`; 
            }).join(''); 
        }); 
    }
    function updateUserBranch(uid, val) { apiRequest({ action: 'update_user_branch', user_id: uid, branch: val }).then(d => { if(d.success) showToast("User Branch Updated"); }); }
    function terminateUser(uid, name) { if(confirm("⚠️ ARE YOU SURE?\n\nThis will permanently remove " + name + " from the system.\nThis action cannot be undone.")) { apiRequest({ action: 'delete_user', user_id: uid }).then(d => { if(d.success) { showToast("Staff Terminated", "success"); fetchUsers(); } }); } }
    function updatePerm(el, uid) { 
        const row = el.closest('tr'); 
        const editChk = row.cells[3].querySelector('input').checked ? 1 : 0; 
        const delChk = row.cells[4].querySelector('input').checked ? 1 : 0; 
        const transChk = row.cells[5].querySelector('input').checked ? 1 : 0; 
        const refChk = row.cells[6].querySelector('input').checked ? 1 : 0; 
        const resChk = row.cells[7].querySelector('input').checked ? 1 : 0; 
        const restChk = row.cells[8].querySelector('input').checked ? 1 : 0; 
        const crossStockChk = row.cells[9].querySelector('input').checked ? 1 : 0; 
        const stockLogsChk = row.cells[10].querySelector('input').checked ? 1 : 0; 
        const mergeStockChk = row.cells[11].querySelector('input').checked ? 1 : 0; 
        const bulkOpsChk = row.cells[12].querySelector('input').checked ? 1 : 0; 
        const bulkPrintChk = row.cells[13].querySelector('input').checked ? 1 : 0; 
        const bulkImportChk = row.cells[14].querySelector('input').checked ? 1 : 0; 
        const convertUppercaseChk = row.cells[15].querySelector('input').checked ? 1 : 0; 
        apiRequest({ 
            action:'update_user_permissions', 
            user_id:uid, 
            can_edit:editChk, 
            can_delete:delChk, 
            can_transfer:transChk, 
            can_refund:refChk, 
            can_restore:resChk, 
            restrict_branch:restChk, 
            can_add_cross_branch_stock:crossStockChk,
            can_view_stock_logs:stockLogsChk,
            can_merge_stock:mergeStockChk,
            can_bulk_ops:bulkOpsChk,
            can_bulk_print:bulkPrintChk,
            can_bulk_import:bulkImportChk,
            can_convert_uppercase:convertUppercaseChk
        }).then(d=>{ 
            if(d.success) showToast("Permissions Updated"); 
        }); 
    }
    function openAdminPass(uid) { document.getElementById('passwordModal').style.display='flex'; document.getElementById('pass_user_id').value = uid; document.getElementById('oldPassField').style.display = 'none'; }
    function openChangePassword() { document.getElementById('passwordModal').style.display='flex'; document.getElementById('pass_user_id').value = 'SELF'; document.getElementById('oldPassField').style.display = 'block'; }
    function submitPassChange() { const uid = document.getElementById('pass_user_id').value; const newP = document.getElementById('new_pass').value; if(uid === 'SELF') { const oldP = document.getElementById('old_pass').value; apiRequest({ action:'change_own_password', old_pass:oldP, new_pass:newP }).then(d=>{ if(d.success){ showToast("Password Changed"); document.getElementById('passwordModal').style.display='none'; } }); } else { apiRequest({ action:'admin_reset_password', user_id:uid, new_pass:newP }).then(d=>{ if(d.success){ showToast("Password Reset"); document.getElementById('passwordModal').style.display='none'; } }); } }
    function submitNewUser() { const u = document.getElementById('new_user_name').value; const p = document.getElementById('new_user_pass').value; const b = document.getElementById('new_user_branch').value; if(!u || !p) return showToast("Enter Username and Password", 'error'); apiRequest({ action: 'create_user', username: u, password: p, assigned_branch: b }).then(d => { if(d.success) { showToast("User Created Successfully"); document.getElementById('createUserModal').style.display = 'none'; fetchUsers(); document.getElementById('new_user_name').value = ''; document.getElementById('new_user_pass').value = '123456'; } }); }
    function openCreateUserModal() { document.getElementById('createUserModal').style.display = 'flex'; }
    // Duplicate functions removed - using the earlier, more complete versions

    // --- QR CODE GENERATION FOR STOCK ---
    function generateStockQR(data, sellingPrice = 0) {
        const overlay = document.getElementById('qrOverlay');
        const canvas = document.getElementById('qrCanvas');
        const branchEl = document.getElementById('qrBranch');
        const titleEl = document.getElementById('qrTitle');
        const priceEl = document.getElementById('qrPrice');
        
        // Parse the data (format: "Branch|Part Name" or just "Part Name")
        // Extract branch and part name, but QR code will only contain part name (branch-agnostic)
        const parts = data.split('|');
        let branch = '';
        let partName = '';
        
        if (parts.length > 1) {
            // Old format: "Branch|Part Name"
            branch = parts[0] || '';
            partName = parts.slice(1).join('|') || 'Unknown';
        } else {
            // New format: just "Part Name" (no branch prefix)
            partName = data || 'Unknown';
            branch = ''; // Will be determined dynamically when scanned
        }
        
        // Format part name to match top label style - ALL UPPERCASE, clean formatting
        partName = partName.toUpperCase().trim();
        
        // Set branch and title (both uppercase to match reference)
        // Branch is only for display - QR code will not contain it
        if (branch) {
            branchEl.textContent = branch.toUpperCase();
        } else {
            branchEl.textContent = '';
        }
        titleEl.textContent = partName;
        titleEl.style.textTransform = 'uppercase'; // Force uppercase
        
        // Set selling price or additional info (formatted like top label)
        if (sellingPrice && sellingPrice > 0) {
            priceEl.textContent = 'PRICE : RM' + parseFloat(sellingPrice).toFixed(2);
            priceEl.style.display = 'block';
        } else {
            priceEl.style.display = 'none';
        }
        
        // Set canvas dimensions for 40mm x 30mm label
        // Render at higher resolution (350px) but display at 20mm for thinner lines
        // Higher resolution = more pixels = thinner individual lines when scaled down
        const renderSize = 350; // Render at high resolution
        canvas.width = renderSize;
        canvas.height = renderSize;
        
        // Clear previous QR code
        const ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // IMPORTANT: QR code only contains the part name (no branch)
        // This makes it branch-agnostic - works correctly even after stock transfer
        const qrData = partName; // Only part name, no branch prefix
        
        // Generate QR code using qrious library
        // Use level L (Low error correction) for smaller QR code footprint
        // Higher render size creates thinner lines when CSS-scaled to 20mm
        const qr = new QRious({
            element: canvas,
            value: qrData, // Only part name - branch-agnostic
            size: renderSize,
            level: 'L',  // Low error correction = smaller QR code, more data fits
            background: 'white',
            foreground: 'black',
            padding: 15  // Add padding for better scanning margin
        });
        
        // CSS will scale this down to 20mm for printing, making lines appear thinner
        // On screen, display at 200px for preview (larger QR code)
        canvas.style.width = '200px';
        canvas.style.height = '200px';
        canvas.style.imageRendering = 'crisp-edges'; // Keep lines sharp
        
        // Show overlay
        overlay.style.display = 'flex';
    }

    function closeQR() {
        document.getElementById('qrOverlay').style.display = 'none';
    }
    // Duplicate functions removed - using the earlier, more complete versions:
    // - calcTotal() at line 2830
    // - openTransfer() at line 4309
    // - submitTransfer() at line 4310
    // - viewTransferLog() at line 4311
    // --- NEW FUNCTIONS TO ADD ---

// Device Models Management
let allDeviceModels = [];
let deviceDropdownVisible = false;

function fetchDeviceModels() {
    fetch('api.php?action=fetch_device_models')
        .then(r => r.json())
        .then(d => {
            if (d.success) {
                allDeviceModels = d.models || [];
                populateDeviceDropdown();
            }
        })
        .catch(err => {
            console.error('Error fetching device models:', err);
            allDeviceModels = [];
        });
}

function handleCategoryChange() {
    const category = document.getElementById('np_cat').value;
    const deviceSearch = document.getElementById('np_device_search');
    const deviceEl = document.getElementById('np_device');
    
    if (category) {
        if (deviceSearch) {
            deviceSearch.disabled = false;
            deviceSearch.style.background = '#fff';
            deviceSearch.style.cursor = 'text';
            deviceSearch.placeholder = 'Search or type new device model...';
            deviceSearch.value = '';
            if (deviceEl && deviceEl.tagName === 'INPUT') deviceEl.value = '';
            fetchDeviceModels();
        }
        if (deviceEl && deviceEl.tagName === 'SELECT') {
            deviceEl.disabled = false;
            deviceEl.value = '';
        }
    } else {
        if (deviceSearch) {
            deviceSearch.disabled = true;
            deviceSearch.style.background = '#f5f5f5';
            deviceSearch.style.cursor = 'not-allowed';
            deviceSearch.value = '';
            if (deviceEl && deviceEl.tagName === 'INPUT') deviceEl.value = '';
            hideDeviceDropdown();
        }
        if (deviceEl && deviceEl.tagName === 'SELECT') {
            deviceEl.disabled = true;
            deviceEl.value = '';
        }
    }
    
    generatePartName();
}

function populateDeviceDropdown() {
    const searchTerm = document.getElementById('np_device_search').value.toLowerCase();
    const filtered = allDeviceModels.filter(m => m.toLowerCase().includes(searchTerm));
    const listDiv = document.getElementById('np_device_list');
    const previewSpan = document.getElementById('new_device_name_preview');
    const searchValue = document.getElementById('np_device_search').value.trim();
    
    if (filtered.length === 0 && !searchValue) {
        listDiv.innerHTML = '<div style="padding:10px; color:#999; text-align:center;">No device models found. Type to add a new one.</div>';
    } else {
        listDiv.innerHTML = filtered.map(model => 
            `<div onclick="selectDeviceModel('${escapeHtml(model)}')" style="padding:8px 12px; cursor:pointer; border-bottom:1px solid #f0f0f0;" onmouseover="this.style.background='#f8f9fa'" onmouseout="this.style.background='white'">${escapeHtml(model)}</div>`
        ).join('');
    }
    
    // Update preview for add button
    if (previewSpan) {
        previewSpan.textContent = searchValue || 'New Model';
    }
}

function handleDeviceSearchInput() {
    const searchValue = document.getElementById('np_device_search').value.trim();
    // Update hidden field with current search value (user might be typing a new model)
    document.getElementById('np_device').value = searchValue;
    filterDeviceModels();
    generatePartName();
}

function filterDeviceModels() {
    populateDeviceDropdown();
    showDeviceDropdown();
}

function handleDeviceSearchKeydown(event) {
    if (event.key === 'Enter') {
        event.preventDefault();
        const searchValue = document.getElementById('np_device_search').value.trim();
        if (searchValue) {
            // Check if it matches an existing model
            const matches = allDeviceModels.filter(m => m.toLowerCase() === searchValue.toLowerCase());
            if (matches.length > 0) {
                selectDeviceModel(matches[0]);
            } else {
                addNewDeviceModel();
            }
        }
    } else if (event.key === 'Escape') {
        hideDeviceDropdown();
    }
}

function showDeviceDropdown() {
    const category = document.getElementById('np_cat').value;
    if (!category) return;
    
    const dropdown = document.getElementById('np_device_dropdown');
    dropdown.style.display = 'block';
    deviceDropdownVisible = true;
    populateDeviceDropdown();
}

function hideDeviceDropdown() {
    const dropdown = document.getElementById('np_device_dropdown');
    if (dropdown) {
        dropdown.style.display = 'none';
        deviceDropdownVisible = false;
    }
}

function selectDeviceModel(model) {
    document.getElementById('np_device_search').value = model;
    document.getElementById('np_device').value = model;
    hideDeviceDropdown();
    generatePartName();
}

function addNewDeviceModel() {
    const searchInput = document.getElementById('np_device_search');
    const newModel = searchInput.value.trim();
    
    if (!newModel) {
        showToast('Please enter a device model name', 'error');
        return;
    }
    
    // Add to local list if not already present
    if (!allDeviceModels.includes(newModel)) {
        allDeviceModels.push(newModel);
        allDeviceModels.sort();
    }
    
    // Set the value
    document.getElementById('np_device').value = newModel;
    hideDeviceDropdown();
    generatePartName();
    showToast(`Device model "${newModel}" added`, 'success');
}

function generatePartName() {
    const dev = document.getElementById('np_device').value.trim();
    const cat = document.getElementById('np_cat').value.trim();
    const nameField = document.getElementById('np_name');
    const labelSpan = document.getElementById('np_name_label');
    
    // Always keep the field editable
    nameField.readOnly = false;
    nameField.style.background = '#fff';
    nameField.style.color = '#333';
    nameField.style.fontWeight = 'normal';
    nameField.placeholder = 'Device Model + Category';
    
    // Generate suggested name from Device Model + Category
    let suggestedName = '';
    if (dev && cat) {
        suggestedName = dev + " " + cat;
    } else if (dev) {
        suggestedName = dev;
    } else if (cat) {
        suggestedName = cat;
    }
    
    // Check if device or category has changed
    const previousDev = nameField.dataset.lastDev || '';
    const previousCat = nameField.dataset.lastCat || '';
    const devChanged = previousDev !== dev;
    const catChanged = previousCat !== cat;
    const currentValue = nameField.value.trim();
    
    // Update the field if:
    // 1. Field is empty, OR
    // 2. Device or category has changed (follow the pattern), OR
    // 3. Current value matches the previous auto-generated pattern (not manually edited)
    const previousPattern = previousDev && previousCat ? (previousDev + " " + previousCat) : (previousDev || previousCat || '');
    const wasManualEdit = nameField.dataset.isManualEdit === 'true';
    
    if (!currentValue || devChanged || catChanged || (currentValue === previousPattern && !wasManualEdit)) {
        nameField.value = suggestedName;
        nameField.dataset.isManualEdit = 'false'; // Reset manual edit flag when auto-updating
    }
    
    // Store current device and category for next comparison
    nameField.dataset.lastDev = dev;
    nameField.dataset.lastCat = cat;
    
    // Update label to show it's editable but follows the pattern
    if (labelSpan) {
        labelSpan.textContent = '(Manual Entry)';
        labelSpan.style.color = '#f39c12';
    }
}

function updatePartNameLabel() {
    // When user manually edits, track it so we don't overwrite unless device/category changes
    const nameField = document.getElementById('np_name');
    const dev = document.getElementById('np_device').value.trim();
    const cat = document.getElementById('np_cat').value.trim();
    const currentValue = nameField.value.trim();
    
    // Check if the current value matches the expected pattern
    const expectedPattern = dev && cat ? (dev + " " + cat) : (dev || cat || '');
    if (currentValue === expectedPattern) {
        // Matches pattern - user might have typed it manually or it's auto-generated
        // Don't mark as manual edit if it matches the pattern
        nameField.dataset.isManualEdit = 'false';
    } else if (currentValue && currentValue !== expectedPattern) {
        // Doesn't match pattern - user has manually edited
        nameField.dataset.isManualEdit = 'true';
    }
}

function prependBrandToPartName() {
    const brandEl = document.getElementById('np_brand');
    const nameEl = document.getElementById('np_name');
    if (!brandEl || !nameEl) return;
    const brand = (brandEl.value || '').trim().toUpperCase();
    let partName = (nameEl.value || '').trim();
    if (!brand) return;
    if (!partName) return;
    // Strip any existing brand from the front (from dropdown options or if part name starts with current brand)
    const brandUpper = brand.toUpperCase();
    if (partName.toUpperCase().startsWith(brandUpper + ' ')) return; // Already has this brand
    if (partName.toUpperCase() === brandUpper) return;
    if (brandEl.tagName === 'SELECT') {
        const brands = [].slice.call(brandEl.options).map(o => (o.value || '').trim()).filter(Boolean);
        for (const b of brands) {
            const bUpper = b.toUpperCase();
            if (partName.toUpperCase().startsWith(bUpper + ' ')) {
                partName = partName.substring(b.length).trim();
                break;
            }
        }
    } else {
        if (partName.toUpperCase().startsWith(brandUpper + ' ')) return;
        const firstWord = partName.split(/\s+/)[0] || '';
        if (firstWord.toUpperCase() === brandUpper) return;
    }
    nameEl.value = brand + ' ' + partName;
}


function applyQuickFix(selectEl, targetId) {
    if(selectEl.value) {
        document.getElementById(targetId).value = selectEl.value;
        // Keep the selected value visible in the dropdown
    }
}

// --- UPDATE THIS EXISTING FUNCTION ---
// Find your existing 'addNewStockItem' function and replace it with this one:
// REMOVED: Duplicate addNewStockItem function - using the complete version at line 3695
    // --- TODAY'S SUMMARY & LOW STOCK DETECTION ---
    function updateTodaysSummary() {
        const today = new Date().toISOString().split('T')[0];
        let todaySales = 0;
        let todayJobs = 0;
        let pendingJobs = 0;
        let lowStockCount = 0;
        
        // Calculate today's stats from jobs - ONLY include Retail Sales, exclude Drop Off Repairs
        const allCombinedJobs = [...(allJobs || []), ...(allRetailJobs || [])];
        allCombinedJobs.forEach(j => {
            if (j.date === today) {
                // Identify retail sales - only count these in statistics
                const isRetail = (j.model === 'Retail Sale' || j.remarks === 'Retail Order');
                
                // Only count retail sales in today's statistics
                if (isRetail) {
                    if (j.status === 'Completed') {
                        todaySales += parseFloat(j.price || 0);
                        todayJobs++;
                    } else if (j.status === 'Pending' || j.status === 'In Progress') {
                        pendingJobs++;
                    }
                }
                // Drop Off Repairs are excluded from statistics (for record purposes only)
            }
        });
        
        // Check low stock (items with 5 or fewer units)
        if (allStock && typeof allStock === 'object') {
            Object.values(allStock).forEach(type => {
                if (typeof type === 'object' && type !== null) {
                    Object.values(type).forEach(category => {
                        if (Array.isArray(category)) {
                            category.forEach(item => {
                                const branch = '<?php echo strtolower($my_branch); ?>';
                                const currentStock = branch.includes('gombak') 
                                    ? parseFloat(item.stock_gombak || 0)
                                    : parseFloat(item.stock_sr || 0);
                                if (currentStock > 0 && currentStock <= 5) {
                                    lowStockCount++;
                                }
                            });
                        }
                    });
                }
            });
        }
        
        // Update display
        const todaySalesEl = document.getElementById('todaySales');
        const todayJobsEl = document.getElementById('todayJobs');
        const pendingJobsEl = document.getElementById('pendingJobs');
        const lowStockEl = document.getElementById('lowStock');
        
        if (todaySalesEl) todaySalesEl.textContent = 'RM ' + todaySales.toFixed(2);
        if (todayJobsEl) todayJobsEl.textContent = todayJobs;
        if (pendingJobsEl) pendingJobsEl.textContent = pendingJobs;
        
        if (lowStockEl) {
            lowStockEl.textContent = lowStockCount;
            const parentEl = lowStockEl.parentElement;
            if (lowStockCount > 0) {
                lowStockEl.style.color = '#e74c3c';
                if (parentEl) {
                    parentEl.style.border = '2px solid #e74c3c';
                    parentEl.style.cursor = 'pointer';
                    parentEl.onclick = () => {
                        switchMainTab('stock');
                        showToast(`⚠️ ${lowStockCount} items are low on stock!`, 'error');
                    };
                }
            } else {
                lowStockEl.style.color = '#2ecc71';
                if (parentEl) {
                    parentEl.style.border = '';
                    parentEl.style.cursor = '';
                    parentEl.onclick = null;
                }
            }
        }
    }
    
    // updateTodaysSummary is now called directly from fetchJobs, fetchRetailHistory, and fetchStock callbacks

    // --- KEYBOARD SHORTCUTS ---
    document.addEventListener('keydown', function(e) {
        // Don't trigger shortcuts when typing in inputs/textareas
        if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') {
            // Allow Enter to submit forms
            if (e.key === 'Enter' && e.target.type !== 'textarea' && !e.shiftKey) {
                const form = e.target.closest('.card');
                if (form) {
                    const submitBtn = form.querySelector('.btn-primary, .btn-success');
                    if (submitBtn && !submitBtn.disabled) {
                        e.preventDefault();
                        submitBtn.click();
                    }
                }
            }
            // Allow Esc to clear input or close modals
            if (e.key === 'Escape') {
                e.target.value = '';
                e.target.blur();
            }
            return;
        }
        
        // Number keys 1-7 for tab switching
        if (e.key >= '1' && e.key <= '7' && !e.ctrlKey && !e.altKey && !e.metaKey) {
            const tabs = ['repair', 'billing', 'retail', 'stock', 'report', 'trash', 'users'];
            const tabIndex = parseInt(e.key) - 1;
            if (tabs[tabIndex] && document.getElementById('tab' + tabs[tabIndex].charAt(0).toUpperCase() + tabs[tabIndex].slice(1))) {
                e.preventDefault();
                switchMainTab(tabs[tabIndex]);
            }
        }
        
        // Esc to close modals
        if (e.key === 'Escape') {
            document.querySelectorAll('.modal').forEach(modal => {
                if (modal.style.display === 'flex' || modal.style.display === '') {
                    modal.style.display = 'none';
                }
            });
        }
        
        // Ctrl/Cmd + K for quick search (focus search input)
        if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
            e.preventDefault();
            const activeTab = document.querySelector('.mode-btn.active');
            if (activeTab) {
                const tabId = activeTab.id.replace('tab', '').toLowerCase();
                let searchInput = null;
                if (tabId === 'repair') searchInput = document.getElementById('searchInput');
                else if (tabId === 'retail') searchInput = document.getElementById('retailSearchInput');
                else if (tabId === 'billing') searchInput = document.getElementById('billingSearch');
                else if (tabId === 'stock') searchInput = document.getElementById('stockSearchInput');
                
                if (searchInput) {
                    searchInput.focus();
                    searchInput.select();
                }
            }
        }
    });
    
    // Add tooltips to buttons
    function addTooltips() {
        document.querySelectorAll('[onclick]').forEach(btn => {
            if (btn.title) return; // Already has tooltip
            const onclick = btn.getAttribute('onclick');
            if (onclick.includes('openEditModal')) btn.title = 'Edit (Ctrl+Click for details)';
            else if (onclick.includes('sendWhatsapp')) btn.title = 'Send WhatsApp';
            else if (onclick.includes('confirmDelete')) btn.title = 'Delete';
            else if (onclick.includes('switchMainTab')) {
                const match = onclick.match(/switchMainTab\('(\w+)'\)/);
                if (match) btn.title = `Switch to ${match[1]} (Keyboard: ${getTabShortcut(match[1])})`;
            }
        });
    }
    
    function getTabShortcut(tab) {
        const shortcuts = {repair: '1', billing: '2', retail: '3', stock: '4', report: '5', trash: '6', users: '7'};
        return shortcuts[tab] || '';
    }
    
    // Show keyboard shortcut hints in tab buttons
    setTimeout(() => {
        document.querySelectorAll('.mode-btn').forEach((btn, index) => {
            const shortcuts = ['1', '2', '3', '4', '5', '6', '7'];
            if (shortcuts[index]) {
                btn.setAttribute('title', `Press ${shortcuts[index]} to switch`);
            }
        });
        addTooltips();
    }, 500);
    
    // Add loading indicators for async operations (will be overridden by performance optimization section)
    // Note: Loading indicators are handled in the performance optimization section
    
    function showLoading() {
        let loader = document.getElementById('globalLoader');
        if (!loader) {
            loader = document.createElement('div');
            loader.id = 'globalLoader';
            loader.style.cssText = 'position:fixed; top:0; left:0; width:100%; height:3px; background:linear-gradient(90deg, #3498db, #2ecc71); z-index:99999; animation:loading 1s infinite;';
            document.body.appendChild(loader);
        }
        loader.style.display = 'block';
    }
    
    function hideLoading() {
        const loader = document.getElementById('globalLoader');
        if (loader) loader.style.display = 'none';
    }
    
    // Add CSS for loading animation
    const style = document.createElement('style');
    style.textContent = `
        @keyframes loading {
            0% { transform: translateX(-100%); }
            100% { transform: translateX(100vw); }
        }
        .btn:disabled { opacity: 0.5; cursor: not-allowed; }
        input:invalid { border-color: #e74c3c !important; }
        .form-group:hover label { color: var(--primary); }
        .btn-action:hover { transform: scale(1.1); }
        .quick-tip { font-size: 0.75rem; color: #777; margin-top: 3px; font-style: italic; }
    `;
    document.head.appendChild(style);
    
    // Add Enter key support for submitting forms
    document.addEventListener('keypress', function(e) {
        if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
            // Ctrl+Enter or Cmd+Enter submits form
            const activeForm = document.querySelector('.card:not(.d-none)');
            if (activeForm) {
                const submitBtn = activeForm.querySelector('.btn-primary');
                if (submitBtn && !submitBtn.disabled) {
                    e.preventDefault();
                    submitBtn.click();
                }
            }
        }
    });
    
    // Add helpful placeholder text enhancements
    document.querySelectorAll('input[type="number"]').forEach(input => {
        if (input.id.includes('price') || input.id.includes('amount')) {
            input.setAttribute('placeholder', input.placeholder || '0.00');
            input.addEventListener('focus', function() {
                if (this.value === '0' || this.value === '0.00') this.select();
            });
        }
    });

    // ============================================================
    // EFFICIENCY FEATURES: #5 Auto-Save Drafts, #6 Smart Defaults
    // ============================================================
    
    // Smart Defaults: Remember last customer/model per phone number
    const smartDefaults = {
        customerHistory: {}, // phone => {name, lastModel, lastDate}
        
        saveCustomerData: function(phone, customer, model) {
            if (phone && phone.length >= 3) {
                this.customerHistory[phone] = {
                    name: customer || this.customerHistory[phone]?.name,
                    lastModel: model || this.customerHistory[phone]?.lastModel,
                    lastDate: new Date().toISOString()
                };
                try {
                    localStorage.setItem('smartDefaults', JSON.stringify(this.customerHistory));
                } catch(e) {}
            }
        },
        
        getCustomerData: function(phone) {
            if (phone && phone.length >= 3 && this.customerHistory[phone]) {
                return this.customerHistory[phone];
            }
            return null;
        },
        
        loadFromStorage: function() {
            try {
                const stored = localStorage.getItem('smartDefaults');
                if (stored) this.customerHistory = JSON.parse(stored);
            } catch(e) {}
        }
    };
    smartDefaults.loadFromStorage();
    
    // Auto-Save Drafts: Save form data every 10 seconds
    const draftAutoSave = {
        intervals: {},
        
        saveDraft: function(formType) {
            const formData = {timestamp: new Date().toISOString()};
            
            if (formType === 'repair') {
                formData.customer = document.getElementById('rep_cust')?.value || '';
                formData.phone = document.getElementById('rep_phone')?.value || '';
                formData.model = document.getElementById('rep_model')?.value || '';
                formData.imei = document.getElementById('rep_imei')?.value || '';
                formData.passcode = document.getElementById('rep_pass')?.value || '';
                formData.repair = document.getElementById('rep_desc')?.value || '';
                formData.remarks = document.getElementById('rep_remarks')?.value || '';
                formData.price = document.getElementById('rep_price')?.value || '';
                formData.deposit = document.getElementById('rep_deposit')?.value || '';
                formData.warranty = document.getElementById('rep_war')?.value || '';
                // Save parts container HTML
                const partsContainer = document.getElementById('repairPartsContainer');
                if (partsContainer) {
                    formData.partsHTML = partsContainer.innerHTML;
                }
            } else if (formType === 'retail') {
                formData.customer = document.getElementById('ret_cust')?.value || '';
                formData.phone = document.getElementById('ret_phone')?.value || '';
                formData.imei = document.getElementById('ret_imei')?.value || '';
                formData.repair = document.getElementById('ret_desc')?.value || '';
                formData.remarks = document.getElementById('ret_remarks')?.value || '';
                // Save items container HTML
                const itemsContainer = document.getElementById('itemsContainer');
                if (itemsContainer) {
                    formData.itemsHTML = itemsContainer.innerHTML;
                }
            }
            
            try {
                localStorage.setItem(`draft_${formType}`, JSON.stringify(formData));
            } catch(e) {}
        },
        
        restoreDraft: function(formType) {
            try {
                const draft = localStorage.getItem(`draft_${formType}`);
                if (!draft) return false;
                
                const formData = JSON.parse(draft);
                const draftAge = Date.now() - new Date(formData.timestamp).getTime();
                // Only restore drafts less than 24 hours old
                if (draftAge > 24 * 60 * 60 * 1000) {
                    localStorage.removeItem(`draft_${formType}`);
                    return false;
                }
                
                if (confirm(`💾 Found saved draft from ${new Date(formData.timestamp).toLocaleString()}.\n\nRestore draft?`)) {
                    if (formType === 'repair') {
                        if (formData.customer) document.getElementById('rep_cust').value = formData.customer;
                        if (formData.phone) document.getElementById('rep_phone').value = formData.phone;
                        if (formData.model) document.getElementById('rep_model').value = formData.model;
                        if (formData.imei) document.getElementById('rep_imei').value = formData.imei;
                        if (formData.passcode) document.getElementById('rep_pass').value = formData.passcode;
                        if (formData.repair) document.getElementById('rep_desc').value = formData.repair;
                        if (formData.remarks) document.getElementById('rep_remarks').value = formData.remarks;
                        if (formData.price) document.getElementById('rep_price').value = formData.price;
                        if (formData.deposit) document.getElementById('rep_deposit').value = formData.deposit;
                        if (formData.warranty) document.getElementById('rep_war').value = formData.warranty;
                        if (formData.partsHTML) {
                            const partsContainer = document.getElementById('repairPartsContainer');
                            if (partsContainer) partsContainer.innerHTML = formData.partsHTML;
                        }
                    } else if (formType === 'retail') {
                        if (formData.customer) document.getElementById('ret_cust').value = formData.customer;
                        if (formData.phone) document.getElementById('ret_phone').value = formData.phone;
                        if (formData.imei) document.getElementById('ret_imei').value = formData.imei;
                        if (formData.repair) document.getElementById('ret_desc').value = formData.repair;
                        if (formData.remarks) document.getElementById('ret_remarks').value = formData.remarks;
                        if (formData.itemsHTML) {
                            const itemsContainer = document.getElementById('itemsContainer');
                            if (itemsContainer) itemsContainer.innerHTML = formData.itemsHTML;
                            // Recalculate total
                            if (typeof calcTotal === 'function') calcTotal();
                        }
                    }
                    showToast('✅ Draft restored');
                    return true;
                }
            } catch(e) {}
            return false;
        },
        
        clearDraft: function(formType) {
            try {
                localStorage.removeItem(`draft_${formType}`);
            } catch(e) {}
        },
        
        startAutoSave: function(formType) {
            // Stop existing interval if any
            if (this.intervals[formType]) {
                clearInterval(this.intervals[formType]);
            }
            // Save every 10 seconds
            this.intervals[formType] = setInterval(() => {
                this.saveDraft(formType);
            }, 10000);
        },
        
        stopAutoSave: function(formType) {
            if (this.intervals[formType]) {
                clearInterval(this.intervals[formType]);
                delete this.intervals[formType];
            }
        }
    };
    
    // Global clearDraft function (called from submitRepair/submitRetail)
    function clearDraft(formType) {
        draftAutoSave.clearDraft(formType);
    }
    
    // Enhanced customer search with smart defaults
    const originalSearchCustomer = window.searchCustomer || function() {};
    window.searchCustomer = function(val, type) {
        originalSearchCustomer(val, type);
        
        // Apply smart defaults
        if (val && val.length >= 3) {
            const customerData = smartDefaults.getCustomerData(val);
            if (customerData) {
                const nameField = document.getElementById(type + '_cust');
                const modelField = document.getElementById(type + '_model');
                
                // Auto-fill customer name if field is empty or "Walk-in Customer"
                if (nameField && (!nameField.value || nameField.value === 'Walk-in Customer') && customerData.name) {
                    nameField.value = customerData.name;
                }
                
                // Auto-fill model for repair jobs
                if (modelField && !modelField.value && customerData.lastModel) {
                    modelField.value = customerData.lastModel;
                }
            }
        }
    };
    
    // Save smart defaults when customer/model changes
    ['rep_phone', 'ret_phone'].forEach(phoneId => {
        const phoneInput = document.getElementById(phoneId);
        if (phoneInput) {
            phoneInput.addEventListener('blur', function() {
                const phone = this.value;
                const type = phoneId.includes('rep') ? 'repair' : 'retail';
                const customerField = document.getElementById(type === 'repair' ? 'rep_cust' : 'ret_cust');
                const modelField = type === 'repair' ? document.getElementById('rep_model') : null;
                
                if (phone && phone.length >= 3) {
                    smartDefaults.saveCustomerData(
                        phone,
                        customerField?.value,
                        modelField?.value
                    );
                }
            });
        }
    });
    
    // Start auto-save when forms are active
    document.getElementById('rep_date')?.addEventListener('focus', () => draftAutoSave.startAutoSave('repair'));
    document.getElementById('ret_date')?.addEventListener('focus', () => draftAutoSave.startAutoSave('retail'));
    
    // Restore drafts on page load (check after 1 second to ensure DOM is ready)
    setTimeout(() => {
        if (window.location.hash === '#repair' || document.getElementById('repairMode')?.classList.contains('active')) {
            draftAutoSave.restoreDraft('repair');
        } else if (window.location.hash === '#retail' || document.getElementById('retailMode')?.classList.contains('active')) {
            draftAutoSave.restoreDraft('retail');
        }
    }, 1000);

    // ============================================================
    // EFFICIENCY FEATURE: #9 Batch Print Receipts
    // ============================================================
    
    let selectedJobsForPrint = new Set();
    
    function toggleJobSelection(jobId) {
        if (selectedJobsForPrint.has(jobId)) {
            selectedJobsForPrint.delete(jobId);
        } else {
            selectedJobsForPrint.add(jobId);
        }
        updateBatchPrintButton();
    }
    
    function toggleAllBillingJobs(checked) {
        const rows = document.querySelectorAll('#billingTableBody tr');
        rows.forEach(row => {
            const checkbox = row.querySelector('input[type="checkbox"]');
            const jobIdCell = row.querySelector('.job-id');
            if (checkbox && jobIdCell) {
                const jobId = jobIdCell.textContent.trim();
                if (checked) {
                    selectedJobsForPrint.add(jobId);
                } else {
                    selectedJobsForPrint.delete(jobId);
                }
                checkbox.checked = checked;
            }
        });
        updateBatchPrintButton();
    }
    
    function updateBatchPrintButton() {
        const btn = document.getElementById('batchPrintBtn');
        if (btn) {
            const count = selectedJobsForPrint.size;
            btn.textContent = count > 0 ? `🖨️ PRINT SELECTED (${count})` : '🖨️ BATCH PRINT';
            btn.disabled = count === 0;
        }
    }
    
    function batchPrintReceipts() {
        if (selectedJobsForPrint.size === 0) {
            showToast('Please select jobs to print', 'error');
            return;
        }
        
        const jobIds = Array.from(selectedJobsForPrint);
        jobIds.forEach((jobId, index) => {
            setTimeout(() => {
                window.open(`receipt.php?id=${jobId}`, '_blank');
            }, index * 300); // Stagger print windows by 300ms
        });
        
        showToast(`✅ Opened ${jobIds.length} receipt(s) for printing`);
        selectedJobsForPrint.clear();
        updateBatchPrintButton();
        // Re-render table to clear checkboxes
        filterBilling();
    }
    
    // ============================================================
    // EFFICIENCY FEATURE: #10 Quick Stock Transfer
    // ============================================================
    
    function openQuickTransferModal(stockId) {
        if (!liveCanTransfer) {
            showToast('You do not have permission to transfer stock', 'error');
            return;
        }
        
        // Find stock item from allStock structure
        let stockItem = null;
        ['Part', 'Retail'].forEach(type => {
            if (allStock[type]) {
                for (let g in allStock[type]) {
                    const found = allStock[type][g].find(i => i.id === stockId);
                    if (found) {
                        stockItem = found;
                        return;
                    }
                }
            }
        });
        
        if (!stockItem) {
            showToast('Stock item not found', 'error');
            return;
        }
        
        const currentBranch = MY_BRANCH_NAME;
        const otherBranch = currentBranch === 'Gombak' ? 'Sri Rampai' : 'Gombak';
        const currentStock = currentBranch === 'Gombak' ? (stockItem.stock_gombak || 0) : (stockItem.stock_sr || 0);
        const otherStock = otherBranch === 'Gombak' ? (stockItem.stock_gombak || 0) : (stockItem.stock_sr || 0);
        
        // Create modal if doesn't exist
        let modal = document.getElementById('quickTransferModal');
        if (!modal) {
            modal = document.createElement('div');
            modal.id = 'quickTransferModal';
            modal.className = 'modal';
            modal.innerHTML = `
                <div class="modal-content" style="border-top:4px solid #3498db;">
                    <h3 style="color:#3498db;text-align:center;">🚚 QUICK STOCK TRANSFER</h3>
                    <div id="quickTransferContent"></div>
                    <div style="display:flex; gap:10px; margin-top:20px;">
                        <button class="btn btn-primary" onclick="executeQuickTransfer()">TRANSFER</button>
                        <button class="btn" style="background:#eee; color:#333; border:1px solid #ccc;" onclick="document.getElementById('quickTransferModal').style.display='none'">CANCEL</button>
                    </div>
                </div>
            `;
            document.body.appendChild(modal);
        }
        
        // Populate modal content
        document.getElementById('quickTransferContent').innerHTML = `
            <p style="font-weight:bold; margin:10px 0;">${escapeHtml(stockItem.part_name)}</p>
            <div style="display:flex; gap:20px; margin:15px 0; padding:15px; background:#f8f9fa; border-radius:8px;">
                <div style="flex:1;">
                    <div style="font-size:0.9em; color:#777;">${currentBranch}</div>
                    <div style="font-size:1.5em; font-weight:bold; color:#3498db;">${currentStock}</div>
                </div>
                <div style="flex:1;">
                    <div style="font-size:0.9em; color:#777;">${otherBranch}</div>
                    <div style="font-size:1.5em; font-weight:bold; color:#2ecc71;">${otherStock}</div>
                </div>
            </div>
            <div class="form-group">
                <label>Transfer Quantity</label>
                <input type="number" id="transferQty" value="1" min="1" max="${currentStock}" style="width:100%;">
            </div>
            <div class="form-group">
                <label>Destination</label>
                <select id="transferDestination" style="width:100%;">
                    <option value="${otherBranch}">Transfer to ${otherBranch}</option>
                </select>
            </div>
        `;
        
        window.currentTransferStockId = stockId;
        window.currentTransferFromBranch = currentBranch;
        modal.style.display = 'flex';
    }
    
    function executeQuickTransfer() {
        const stockId = window.currentTransferStockId;
        const qty = parseInt(document.getElementById('transferQty').value) || 0;
        const destination = document.getElementById('transferDestination').value;
        
        if (qty <= 0) {
            showToast('Please enter a valid quantity', 'error');
            return;
        }
        
        // Find stock item from allStock structure
        let stockItem = null;
        ['Part', 'Retail'].forEach(type => {
            if (allStock[type]) {
                for (let g in allStock[type]) {
                    const found = allStock[type][g].find(i => i.id === stockId);
                    if (found) {
                        stockItem = found;
                        return;
                    }
                }
            }
        });
        
        if (!stockItem) {
            showToast('Stock item not found', 'error');
            return;
        }
        
        apiRequest({
            action: 'transfer_stock',
            id: stockId,
            qty: qty,
            from: window.currentTransferFromBranch,
            to: destination,
            name: stockItem.part_name
        }).then(d => {
            if (d.success) {
                showToast(`✅ Transferred ${qty} item(s) to ${destination}`);
                document.getElementById('quickTransferModal').style.display = 'none';
                fetchStock();
            } else {
                showToast('Transfer failed: ' + (d.error || 'Unknown error'), 'error');
            }
        });
    }
    
    // ============================================================
    // EFFICIENCY FEATURE: #11 Customer Order History Panel (Enhanced)
    // ============================================================
    
    // Enhanced: Click customer name to see full history
    function showFullCustomerHistory(customerPhone, customerName) {
        apiRequest({action: 'search_customer', term: customerPhone})
        .then(d => {
            if (d.history && d.history.length > 0) {
                // Create or update history modal
                let modal = document.getElementById('customerHistoryModal');
                if (!modal) {
                    modal = document.createElement('div');
                    modal.id = 'customerHistoryModal';
                    modal.className = 'modal';
                    modal.innerHTML = `
                        <div class="modal-content" style="border-top:4px solid #9b59b6; max-width:800px; max-height:80vh; overflow-y:auto;">
                            <h3 style="color:#9b59b6;text-align:center;">📋 CUSTOMER ORDER HISTORY</h3>
                            <div id="customerHistoryContent"></div>
                            <button class="btn" style="background:#eee; color:#333; border:1px solid #ccc; margin-top:20px;" onclick="document.getElementById('customerHistoryModal').style.display='none'">CLOSE</button>
                        </div>
                    `;
                    document.body.appendChild(modal);
                }
                
                const content = d.history.map(h => `
                    <div style="padding:12px; margin-bottom:10px; background:#f8f9fa; border-radius:6px; border-left:3px solid #9b59b6; cursor:pointer;"
                         onclick="window.open('receipt.php?id=${h.job_id}', '_blank')"
                         onmouseover="this.style.background='#e8eaf6'" 
                         onmouseout="this.style.background='#f8f9fa'">
                        <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:5px;">
                            <div style="font-weight:bold; color:#333;">${escapeHtml(h.job_id)}</div>
                            <div style="font-weight:bold; color:#2ecc71;">RM ${parseFloat(h.price).toFixed(2)}</div>
                        </div>
                        <div style="font-size:0.85em; color:#666; margin-bottom:3px;">
                            ${escapeHtml(h.model || 'Retail Sale')} | ${h.date} | ${escapeHtml(h.status)}
                        </div>
                        <div style="font-size:0.8em; color:#999;">
                            ${escapeHtml((h.repair || '').substring(0, 80))}${(h.repair || '').length > 80 ? '...' : ''}
                        </div>
                    </div>
                `).join('');
                
                document.getElementById('customerHistoryContent').innerHTML = `
                    <p style="font-weight:bold; margin:15px 0;">${escapeHtml(customerName)} (${escapeHtml(customerPhone)})</p>
                    <p style="color:#777; margin-bottom:15px;">Total Orders: ${d.history.length} | Click any order to view receipt</p>
                    ${content}
                `;
                
                modal.style.display = 'flex';
            } else {
                showToast('No order history found for this customer', 'info');
            }
        });
    }
    
    // ============================================================
    // EFFICIENCY FEATURE: #12 Smart Price Suggestions
    // ============================================================
    
    const priceHistory = {
        items: {}, // part_name => {lastPrice, minPrice, maxPrice, count}
        
        recordPrice: function(itemName, price) {
            if (!itemName || !price) return;
            const cleanName = itemName.trim().toUpperCase();
            if (!this.items[cleanName]) {
                this.items[cleanName] = {lastPrice: 0, minPrice: Infinity, maxPrice: 0, count: 0};
            }
            const p = parseFloat(price);
            if (isNaN(p)) return;
            
            this.items[cleanName].lastPrice = p;
            this.items[cleanName].minPrice = Math.min(this.items[cleanName].minPrice, p);
            this.items[cleanName].maxPrice = Math.max(this.items[cleanName].maxPrice, p);
            this.items[cleanName].count++;
            
            // Save to localStorage
            try {
                localStorage.setItem('priceHistory', JSON.stringify(this.items));
            } catch(e) {}
        },
        
        getPriceSuggestion: function(itemName, cost) {
            const cleanName = itemName.trim().toUpperCase();
            const history = this.items[cleanName];
            if (!history || history.count === 0) return null;
            
            return {
                lastPrice: history.lastPrice,
                minPrice: history.minPrice === Infinity ? null : history.minPrice,
                maxPrice: history.maxPrice,
                suggestedMarkup: cost && cost > 0 ? ((history.lastPrice / cost - 1) * 100).toFixed(0) + '%' : null
            };
        },
        
        loadFromStorage: function() {
            try {
                const stored = localStorage.getItem('priceHistory');
                if (stored) this.items = JSON.parse(stored);
                // Fix minPrice if it's Infinity
                Object.keys(this.items).forEach(key => {
                    if (this.items[key].minPrice === Infinity) this.items[key].minPrice = this.items[key].lastPrice;
                });
            } catch(e) {}
        }
    };
    priceHistory.loadFromStorage();
    
    // Enhanced addRetailItem with smart price suggestions
    const originalAddRetailItem = window.addRetailItem || function() {};
    window.addRetailItem = function(name = '') {
        // Call original function first to create the row
        const result = originalAddRetailItem(name);
        
        // After row is created, add price suggestions
        setTimeout(() => {
            if (name) {
                const rows = document.querySelectorAll('#itemsContainer .form-row');
                if (rows.length > 0) {
                    const lastRow = rows[rows.length - 1];
                    const priceInput = lastRow.querySelector('.r-price');
                    const nameSelect = lastRow.querySelector('.r-name');
                    
                    if (nameSelect && priceInput) {
                        // Find stock item for cost
                        let stockCost = 0;
                        if (allStock) {
                            for (let type in allStock) {
                                for (let group in allStock[type]) {
                                    const item = allStock[type][group].find(i => 
                                        i.part_name && i.part_name.toLowerCase() === name.toLowerCase()
                                    );
                                    if (item) {
                                        stockCost = parseFloat(item.cost || 0);
                                        break;
                                    }
                                }
                                if (stockCost > 0) break;
                            }
                        }
                        
                        const suggestion = priceHistory.getPriceSuggestion(name, stockCost);
                        if (suggestion) {
                            // Show suggestion tooltip
                            priceInput.title = `Last: RM ${suggestion.lastPrice.toFixed(2)} | Range: RM ${(suggestion.minPrice || 0).toFixed(2)} - RM ${suggestion.maxPrice.toFixed(2)}${suggestion.suggestedMarkup ? ' | Markup: ' + suggestion.suggestedMarkup : ''}`;
                            priceInput.style.borderLeft = '3px solid #2ecc71';
                            
                            // Auto-fill last price if empty
                            if (!priceInput.value || priceInput.value === '0') {
                                priceInput.value = suggestion.lastPrice.toFixed(2);
                                if (typeof calcTotal === 'function') calcTotal();
                            }
                        }
                    }
                }
            }
        }, 100);
    };
    
    // Record price when retail sale is completed
    const originalSubmitRetail = window.submitRetail || function() {};
    window.submitRetail = function() {
        // Record prices before submission
        document.querySelectorAll('#itemsContainer .form-row').forEach(row => {
            const nameEl = row.querySelector('.r-name');
            const priceEl = row.querySelector('.r-price');
            if (nameEl && priceEl) {
                const itemName = nameEl.value || nameEl.textContent;
                const price = priceEl.value;
                if (itemName && price) {
                    priceHistory.recordPrice(itemName, price);
                }
            }
        });
        
        // Call original function
        return originalSubmitRetail();
    };

    // ============================================================
    // PERFORMANCE OPTIMIZATIONS & UI ENHANCEMENTS
    // ============================================================
    
    // --- SKELETON LOADING SCREENS ---
    function showSkeleton(containerId, type = 'table') {
        const container = document.getElementById(containerId);
        if (!container) return;
        
        let skeletonHTML = '';
        if (type === 'table') {
            for (let i = 0; i < 5; i++) {
                skeletonHTML += `
                    <tr class="skeleton-table-row">
                        <td><div class="skeleton skeleton-text" style="width: 80%;"></div></td>
                        <td><div class="skeleton skeleton-text" style="width: 60%;"></div></td>
                        <td><div class="skeleton skeleton-text" style="width: 70%;"></div></td>
                        <td><div class="skeleton skeleton-text" style="width: 50%;"></div></td>
                    </tr>
                `;
            }
        } else if (type === 'card') {
            skeletonHTML = `
                <div class="skeleton-card">
                    <div class="skeleton skeleton-title"></div>
                    <div class="skeleton skeleton-text"></div>
                    <div class="skeleton skeleton-text" style="width: 80%;"></div>
                    <div class="skeleton skeleton-text" style="width: 60%;"></div>
                </div>
            `;
        } else if (type === 'list') {
            for (let i = 0; i < 3; i++) {
                skeletonHTML += `
                    <div class="skeleton-card" style="margin-bottom: 10px;">
                        <div class="skeleton skeleton-text" style="width: 70%;"></div>
                        <div class="skeleton skeleton-text" style="width: 50%; margin-top: 8px;"></div>
                    </div>
                `;
            }
        }
        
        container.innerHTML = skeletonHTML;
    }
    
    // --- DEBOUNCE & THROTTLE UTILITIES ---
    function debounce(func, wait) {
        let timeout;
        return function executedFunction(...args) {
            const later = () => {
                clearTimeout(timeout);
                func(...args);
            };
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    }
    
    function throttle(func, limit) {
        let inThrottle;
        return function(...args) {
            if (!inThrottle) {
                func.apply(this, args);
                inThrottle = true;
                setTimeout(() => inThrottle = false, limit);
            }
        };
    }
    
    // --- API RESPONSE CACHING ---
    const apiCache = {
        cache: new Map(),
        maxAge: 30000, // 30 seconds
        
        get: function(key) {
            const item = this.cache.get(key);
            if (!item) return null;
            if (Date.now() - item.timestamp > this.maxAge) {
                this.cache.delete(key);
                return null;
            }
            return item.data;
        },
        
        set: function(key, data) {
            this.cache.set(key, {
                data: data,
                timestamp: Date.now()
            });
            // Limit cache size
            if (this.cache.size > 50) {
                const firstKey = this.cache.keys().next().value;
                this.cache.delete(firstKey);
            }
        },
        
        clear: function() {
            this.cache.clear();
        }
    };
    
    // Enhanced apiRequest with caching
    // Save original apiRequest if it exists
    const originalApiRequest = (typeof window.apiRequest === 'function') ? window.apiRequest : 
                                (typeof apiRequest === 'function') ? apiRequest : 
                                async function(body) {
                                    const isFormData = body instanceof FormData;
                                    const opts = {
                                        method: 'POST',
                                        headers: isFormData ? { 'X-CSRF-Token': CSRF } : HEADERS,
                                        body: isFormData ? body : JSON.stringify(body)
                                    };
                                    const r = await fetch('api.php', opts);
                                    return await r.json();
                                };
    window.apiRequest = async function(body) {
        // Don't cache POST requests or state-changing actions
        const isGetRequest = !body || Object.keys(body).length === 0;
        const cacheKey = isGetRequest ? `api_${JSON.stringify(body)}` : null;
        
        // Check cache for GET requests
        if (cacheKey) {
            const cached = apiCache.get(cacheKey);
            if (cached) {
                return Promise.resolve(cached);
            }
        }
        
        try {
            const isFormData = body instanceof FormData;
            const opts = {
                method: 'POST',
                headers: isFormData ? { 'X-CSRF-Token': CSRF } : HEADERS,
                body: isFormData ? body : JSON.stringify(body)
            };
            const r = await fetch('api.php', opts);
            const result = await r.json();
            
            // Cache successful GET responses
            if (cacheKey && result.success) {
                apiCache.set(cacheKey, result);
            }
            
            return result;
        } catch (e) {
            return { success: false, error: 'Network Error' };
        }
    };
    
    // --- LAZY LOADING FOR IMAGES ---
    if ('IntersectionObserver' in window) {
        const imageObserver = new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    const img = entry.target;
                    if (img.dataset.src) {
                        img.src = img.dataset.src;
                        img.removeAttribute('data-src');
                        observer.unobserve(img);
                    }
                }
            });
        });
        
        // Observe all images with data-src
        document.querySelectorAll('img[data-src]').forEach(img => {
            imageObserver.observe(img);
        });
    }
    
    // --- ENHANCED EMPTY STATES ---
    function showEmptyState(containerId, options = {}) {
        const container = document.getElementById(containerId);
        if (!container) return;
        
        const {
            icon = '📦',
            title = 'No items found',
            message = 'Get started by adding your first item.',
            actionText = 'Add Item',
            actionCallback = null
        } = options;
        
        container.innerHTML = `
            <div class="empty-state">
                <div class="empty-state-icon">${icon}</div>
                <div class="empty-state-title">${title}</div>
                <div class="empty-state-text">${message}</div>
                ${actionCallback ? `
                    <button class="btn btn-primary empty-state-action" onclick="${actionCallback}">
                        ${actionText}
                    </button>
                ` : ''}
            </div>
        `;
    }
    
    // --- VULNERABILITY MANAGEMENT ---
    const securityScanner = {
        // Check for common vulnerabilities
        scan: function() {
            const issues = [];
            
            // Check for inline event handlers (XSS risk)
            const inlineHandlers = document.querySelectorAll('[onclick], [onerror], [onload]');
            if (inlineHandlers.length > 0) {
                issues.push({
                    type: 'warning',
                    message: `${inlineHandlers.length} inline event handlers found (consider using addEventListener)`,
                    severity: 'medium'
                });
            }
            
            // Check for external scripts without integrity
            const externalScripts = document.querySelectorAll('script[src]');
            externalScripts.forEach(script => {
                if (script.src.startsWith('http') && !script.hasAttribute('integrity')) {
                    issues.push({
                        type: 'info',
                        message: `External script without integrity: ${script.src}`,
                        severity: 'low'
                    });
                }
            });
            
            // Log issues (in production, send to monitoring service)
            if (issues.length > 0 && console && console.group) {
                console.group('🔒 Security Scan Results');
                issues.forEach(issue => {
                    console[issue.type](`[${issue.severity.toUpperCase()}] ${issue.message}`);
                });
                console.groupEnd();
            }
            
            return issues;
        },
        
        // Run scan on page load (development only)
        init: function() {
            // Only run in development (check for localhost or dev domain)
            const isDev = window.location.hostname === 'localhost' || 
                         window.location.hostname.includes('dev') ||
                         window.location.hostname.includes('test');
            
            if (isDev) {
                setTimeout(() => this.scan(), 2000);
            }
        }
    };
    
    // Initialize security scanner
    securityScanner.init();
    
    // --- ENHANCED LOADING INDICATORS ---
    function showLoadingState(elementId, message = 'Loading...') {
        const element = document.getElementById(elementId);
        if (!element) return;
        
        element.innerHTML = `
            <div style="text-align: center; padding: 40px 20px;">
                <div class="loading-spinner" style="margin: 0 auto 20px;"></div>
                <div style="color: var(--text-secondary); font-size: var(--font-sm);">${message}</div>
            </div>
        `;
    }
    
    // --- OPTIMIZED SEARCH WITH DEBOUNCING ---
    const _searchHandlers = {
        searchInput: filterJobs,
        retailSearchInput: filterRetailHistory,
        billingSearch: filterBilling,
        stockSearchInput: filterStockList
    };
    Object.entries(_searchHandlers).forEach(([id, handler]) => {
        const input = document.getElementById(id);
        if (input) {
            const debouncedHandler = debounce(handler, 250);
            input.onkeyup = debouncedHandler;
            input.oninput = debouncedHandler;
        }
    });

    const _debouncedSearchCustomer = debounce(function(val, type) {
        searchCustomer(val, type);
    }, 400);
    document.querySelectorAll('#rep_phone, #ret_phone').forEach(input => {
        const type = input.id === 'rep_phone' ? 'rep' : 'ret';
        input.onkeyup = function() { _debouncedSearchCustomer(this.value, type); };
    });
    
    // --- PERFORMANCE MONITORING ---
    if ('PerformanceObserver' in window) {
        try {
            const perfObserver = new PerformanceObserver((list) => {
                for (const entry of list.getEntries()) {
                    // Log slow API calls (> 1 second)
                    if (entry.entryType === 'resource' && entry.name.includes('api.php')) {
                        if (entry.duration > 1000) {
                            console.warn(`Slow API call: ${entry.name} took ${entry.duration.toFixed(0)}ms`);
                        }
                    }
                }
            });
            perfObserver.observe({ entryTypes: ['resource'] });
        } catch (e) {
            // PerformanceObserver not supported
        }
    }
    
    // --- SUCCESS ANIMATIONS ---
    function showSuccessAnimation(element) {
        if (!element) return;
        
        const checkmark = document.createElement('div');
        checkmark.className = 'success-checkmark';
        checkmark.style.cssText = 'position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 1000;';
        
        element.style.position = 'relative';
        element.appendChild(checkmark);
        
        setTimeout(() => {
            checkmark.remove();
        }, 1000);
    }
    
    // --- SMOOTH SCROLL TO ELEMENT ---
    function smoothScrollTo(elementId) {
        const element = document.getElementById(elementId);
        if (element) {
            element.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
        }
    }
    
    // --- ENHANCED TOAST WITH ACTIONS ---
    const originalShowToast = window.showToast || function() {};
    window.showToast = function(message, type = 'success', duration = 4000, action = null) {
        originalShowToast(message, type);
        
        // If action provided, add action button to toast
        if (action && action.text && action.callback) {
            setTimeout(() => {
                const toasts = document.querySelectorAll('.toast');
                const lastToast = toasts[toasts.length - 1];
                if (lastToast) {
                    const actionBtn = document.createElement('button');
                    actionBtn.textContent = action.text;
                    actionBtn.style.cssText = 'margin-left: 10px; padding: 4px 12px; background: white; border: 1px solid currentColor; border-radius: 4px; cursor: pointer; font-size: 0.85rem;';
                    actionBtn.onclick = () => {
                        action.callback();
                        lastToast.remove();
                    };
                    lastToast.appendChild(actionBtn);
                }
            }, 100);
        }
    };

    // ============================================================
    // INVENTORY MANAGEMENT FUNCTIONS
    // ============================================================
    
    function showLowStockAlerts() {
        document.getElementById('lowStockAlertsModal').style.display = 'flex';
        loadLowStockAlerts();
    }
    
    function loadLowStockAlerts() {
        const branch = document.getElementById('lowStockBranchFilter')?.value || 'all';
        apiRequest({ action: 'get_low_stock_alerts', branch: branch }).then(d => {
            if (d.success) {
                const alerts = d.alerts || [];
                const content = document.getElementById('lowStockAlertsContent');
                
                // Update count badge
                document.getElementById('lowStockCount').textContent = alerts.length;
                
                if (alerts.length === 0) {
                    content.innerHTML = '<div class="empty-state"><div class="empty-state-icon">✅</div><div class="empty-state-title">All Stock Levels Good!</div><div class="empty-state-text">No items are below reorder points.</div></div>';
                    return;
                }
                
                let html = '<div class="table-container"><table style="width:100%;"><thead><tr><th>Item</th><th>Type</th><th>Category</th><th>Supplier</th><th>Stock (Gombak)</th><th>Stock (SR)</th><th>Status</th></tr></thead><tbody>';
                
                alerts.forEach(item => {
                    const statusBadges = item.status.map(s => 
                        `<span style="background:${s.level === 'critical' ? '#e74c3c' : '#f39c12'}; color:white; padding:2px 6px; border-radius:4px; font-size:0.75rem; margin:2px;">${s.branch}: ${s.stock} (${s.level})</span>`
                    ).join(' ');
                    
                    html += `<tr>
                        <td>${escapeHtml(item.part_name)}</td>
                        <td>${escapeHtml(item.type)}</td>
                        <td>${escapeHtml(item.category)}</td>
                        <td>${escapeHtml(item.supplier || '-')}</td>
                        <td style="text-align:center; ${item.stock_gombak <= item.threshold_gombak ? 'color:#e74c3c; font-weight:bold;' : item.stock_gombak <= item.reorder_gombak ? 'color:#f39c12;' : ''}">${item.stock_gombak}</td>
                        <td style="text-align:center; ${item.stock_sr <= item.threshold_sr ? 'color:#e74c3c; font-weight:bold;' : item.stock_sr <= item.reorder_sr ? 'color:#f39c12;' : ''}">${item.stock_sr}</td>
                        <td>${statusBadges}</td>
                    </tr>`;
                });
                
                html += '</tbody></table></div>';
                content.innerHTML = html;
            } else {
                showToast('Failed to load low stock alerts: ' + (d.error || 'Unknown error'), 'error');
            }
        }).catch(err => {
            console.error('Error loading low stock alerts:', err);
            showToast('Error loading low stock alerts', 'error');
        });
    }
    
    function showStockValuation() {
        document.getElementById('stockValuationModal').style.display = 'flex';
        apiRequest({ action: 'get_stock_valuation' }).then(d => {
            if (d.success) {
                const totals = d.totals || {};
                const valuation = d.valuation || [];
                
                document.getElementById('valGombak').textContent = 'RM ' + totals.gombak_value.toFixed(2);
                document.getElementById('valSR').textContent = 'RM ' + totals.sr_value.toFixed(2);
                document.getElementById('valTotal').textContent = 'RM ' + totals.total_value.toFixed(2);
                
                const content = document.getElementById('stockValuationContent');
                let html = '<div class="table-container"><table style="width:100%;"><thead><tr><th>Type</th><th>Category</th><th>Gombak Value</th><th>Sri Rampai Value</th><th>Total Value</th><th>Items</th><th>Total Qty</th></tr></thead><tbody>';
                
                valuation.forEach(v => {
                    html += `<tr>
                        <td>${escapeHtml(v.type)}</td>
                        <td>${escapeHtml(v.category)}</td>
                        <td style="text-align:right;">RM ${parseFloat(v.value_gombak).toFixed(2)}</td>
                        <td style="text-align:right;">RM ${parseFloat(v.value_sr).toFixed(2)}</td>
                        <td style="text-align:right; font-weight:bold;">RM ${parseFloat(v.total_value).toFixed(2)}</td>
                        <td style="text-align:center;">${v.item_count}</td>
                        <td style="text-align:center;">${parseInt(v.qty_gombak) + parseInt(v.qty_sr)}</td>
                    </tr>`;
                });
                
                html += '</tbody></table></div>';
                content.innerHTML = html;
            } else {
                showToast('Failed to load stock valuation: ' + (d.error || 'Unknown error'), 'error');
            }
        }).catch(err => {
            console.error('Error loading stock valuation:', err);
            showToast('Error loading stock valuation', 'error');
        });
    }
    
    function showPurchaseOrders() {
        document.getElementById('purchaseOrdersModal').style.display = 'flex';
        loadPurchaseOrders();
    }
    
    function loadPurchaseOrders() {
        const status = document.getElementById('poStatusFilter')?.value || 'all';
        apiRequest({ action: 'get_purchase_orders', status: status }).then(d => {
            if (d.success) {
                const orders = d.orders || [];
                const content = document.getElementById('purchaseOrdersContent');
                
                if (orders.length === 0) {
                    content.innerHTML = '<div class="empty-state"><div class="empty-state-icon">📋</div><div class="empty-state-title">No Purchase Orders</div><div class="empty-state-text">Create your first purchase order to track inventory purchases.</div></div>';
                    return;
                }
                
                let html = '<div class="table-container"><table style="width:100%;"><thead><tr><th>PO Number</th><th>Supplier</th><th>Order Date</th><th>Expected Date</th><th>Items</th><th>Total Amount</th><th>Status</th><th>Actions</th></tr></thead><tbody>';
                
                orders.forEach(order => {
                    const statusColor = order.status === 'Received' ? '#2ecc71' : order.status === 'Pending' ? '#f39c12' : '#95a5a6';
                    html += `<tr>
                        <td><strong>${escapeHtml(order.po_number)}</strong></td>
                        <td>${escapeHtml(order.supplier)}</td>
                        <td>${order.order_date}</td>
                        <td>${order.expected_date || '-'}</td>
                        <td style="text-align:center;">${order.item_count || 0}</td>
                        <td style="text-align:right;">RM ${parseFloat(order.total_amount || 0).toFixed(2)}</td>
                        <td><span style="background:${statusColor}; color:white; padding:2px 8px; border-radius:4px; font-size:0.85rem;">${order.status}</span></td>
                        <td><button class="btn-action" onclick="viewPurchaseOrder(${order.id})" title="View Details">👁️</button></td>
                    </tr>`;
                });
                
                html += '</tbody></table></div>';
                content.innerHTML = html;
            } else {
                showToast('Failed to load purchase orders: ' + (d.error || 'Unknown error'), 'error');
            }
        }).catch(err => {
            console.error('Error loading purchase orders:', err);
            showToast('Error loading purchase orders', 'error');
        });
    }
    
    function createPurchaseOrder() {
        // Placeholder - will implement full PO creation later
        showToast('Purchase Order creation coming soon!', 'info');
    }
    
    function viewPurchaseOrder(poId) {
        // Placeholder - will implement PO details view later
        showToast('Purchase Order details coming soon!', 'info');
    }
    
    function showInventoryAnalytics() {
        document.getElementById('inventoryAnalyticsModal').style.display = 'flex';
        loadInventoryAnalytics();
    }
    
    function loadInventoryAnalytics() {
        const days = parseInt(document.getElementById('analyticsDays')?.value || 90);
        apiRequest({ action: 'get_inventory_analytics', days: days }).then(d => {
            if (d.success) {
                const analytics = d.analytics || [];
                const deadStock = d.dead_stock || [];
                const abcAnalysis = d.abc_analysis || {};
                const summary = d.summary || {};
                
                const content = document.getElementById('inventoryAnalyticsContent');
                
                let html = `<div class="summary-stats" style="margin:20px 0;">
                    <div class="stat-card"><h2 style="color:#3498db;">${summary.total_items || 0}</h2><small>Total Items</small></div>
                    <div class="stat-card"><h2 style="color:#e74c3c;">${summary.dead_stock_count || 0}</h2><small>Dead Stock</small></div>
                    <div class="stat-card"><h2 style="color:#2ecc71;">RM ${(summary.total_revenue || 0).toFixed(2)}</h2><small>Total Revenue</small></div>
                    <div class="stat-card"><h2 style="color:#9b59b6;">${summary.period_days || 0}</h2><small>Days Analyzed</small></div>
                </div>`;
                
                // ABC Analysis
                html += '<div class="card" style="margin-top:20px;"><div class="section-title">📊 ABC ANALYSIS</div>';
                ['A', 'B', 'C'].forEach(abc => {
                    const items = abcAnalysis[abc] || [];
                    if (items.length > 0) {
                        html += `<h4 style="color:${abc === 'A' ? '#e74c3c' : abc === 'B' ? '#f39c12' : '#3498db'}; margin:10px 0;">Class ${abc} (${items.length} items - ${abc === 'A' ? 'Top 80%' : abc === 'B' ? 'Next 15%' : 'Remaining 5%'})</h4>`;
                        html += '<div class="table-container" style="max-height:200px; overflow-y:auto; margin-bottom:15px;"><table style="width:100%; font-size:0.85rem;"><thead><tr><th>Item</th><th>Turnover Rate</th><th>Revenue</th><th>Stock</th></tr></thead><tbody>';
                        items.slice(0, 10).forEach(item => {
                            html += `<tr>
                                <td>${escapeHtml(item.part_name)}</td>
                                <td style="text-align:center;">${parseFloat(item.turnover_rate || 0).toFixed(2)}</td>
                                <td style="text-align:right;">RM ${parseFloat(item.revenue || 0).toFixed(2)}</td>
                                <td style="text-align:center;">${(parseInt(item.stock_gombak || 0) + parseInt(item.stock_sr || 0))}</td>
                            </tr>`;
                        });
                        html += '</tbody></table></div>';
                    }
                });
                html += '</div>';
                
                // Dead Stock
                if (deadStock.length > 0) {
                    html += '<div class="card" style="margin-top:20px; border-left:4px solid #e74c3c;"><div class="section-title" style="color:#e74c3c;">⚠️ DEAD STOCK (No sales in last ' + days + ' days)</div>';
                    html += '<div class="table-container" style="max-height:300px; overflow-y:auto;"><table style="width:100%; font-size:0.85rem;"><thead><tr><th>Item</th><th>Type</th><th>Days Since Sold</th><th>Current Stock</th><th>Value (RM)</th></tr></thead><tbody>';
                    deadStock.slice(0, 20).forEach(item => {
                        const stockValue = (parseInt(item.stock_gombak || 0) + parseInt(item.stock_sr || 0)) * parseFloat(item.cost || 0);
                        html += `<tr>
                            <td>${escapeHtml(item.part_name)}</td>
                            <td>${escapeHtml(item.type)}</td>
                            <td style="text-align:center;">${item.days_since_sold || 0}</td>
                            <td style="text-align:center;">${(parseInt(item.stock_gombak || 0) + parseInt(item.stock_sr || 0))}</td>
                            <td style="text-align:right;">RM ${stockValue.toFixed(2)}</td>
                        </tr>`;
                    });
                    html += '</tbody></table></div></div>';
                }
                
                content.innerHTML = html;
            } else {
                showToast('Failed to load inventory analytics: ' + (d.error || 'Unknown error'), 'error');
            }
        }).catch(err => {
            console.error('Error loading inventory analytics:', err);
            showToast('Error loading inventory analytics', 'error');
        });
    }
    
    // Parallel page initialization
    (async function initPage() {
        const stockPromise = fetchStock().then(() => { _stockLoaded = true; });
        const retailPromise = fetchRetailHistory();
        const lowStockPromise = apiRequest({ action: 'get_low_stock_alerts', branch: 'all' }).then(d => {
            if (d.success) {
                const el = document.getElementById('lowStock');
                if (el) el.textContent = d.count || 0;
            }
        }).catch(() => {});

        // Show the retail tab immediately (UI-only, data loads in parallel)
        document.querySelectorAll('.main-tab').forEach(el => el.classList.add('d-none'));
        document.querySelectorAll('.mode-btn').forEach(el => el.classList.remove('active'));
        document.getElementById('retailMode').classList.remove('d-none');
        document.getElementById('tabRetail').classList.add('active');

        await Promise.all([stockPromise, retailPromise, lowStockPromise]);
        updateTodaysSummary();
    })();

    // ==============================================================
    // === v18.0 ARCHIVE CONSOLE - client module ====================
    // ==============================================================
    let archState = {
        scope: 'dropoff',
        subtab: 'dropoff',
        page: 1,
        pageSize: 50,
        previewCount: null,
        initialised: false,
    };

    function archScopeForApi(subtab) {
        // 'retail' and 'retail-billing' both hit scope=retail on the backend
        if (subtab === 'retail-billing') return 'retail';
        return subtab;
    }

    function archInitIfNeeded() {
        if (archState.initialised) return;
        archState.initialised = true;
    }

    function archSwitchSubtab(subtab) {
        archState.subtab = subtab;
        archState.scope = archScopeForApi(subtab);
        archState.page = 1;
        document.querySelectorAll('.arch-subtab').forEach(el => {
            const active = el.getAttribute('data-scope') === subtab;
            el.style.borderBottom = active ? '3px solid #8e44ad' : '3px solid transparent';
            el.style.fontWeight = active ? 'bold' : 'normal';
            el.classList.toggle('active', active);
        });
        // Reset filters that don't apply to all scopes
        const dateFrom = document.getElementById('archDateFrom');
        const dateTo = document.getElementById('archDateTo');
        if (dateFrom) dateFrom.value = '';
        if (dateTo) dateTo.value = '';
        const search = document.getElementById('archSearch');
        if (search) search.value = '';
        archReload();
    }

    let _archDebounceTimer = null;
    function archDebouncedReload() {
        clearTimeout(_archDebounceTimer);
        _archDebounceTimer = setTimeout(() => archReload(), 350);
    }

    async function archReload() {
        const scope = archState.scope;
        const search = document.getElementById('archSearch').value.trim();
        const dateFrom = document.getElementById('archDateFrom').value;
        const dateTo = document.getElementById('archDateTo').value;
        const qs = new URLSearchParams({
            action: 'archive_list',
            scope,
            page: archState.page,
            page_size: archState.pageSize,
            search,
            date_from: dateFrom,
            date_to: dateTo,
            t: Date.now(),
        });

        const body = document.getElementById('archTableBody');
        body.innerHTML = '<tr><td colspan="9" style="text-align:center; padding:20px; color:#999;">Loading…</td></tr>';

        try {
            const r = await fetch('api.php?' + qs.toString());
            const d = await r.json();
            if (!d.success) {
                body.innerHTML = '<tr><td colspan="9" style="text-align:center; padding:20px; color:#e74c3c;">' + escapeHtml(d.error || 'Failed to load archive.') + '</td></tr>';
                return;
            }
            archRenderHead(scope, archState.subtab);
            archRenderRows(scope, archState.subtab, d.rows || []);
            archRenderPager(d.total || 0, d.page || 1, d.page_size || 50);
            archRenderStats(d);
        } catch (e) {
            body.innerHTML = '<tr><td colspan="9" style="text-align:center; padding:20px; color:#e74c3c;">Network error: ' + escapeHtml(String(e)) + '</td></tr>';
        }
    }

    function archRenderHead(scope, subtab) {
        const head = document.getElementById('archTableHead');
        let cols;
        if (scope === 'dropoff' || scope === 'retail') {
            if (subtab === 'retail-billing') {
                cols = ['Job ID', 'Date', 'Customer', 'Phone', 'Model', 'Price', 'Payment', 'Status', 'Actions'];
            } else {
                cols = ['Job ID', 'Date', 'Customer', 'Phone', 'Model', 'Repair / Items', 'Price', 'Status', 'Actions'];
            }
        } else if (scope === 'expenses') {
            cols = ['ID', 'Date', 'Branch', 'Description', 'Amount', 'Created By', 'Actions'];
        } else if (scope === 'activity_logs') {
            cols = ['ID', 'When', 'User', 'Action', 'Description', 'Actions'];
        } else {
            cols = ['ID', 'When', 'Info', 'Actions'];
        }
        head.innerHTML = '<tr>' + cols.map(c => '<th>' + c + '</th>').join('') + '</tr>';
    }

    function archRenderRows(scope, subtab, rows) {
        const body = document.getElementById('archTableBody');
        if (rows.length === 0) {
            const colspan = (scope === 'expenses') ? 7 : (scope === 'activity_logs') ? 6 : 9;
            body.innerHTML = '<tr><td colspan="' + colspan + '" style="text-align:center; padding:20px; color:#999;">No archived rows in range.</td></tr>';
            return;
        }
        body.innerHTML = rows.map(row => {
            const restoreBtn = '<button class="btn-action" title="Restore to live" style="color:#27ae60;" onclick="archRestoreOne(\'' + scope + '\', ' + (row.id || 0) + ')">↩️</button>';
            if (scope === 'dropoff' || scope === 'retail') {
                if (subtab === 'retail-billing') {
                    return '<tr>' +
                        '<td><code style="background:#ecf0f1; padding:2px 6px; border-radius:3px;">' + escapeHtml(row.job_id || '') + '</code></td>' +
                        '<td>' + escapeHtml(row.date || '') + '</td>' +
                        '<td>' + escapeHtml(row.customer || '') + '</td>' +
                        '<td>' + escapeHtml(row.phone || '') + '</td>' +
                        '<td>' + escapeHtml(row.model || '') + '</td>' +
                        '<td>RM ' + escapeHtml(row.price || '0') + '</td>' +
                        '<td>' + escapeHtml(row.payment_method || '-') + ' / ' + escapeHtml(row.payment_status || '-') + '</td>' +
                        '<td>' + escapeHtml(row.status || '-') + '</td>' +
                        '<td>' + restoreBtn + '</td>' +
                        '</tr>';
                }
                return '<tr>' +
                    '<td><code style="background:#ecf0f1; padding:2px 6px; border-radius:3px;">' + escapeHtml(row.job_id || '') + '</code></td>' +
                    '<td>' + escapeHtml(row.date || '') + '</td>' +
                    '<td>' + escapeHtml(row.customer || '') + '</td>' +
                    '<td>' + escapeHtml(row.phone || '') + '</td>' +
                    '<td>' + escapeHtml(row.model || '') + '</td>' +
                    '<td style="max-width:300px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;" title="' + escapeHtml(row.repair || '') + '">' + escapeHtml((row.repair || '').substring(0, 80)) + '</td>' +
                    '<td>RM ' + escapeHtml(row.price || '0') + '</td>' +
                    '<td>' + escapeHtml(row.status || '-') + '</td>' +
                    '<td>' + restoreBtn + '</td>' +
                    '</tr>';
            }
            if (scope === 'expenses') {
                return '<tr>' +
                    '<td>' + escapeHtml(String(row.id || '')) + '</td>' +
                    '<td>' + escapeHtml(row.date || '') + '</td>' +
                    '<td>' + escapeHtml(row.branch || '') + '</td>' +
                    '<td>' + escapeHtml(row.description || '') + '</td>' +
                    '<td>RM ' + escapeHtml(String(row.amount || '0')) + '</td>' +
                    '<td>' + escapeHtml(row.created_by || '') + '</td>' +
                    '<td>' + restoreBtn + '</td>' +
                    '</tr>';
            }
            if (scope === 'activity_logs') {
                return '<tr>' +
                    '<td>' + escapeHtml(String(row.id || '')) + '</td>' +
                    '<td>' + escapeHtml(row.created_at || '') + '</td>' +
                    '<td>' + escapeHtml(row.username || row.user || '') + '</td>' +
                    '<td>' + escapeHtml(row.action || '') + '</td>' +
                    '<td>' + escapeHtml(row.description || '') + '</td>' +
                    '<td>' + restoreBtn + '</td>' +
                    '</tr>';
            }
            return '<tr><td colspan="9">' + escapeHtml(JSON.stringify(row)) + '</td></tr>';
        }).join('');
    }

    function archRenderPager(total, page, pageSize) {
        const pages = Math.max(1, Math.ceil(total / pageSize));
        const pager = document.getElementById('archPager');
        const from = total === 0 ? 0 : ((page - 1) * pageSize + 1);
        const to = Math.min(total, page * pageSize);
        pager.innerHTML =
            '<div style="color:#666; font-size:0.85rem;">Showing <b>' + from + '–' + to + '</b> of <b>' + total + '</b> archived rows</div>' +
            '<div style="display:flex; gap:6px; align-items:center;">' +
                '<button class="btn" style="width:auto; padding:6px 12px; margin:0; background:#ecf0f1; color:#333;" ' + (page <= 1 ? 'disabled' : '') + ' onclick="archGotoPage(' + (page - 1) + ')">◀ Prev</button>' +
                '<span style="color:#666;">Page <b>' + page + '</b> / ' + pages + '</span>' +
                '<button class="btn" style="width:auto; padding:6px 12px; margin:0; background:#ecf0f1; color:#333;" ' + (page >= pages ? 'disabled' : '') + ' onclick="archGotoPage(' + (page + 1) + ')">Next ▶</button>' +
            '</div>';
    }

    function archGotoPage(p) {
        archState.page = Math.max(1, p);
        archReload();
    }

    function archRenderStats(d) {
        const strip = document.getElementById('archStatStrip');
        const label = d.label || archState.scope;
        strip.innerHTML =
            '<div style="background:#f4ecf7; color:#8e44ad; padding:6px 12px; border-radius:6px; font-weight:bold;">' + escapeHtml(label) + '</div>' +
            '<div style="background:#ecf0f1; padding:6px 12px; border-radius:6px;">Total archived: <b>' + (d.total || 0) + '</b></div>';
    }

    // === Move dialog ===
    function archOpenMoveDialog() {
        const scope = archState.scope;
        const labelMap = { dropoff: 'Drop-off Repairs', retail: 'Retail Sales / Billing', expenses: 'Expenses', activity_logs: 'Activity Logs' };
        document.getElementById('archMoveScopeLabel').textContent = 'Scope: ' + (labelMap[scope] || scope);
        // Default days based on scope (conservative tier)
        const defaultDays = { dropoff: 730, retail: 365, expenses: 1825, activity_logs: 365 };
        document.getElementById('archMoveDays').value = defaultDays[scope] || 365;
        // Hide status filter for non-job scopes
        const statusLabel = document.getElementById('archMoveStatusLabel');
        const statusSel = document.getElementById('archMoveStatus');
        const branchSel = document.getElementById('archMoveBranch');
        const showStatus = (scope === 'dropoff' || scope === 'retail');
        statusLabel.style.display = showStatus ? '' : 'none';
        statusSel.style.display = showStatus ? '' : 'none';
        const showBranch = (scope === 'dropoff' || scope === 'retail' || scope === 'expenses');
        branchSel.parentElement.style.display = showBranch ? '' : 'none';

        statusSel.value = 'all';
        branchSel.value = 'all';
        document.getElementById('archPreviewResult').textContent = '';
        document.getElementById('archConfirmTokenBox').style.display = 'none';
        document.getElementById('archConfirmToken').value = '';
        archState.previewCount = null;
        document.getElementById('archMoveModal').style.display = 'flex';
    }

    function archCloseMoveDialog() {
        document.getElementById('archMoveModal').style.display = 'none';
    }

    async function archPreview() {
        const scope = archState.scope;
        const qs = new URLSearchParams({
            action: 'archive_preview',
            scope,
            days: document.getElementById('archMoveDays').value || '365',
            status: document.getElementById('archMoveStatus').value,
            branch: document.getElementById('archMoveBranch').value,
            t: Date.now(),
        });
        const resultEl = document.getElementById('archPreviewResult');
        resultEl.textContent = 'Calculating…';
        try {
            const r = await fetch('api.php?' + qs.toString());
            const d = await r.json();
            if (!d.success) { resultEl.textContent = '❌ ' + (d.error || 'Failed'); return; }
            archState.previewCount = d.count || 0;
            resultEl.textContent = '→ ' + d.count + ' row(s) would be archived';
            if (d.count > 500) {
                const tokenBox = document.getElementById('archConfirmTokenBox');
                document.getElementById('archConfirmTokenExpected').textContent = 'ARCHIVE ' + d.count;
                tokenBox.style.display = 'block';
            } else {
                document.getElementById('archConfirmTokenBox').style.display = 'none';
            }
        } catch (e) {
            resultEl.textContent = '❌ Network error';
        }
    }

    async function archDoMove() {
        const scope = archState.scope;
        const payload = {
            action: 'archive_move',
            scope,
            days: parseInt(document.getElementById('archMoveDays').value || '365', 10),
            status: document.getElementById('archMoveStatus').value,
            branch: document.getElementById('archMoveBranch').value,
            confirm_token: document.getElementById('archConfirmToken').value.trim(),
            csrf_token: CSRF,
        };
        if (!confirm('Archive ' + (archState.previewCount !== null ? archState.previewCount : '?') + ' row(s)? This is reversible via Restore.')) return;
        const d = await apiRequest(payload);
        if (!d.success) {
            showToast('❌ ' + (d.error || 'Archive failed'), 'error');
            return;
        }
        showToast('✅ Archived ' + (d.moved || 0) + ' row(s) from ' + (d.label || scope), 'success');
        archCloseMoveDialog();
        archReload();
    }

    async function archRestoreOne(scope, archiveId) {
        if (!confirm('Restore this archived row back into the live table?')) return;
        const d = await apiRequest({
            action: 'archive_restore_one',
            scope,
            archive_id: archiveId,
            csrf_token: CSRF,
        });
        if (!d.success) { showToast('❌ ' + (d.error || 'Restore failed'), 'error'); return; }
        showToast('✅ Restored 1 row back to live table.', 'success');
        archReload();
    }

    // Expose for inline onclick handlers
    window.archSwitchSubtab = archSwitchSubtab;
    window.archDebouncedReload = archDebouncedReload;
    window.archReload = archReload;
    window.archOpenMoveDialog = archOpenMoveDialog;
    window.archCloseMoveDialog = archCloseMoveDialog;
    window.archPreview = archPreview;
    window.archDoMove = archDoMove;
    window.archRestoreOne = archRestoreOne;
    window.archGotoPage = archGotoPage;
    window.archInitIfNeeded = archInitIfNeeded;

    // ==============================================================
    // === v18.0 UNIVERSAL CLIENT-SIDE PAGINATOR =====================
    // ==============================================================
    // The Repair / Billing / Retail tabs all fetch up to 500 rows and
    // dump them straight into the DOM. As data grows, that means
    // hundreds of rows are rendered even when the user only needs to
    // see the latest 15. The paginator does NOT change how data is
    // fetched (existing filterX() and renderX() functions still work)
    // but adds a Prev/Next/PageSize bar that slices the visible rows.
    //
    // Filter functions now set row.dataset.filterHidden='1' instead of
    // row.style.display='none'. The paginator then walks the same rows
    // and decides what's actually shown.
    const _f2fPagers = {};

    function f2fInitPager(tbodyId, defaultPageSize) {
        const ctrl = document.getElementById(tbodyId + '_pgCtrl');
        if (!ctrl) return;
        if (_f2fPagers[tbodyId]) return; // idempotent
        const pageSize = defaultPageSize || 15;
        _f2fPagers[tbodyId] = { page: 1, pageSize: pageSize, tbodyId: tbodyId };
        ctrl.innerHTML =
            '<button type="button" onclick="f2fPagerNav(\'' + tbodyId + '\', -1)" ' +
                'style="padding:6px 14px; border:1px solid #bdc3c7; background:#fff; border-radius:4px; cursor:pointer; font-weight:bold;">◀ Prev</button>' +
            '<button type="button" onclick="f2fPagerNav(\'' + tbodyId + '\', 1)" ' +
                'style="padding:6px 14px; border:1px solid #bdc3c7; background:#fff; border-radius:4px; cursor:pointer; font-weight:bold;">Next ▶</button>' +
            '<label style="font-size:0.85rem; color:#666; white-space:nowrap; display:inline-flex; align-items:center; gap:6px;">Per page: ' +
                '<select id="' + tbodyId + '_pgSize" onchange="f2fSetPageSize(\'' + tbodyId + '\', this.value)" ' +
                    'style="padding:4px 6px; border:1px solid #ccc; border-radius:3px;">' +
                    '<option value="15"' + (pageSize===15?' selected':'') + '>15</option>' +
                    '<option value="30"' + (pageSize===30?' selected':'') + '>30</option>' +
                    '<option value="50"' + (pageSize===50?' selected':'') + '>50</option>' +
                    '<option value="100"' + (pageSize===100?' selected':'') + '>100</option>' +
                    '<option value="all">All</option>' +
                '</select>' +
            '</label>' +
            '<span id="' + tbodyId + '_pgInfo" style="color:#666; font-size:0.85rem;">—</span>';
    }

    function f2fSetPageSize(tbodyId, size) {
        const s = _f2fPagers[tbodyId];
        if (!s) return;
        s.pageSize = (size === 'all') ? Number.MAX_SAFE_INTEGER : (parseInt(size, 10) || 15);
        s.page = 1;
        f2fApplyPagination(tbodyId);
    }

    function f2fPagerNav(tbodyId, delta) {
        const s = _f2fPagers[tbodyId];
        if (!s) return;
        const tbody = document.getElementById(tbodyId);
        if (!tbody) return;
        let visible = 0;
        tbody.querySelectorAll('tr').forEach(r => { if (r.dataset.filterHidden !== '1') visible++; });
        const totalPages = Math.max(1, Math.ceil(visible / s.pageSize));
        s.page = Math.max(1, Math.min(totalPages, s.page + delta));
        f2fApplyPagination(tbodyId);
    }

    // Called after filter functions tag rows with data-filter-hidden.
    // Walks the tbody, hides everything outside the current page slice.
    function f2fApplyPagination(tbodyId) {
        const s = _f2fPagers[tbodyId];
        if (!s) { f2fInitPager(tbodyId, 15); return f2fApplyPagination(tbodyId); }
        const tbody = document.getElementById(tbodyId);
        if (!tbody) return;

        let totalVisible = 0;
        tbody.querySelectorAll('tr').forEach(r => { if (r.dataset.filterHidden !== '1') totalVisible++; });

        const totalPages = Math.max(1, Math.ceil(totalVisible / s.pageSize));
        if (s.page > totalPages) s.page = totalPages;

        const startIdx = (s.page - 1) * s.pageSize;
        const endIdx = startIdx + s.pageSize;

        let visibleIndex = 0;
        tbody.querySelectorAll('tr').forEach(r => {
            if (r.dataset.filterHidden === '1') {
                r.style.display = 'none';
                return;
            }
            const inPage = (visibleIndex >= startIdx && visibleIndex < endIdx);
            r.style.display = inPage ? '' : 'none';
            visibleIndex++;
        });

        const info = document.getElementById(tbodyId + '_pgInfo');
        if (info) {
            const from = totalVisible === 0 ? 0 : startIdx + 1;
            const to = Math.min(totalVisible, endIdx);
            const allMode = s.pageSize >= Number.MAX_SAFE_INTEGER;
            info.textContent = (totalVisible === 0)
                ? 'No matching rows'
                : (allMode
                    ? ('Showing all ' + totalVisible)
                    : ('Showing ' + from + '\u2013' + to + ' of ' + totalVisible + ' \u2022 Page ' + s.page + '/' + totalPages));
        }
    }

    function f2fResetPagerPage(tbodyId) {
        const s = _f2fPagers[tbodyId];
        if (s) s.page = 1;
    }

    // Init the three pagers on first script execution. Idempotent so multiple
    // tab switches don't double-bind.
    f2fInitPager('jobTableBody', 15);
    f2fInitPager('billingTableBody', 15);
    f2fInitPager('retailTableBody', 15);

    window.f2fSetPageSize = f2fSetPageSize;
    window.f2fPagerNav = f2fPagerNav;
    window.f2fApplyPagination = f2fApplyPagination;
    window.f2fResetPagerPage = f2fResetPagerPage;
</script>
</body>
</html>