<?php
// whatsapp.php — WhatsApp Business CRM (full edition)
// ============================================================
// Location: /public_html/whatsapp.php
// Access: authenticated staff only — never public
// ============================================================

require_once __DIR__ . '/session.php';          // ← MUST be first (sets PAKTIASESSID)
require_once __DIR__ . '/csrf.php';
require_once __DIR__ . '/includes/auth_guard.php';

/* ---------- HARD 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');
header('Permissions-Policy: geolocation=(self), camera=(), microphone=()');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');

/* ---------- AUTH GUARD ---------- */
if (empty($_SESSION['user_id'])) {
    if (!empty($_SERVER['HTTP_X_REQUESTED_WITH'])) {
        header('Content-Type: application/json');
        http_response_code(401);
        echo json_encode(['success' => false, 'error' => 'Unauthorized']);
        exit;
    }
    header('Location: /login.php');
    exit;
}

$allowed_roles = ['OWNER', 'ADMIN', 'FINANCE_OFFICER', 'SALES_STAFF'];
$user_role = strtoupper(trim($_SESSION['role_type'] ?? ''));
if (!in_array($user_role, $allowed_roles, true)) {
    http_response_code(403);
    die('Access Denied.');
}

/* Session idle check (uses session.php's _last_activity field) */
if (!empty($_SESSION['_last_activity']) && (time() - $_SESSION['_last_activity']) > 1800) {
    $_SESSION = [];
    session_destroy();
    header('Location: /login.php?timeout=1');
    exit;
}

/* NOTE: session_regenerate_id() block REMOVED — rotation happens once
   in ajax_login.php / auth.php at login. Rotating mid-session deletes
   the session file and breaks every in-flight AJAX poll. */

$staff_id   = $_SESSION['user_id'];
$staff_name = $_SESSION['full_name'] ?? 'Staff Member';
$staff_role = $_SESSION['role_type'] ?? 'SALES_STAFF';

require_once __DIR__ . '/db.php';
require_once __DIR__ . '/includes/dashboard_router.php';

$csrf_token = generate_csrf_token();

$unread_count = 0;
$templates    = [];
try {
    $r = $conn->query("SELECT COALESCE(SUM(unread_count),0) t FROM whatsapp_conversations WHERE status='active'")->fetch(PDO::FETCH_ASSOC);
    $unread_count = (int)($r['t'] ?? 0);

    $templates = $conn->query("SELECT id,name,message,category,shortcut FROM whatsapp_templates WHERE is_active=1 ORDER BY usage_count DESC LIMIT 20")->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
    error_log('wa init: ' . $e->getMessage());
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex, nofollow, noarchive">
<title>WhatsApp CRM — Paktia Travel</title>
<?php echo csrf_meta(); ?>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="csrf.js"></script>
<style>
* { margin:0; padding:0; box-sizing:border-box; -webkit-tap-highlight-color:transparent; }
body { font-family:'Inter',sans-serif; background:#eaf1f8; height:100vh; overflow:hidden; color:#0f1e33; }
:root {
    --wa-green:#25D366; --wa-dark:#0a3358; --wa-teal:#144a7a;
    --wa-bg:#efeae2; --wa-out:#dcf8c6; --wa-in:#fff;
    --navy:#0a3358; --navy-mid:#144a7a; --orange:#e8621f;
    --border:#d5e0ec; --border-strong:#b8c9dc;
    --shadow-sm:0 2px 8px rgba(10,51,88,0.08);
    --shadow-md:0 6px 22px rgba(10,51,88,0.14);
    --shadow-lg:0 12px 40px rgba(10,51,88,0.20);
    --trans:all 0.2s ease;
}

/* ============================================================
   HEADER
   ============================================================ */
.wa-header {
    background: linear-gradient(135deg, var(--navy) 0%, var(--navy-mid) 100%);
    color:#fff; padding:12px 20px;
    display:flex; justify-content:space-between; align-items:center;
    z-index:100; height:64px;
    box-shadow: 0 4px 16px rgba(10,51,88,.15);
}
.logo-area { display:flex; align-items:center; gap:12px; }
.mobile-menu-btn { display:none; background:rgba(255,255,255,.15); border:none; color:#fff; padding:8px 12px; border-radius:10px; cursor:pointer; }
.logo { width:40px; height:40px; background:#fff; border-radius:50%; display:flex; align-items:center; justify-content:center; overflow:hidden; box-shadow: 0 2px 8px rgba(0,0,0,.15); }
.logo img { width:100%; height:100%; object-fit:cover; }
.logo-text h2 { font-size:1rem; margin:0; font-weight:800; letter-spacing:-0.2px; }
.logo-text p { font-size:.7rem; opacity:.85; margin:0; font-weight:600; }
.user-area { display:flex; align-items:center; gap:10px; }

.session-dot {
    display:inline-flex; align-items:center; gap:6px;
    padding:5px 11px; border-radius:20px;
    background:rgba(255,255,255,.10);
    font-size:.68rem; font-weight:700;
    text-transform:uppercase; letter-spacing:.4px;
    color:#fff; opacity:.85;
}
.session-dot i { font-size:.55rem; color:#25D366; }
.session-dot.stale i { color:#f59e0b; }
.session-dot.offline i { color:#dc3545; }

.back-dash, .logout-btn {
    background:rgba(255,255,255,.15); color:#fff;
    padding:8px 14px; border-radius:22px; text-decoration:none;
    font-size:.78rem; font-weight:700;
    display:inline-flex; align-items:center; gap:6px;
    transition: var(--trans);
    border: 1px solid rgba(255,255,255,.15);
}
.back-dash:hover { background:rgba(255,255,255,.25); color:#fff; transform: translateY(-1px); }
.logout-btn { background:rgba(220,53,69,.85); border-color: rgba(220,53,69,.4); }
.logout-btn:hover { background:rgba(200,35,51,.95); color:#fff; transform: translateY(-1px); }

.user-profile {
    display:flex; align-items:center; gap:9px;
    padding:5px 12px 5px 5px; border-radius:30px;
    background:rgba(255,255,255,.12); position:relative;
}
.user-avatar {
    width:34px; height:34px; border-radius:50%;
    background: linear-gradient(135deg, var(--orange), #c44f10);
    display:flex; align-items:center; justify-content:center;
    font-weight:800; color:#fff; font-size: .9rem;
}
.user-info-name { font-size:.82rem; font-weight:700; line-height:1.1; }
.user-info-role { font-size:.65rem; opacity:.75; font-weight:600; text-transform: uppercase; letter-spacing: .5px; }
.notif-badge {
    position:absolute; top:-4px; right:-4px;
    background:#dc3545; color:#fff; border-radius:50%;
    padding:2px 6px; font-size:.62rem; font-weight:800;
    min-width:20px; text-align:center;
    border: 2px solid var(--navy);
}

/* ============================================================
   LAYOUT
   ============================================================ */
.wa-container { display:flex; height:calc(100vh - 64px); position:relative; }

/* ============================================================
   SIDEBAR
   ============================================================ */
.sidebar {
    width:390px; border-right:1px solid var(--border);
    background:#fff; display:flex; flex-direction:column;
    z-index:100; flex-shrink:0; transition:transform .3s ease;
}
.sidebar-head { padding:14px 16px; border-bottom:1px solid var(--border); background:#f8fafc; }
.staff-info {
    background: linear-gradient(135deg, #e6f0fa, #dbe9f7);
    padding:10px 14px; border-radius:10px; margin-bottom:12px;
    font-size:.75rem; color: var(--navy); font-weight:700;
    display:flex; align-items:center; gap:8px;
    border-left: 3px solid var(--navy);
}
.staff-info i { color: var(--orange); }
.btn-new {
    background: linear-gradient(135deg, var(--wa-green), #128c7e);
    border:none; color:#fff; padding:10px 14px; border-radius:12px;
    width:100%; margin-bottom:12px; cursor:pointer;
    font-weight:700; font-size:.85rem;
    display:flex; align-items:center; justify-content:center; gap:8px;
    box-shadow: 0 4px 12px rgba(37,211,102,.25);
    transition: var(--trans);
}
.btn-new:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(37,211,102,.35); }

.search-box { position:relative; margin-bottom:12px; }
.search-box i { position:absolute; left:14px; top:50%; transform:translateY(-50%); color:#94a3b8; font-size:.85rem; }
.search-box input {
    width:100%; padding:10px 40px 10px 38px;
    border:1.5px solid var(--border); border-radius:12px;
    font-size:.85rem; outline:none; font-family: inherit;
    background:#fff; font-weight:500;
    transition: var(--trans);
}
.search-box input:focus { border-color:var(--navy-mid); box-shadow: 0 0 0 3px rgba(20,74,122,.10); }
.search-clear {
    position:absolute; right:10px; top:50%; transform:translateY(-50%);
    background:none; border:none; cursor:pointer; color:#94a3b8;
    width:24px; height:24px; border-radius:50%; display:none;
    align-items:center; justify-content:center;
}
.search-clear:hover { background:#f1f5f9; color:#3d5a7a; }
.search-clear.show { display:flex; }

.filter-row {
    display:flex; gap:6px; margin-bottom:8px;
    align-items:center;
}
.filter-row .filters { flex:1; display:flex; gap:6px; flex-wrap:wrap; }
.sort-btn {
    background:#f1f5f9; border:none; border-radius:10px;
    width:36px; height:32px; cursor:pointer;
    color:var(--navy); font-size:.8rem;
    display:inline-flex; align-items:center; justify-content:center;
    transition: var(--trans);
}
.sort-btn:hover { background:#e2eaf3; }
.filter-btn {
    padding:6px 14px; border-radius:20px; font-size:.72rem;
    background:#f1f5f9; border:none; cursor:pointer;
    font-weight:700; color:#3d5a7a;
    transition: var(--trans);
}
.filter-btn:hover { background:#e2eaf3; }
.filter-btn.active { background: var(--navy); color:#fff; }

.sidebar-actions {
    display:flex; gap:6px; margin-top:10px;
    padding-top:10px; border-top:1px solid var(--border);
}
.sidebar-action {
    flex:1;
    background:#fff; border:1px solid var(--border);
    border-radius:8px; padding:6px 8px;
    font-size:.7rem; font-weight:700; color:#3d5a7a;
    cursor:pointer; transition:var(--trans);
    display:inline-flex; align-items:center; justify-content:center; gap:4px;
}
.sidebar-action:hover { background:#f1f5f9; border-color:var(--navy-mid); color:var(--navy); }
.sidebar-action i { font-size:.7rem; }

.conv-list { flex:1; overflow-y:auto; }
.conv-item {
    padding:12px 16px; border-bottom:1px solid #f1f5f9;
    cursor:pointer; display:flex; align-items:center; gap:14px;
    transition: background .12s;
    position: relative;
}
.conv-item:hover { background:#f8fbff; }
.conv-item.active {
    background: linear-gradient(90deg, #eef5fb, #f8fbff);
    border-left: 4px solid var(--orange);
    padding-left: 12px;
}
.conv-item.unread .conv-name { font-weight:800; }
.conv-item.unread .conv-preview { color:#3d5a7a; font-weight:600; }
.conv-avatar {
    width:48px; height:48px; border-radius:50%;
    background: linear-gradient(135deg, var(--navy), var(--navy-mid));
    display:flex; align-items:center; justify-content:center;
    color:#fff; font-weight:800; font-size:1.05rem; flex-shrink:0;
    letter-spacing: -.3px; position:relative;
}
.conv-avatar .priority-dot {
    position:absolute; bottom:-1px; right:-1px;
    width:12px; height:12px; border-radius:50%;
    border:2px solid #fff;
}
.priority-vip .priority-dot { background:#9333ea; }
.priority-high .priority-dot { background:#dc3545; }

.conv-info { flex:1; min-width:0; }
.conv-name { font-weight:700; font-size:.88rem; display:flex; justify-content:space-between; margin-bottom:3px; color:#0f1e33; gap:8px; }
.conv-preview { font-size:.76rem; color:#6b8095; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; font-weight:500; display:flex; align-items:center; gap:6px; }
.conv-preview .preview-icon { font-size:.7rem; color:#94a3b8; flex-shrink:0; }
.conv-time { font-size:.66rem; color:#94a3b8; font-weight:600; white-space:nowrap; }
.unread-badge {
    background: var(--wa-green); color:#fff; border-radius:50%;
    padding:2px 7px; font-size:.65rem; font-weight:800;
    min-width:22px; text-align:center;
    box-shadow: 0 2px 6px rgba(37,211,102,.35);
    flex-shrink:0;
}

/* ============================================================
   CHAT AREA
   ============================================================ */
.chat-area { flex:1; display:flex; flex-direction:column; background:var(--wa-bg); min-width:0; position:relative; }
.chat-header {
    background:#fff; padding:10px 18px; border-bottom:1px solid var(--border);
    display:flex; justify-content:space-between; align-items:center; gap:12px;
    box-shadow: 0 1px 4px rgba(10,51,88,.04);
    flex-wrap:wrap;
}
.chat-head-info { display:flex; align-items:center; gap:12px; min-width:0; flex:1; }
.chat-avatar {
    width:44px; height:44px; border-radius:50%;
    background: linear-gradient(135deg, var(--navy), var(--navy-mid));
    display:flex; align-items:center; justify-content:center;
    color:#fff; font-weight:800; font-size: 1rem; flex-shrink:0;
}
.chat-head-text { min-width:0; }
.chat-name-line { display:flex; align-items:center; gap:8px; }
.chat-name-line h6 { font-weight:800; color:var(--navy); margin:0; font-size:.95rem; }
.chat-badge {
    font-size:.6rem; padding:2px 7px; border-radius:10px;
    font-weight:800; text-transform:uppercase; letter-spacing:.3px;
}
.chat-badge.vip { background:#f3e8ff; color:#6b21a8; }
.chat-badge.high { background:#fee2e2; color:#991b1b; }
.chat-badge.closed { background:#f1f5f9; color:#64748b; }

.chat-actions { display:flex; gap:6px; flex-wrap:wrap; }
.chat-act {
    width:36px; height:36px; border-radius:10px;
    display:flex; align-items:center; justify-content:center;
    cursor:pointer; color:var(--navy); background:#f1f5f9;
    transition: var(--trans); font-size:.88rem;
    position:relative;
}
.chat-act:hover { background:#e2eaf3; transform: translateY(-1px); }
.chat-act.active { background:var(--navy); color:#fff; }

/* Filter chips row */
.chat-filter-row {
    background:#fff; border-bottom:1px solid var(--border);
    padding:6px 18px 10px;
    display:flex; gap:6px; flex-wrap:wrap; align-items:center;
    overflow-x:auto;
}
.chat-filter-row::-webkit-scrollbar { height:0; }
.chip {
    padding:5px 12px; border-radius:16px; font-size:.7rem;
    background:#f1f5f9; border:none; cursor:pointer;
    font-weight:700; color:#3d5a7a;
    transition: var(--trans);
    display:inline-flex; align-items:center; gap:5px;
    white-space:nowrap;
}
.chip:hover { background:#e2eaf3; }
.chip.active { background:var(--navy); color:#fff; }
.chip i { font-size:.65rem; }

.chat-search-bar {
    background:#fff; border-bottom:1px solid var(--border);
    padding:8px 18px; display:none;
    align-items:center; gap:10px;
}
.chat-search-bar.show { display:flex; }
.chat-search-bar input {
    flex:1; padding:8px 12px; border:1.5px solid var(--border);
    border-radius:10px; font-size:.82rem; outline:none;
    font-family:inherit;
}
.chat-search-bar input:focus { border-color:var(--navy-mid); }
.chat-search-count { font-size:.72rem; font-weight:700; color:#3d5a7a; white-space:nowrap; }
.chat-search-nav {
    display:flex; gap:4px;
}
.chat-search-nav button {
    width:28px; height:28px; border-radius:8px; border:none;
    background:#f1f5f9; cursor:pointer; color:var(--navy);
    font-size:.75rem;
}
.chat-search-nav button:hover { background:#e2eaf3; }

.chat-msgs {
    flex:1; overflow-y:auto; padding:20px;
    display:flex; flex-direction:column; gap:2px;
    background-image:
        radial-gradient(circle at 10% 20%, rgba(10,51,88,.025) 1px, transparent 1px),
        radial-gradient(circle at 80% 70%, rgba(232,98,31,.02) 1px, transparent 1px);
    background-size: 40px 40px, 60px 60px;
    position:relative;
}

/* Message wrappers */
.msg-wrap { display:flex; margin-bottom:2px; animation:fadeSlideUp .2s; }
.msg-wrap.out { justify-content:flex-end; }
.msg-wrap.group-start { margin-top:8px; }
.msg-bubble {
    max-width:70%; padding:8px 13px; border-radius:16px;
    word-wrap:break-word; box-shadow: 0 1px 2px rgba(10,51,88,.06);
    position:relative; transition:var(--trans);
}
.msg-bubble.in { background:var(--wa-in); border-bottom-left-radius:4px; }
.msg-bubble.out { background:var(--wa-out); border-bottom-right-radius:4px; }
.msg-bubble.grouped.out { border-top-right-radius:6px; border-bottom-right-radius:6px; }
.msg-bubble.grouped.in  { border-top-left-radius:6px;  border-bottom-left-radius:6px; }
.msg-wrap.grouped { margin-bottom:2px; }
.msg-wrap.group-start .msg-bubble { margin-top:2px; }

.msg-sender {
    font-size:.68rem; font-weight:800; margin-bottom:3px;
    color:var(--orange);
}
.msg-text { font-size:.86rem; line-height:1.5; word-break:break-word; color:#0f1e33; }
.msg-text a { color:var(--wa-teal); text-decoration: underline; }

.msg-quote {
    background:rgba(0,0,0,.05); border-left:3px solid var(--navy-mid);
    padding:5px 9px; border-radius:6px; margin-bottom:6px;
    font-size:.75rem; color:#3d5a7a; font-style:italic;
    max-width:100%; overflow:hidden; text-overflow:ellipsis;
    white-space:nowrap;
}

.msg-time {
    font-size:.63rem; color:#6b8095; margin-top:4px;
    text-align:right; display:flex; align-items:center;
    justify-content:flex-end; gap:4px; font-weight:600;
}

.msg-actions {
    position:absolute; top:-12px; right:8px;
    display:none; gap:2px;
    background:#fff; border-radius:8px;
    box-shadow: 0 4px 12px rgba(10,51,88,.15);
    padding:2px; z-index:10;
}
.msg-wrap:hover .msg-actions { display:flex; }
.msg-wrap.out .msg-actions { right:auto; left:8px; }
.msg-act {
    width:26px; height:26px; border-radius:6px; border:none;
    background:transparent; cursor:pointer; color:var(--navy);
    font-size:.7rem; display:flex; align-items:center; justify-content:center;
}
.msg-act:hover { background:#f1f5f9; color:var(--orange); }

/* Media */
.media-preview { max-width:250px; border-radius:10px; margin:4px 0; cursor:pointer; display: block; }
.media-preview img { width:100%; max-height:220px; border-radius:10px; object-fit:cover; }
.video-player video { width:100%; max-width:280px; border-radius:10px; }
.audio-player {
    display:flex; align-items:center; gap:8px;
    background:rgba(255,255,255,.6); padding:6px 10px;
    border-radius:20px; max-width:280px;
}
.audio-player i { color:var(--navy); }
.audio-player audio { height:28px; flex:1; }

.doc-card {
    display:flex; align-items:center; gap:12px; padding:10px 14px;
    background:#fff; border:1.5px solid var(--border);
    border-radius:12px; max-width:320px; text-decoration:none;
    transition: var(--trans);
}
.doc-card:hover { background:#f8fafc; border-color: var(--navy-mid); text-decoration:none; }
.doc-name { font-weight:800; font-size:.78rem; color: var(--navy); word-break:break-all; }
.doc-meta { font-size:.68rem; color:#6b8095; font-weight:600; }

.loc-card { padding:12px 14px; background:#fff; border:1.5px solid var(--border); border-radius:12px; max-width:280px; }
.loc-card a { text-decoration:none; color: var(--navy); display:block; font-weight: 700; }
.contact-card { padding:12px 14px; background:#fff; border:1.5px solid var(--border); border-radius:12px; max-width:240px; }

.sticker-img { max-width:120px; }

/* Date separator */
.date-sep { text-align:center; margin:18px 0 12px; }
.date-sep span {
    background:rgba(255,255,255,.9); backdrop-filter: blur(4px);
    padding:5px 14px; border-radius:20px;
    font-size:.7rem; color:#3d5a7a; font-weight:700;
    box-shadow: 0 2px 8px rgba(10,51,88,.06);
}

/* Jump to latest */
.jump-latest {
    position:absolute; bottom:110px; right:24px;
    background:var(--navy); color:#fff;
    border:none; border-radius:24px; padding:9px 16px;
    font-size:.75rem; font-weight:800;
    box-shadow: 0 6px 20px rgba(10,51,88,.3);
    cursor:pointer; display:none; align-items:center; gap:6px;
    z-index:20; transition:var(--trans);
}
.jump-latest:hover { background:var(--navy-mid); transform:translateY(-2px); }
.jump-latest.show { display:inline-flex; }
.jump-latest .count {
    background:var(--orange); border-radius:10px;
    padding:1px 7px; font-size:.65rem;
}

/* Message toolbar */
.msg-toolbar {
    display:flex; gap:4px; padding:8px 18px;
    background:#fff; border-top:1px solid var(--border);
    flex-wrap:wrap;
}
.tb-btn {
    background:transparent; border:none; width:36px; height:36px;
    border-radius:10px; cursor:pointer; color:var(--navy);
    font-size:.9rem; transition: var(--trans);
}
.tb-btn:hover { background:#f1f5f9; color: var(--orange); }

/* Compose */
.chat-input { background:#fff; padding:10px 18px 14px; border-top:1px solid var(--border); position:relative; }
.reply-preview {
    background:#f1f5f9; border-left:3px solid var(--navy-mid);
    padding:8px 12px; border-radius:8px; margin-bottom:8px;
    display:none; align-items:center; gap:10px;
}
.reply-preview.show { display:flex; }
.reply-preview .reply-body { flex:1; min-width:0; }
.reply-preview .reply-name { font-size:.68rem; font-weight:800; color:var(--orange); }
.reply-preview .reply-text {
    font-size:.75rem; color:#3d5a7a; white-space:nowrap;
    overflow:hidden; text-overflow:ellipsis;
}
.reply-preview button {
    background:none; border:none; color:#94a3b8; cursor:pointer;
    width:24px; height:24px; border-radius:50%;
}
.reply-preview button:hover { background:#e2eaf3; color:#3d5a7a; }

.input-wrap {
    display:flex; gap:10px; align-items:flex-end;
    background:#f1f5f9; border-radius:24px;
    padding:6px 8px 6px 16px; position:relative;
}
.msg-input {
    flex:1; border:none; background:transparent; padding:10px 4px;
    resize:none; font-family:inherit; font-size:.88rem;
    max-height:120px; outline:none; font-weight: 500;
}
.char-counter {
    position:absolute; right:56px; bottom:-18px;
    font-size:.65rem; color:#94a3b8; font-weight:700;
    display:none;
}
.char-counter.show { display:block; }
.char-counter.warn { color:#f59e0b; }
.char-counter.danger { color:#dc3545; }

.send-btn {
    background: linear-gradient(135deg, var(--wa-green), #128c7e);
    color:#fff; border:none; width:40px; height:40px;
    border-radius:50%; cursor:pointer; flex-shrink: 0;
    box-shadow: 0 3px 10px rgba(37,211,102,.3);
    transition: var(--trans);
}
.send-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 5px 15px rgba(37,211,102,.4); }
.send-btn:disabled { opacity:.5; cursor:not-allowed; }

/* Empty state */
.empty-state { text-align:center; padding:60px 20px; color:#94a3b8; margin:auto; }
.empty-state i { font-size:3.2rem; margin-bottom:16px; opacity:.5; display: block; }
.empty-state h5 { color: var(--navy); font-weight: 800; }
.empty-state p { font-size:.85rem; }

/* ============================================================
   INFO PANEL (right slide-out)
   ============================================================ */
.info-panel {
    position:absolute; top:0; right:0; bottom:0;
    width:340px; background:#fff;
    border-left:1px solid var(--border);
    box-shadow: -8px 0 24px rgba(10,51,88,.08);
    transform:translateX(100%);
    transition:transform .25s ease;
    display:flex; flex-direction:column;
    z-index:60;
}
.info-panel.show { transform:translateX(0); }
.info-panel-head {
    background: linear-gradient(135deg, var(--navy), var(--navy-mid));
    color:#fff; padding:16px 18px;
    display:flex; align-items:center; justify-content:space-between;
}
.info-panel-head h6 { margin:0; font-weight:800; font-size:.9rem; }
.info-panel-head button {
    background:rgba(255,255,255,.15); border:none; color:#fff;
    width:28px; height:28px; border-radius:8px; cursor:pointer;
}
.info-panel-body { flex:1; overflow-y:auto; padding:18px; }
.info-customer {
    text-align:center; padding-bottom:16px;
    border-bottom:1px solid var(--border); margin-bottom:16px;
}
.info-customer-avatar {
    width:72px; height:72px; border-radius:50%;
    background: linear-gradient(135deg, var(--navy), var(--navy-mid));
    color:#fff; font-size:1.6rem; font-weight:800;
    display:flex; align-items:center; justify-content:center;
    margin:0 auto 10px;
}
.info-customer-name { font-weight:800; font-size:.95rem; color:var(--navy); }
.info-customer-phone { font-size:.75rem; color:#6b8095; font-weight:600; }

.info-stats {
    display:grid; grid-template-columns:1fr 1fr; gap:8px;
    margin-bottom:16px;
}
.info-stat {
    background:#f8fafc; border:1px solid var(--border);
    border-radius:10px; padding:10px;
    text-align:center;
}
.info-stat .num { font-size:1.15rem; font-weight:800; color:var(--navy); }
.info-stat .lbl {
    font-size:.62rem; color:#6b8095; font-weight:700;
    text-transform:uppercase; letter-spacing:.4px;
}

.info-row {
    display:flex; justify-content:space-between;
    padding:8px 0; border-bottom:1px solid #f1f5f9;
    font-size:.78rem;
}
.info-row .lbl { color:#6b8095; font-weight:600; }
.info-row .val { color:#0f1e33; font-weight:700; text-align:right; word-break:break-word; max-width:60%; }

.info-section-title {
    font-size:.68rem; font-weight:800; color:var(--navy);
    text-transform:uppercase; letter-spacing:.5px;
    margin:18px 0 8px;
    display:flex; align-items:center; gap:6px;
}
.info-section-title i { color:var(--orange); }

.info-actions {
    display:flex; gap:6px; flex-wrap:wrap; margin-top:12px;
}
.info-action {
    flex:1 0 auto; min-width:calc(50% - 3px);
    padding:9px 12px; border-radius:10px;
    background:#f1f5f9; border:none; cursor:pointer;
    font-size:.75rem; font-weight:700; color:var(--navy);
    transition:var(--trans);
    display:inline-flex; align-items:center; justify-content:center; gap:6px;
}
.info-action:hover { background:#e2eaf3; transform:translateY(-1px); }
.info-action.primary { background:var(--navy); color:#fff; }
.info-action.primary:hover { background:var(--navy-mid); }
.info-action.danger { background:#fee2e2; color:#991b1b; }
.info-action.danger:hover { background:#fecaca; }

/* ============================================================
   DROPDOWNS & PICKERS
   ============================================================ */
.dropdown-menu {
    position:fixed; bottom:110px; left:20px;
    background:#fff; border-radius:14px;
    box-shadow: var(--shadow-md);
    display:none; z-index:1000;
    width:260px; max-height:65vh; overflow-y:auto;
    border: 1px solid var(--border);
    padding: 6px;
}
.dropdown-menu.show { display:block; animation: fadeSlideUp .15s; }
.dd-item {
    padding:10px 14px; cursor:pointer;
    display:flex; align-items:center; gap:12px;
    border-bottom:1px solid #f1f5f9;
    font-size:.82rem; font-weight: 600;
    border-radius: 8px;
}
.dd-item:last-child { border-bottom: 0; }
.dd-item:hover { background:#f1f5f9; }
.dd-item i { color: var(--navy); width: 18px; text-align: center; }

.emoji-picker {
    position:fixed; bottom:110px; left:20px; z-index:1000;
    background:#fff; border-radius:14px;
    box-shadow: var(--shadow-md); padding:12px;
    min-width:300px; border: 1px solid var(--border);
    max-height: 300px; overflow-y: auto;
}
.emoji-btn { width:42px; height:42px; font-size:1.5rem; border-radius:10px; border:none; background:transparent; cursor:pointer; }
.emoji-btn:hover { background:#f1f5f9; }

.fab {
    position:fixed; bottom:24px; right:24px;
    width:58px; height:58px; border-radius:29px;
    background: linear-gradient(135deg, var(--wa-green), #128c7e); color:#fff;
    display:none; align-items:center; justify-content:center;
    box-shadow: 0 8px 24px rgba(37,211,102,.4);
    cursor:pointer; z-index:100;
}
.overlay { position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(10,51,88,.5); z-index:1040; display:none; }
.overlay.show { display:block; }

.spinner {
    display:inline-block; width:22px; height:22px;
    border:2.5px solid #f3f3f3; border-top:2.5px solid var(--wa-green);
    border-radius:50%; animation:spin 1s linear infinite;
}
@keyframes spin { to { transform:rotate(360deg); } }
@keyframes fadeSlideUp { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:translateY(0); } }
@keyframes pulse { 0%, 100% { opacity:1; } 50% { opacity:.5; } }
::-webkit-scrollbar { width:6px; height:6px; }
::-webkit-scrollbar-thumb { background:#cbd5e1; border-radius:10px; }
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width:992px) {
    .sidebar { position:fixed; left:-100%; top:0; width:85%; max-width:360px; height:100%; z-index:1050; }
    .sidebar.show { left:0; }
    .mobile-menu-btn { display:flex; align-items: center; justify-content: center; }
    .msg-bubble { max-width:85%; }
    .wa-container { height: calc(100vh - 64px); }
    .info-panel { width:100%; max-width:100%; }
    .session-dot span { display:none; }
}
@media (max-width:576px) {
    .user-info-name, .user-info-role { display:none; }
    .back-dash span, .logout-btn span { display:none; }
    .logo-text p { display:none; }
    .chat-filter-row { padding:6px 12px 10px; }
    .chat-actions .chat-act { width:34px; height:34px; }
}
@media (max-width:768px) { .fab { display:flex; } }
</style>
</head>
<body>

<!-- ============================================================
     HEADER
     ============================================================ -->
<header class="wa-header">
    <div class="logo-area">
        <button class="mobile-menu-btn" id="mobileMenuBtn"><i class="fas fa-bars"></i></button>
        <div class="logo"><img src="/roundlogo.png" alt="Paktia Travel" onerror="this.style.display='none'"></div>
        <div class="logo-text">
            <h2>WhatsApp Business CRM</h2>
            <p>Customer Communication Center</p>
        </div>
    </div>
    <div class="user-area">
        <div class="session-dot" id="sessionDot" title="Live connection">
            <i class="fas fa-circle"></i> <span id="sessionText">Connected</span>
        </div>

        <a href="<?php echo htmlspecialchars(wa_dashboard_url()); ?>"
           target="_blank" rel="noopener noreferrer"
           class="back-dash"
           title="<?php echo htmlspecialchars(wa_dashboard_label()); ?>">
            <i class="fas <?php echo htmlspecialchars(wa_dashboard_icon()); ?>"></i>
            <span><?php echo htmlspecialchars(wa_dashboard_label()); ?></span>
        </a>

        <a href="/logout.php" class="logout-btn">
            <i class="fas fa-sign-out-alt"></i> <span>Logout</span>
        </a>

        <div class="user-profile">
            <div class="user-avatar"><?php echo htmlspecialchars(strtoupper(substr($staff_name,0,1))); ?></div>
            <div class="d-none d-md-block">
                <div class="user-info-name"><?php echo htmlspecialchars($staff_name); ?></div>
                <div class="user-info-role"><?php echo htmlspecialchars(str_replace('_',' ', $staff_role)); ?></div>
            </div>
            <?php if ($unread_count > 0): ?>
                <span class="notif-badge" id="globalBadge"><?php echo (int)$unread_count; ?></span>
            <?php endif; ?>
        </div>
    </div>
</header>

<div class="overlay" id="mobileOverlay" onclick="closeSidebar()"></div>

<!-- ============================================================
     MAIN CONTAINER
     ============================================================ -->
<div class="wa-container">

    <!-- ============ SIDEBAR ============ -->
    <div class="sidebar" id="sidebar">
        <div class="sidebar-head">
            <div class="staff-info">
                <i class="fas fa-user-check"></i>
                Logged in as <strong><?php echo htmlspecialchars($staff_name); ?></strong>
            </div>
            <button class="btn-new" id="newChatBtn">
                <i class="fas fa-plus-circle"></i> New Chat
            </button>
            <div class="search-box">
                <i class="fas fa-search"></i>
                <input type="text" id="searchInput" placeholder="Search name or phone...  ( / )" autocomplete="off">
                <button class="search-clear" id="searchClear" title="Clear"><i class="fas fa-times"></i></button>
            </div>
            <div class="filter-row">
                <div class="filters">
                    <button class="filter-btn active" data-filter="all">All</button>
                    <button class="filter-btn" data-filter="unread">Unread</button>
                    <button class="filter-btn" data-filter="assigned">Mine</button>
                    <button class="filter-btn" data-filter="high">Priority</button>
                </div>
                <button class="sort-btn" id="sortBtn" title="Sort conversations">
                    <i class="fas fa-sort" id="sortIcon"></i>
                </button>
            </div>
            <div class="sidebar-actions">
                <button class="sidebar-action" id="markAllReadBtn" title="Mark all conversations as read">
                    <i class="fas fa-check-double"></i> Read all
                </button>
                <button class="sidebar-action" id="exportCsvBtn" title="Export conversation list as CSV">
                    <i class="fas fa-download"></i> Export
                </button>
            </div>
        </div>
        <div class="conv-list" id="convList">
            <div class="text-center p-4"><div class="spinner"></div></div>
        </div>
    </div>

    <!-- ============ CHAT AREA ============ -->
    <div class="chat-area">
        <div class="chat-header" id="chatHeader" style="display:none;">
            <div class="chat-head-info">
                <button class="btn btn-link d-md-none p-0 text-dark" id="toggleSidebarBtn"><i class="fas fa-bars"></i></button>
                <div class="chat-avatar" id="chatAvatar">?</div>
                <div class="chat-head-text">
                    <div class="chat-name-line">
                        <h6 id="chatName">Select a conversation</h6>
                        <span class="chat-badge" id="chatBadge" style="display:none;"></span>
                    </div>
                    <small class="text-muted" id="chatStatus" style="font-weight: 600;">Click a chat to start</small>
                </div>
            </div>
            <div class="chat-actions">
                <div class="chat-act" id="searchToggleBtn" title="Search messages (Ctrl+F)"><i class="fas fa-search"></i></div>
                <div class="chat-act" id="infoBtn" title="Customer info"><i class="fas fa-info-circle"></i></div>
                <div class="chat-act" id="editBtn" title="Edit"><i class="fas fa-edit"></i></div>
                <div class="chat-act" id="templatesBtn" title="Quick replies"><i class="fas fa-bolt"></i></div>
                <div class="chat-act" id="templateBtn" title="Send Meta template"><i class="fas fa-file-invoice"></i></div>
                <div class="chat-act" id="assignBtn" title="Assign to me"><i class="fas fa-user-plus"></i></div>
            </div>
        </div>

        <!-- Message type filter chips -->
        <div class="chat-filter-row" id="chatFilterRow" style="display:none;">
            <button class="chip active" data-msg-filter="all"><i class="fas fa-comment"></i> All</button>
            <button class="chip" data-msg-filter="text"><i class="fas fa-font"></i> Text</button>
            <button class="chip" data-msg-filter="media"><i class="fas fa-photo-video"></i> Media</button>
            <button class="chip" data-msg-filter="image"><i class="fas fa-image"></i> Images</button>
            <button class="chip" data-msg-filter="video"><i class="fas fa-video"></i> Videos</button>
            <button class="chip" data-msg-filter="document"><i class="fas fa-file-pdf"></i> Documents</button>
            <button class="chip" data-msg-filter="audio"><i class="fas fa-microphone"></i> Audio</button>
            <button class="chip" data-msg-filter="link"><i class="fas fa-link"></i> Links</button>
            <button class="chip" data-msg-filter="incoming"><i class="fas fa-arrow-down"></i> Inbound</button>
            <button class="chip" data-msg-filter="outgoing"><i class="fas fa-arrow-up"></i> Outbound</button>
        </div>

        <!-- In-conversation search -->
        <div class="chat-search-bar" id="chatSearchBar">
            <i class="fas fa-search text-muted"></i>
            <input type="text" id="chatSearchInput" placeholder="Search messages...">
            <span class="chat-search-count" id="chatSearchCount">0</span>
            <div class="chat-search-nav">
                <button id="searchPrev" title="Previous"><i class="fas fa-chevron-up"></i></button>
                <button id="searchNext" title="Next"><i class="fas fa-chevron-down"></i></button>
            </div>
            <button class="chat-search-nav" style="padding:0;border:none;background:none;" id="searchClose"><i class="fas fa-times"></i></button>
        </div>

        <div class="chat-msgs" id="chatMsgs">
            <div class="empty-state" id="noChat">
                <i class="fab fa-whatsapp"></i>
                <h5>WhatsApp Business CRM</h5>
                <p>Select a conversation or start a new chat</p>
                <button class="btn btn-success btn-sm mt-3" id="emptyNewBtn" style="border-radius: 20px; padding: 8px 20px;">
                    <i class="fas fa-plus-circle"></i> New Chat
                </button>
            </div>

            <button class="jump-latest" id="jumpLatest">
                <i class="fas fa-arrow-down"></i>
                <span>Jump to latest</span>
                <span class="count" id="jumpCount" style="display:none;">0</span>
            </button>
        </div>

        <!-- Compose toolbar -->
        <div class="msg-toolbar" id="msgToolbar" style="display:none;">
            <button class="tb-btn" id="attachBtn" title="Attach file"><i class="fas fa-paperclip"></i></button>
            <button class="tb-btn" id="emojiBtn" title="Emoji"><i class="fas fa-smile"></i></button>
            <button class="tb-btn" onclick="pickMedia('image')" title="Send image"><i class="fas fa-image"></i></button>
            <button class="tb-btn" onclick="pickMedia('document')" title="Send document"><i class="fas fa-file-pdf"></i></button>
            <button class="tb-btn" onclick="openLocation()" title="Send location"><i class="fas fa-map-marker-alt"></i></button>
            <button class="tb-btn" onclick="openContact()" title="Send contact"><i class="fas fa-address-card"></i></button>
        </div>

        <!-- Compose input -->
        <div class="chat-input" id="chatInput" style="display:none;">
            <div class="reply-preview" id="replyPreview">
                <i class="fas fa-reply text-muted"></i>
                <div class="reply-body">
                    <div class="reply-name" id="replyName"></div>
                    <div class="reply-text" id="replyText"></div>
                </div>
                <button type="button" id="replyCancel"><i class="fas fa-times"></i></button>
            </div>
            <div class="input-wrap">
                <textarea class="msg-input" id="msgText" placeholder="Type a message...  (Ctrl+Enter to send, / to search)" rows="1"></textarea>
                <button class="send-btn" id="sendBtn" disabled><i class="fas fa-paper-plane"></i></button>
                <div class="char-counter" id="charCounter"></div>
            </div>
        </div>
    </div>

    <!-- ============ INFO PANEL ============ -->
    <aside class="info-panel" id="infoPanel">
        <div class="info-panel-head">
            <h6><i class="fas fa-user-circle"></i> Customer Details</h6>
            <button id="infoClose"><i class="fas fa-times"></i></button>
        </div>
        <div class="info-panel-body" id="infoPanelBody">
            <!-- populated by JS -->
        </div>
    </aside>
</div>

<div class="fab" id="fabBtn"><i class="fas fa-plus-circle fa-2x"></i></div>

<!-- ============================================================
     HIDDEN INPUTS
     ============================================================ -->
<input type="file" id="inpImage" style="display:none;" accept="image/*">
<input type="file" id="inpVideo" style="display:none;" accept="video/*">
<input type="file" id="inpDoc" style="display:none;" accept=".pdf,.doc,.docx,.txt,.xls,.xlsx,.ppt,.pptx,.zip">
<input type="file" id="inpAudio" style="display:none;" accept="audio/*">

<!-- Attachment menu -->
<div class="dropdown-menu" id="attachMenu">
    <div class="dd-item" onclick="pickMedia('image')"><i class="fas fa-image"></i> Photo</div>
    <div class="dd-item" onclick="pickMedia('video')"><i class="fas fa-video"></i> Video</div>
    <div class="dd-item" onclick="pickMedia('document')"><i class="fas fa-file-pdf"></i> Document</div>
    <div class="dd-item" onclick="pickMedia('audio')"><i class="fas fa-microphone"></i> Voice</div>
    <div class="dd-item" onclick="openLocation()"><i class="fas fa-map-marker-alt"></i> Location</div>
    <div class="dd-item" onclick="openContact()"><i class="fas fa-address-card"></i> Contact</div>
</div>

<!-- Emoji picker -->
<div class="emoji-picker" id="emojiPicker" style="display:none;">
    <div style="display:flex;flex-wrap:wrap;">
        <?php foreach (['😀','😊','😂','🤣','❤️','👍','🎉','🔥','👋','🙏','💯','✅','⭐','🍕','🏆','🎯','✈️','🌍','💼','📞','📧','💬','😍','🤝','✨','🙌','🙏','👏','🤲','💐','🥳','😎','🤔','👌','💪','🌟','🎁','📌','📍','📎','🗂️','📋','🕐','⏰','📅','🗓️','💳','💰','💵','🧾','📊','📈','🏦'] as $e): ?>
        <button class="emoji-btn" onclick="insertEmoji('<?php echo $e; ?>')"><?php echo $e; ?></button>
        <?php endforeach; ?>
    </div>
</div>

<!-- Quick replies menu -->
<div class="dropdown-menu" id="templatesMenu">
    <div class="dd-item" style="background:#f1f5f9;font-weight:800;color:var(--navy);cursor:default;border-radius:8px;">
        <i class="fas fa-bolt"></i> Quick Replies
    </div>
    <?php if (empty($templates)): ?>
        <div class="dd-item" style="cursor:default;color:#94a3b8;font-size:.8rem;">
            <i class="fas fa-info-circle"></i> No templates yet
        </div>
    <?php else: ?>
        <?php foreach ($templates as $t): ?>
        <div class="dd-item template-pick" data-msg="<?php echo htmlspecialchars($t['message']); ?>">
            <div style="min-width:0;flex:1;">
                <div style="font-weight:800;color:var(--navy);"><i class="fas fa-reply-all"></i> <?php echo htmlspecialchars($t['name']); ?></div>
                <div style="font-size:.7rem;color:#6b8095;font-weight:500;margin-top:2px;"><?php echo htmlspecialchars(substr($t['message'],0,50)); ?></div>
            </div>
        </div>
        <?php endforeach; ?>
    <?php endif; ?>
</div>

<!-- ============================================================
     MODALS
     ============================================================ -->

<!-- New Chat -->
<div class="modal fade" id="newChatModal" tabindex="-1">
    <div class="modal-dialog modal-dialog-centered"><div class="modal-content" style="border-radius:16px;border:0;">
        <div class="modal-header" style="background:linear-gradient(135deg,var(--navy),var(--navy-mid));color:#fff;border-radius:16px 16px 0 0;">
            <h5 class="modal-title" style="font-weight:800;"><i class="fas fa-plus-circle"></i> New Chat</h5>
            <button class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body">
            <div class="mb-3"><label style="font-weight:700;font-size:.8rem;">Phone <span class="text-danger">*</span></label><input type="tel" class="form-control" id="newPhone" placeholder="e.g., 93779777516"></div>
            <div class="mb-3"><label style="font-weight:700;font-size:.8rem;">Name (optional)</label><input type="text" class="form-control" id="newName" placeholder="Customer name"></div>
            <div class="mb-3"><label style="font-weight:700;font-size:.8rem;">First Message</label><textarea class="form-control" id="newMsg" rows="2"></textarea></div>
            <div class="mb-3"><label style="font-weight:700;font-size:.8rem;">Priority</label><select class="form-control" id="newPriority"><option value="normal">Normal</option><option value="high">High</option><option value="vip">VIP</option></select></div>
        </div>
        <div class="modal-footer"><button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button><button class="btn btn-success" id="createChatBtn" style="font-weight:700;">Start Chat</button></div>
    </div></div>
</div>

<!-- Edit -->
<div class="modal fade" id="editModal" tabindex="-1"><div class="modal-dialog modal-dialog-centered"><div class="modal-content" style="border-radius:16px;border:0;">
    <div class="modal-header bg-warning"><h5 class="modal-title"><i class="fas fa-edit"></i> Edit Customer</h5><button class="btn-close" data-bs-dismiss="modal"></button></div>
    <div class="modal-body">
        <input type="hidden" id="editId">
        <div class="mb-2"><label style="font-weight:700;font-size:.8rem;">Name</label><input class="form-control" id="editName"></div>
        <div class="mb-2"><label style="font-weight:700;font-size:.8rem;">Phone</label><input class="form-control" id="editPhone" readonly></div>
        <div class="mb-2"><label style="font-weight:700;font-size:.8rem;">Notes</label><textarea class="form-control" id="editNotes" rows="3"></textarea></div>
        <div class="mb-2"><label style="font-weight:700;font-size:.8rem;">Status</label><select class="form-control" id="editStatus"><option value="active">Active</option><option value="pending">Pending</option><option value="closed">Closed</option></select></div>
        <div class="mb-2"><label style="font-weight:700;font-size:.8rem;">Priority</label><select class="form-control" id="editPriority"><option value="low">Low</option><option value="normal">Normal</option><option value="high">High</option><option value="vip">VIP</option></select></div>
    </div>
    <div class="modal-footer"><button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button><button class="btn btn-success" id="saveEdit">Save</button></div>
</div></div></div>

<!-- Location -->
<div class="modal fade" id="locModal" tabindex="-1"><div class="modal-dialog modal-dialog-centered"><div class="modal-content" style="border-radius:16px;border:0;">
    <div class="modal-header" style="background:linear-gradient(135deg,var(--navy),var(--navy-mid));color:#fff;border-radius:16px 16px 0 0;">
        <h5 class="modal-title" style="font-weight:800;"><i class="fas fa-map-marker-alt"></i> Send Location</h5>
        <button class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
    </div>
    <div class="modal-body">
        <div class="mb-2"><label style="font-weight:700;font-size:.8rem;">Name / Address</label><input class="form-control" id="locName"></div>
        <div class="mb-2"><label style="font-weight:700;font-size:.8rem;">Address Line</label><input class="form-control" id="locAddr"></div>
        <div class="row">
            <div class="col-6 mb-2"><label style="font-weight:700;font-size:.8rem;">Latitude</label><input class="form-control" id="locLat"></div>
            <div class="col-6 mb-2"><label style="font-weight:700;font-size:.8rem;">Longitude</label><input class="form-control" id="locLng"></div>
        </div>
        <button class="btn btn-info w-100" onclick="detectLocation()" style="font-weight:700;"><i class="fas fa-location-dot"></i> Use My Location</button>
    </div>
    <div class="modal-footer"><button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button><button class="btn btn-primary" id="sendLocBtn">Send Location</button></div>
</div></div></div>

<!-- Contact -->
<div class="modal fade" id="contactModal" tabindex="-1"><div class="modal-dialog modal-dialog-centered"><div class="modal-content" style="border-radius:16px;border:0;">
    <div class="modal-header" style="background:linear-gradient(135deg,var(--navy),var(--navy-mid));color:#fff;border-radius:16px 16px 0 0;">
        <h5 class="modal-title" style="font-weight:800;"><i class="fas fa-address-card"></i> Send Contact</h5>
        <button class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
    </div>
    <div class="modal-body">
        <div class="mb-2"><label style="font-weight:700;font-size:.8rem;">Contact Name</label><input class="form-control" id="cName"></div>
        <div class="mb-2"><label style="font-weight:700;font-size:.8rem;">Phone Number</label><input type="tel" class="form-control" id="cPhone" placeholder="e.g., 93779777516"></div>
    </div>
    <div class="modal-footer"><button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button><button class="btn btn-success" id="sendContactBtn">Send Contact</button></div>
</div></div></div>

<!-- Template -->
<div class="modal fade" id="templateModal" tabindex="-1">
    <div class="modal-dialog modal-dialog-centered"><div class="modal-content" style="border-radius:16px;border:0;">
        <div class="modal-header" style="background:linear-gradient(135deg,var(--navy),var(--navy-mid));color:#fff;border-radius:16px 16px 0 0;">
            <h5 class="modal-title" style="font-weight:800;"><i class="fas fa-file-invoice"></i> Send Meta Template</h5>
            <button class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body">
            <p class="text-muted small mb-3">
                Meta-approved templates can be sent at any time, even outside the
                24-hour window since the customer's last message.
            </p>
            <div class="mb-3">
                <label style="font-weight:700;font-size:.8rem;">Template</label>
                <select class="form-control" id="tplSelect">
                    <option value="">Loading...</option>
                </select>
            </div>
            <div class="mb-3">
                <label style="font-weight:700;font-size:.8rem;">Language code</label>
                <input class="form-control" id="tplLang" value="en" placeholder="en">
            </div>
            <div id="tplParams"></div>
        </div>
        <div class="modal-footer">
            <button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
            <button class="btn btn-success" id="tplSend" style="font-weight:700;">Send Template</button>
        </div>
    </div></div>
</div>

<!-- ============================================================
     JAVASCRIPT
     ============================================================ -->
<script>
/* ============================================================
   CONFIG
   ============================================================ */
const API_URL    = '/whatsapp_api.php';
const CSRF_TOKEN = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '';
const STAFF_ID   = <?php echo json_encode($staff_id); ?>;
const STAFF_NAME = <?php echo json_encode($staff_name); ?>;

/* ============================================================
   STATE
   ============================================================ */
let currentConvId     = null;
let lastMsgId         = 0;
let allConvs          = [];
let currentFilter     = 'all';
let currentSort       = 'recent';        // recent | oldest | unread | priority | name
let searchTerm        = '';
let msgFilter         = 'all';           // all | text | media | image | video | document | audio | link | incoming | outgoing
let msgSearch         = '';
let msgSearchMatches  = [];
let msgSearchIndex    = 0;
let displayedMessages = [];
let pollTimer         = null;
let pollFailures      = 0;
let isMobile          = window.innerWidth < 768;
let autoScroll        = true;
let unreadSinceScroll = 0;
let modals            = {};
let templates         = [];
let replyContext      = null;
let audioUnlocked     = false;
let currentDraftKey   = null;
let notificationSound = null;

/* ============================================================
   SMALL HELPERS
   ============================================================ */
function esc(s) {
    if (s == null) return '';
    const d = document.createElement('div');
    d.textContent = String(s);
    return d.innerHTML;
}

function parseUTC(dt) {
    if (!dt) return new Date();
    if (dt instanceof Date) return dt;
    const s = String(dt);
    if (s.includes('T')) {
        return new Date(s.endsWith('Z') || /[+-]\d\d:?\d\d$/.test(s) ? s : s + 'Z');
    }
    return new Date(s.replace(' ', 'T') + 'Z');
}

function fmtAgo(dt) {
    if (!dt) return 'now';
    const d = parseUTC(dt);
    const s = Math.floor((Date.now() - d.getTime()) / 1000);
    if (isNaN(s)) return 'now';
    if (s < 60)     return 'now';
    if (s < 3600)   return Math.floor(s/60)+'m';
    if (s < 86400)  return Math.floor(s/3600)+'h';
    if (s < 604800) return Math.floor(s/86400)+'d';
    return d.toLocaleDateString();
}

function fmtFull(dt) {
    if (!dt) return '';
    return parseUTC(dt).toLocaleString([], {
        year: 'numeric', month: 'short', day: 'numeric',
        hour: '2-digit', minute: '2-digit'
    });
}

function fmtBytes(n) {
    n = parseInt(n) || 0;
    if (n < 1024) return n + ' B';
    if (n < 1048576) return (n/1024).toFixed(1) + ' KB';
    return (n/1048576).toFixed(1) + ' MB';
}

function toast(msg, type) {
    const bg = type === 'success'
        ? 'linear-gradient(135deg,#25D366,#128c7e)'
        : type === 'warn'
            ? 'linear-gradient(135deg,#f59e0b,#d97706)'
            : 'linear-gradient(135deg,#dc3545,#b91c1c)';
    const t = $('<div style="position:fixed;bottom:24px;right:24px;background:' + bg +
                ';color:#fff;padding:12px 18px;border-radius:12px;z-index:9999;' +
                'font-size:.82rem;font-weight:700;box-shadow:0 10px 30px rgba(0,0,0,.2)">' +
                esc(msg) + '</div>');
    $('body').append(t);
    setTimeout(() => t.fadeOut(300, function(){ $(this).remove(); }), 3200);
}

function closeSidebar() {
    $('#sidebar').removeClass('show');
    $('#mobileOverlay').removeClass('show');
}

function scrollBottom(smooth) {
    const c = document.getElementById('chatMsgs');
    if (!c) return;
    if (smooth) c.scrollTo({ top: c.scrollHeight, behavior: 'smooth' });
    else c.scrollTop = c.scrollHeight;
}

function isNearBottom() {
    const c = document.getElementById('chatMsgs');
    if (!c) return true;
    return (c.scrollHeight - c.scrollTop - c.clientHeight) < 120;
}

function linkify(text) {
    let s = esc(text || '');
    s = s.replace(/(https?:\/\/[^\s]+)/g, '<a href="$1" target="_blank" rel="noopener">$1</a>');
    s = s.replace(/\n/g, '<br>');
    return s;
}

function captionOf(m) {
    const c = (m.message_content || '').trim();
    if (c === '') return '';

    // Auto-generated placeholders — don't show them as captions
    const placeholders = [
        '📷 Image', '📹 Video', '🎵 Audio',
        '🎨 Sticker', '📍 Location', '👤 Contact'
    ];
    if (placeholders.includes(c)) return '';
    if (/^📄 /.test(c) && c.length < 100) return '';
    if (/^📎 \w+:/.test(c) && c.length < 100) return '';
    if (/^👤 /.test(c) && c.length < 100) return '';
    if (/^📩 Template:/.test(c)) return c;  // keep template label

    return c;
}

function playPing() {
    if (!audioUnlocked) return;
    try {
        const ctx = new (window.AudioContext || window.webkitAudioContext)();
        const o = ctx.createOscillator();
        const g = ctx.createGain();
        o.connect(g);
        g.connect(ctx.destination);
        o.type = 'sine';
        o.frequency.value = 880;
        g.gain.setValueAtTime(0.0001, ctx.currentTime);
        g.gain.exponentialRampToValueAtTime(0.12, ctx.currentTime + 0.02);
        g.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + 0.35);
        o.start();
        o.stop(ctx.currentTime + 0.4);
    } catch (e) { /* silent */ }
}

/* ============================================================
   STAFF PRESENCE HEARTBEAT (Phase 2)
   ============================================================ */
let presenceTimer = null;
let currentPresenceStatus = 'online';

function sendHeartbeat(status) {
    currentPresenceStatus = status;
    $.ajax({
        url: '/wa_presence.php',
        method: 'POST',
        dataType: 'json',
        data: { action: 'heartbeat', status: status },
        xhrFields: { withCredentials: true },
        success: function(r) {
            if (r.success && r.queue_drained > 0) {
                toast('📥 ' + r.queue_drained + ' chat(s) assigned to you', 'success');
                loadConversations();     // refresh the sidebar
            }
        }
    });
}

function startPresence() {
    sendHeartbeat('online');
    if (presenceTimer) clearInterval(presenceTimer);
    presenceTimer = setInterval(function() {
        sendHeartbeat(document.visibilityState === 'visible' ? 'online' : 'away');
    }, 60000);   // every 60 seconds
}

// Mark offline when leaving (best-effort)
$(window).on('beforeunload', function() {
    navigator.sendBeacon('/wa_presence.php?action=offline');
});

// Pause heartbeat when tab is hidden, resume when visible
document.addEventListener('visibilitychange', function() {
    if (document.visibilityState === 'visible') {
        sendHeartbeat('online');
    } else {
        sendHeartbeat('away');
    }
});

// Kick off on page load (only for real staff pages, not login)
if ($('#convList').length > 0) {
    startPresence();
}

/* ============================================================
   BOOT
   ============================================================ */
$(function() {
    modals.newChat  = new bootstrap.Modal(document.getElementById('newChatModal'));
    modals.edit     = new bootstrap.Modal(document.getElementById('editModal'));
    modals.loc      = new bootstrap.Modal(document.getElementById('locModal'));
    modals.contact  = new bootstrap.Modal(document.getElementById('contactModal'));
    modals.template = new bootstrap.Modal(document.getElementById('templateModal'));

    bindEvents();
    loadConversations();
    loadTemplates();
    startPolling();

    // Unlock audio on first interaction
    $(document).one('click keydown', () => { audioUnlocked = true; });

    $(window).on('resize', function() {
        isMobile = window.innerWidth < 768;
        if (!isMobile) closeSidebar();
    });
});

/* ============================================================
   BIND EVENTS
   ============================================================ */
function bindEvents() {
    // Sidebar open/close
    $('#mobileMenuBtn, #fabBtn, #emptyNewBtn').on('click', function() {
        $('#sidebar').addClass('show');
        $('#mobileOverlay').addClass('show');
    });
    $('#toggleSidebarBtn').on('click', function() {
        $('#sidebar').addClass('show');
        $('#mobileOverlay').addClass('show');
    });

    // New chat
    $('#newChatBtn').on('click', () => modals.newChat.show());
    $('#createChatBtn').on('click', createChat);

    // Chat header actions
    $('#infoBtn').on('click', showInfoPanel);
    $('#editBtn').on('click', editConv);
    $('#assignBtn').on('click', assignToMe);
    $('#templateBtn').on('click', openTemplatePicker);
    $('#tplSend').on('click', sendTemplate);
    $('#saveEdit').on('click', saveEdit);

    // Info panel
    $('#infoClose').on('click', () => $('#infoPanel').removeClass('show'));

    // Search
    $('#searchInput').on('input', function() {
        searchTerm = $(this).val().toLowerCase();
        $('#searchClear').toggleClass('show', searchTerm.length > 0);
        renderConvList();
    });
    $('#searchClear').on('click', function() {
        $('#searchInput').val('').trigger('input').focus();
    });

    // Chat search
    $('#searchToggleBtn').on('click', toggleChatSearch);
    $('#searchClose').on('click', () => { $('#chatSearchBar').removeClass('show'); msgSearch = ''; $('#chatSearchInput').val(''); renderMessages(displayedMessages); });
    $('#chatSearchInput').on('input', function() {
        msgSearch = $(this).val().toLowerCase();
        renderMessages(displayedMessages);
    });
    $('#searchPrev').on('click', () => navigateSearch(-1));
    $('#searchNext').on('click', () => navigateSearch(1));

    // Filters
    $('.filter-btn').on('click', function() {
        $('.filter-btn').removeClass('active');
        $(this).addClass('active');
        currentFilter = $(this).data('filter');
        renderConvList();
    });
    $('.chip').on('click', function() {
        $('.chip').removeClass('active');
        $(this).addClass('active');
        msgFilter = $(this).data('msg-filter');
        renderMessages(displayedMessages);
    });
    $('#sortBtn').on('click', cycleSort);

    // Bulk actions
    $('#markAllReadBtn').on('click', markAllRead);
    $('#exportCsvBtn').on('click', exportCsv);

    // Compose
    $('#sendBtn').on('click', sendText);
    $('#msgText').on('keydown', function(e) {
        if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
            e.preventDefault();
            sendText();
        }
        if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
            e.preventDefault();
            sendText();
        }
        // Up arrow with empty input = edit last message
        if (e.key === 'ArrowUp' && $(this).val() === '') {
            const lastOut = displayedMessages.slice().reverse().find(m => m.direction === 'outgoing');
            if (lastOut && lastOut.message_type === 'text') {
                e.preventDefault();
                $(this).val(lastOut.message_content || '').trigger('input').focus();
            }
        }
    }).on('input', function() {
        const v = $(this).val();
        $('#sendBtn').prop('disabled', !v.trim());

        const len = v.length;
        const counter = $('#charCounter');
        counter.text(len + '/4096');
        counter.toggleClass('show', len > 0);
        counter.toggleClass('warn', len > 3500 && len <= 3900);
        counter.toggleClass('danger', len > 3900);

        $(this).css('height','auto').css('height', Math.min(this.scrollHeight, 120)+'px');

        saveDraft(currentConvId, v);
    });

    // Reply preview
    $('#replyCancel').on('click', clearReply);

    // Menus
    $('#attachBtn').on('click', function(e) {
        e.stopPropagation();
        $('#attachMenu').toggleClass('show');
        $('#templatesMenu').removeClass('show');
        $('#emojiPicker').hide();
    });
    $('#templatesBtn').on('click', function(e) {
        e.stopPropagation();
        $('#templatesMenu').toggleClass('show');
        $('#attachMenu').removeClass('show');
        $('#emojiPicker').hide();
    });
    $('#emojiBtn').on('click', function(e) {
        e.stopPropagation();
        $('#emojiPicker').toggle();
        $('#attachMenu').removeClass('show');
        $('#templatesMenu').removeClass('show');
    });
    $(document).on('click', '.template-pick', function() {
        const current = $('#msgText').val();
        const toAdd = $(this).data('msg');
        $('#msgText').val(current ? current + '\n' + toAdd : toAdd).trigger('input').focus();
        $('#templatesMenu').removeClass('show');
    });
    $(document).on('click', function(e) {
        if (!$(e.target).closest('#attachBtn, #attachMenu').length)     $('#attachMenu').removeClass('show');
        if (!$(e.target).closest('#templatesBtn, #templatesMenu').length) $('#templatesMenu').removeClass('show');
        if (!$(e.target).closest('#emojiBtn, #emojiPicker').length)     $('#emojiPicker').hide();
    });

    // File uploads
    $('#inpImage').on('change', function(e) { if (e.target.files[0]) queueMedia(e.target.files[0]); $(this).val(''); });
    $('#inpVideo').on('change', function(e) { if (e.target.files[0]) queueMedia(e.target.files[0]); $(this).val(''); });
    $('#inpDoc').on('change',   function(e) { if (e.target.files[0]) queueMedia(e.target.files[0]); $(this).val(''); });
    $('#inpAudio').on('change', function(e) { if (e.target.files[0]) queueMedia(e.target.files[0]); $(this).val(''); });

    // Jump to latest
    $('#jumpLatest').on('click', function() {
        autoScroll = true;
        unreadSinceScroll = 0;
        updateJumpButton();
        scrollBottom(true);
    });

    // Auto-scroll detection
    $('#chatMsgs').on('scroll', function() {
        autoScroll = isNearBottom();
        if (autoScroll) {
            unreadSinceScroll = 0;
            updateJumpButton();
        }
    });

    // Keyboard shortcuts
    $(document).on('keydown', function(e) {
        // `/` focuses search when not in input
        if (e.key === '/' && !$(e.target).is('input, textarea')) {
            e.preventDefault();
            $('#searchInput').focus();
        }
        // Ctrl+F opens chat search
        if ((e.ctrlKey || e.metaKey) && e.key === 'f' && currentConvId) {
            e.preventDefault();
            toggleChatSearch();
        }
        // Esc closes things
        if (e.key === 'Escape') {
            $('#attachMenu, #templatesMenu').removeClass('show');
            $('#emojiPicker').hide();
            $('#infoPanel').removeClass('show');
            if ($('#chatSearchBar').hasClass('show')) { $('#searchClose').click(); }
        }
    });

    // Right-click on message text → native menu; we just enable copy
    $(document).on('contextmenu', '.msg-text', function(e) {
        // allow native menu
    });
}

/* ============================================================
   CONVERSATION LIST
   ============================================================ */
function loadConversations() {
    $('#convList').html('<div class="text-center p-4"><div class="spinner"></div></div>');
    $.ajax({
        url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true}, timeout:10000,
        data: { action:'get_conversations', csrf_token: CSRF_TOKEN },
        success: function(r) {
            allConvs = (r.success && r.conversations) ? r.conversations : [];
            renderConvList();
            updateBadge();
            markSessionHealthy();
        },
        error: function() {
            allConvs = [];
            renderConvList();
            markSessionStale();
            $('#convList').html('<div class="alert alert-danger m-3">Error loading conversations. Refresh the page.</div>');
        }
    });
}

function sortConversations(list) {
    const arr = [...list];
    switch (currentSort) {
        case 'oldest':
            arr.sort((a,b) => parseUTC(a.last_message_time || 0) - parseUTC(b.last_message_time || 0));
            break;
        case 'unread':
            arr.sort((a,b) => (parseInt(b.unread_count)||0) - (parseInt(a.unread_count)||0));
            break;
        case 'priority':
            const order = { vip: 0, high: 1, normal: 2, low: 3 };
            arr.sort((a,b) => (order[a.priority] ?? 99) - (order[b.priority] ?? 99)
                || parseUTC(b.last_message_time||0) - parseUTC(a.last_message_time||0));
            break;
        case 'name':
            arr.sort((a,b) => (a.customer_name||'').localeCompare(b.customer_name||''));
            break;
        case 'recent':
        default:
            arr.sort((a,b) => parseUTC(b.last_message_time||0) - parseUTC(a.last_message_time||0));
    }
    return arr;
}

function cycleSort() {
    const order = ['recent', 'oldest', 'unread', 'priority', 'name'];
    const icons = {
        recent: 'fa-sort-amount-down',
        oldest: 'fa-sort-amount-up',
        unread: 'fa-envelope',
        priority: 'fa-exclamation',
        name: 'fa-font'
    };
    const labels = {
        recent: 'Newest first',
        oldest: 'Oldest first',
        unread: 'Most unread',
        priority: 'Priority first',
        name: 'Name A–Z'
    };
    const idx = (order.indexOf(currentSort) + 1) % order.length;
    currentSort = order[idx];
    $('#sortIcon').removeClass().addClass('fas ' + icons[currentSort]);
    $('#sortBtn').attr('title', 'Sort: ' + labels[currentSort]);
    toast('Sort: ' + labels[currentSort], 'success');
    renderConvList();
}

function renderConvList() {
    let list = [...allConvs];

    if (currentFilter === 'unread')   list = list.filter(c => c.unread_count > 0);
    if (currentFilter === 'assigned') list = list.filter(c => c.assigned_staff_id == STAFF_ID);
    if (currentFilter === 'high')     list = list.filter(c => c.priority === 'high' || c.priority === 'vip');

    if (searchTerm) {
        list = list.filter(c =>
            (c.customer_name||'').toLowerCase().includes(searchTerm) ||
            (c.customer_phone||'').includes(searchTerm));
    }

    list = sortConversations(list);

    if (!list.length) {
        const msg = searchTerm ? 'No matches found' : 'No conversations';
        $('#convList').html(
            '<div class="empty-state"><i class="fas fa-comments"></i>' +
            '<p style="font-weight:700;">' + esc(msg) + '</p></div>');
        return;
    }

    let h = '';
    list.forEach(c => {
        const n = c.customer_name || c.customer_phone || 'Unknown';
        const preview = (c.last_message || 'No messages').substring(0, 60);
        const unread = parseInt(c.unread_count) || 0;
        const priorityClass = c.priority === 'vip' ? 'priority-vip'
                            : c.priority === 'high' ? 'priority-high' : '';
        const priorityDot = (c.priority === 'vip' || c.priority === 'high')
            ? '<span class="priority-dot"></span>' : '';

        // Preview icon by last message type guess (based on text content)
        let previewIcon = '';
        if (/^📷|^📎|^📄|^📹|^🎵|^📍|^👤/.test(preview)) {
            previewIcon = '<span class="preview-icon">' + esc(preview.substring(0,2)) + '</span>';
            // We'll just show the raw preview since DB stores emoji
            previewIcon = '';
        }

        h += `<div class="conv-item ${currentConvId==c.id?'active':''} ${unread?'unread':''}" data-id="${c.id}" onclick="openConversation(${c.id})">
            <div class="conv-avatar ${priorityClass}">
                ${esc(n.charAt(0).toUpperCase())}
                ${priorityDot}
            </div>
            <div class="conv-info">
                <div class="conv-name">
                    <span>${esc(n)}</span>
                    <span class="conv-time" title="${esc(fmtFull(c.last_message_time))}">${fmtAgo(c.last_message_time)}</span>
                </div>
                <div class="conv-preview">
                    ${previewIcon}
                    <span>${esc(preview)}</span>
                </div>
            </div>
            ${unread > 0 ? `<div class="unread-badge">${unread > 99 ? '99+' : unread}</div>` : ''}
        </div>`;
    });
    $('#convList').html(h);
}

function openConversation(id) {
    currentConvId = id;
    lastMsgId = 0;
    autoScroll = true;
    unreadSinceScroll = 0;

    $('.conv-item').removeClass('active');
    $(`.conv-item[data-id="${id}"]`).addClass('active');
    $('#chatHeader, #msgToolbar, #chatInput, #chatFilterRow').show();
    $('#noChat').hide();
    $('#chatMsgs').html('<div class="text-center p-4"><div class="spinner"></div></div>');
    if (isMobile) closeSidebar();

    // Load draft if any
    currentDraftKey = 'wa_draft_' + id;
    const draft = localStorage.getItem(currentDraftKey);
    $('#msgText').val(draft || '').trigger('input');

    clearReply();

    // Mark read
    $.ajax({
        url: API_URL, method:'POST',
        data: { action:'mark_read', conversation_id: id, csrf_token: CSRF_TOKEN },
        xhrFields: { withCredentials:true }
    });

    const c = allConvs.find(x => x.id == id);
    if (c) {
        const n = c.customer_name || c.customer_phone || 'Unknown';
        $('#chatName').text(n);
        $('#chatAvatar').text(n.charAt(0).toUpperCase());

        let st = '<i class="fas fa-circle" style="color:#25D366;font-size:.6rem;"></i> Active';
        if (c.assigned_staff_id == STAFF_ID) {
            st = '<i class="fas fa-user-check" style="color:var(--orange);"></i> Assigned to you';
        } else if (c.assigned_to) {
            st = '<i class="fas fa-user"></i> ' + esc(c.assigned_to);
        }
        $('#chatStatus').html(st);


        // Show department if routed
if (c.department_id) {
    $.ajax({
        url: API_URL, method: 'POST', dataType: 'json',
        data: { action: 'get_department', id: c.department_id, csrf_token: CSRF_TOKEN },
        xhrFields: { withCredentials: true },
        success: function(dr) {
            if (dr.success && dr.department) {
                const d = dr.department;
                const emoji = d.emoji || '💬';
                const name  = d.name_en || d.code;
                $('#chatStatus').append(
                    ' &nbsp;·&nbsp; <span style="background:#e6f0fa;color:#0a3358;' +
                    'padding:2px 8px;border-radius:10px;font-weight:700;font-size:.7rem;">' +
                    emoji + ' ' + name + '</span>'
                );
            }
        }
    });
}
        
        // Badge
        const badge = $('#chatBadge');
        if (c.priority === 'vip') {
            badge.text('VIP').attr('class', 'chat-badge vip').show();
        } else if (c.priority === 'high') {
            badge.text('High').attr('class', 'chat-badge high').show();
        } else if (c.status === 'closed') {
            badge.text('Closed').attr('class', 'chat-badge closed').show();
        } else {
            badge.hide();
        }
    }

    loadMessages(id);
}

function loadMessages(id) {
    $.ajax({
        url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true}, timeout:10000,
        data: { action:'load_messages', conversation_id: id, csrf_token: CSRF_TOKEN },
        success: r => {
            displayedMessages = r.success ? (r.messages || []) : [];
            renderMessages(displayedMessages);
            markSessionHealthy();
        },
        error: () => {
            displayedMessages = [];
            renderMessages([]);
            markSessionStale();
        }
    });
}

/* ============================================================
   MESSAGE FILTERING & RENDERING
   ============================================================ */
function filterMessages(msgs) {
    if (msgFilter === 'all') return msgs;

    return msgs.filter(m => {
        const t = m.message_type || '';
        switch (msgFilter) {
            case 'text':     return t === 'text' || t === 'template';
            case 'media':    return ['image','video','audio','document','sticker'].includes(t);
            case 'image':    return t === 'image';
            case 'video':    return t === 'video';
            case 'document': return t === 'document';
            case 'audio':    return t === 'audio';
            case 'link':     return /https?:\/\//i.test(m.message_content || '');
            case 'incoming': return m.direction === 'incoming';
            case 'outgoing': return m.direction === 'outgoing';
            default: return true;
        }
    });
}

function renderMessages(msgs) {
    if (!msgs || !msgs.length) {
        $('#chatMsgs').find('.empty-state').remove();
        $('#chatMsgs').append('<div class="empty-state"><i class="fas fa-comment-dots"></i><p style="font-weight:700;">No messages yet</p></div>');
        return;
    }

    const filtered = filterMessages(msgs);

    if (!filtered.length) {
        $('#chatMsgs').html('<div class="empty-state"><i class="fas fa-filter"></i><p style="font-weight:700;">No messages match this filter</p></div>');
        return;
    }

    let h = '';
    let lastDate = '';
    let lastSenderKey = '';
    let lastTs = 0;

    filtered.forEach((m, idx) => {
        const ts = m.timestamp || m.created_at;
        const d = parseUTC(ts);

        // Date separator
        const today = new Date(); today.setHours(0,0,0,0);
        const dOnly = new Date(d); dOnly.setHours(0,0,0,0);
        const yest = new Date(today); yest.setDate(yest.getDate() - 1);

        let label = d.toLocaleDateString('en-US', {month:'short', day:'numeric', year:'numeric'});
        if (dOnly.getTime() === today.getTime())  label = 'Today';
        else if (dOnly.getTime() === yest.getTime()) label = 'Yesterday';

        if (label !== lastDate) {
            h += `<div class="date-sep"><span>${label}</span></div>`;
            lastDate = label;
            lastSenderKey = '';   // reset grouping on new day
        }

        // Grouping: same direction + same staff + within 2 min
        const senderKey = (m.direction || '') + '|' + (m.staff_id || m.staff_name || 'customer');
        const withinGroup = Math.abs(d.getTime() - lastTs) < 120000;
        const isGrouped = (senderKey === lastSenderKey) && withinGroup;
        const isGroupStart = !isGrouped;

        h += renderMessage(m, isGrouped, isGroupStart);

        lastSenderKey = senderKey;
        lastTs = d.getTime();

        if (m.id) lastMsgId = Math.max(lastMsgId, parseInt(m.id));
    });

    // Preserve scroll position if user was reading history
    const container = document.getElementById('chatMsgs');
    const wasNearBottom = isNearBottom();
    const prevScrollTop = container.scrollTop;

    $('#chatMsgs').html(h);

    if (autoScroll && wasNearBottom) {
        scrollBottom(false);
    } else {
        container.scrollTop = prevScrollTop;
    }

    applySearchHighlight();
    updateJumpButton();
}

function renderMessage(m, isGrouped, isGroupStart) {
    const isOut = m.direction === 'outgoing';
    const wrapClass = 'msg-wrap ' + (isOut ? 'out' : 'in')
                    + (isGroupStart ? ' group-start' : '')
                    + (isGrouped ? ' grouped' : '');
    const bubbleClass = 'msg-bubble ' + (isOut ? 'out' : 'in')
                      + (isGrouped ? ' grouped' : '');

    const time = parseUTC(m.timestamp || m.created_at)
        .toLocaleTimeString([], { hour:'2-digit', minute:'2-digit' });
    const fullTime = fmtFull(m.timestamp || m.created_at);

    let body = '';

    // Optional reply quote
    if (m.context_body || m.reply_to_body) {
        const quote = m.context_body || m.reply_to_body || '';
        body += `<div class="msg-quote">${esc(String(quote).substring(0, 100))}</div>`;
    }

    const caption = captionOf(m);

    switch (m.message_type) {
        case 'text':
            body += `<div class="msg-text">${linkify(m.message_content || '')}</div>`;
            break;

        case 'template':
            body += `<div class="msg-text" style="color:#0a3358;font-weight:700;">${esc(m.message_content || '📩 Template')}</div>`;
            break;

        case 'image':
            if (caption) body += `<div class="msg-text" style="margin-bottom:6px;">${linkify(caption)}</div>`;
            body += m.media_url
                ? `<img src="${esc(m.media_url)}" class="media-preview" onclick="previewImg('${esc(m.media_url)}')" loading="lazy" alt="image">`
                : '<div class="msg-text">📷 Image</div>';
            break;

        case 'video':
            if (caption) body += `<div class="msg-text" style="margin-bottom:6px;">${linkify(caption)}</div>`;
            body += m.media_url
                ? `<div class="video-player"><video controls preload="metadata"><source src="${esc(m.media_url)}"></video></div>`
                : '<div class="msg-text">📹 Video</div>';
            break;

        case 'audio':
            if (caption) body += `<div class="msg-text" style="margin-bottom:6px;">${linkify(caption)}</div>`;
            body += m.media_url
                ? `<div class="audio-player"><i class="fas fa-volume-up"></i><audio controls preload="metadata"><source src="${esc(m.media_url)}"></audio></div>`
                : '<div class="msg-text">🎵 Audio</div>';
            break;

        case 'document':
            if (caption) body += `<div class="msg-text" style="margin-bottom:8px;">${linkify(caption)}</div>`;
            if (m.media_url) {
                const fn = esc(m.media_filename || 'Document');
                const isPdf = (m.media_filename||'').toLowerCase().endsWith('.pdf');
                const icon = isPdf ? 'fa-file-pdf text-danger' : 'fa-file-alt text-primary';
                const size = m.media_file_size ? fmtBytes(m.media_file_size) : '';
                body += `<a href="${esc(m.media_url)}" target="_blank" rel="noopener" class="doc-card" download>
                    <i class="fas ${icon} fa-2x"></i>
                    <div style="flex:1;min-width:0;">
                        <div class="doc-name">${fn}</div>
                        <div class="doc-meta">${size ? size + ' · ' : ''}Click to open</div>
                    </div>
                    <i class="fas fa-download" style="color:#6b8095;"></i>
                </a>`;
            } else {
                body += `<div class="msg-text">📄 ${esc(m.media_filename || 'Document')}</div>`;
            }
            break;

        case 'sticker':
            body += m.media_url
                ? `<img src="${esc(m.media_url)}" class="sticker-img" alt="sticker">`
                : '<div class="msg-text">🎨 Sticker</div>';
            break;

        case 'location':
            body += (m.latitude && m.longitude)
                ? `<div class="loc-card"><a href="https://maps.google.com/?q=${m.latitude},${m.longitude}" target="_blank" rel="noopener">
                     <i class="fas fa-map-marker-alt text-danger"></i>
                     <strong>${esc(m.address || 'Location')}</strong>
                     <div style="font-size:.7rem;color:#6b8095;margin-top:3px;">${m.latitude}, ${m.longitude}</div>
                   </a></div>`
                : '<div class="msg-text">📍 Location</div>';
            break;

        case 'contact':
            body += `<div class="contact-card">
                <i class="fas fa-user-circle fa-lg text-primary"></i>
                <div style="margin-top:4px;">
                    <div style="font-weight:700;">${esc(m.contact_name || 'Contact')}</div>
                    ${m.contact_phone ? `<div style="font-size:.75rem;color:#6b8095;">${esc(m.contact_phone)}</div>` : ''}
                </div>
            </div>`;
            break;

        default:
            body += `<div class="msg-text">${esc(m.message_content || m.message_type)}</div>`;
    }

    // Status ticks for outgoing
    let status = '';
    if (isOut) {
        if (m.status === 'read')           status = '<i class="fas fa-check-double" style="color:#0a3358;" title="Read"></i>';
        else if (m.status === 'delivered') status = '<i class="fas fa-check-double" style="color:#94a3b8;" title="Delivered"></i>';
        else if (m.status === 'sent')      status = '<i class="fas fa-check" style="color:#94a3b8;" title="Sent"></i>';
        else if (m.status === 'failed')    status = '<i class="fas fa-exclamation-circle" style="color:#dc3545;" title="Failed"></i>';
    }

    // Sender name for group start
    const senderHtml = (isOut && m.staff_name && isGroupStart)
        ? `<div class="msg-sender">${esc(m.staff_name)}</div>`
        : '';

    // Hover actions
    const canCopy = m.message_type === 'text' || caption;
    const copyText = (m.message_type === 'text') ? (m.message_content || '') : caption;
    const actions = `
        <div class="msg-actions">
            ${canCopy ? `<button class="msg-act" title="Copy" onclick="copyMessage(event, ${JSON.stringify(copyText).replace(/"/g,'&quot;')})"><i class="fas fa-copy"></i></button>` : ''}
            <button class="msg-act" title="Reply" onclick="replyToMessage(${m.id}, ${JSON.stringify(m.message_type||'').replace(/"/g,'&quot;')}, ${JSON.stringify((m.message_content||'').substring(0,100)).replace(/"/g,'&quot;')})"><i class="fas fa-reply"></i></button>
            ${m.media_url ? `<button class="msg-act" title="Download" onclick="downloadMedia('${esc(m.media_url)}','${esc(m.media_filename||'file')}')"><i class="fas fa-download"></i></button>` : ''}
            <button class="msg-act" title="Delete from view" onclick="hideMessage(this)"><i class="fas fa-eye-slash"></i></button>
        </div>`;

    return `<div class="${wrapClass}" data-msg-id="${m.id || ''}">
        <div class="${bubbleClass}" style="position:relative;">
            ${senderHtml}
            ${body}
            <div class="msg-time" title="${esc(fullTime)}">${time} ${status}</div>
            ${actions}
        </div>
    </div>`;
}

/* ============================================================
   MESSAGE ACTIONS
   ============================================================ */
function copyMessage(ev, text) {
    ev.stopPropagation();
    if (navigator.clipboard) {
        navigator.clipboard.writeText(text).then(() => toast('Copied', 'success'));
    } else {
        const ta = document.createElement('textarea');
        ta.value = text; document.body.appendChild(ta); ta.select();
        document.execCommand('copy'); ta.remove();
        toast('Copied', 'success');
    }
}

function downloadMedia(url, filename) {
    const a = document.createElement('a');
    a.href = url;
    a.download = filename || 'file';
    a.target = '_blank';
    a.rel = 'noopener';
    document.body.appendChild(a);
    a.click();
    a.remove();
}

function hideMessage(btn) {
    const wrap = btn.closest('.msg-wrap');
    if (wrap) {
        wrap.style.opacity = '0.35';
        wrap.style.pointerEvents = 'none';
        toast('Hidden from this view only', 'success');
    }
}

function replyToMessage(id, type, preview) {
    replyToMessage = { id, type, preview };
    $('#replyName').text('Replying to message');
    $('#replyText').text(preview || '[media]');
    $('#replyPreview').addClass('show');
    $('#msgText').focus();
}

function clearReply() {
    replyToMessage = null;
    $('#replyPreview').removeClass('show');
    $('#replyName, #replyText').text('');
}

/* ============================================================
   SEARCH IN CONVERSATION
   ============================================================ */
function toggleChatSearch() {
    if (!currentConvId) return;
    const bar = $('#chatSearchBar');
    bar.toggleClass('show');
    if (bar.hasClass('show')) {
        setTimeout(() => $('#chatSearchInput').focus(), 100);
    } else {
        msgSearch = '';
        $('#chatSearchInput').val('');
        renderMessages(displayedMessages);
    }
}

function applySearchHighlight() {
    if (!msgSearch) {
        $('#chatSearchCount').text('0');
        msgSearchMatches = [];
        msgSearchIndex = 0;
        return;
    }

    const q = msgSearch.toLowerCase();
    msgSearchMatches = [];

    $('.msg-bubble').each(function() {
        const $b = $(this);
        const $text = $b.find('.msg-text').first();
        if (!$text.length) return;
        if ($text.text().toLowerCase().includes(q)) {
            msgSearchMatches.push($b[0]);
        }
    });

    $('#chatSearchCount').text(msgSearchMatches.length ? (msgSearchIndex + 1) + '/' + msgSearchMatches.length : '0');

    // Highlight current match
    msgSearchMatches.forEach((el, i) => {
        el.style.boxShadow = (i === msgSearchIndex) ? '0 0 0 3px #f59e0b' : '';
    });

    if (msgSearchMatches[msgSearchIndex]) {
        msgSearchMatches[msgSearchIndex].scrollIntoView({ behavior:'smooth', block:'center' });
    }
}

function navigateSearch(dir) {
    if (!msgSearchMatches.length) return;
    msgSearchIndex = (msgSearchIndex + dir + msgSearchMatches.length) % msgSearchMatches.length;
    applySearchHighlight();
}

/* ============================================================
   JUMP TO LATEST
   ============================================================ */
function updateJumpButton() {
    if (unreadSinceScroll > 0 && !autoScroll) {
        $('#jumpLatest').addClass('show');
        if (unreadSinceScroll > 1) {
            $('#jumpCount').text(unreadSinceScroll).show();
        } else {
            $('#jumpCount').hide();
        }
    } else {
        $('#jumpLatest').removeClass('show');
    }
}

/* ============================================================
   SENDING
   ============================================================ */
function handleSendError(r) {
    switch (r.code) {
        case 'WINDOW_CLOSED':
        case 'OUTSIDE_24H_WINDOW_FIRST_MSG':
            Swal.fire({
                icon: 'info',
                title: '24-hour window closed',
                html: (r.hint || "Meta only allows free-form replies within 24 hours of the customer's last message."),
                showCancelButton: true,
                confirmButtonText: 'Send Template',
                confirmButtonColor: '#0a3358'
            }).then(x => { if (x.isConfirmed) openTemplatePicker(); });
            return;

        case 'NUMBER_BLOCKED':
            Swal.fire({ icon: 'warning', title: 'Number is blocked', text: 'Remove the block before sending.' });
            return;

        case 'RATE_LIMITED':
        case 'RATE_LIMIT_STAFF':
        case 'RATE_LIMIT_CONV':
            toast(`Too fast — retry in ${r.retry_after || 30}s`, 'warn');
            return;

        case 'DUPLICATE':
            toast('Duplicate send — ignored', 'warn');
            return;

        case 'NO_CREDENTIALS':
            Swal.fire({
                icon: 'error',
                title: 'WhatsApp API not configured',
                text: 'Missing credentials. Ask your administrator to check the .env file.'
            });
            return;

        default:
            toast('Failed: ' + (r.error || 'Unknown error'), 'error');
    }
}

function sendText() {
    const txt = $('#msgText').val().trim();
    if (!txt || !currentConvId) return;

    // Optional reply context
    let payload = {
        action: 'send_message',
        conversation_id: currentConvId,
        message: txt,
        csrf_token: CSRF_TOKEN
    };
    if (replyToMessage) payload.context_message_id = replyToMessage.id;

    $('#sendBtn').prop('disabled', true);
    $('#msgText').val('').css('height','auto');
    $('#charCounter').removeClass('show');
    clearDraft(currentConvId);
    clearReply();

    $.ajax({
        url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true},
        data: payload,
        success: r => {
            if (r.success) {
                loadMessages(currentConvId);
                refreshConvs();
            } else {
                // Restore text on failure
                $('#msgText').val(txt).trigger('input');
                handleSendError(r);
            }
        },
        error: () => {
            $('#msgText').val(txt).trigger('input');
            toast('Network error', 'error');
        }
    });
}

function queueMedia(file) {
    if (!currentConvId) { toast('Select a conversation first', 'error'); return; }
    if (file.size > 100 * 1024 * 1024) { toast('File too large (max 100 MB)', 'error'); return; }

    const isImage = file.type.startsWith('image/');
    const isVideo = file.type.startsWith('video/');
    const icon = isImage ? 'fa-image' : isVideo ? 'fa-video' : file.name.endsWith('.pdf') ? 'fa-file-pdf' : 'fa-file-alt';
    const color = isImage ? '#25D366' : isVideo ? '#dc3545' : '#0a3358';

    Swal.fire({
        html: `
            <div style="text-align:center;">
                <i class="fas ${icon}" style="font-size:3rem;color:${color};margin-bottom:12px;"></i>
                <div style="font-weight:800;color:#0a3358;word-break:break-all;margin-bottom:6px;">${esc(file.name)}</div>
                <div style="font-size:.75rem;color:#6b8095;margin-bottom:16px;">${fmtBytes(file.size)}</div>
            </div>
        `,
        input: 'textarea',
        inputLabel: 'Add a caption (optional)',
        inputPlaceholder: 'Type a message to send with this file...',
        inputAttributes: { maxlength: 1024 },
        showCancelButton: true,
        confirmButtonText: 'Send',
        confirmButtonColor: '#25D366',
        cancelButtonColor: '#94a3b8'
    }).then(res => {
        if (!res.isConfirmed) return;
        sendMedia(file, (res.value || '').trim());
    });
}

function sendMedia(file, caption) {
    toast('Uploading ' + file.name + '...', 'success');

    const fd = new FormData();
    fd.append('action', 'send_media');
    fd.append('conversation_id', currentConvId);
    fd.append('caption', caption || '');
    fd.append('file', file);
    fd.append('csrf_token', CSRF_TOKEN);

    $.ajax({
        url: API_URL, method:'POST', data: fd,
        processData: false, contentType: false,
        dataType: 'json', xhrFields: { withCredentials: true }, timeout: 120000,
        success: r => {
            if (r.success) {
                toast('Sent!', 'success');
                loadMessages(currentConvId);
                refreshConvs();
            } else {
                handleSendError(r);
            }
        },
        error: () => toast('Upload failed', 'error')
    });
}

function pickMedia(type) {
    const map = { image:'#inpImage', video:'#inpVideo', document:'#inpDoc', audio:'#inpAudio' };
    if (map[type]) $(map[type]).click();
    $('#attachMenu').removeClass('show');
}

function insertEmoji(e) {
    const t = document.getElementById('msgText');
    const s = t.selectionStart, en = t.selectionEnd, v = t.value;
    t.value = v.substring(0,s) + e + v.substring(en);
    t.focus();
    t.selectionStart = t.selectionEnd = s + e.length;
    $('#sendBtn').prop('disabled', false);
    $(t).trigger('input');
    $('#emojiPicker').hide();
}

function openLocation() {
    if (!currentConvId) { toast('Select a conversation first', 'error'); return; }
    modals.loc.show();
}

function detectLocation() {
    if (!navigator.geolocation) { toast('Geolocation not supported', 'error'); return; }
    Swal.fire({ title:'Getting location...', allowOutsideClick:false, didOpen: () => Swal.showLoading() });
    navigator.geolocation.getCurrentPosition(
        p => { Swal.close(); $('#locLat').val(p.coords.latitude); $('#locLng').val(p.coords.longitude); },
        () => { Swal.close(); toast('Could not get location', 'error'); }
    );
}

function sendLocation() {
    const lat = $('#locLat').val(), lng = $('#locLng').val();
    if (!lat || !lng) { toast('Latitude and longitude required', 'error'); return; }
    $.ajax({
        url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true},
        data: {
            action: 'send_location',
            conversation_id: currentConvId,
            latitude: lat,
            longitude: lng,
            name: $('#locName').val(),
            address: $('#locAddr').val(),
            csrf_token: CSRF_TOKEN
        },
        success: r => {
            if (r.success) {
                modals.loc.hide();
                $('#locName,#locAddr,#locLat,#locLng').val('');
                loadMessages(currentConvId);
                toast('Location sent!', 'success');
            } else {
                handleSendError(r);
            }
        },
        error: () => toast('Network error', 'error')
    });
}

function openContact() {
    if (!currentConvId) { toast('Select a conversation first', 'error'); return; }
    modals.contact.show();
}

function sendContact() {
    const name  = $('#cName').val().trim();
    const phone = $('#cPhone').val().trim();
    if (!name || !phone) { toast('Name and phone required', 'error'); return; }

    $.ajax({
        url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true},
        data: {
            action: 'send_contact',
            conversation_id: currentConvId,
            name, phone,
            csrf_token: CSRF_TOKEN
        },
        success: r => {
            if (r.success) {
                modals.contact.hide();
                $('#cName,#cPhone').val('');
                loadMessages(currentConvId);
                toast('Contact sent!', 'success');
            } else {
                handleSendError(r);
            }
        },
        error: () => toast('Network error', 'error')
    });
}

/* ============================================================
   TEMPLATES
   ============================================================ */
function loadTemplates() {
    $.ajax({
        url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true},
        data: { action:'get_templates', csrf_token: CSRF_TOKEN },
        success: r => { templates = (r.success && r.templates) ? r.templates : []; },
        error: () => { templates = []; }
    });
}

function openTemplatePicker() {
    if (!currentConvId) { toast('Select a conversation first', 'error'); return; }

    const sel = $('#tplSelect');
    sel.html('<option value="">— choose —</option>');

    if (!templates.length) {
        sel.append('<option value="" disabled>No templates available</option>');
    } else {
        templates.forEach(t => {
            sel.append(`<option value="${esc(t.name)}" data-msg="${esc(t.message)}">${esc(t.name)}</option>`);
        });
    }

    $('#tplParams').empty();
    modals.template.show();
}

function sendTemplate() {
    const name = $('#tplSelect').val();
    if (!name) { toast('Choose a template', 'error'); return; }

    const lang = $('#tplLang').val().trim() || 'en';
    const params = [];
    $('.tpl-param').each(function() {
        params[parseInt($(this).data('idx')) - 1] = $(this).val();
    });

    $('#tplSend').prop('disabled', true).text('Sending...');

    $.ajax({
        url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true},
        data: {
            action: 'send_template',
            conversation_id: currentConvId,
            template_name: name,
            template_language: lang,
            body_params: params,
            csrf_token: CSRF_TOKEN
        },
        success: r => {
            if (r.success) {
                modals.template.hide();
                loadMessages(currentConvId);
                refreshConvs();
                toast('Template sent', 'success');
            } else {
                handleSendError(r);
            }
        },
        error: () => toast('Network error', 'error'),
        complete: () => $('#tplSend').prop('disabled', false).text('Send Template')
    });
}

/* ============================================================
   NEW CHAT
   ============================================================ */
function createChat() {
    const phone = $('#newPhone').val().trim();
    if (!phone) { toast('Phone required', 'error'); return; }

    $('#createChatBtn').prop('disabled', true).text('Creating...');

    $.ajax({
        url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true},
        data: {
            action: 'create_chat',
            phone,
            name: $('#newName').val(),
            message: $('#newMsg').val(),
            priority: $('#newPriority').val(),
            csrf_token: CSRF_TOKEN
        },
        success: r => {
            if (r.success) {
                modals.newChat.hide();
                $('#newPhone,#newName,#newMsg').val('');
                toast('Chat created', 'success');
                loadConversations();
                setTimeout(() => openConversation(r.conversation_id), 400);

                if (r.warning) {
                    Swal.fire({ icon: 'info', title: 'Heads up', text: r.warning });
                }
            } else {
                handleSendError(r);
            }
        },
        error: () => toast('Network error', 'error'),
        complete: () => $('#createChatBtn').prop('disabled', false).text('Start Chat')
    });
}

/* ============================================================
   INFO PANEL
   ============================================================ */
function showInfoPanel() {
    if (!currentConvId) return;
    const c = allConvs.find(x => x.id == currentConvId);
    if (!c) return;

    const n = c.customer_name || c.customer_phone || 'Unknown';
    const priorityClass = c.priority === 'vip' ? 'vip' : c.priority === 'high' ? 'high' : '';
    const priorityLabel = c.priority === 'vip' ? 'VIP' : c.priority === 'high' ? 'High' : 'Normal';

    // Count message stats
    const total = displayedMessages.length;
    const inbound  = displayedMessages.filter(m => m.direction === 'incoming').length;
    const outbound = total - inbound;
    const mediaCount = displayedMessages.filter(m => ['image','video','document','audio','sticker'].includes(m.message_type)).length;

    const first = displayedMessages[0];
    const last  = displayedMessages[displayedMessages.length - 1];

    $('#infoPanelBody').html(`
        <div class="info-customer">
            <div class="info-customer-avatar">${esc(n.charAt(0).toUpperCase())}</div>
            <div class="info-customer-name">${esc(n)}</div>
            <div class="info-customer-phone">+${esc(c.customer_phone || '—')}</div>
        </div>

        <div class="info-stats">
            <div class="info-stat">
                <div class="num">${total}</div>
                <div class="lbl">Messages</div>
            </div>
            <div class="info-stat">
                <div class="num">${inbound}</div>
                <div class="lbl">Inbound</div>
            </div>
            <div class="info-stat">
                <div class="num">${outbound}</div>
                <div class="lbl">Outbound</div>
            </div>
            <div class="info-stat">
                <div class="num">${mediaCount}</div>
                <div class="lbl">Media</div>
            </div>
        </div>

        <div class="info-section-title"><i class="fas fa-info-circle"></i> Customer</div>
        <div class="info-row"><span class="lbl">Status</span><span class="val">${esc(c.status || 'active')}</span></div>
        <div class="info-row"><span class="lbl">Priority</span><span class="val">${esc(priorityLabel)}</span></div>
        <div class="info-row"><span class="lbl">Assigned</span><span class="val">${esc(c.assigned_to || 'Unassigned')}</span></div>
        <div class="info-row"><span class="lbl">Source</span><span class="val">${esc(c.source || 'whatsapp')}</span></div>
        ${c.notes ? `<div class="info-row"><span class="lbl">Notes</span><span class="val">${esc(c.notes)}</span></div>` : ''}

        <div class="info-section-title"><i class="fas fa-clock"></i> Timeline</div>
        <div class="info-row"><span class="lbl">Created</span><span class="val">${c.created_at ? esc(fmtFull(c.created_at)) : '—'}</span></div>
        <div class="info-row"><span class="lbl">First message</span><span class="val">${first ? esc(fmtFull(first.timestamp || first.created_at)) : '—'}</span></div>
        <div class="info-row"><span class="lbl">Last activity</span><span class="val">${last ? esc(fmtFull(last.timestamp || last.created_at)) : '—'}</span></div>

        <div class="info-section-title"><i class="fas fa-bolt"></i> Actions</div>
        <div class="info-actions">
            <button class="info-action primary" onclick="editConv()"><i class="fas fa-edit"></i> Edit</button>
            <button class="info-action" onclick="assignToMe()"><i class="fas fa-user-plus"></i> Assign</button>
            <button class="info-action" onclick="copyPhone('${esc(c.customer_phone)}')"><i class="fas fa-phone"></i> Copy phone</button>
            <button class="info-action" onclick="exportConversation()"><i class="fas fa-download"></i> Export chat</button>
        </div>
    `);

    $('#infoPanel').addClass('show');
}

function copyPhone(phone) {
    if (navigator.clipboard) {
        navigator.clipboard.writeText('+' + phone).then(() => toast('Phone copied', 'success'));
    }
}

function exportConversation() {
    if (!displayedMessages.length) { toast('No messages to export', 'warn'); return; }

    const c = allConvs.find(x => x.id == currentConvId);
    const name = (c?.customer_name || c?.customer_phone || 'chat').replace(/[^a-z0-9]+/gi, '_');

    let csv = 'timestamp,direction,type,status,staff,content\n';
    displayedMessages.forEach(m => {
        const row = [
            fmtFull(m.timestamp || m.created_at),
            m.direction,
            m.message_type,
            m.status || '',
            m.staff_name || '',
            (m.message_content || '').replace(/"/g, '""')
        ].map(v => `"${v}"`).join(',');
        csv += row + '\n';
    });

    const blob = new Blob([csv], { type: 'text/csv' });
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = 'chat_' + name + '_' + Date.now() + '.csv';
    a.click();
    toast('Conversation exported', 'success');
}

/* ============================================================
   EDIT / ASSIGN
   ============================================================ */
function editConv() {
    if (!currentConvId) return;
    const c = allConvs.find(x => x.id == currentConvId);
    if (!c) return;
    $('#editId').val(c.id);
    $('#editName').val(c.customer_name || '');
    $('#editPhone').val(c.customer_phone || '');
    $('#editNotes').val(c.notes || '');
    $('#editStatus').val(c.status || 'active');
    $('#editPriority').val(c.priority || 'normal');
    $('#infoPanel').removeClass('show');
    modals.edit.show();
}

function saveEdit() {
    const id = $('#editId').val();
    if (!id) return;

    $.ajax({
        url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true},
        data: {
            action: 'update_conversation',
            conversation_id: id,
            customer_name: $('#editName').val(),
            notes: $('#editNotes').val(),
            status: $('#editStatus').val(),
            priority: $('#editPriority').val(),
            csrf_token: CSRF_TOKEN
        },
        success: r => {
            if (r.success) {
                const c = allConvs.find(x => x.id == id);
                if (c) {
                    c.customer_name = $('#editName').val();
                    c.notes  = $('#editNotes').val();
                    c.status = $('#editStatus').val();
                    c.priority = $('#editPriority').val();
                }
                renderConvList();
                modals.edit.hide();
                toast('Saved', 'success');
            } else {
                toast('Save failed: ' + (r.error || ''), 'error');
            }
        },
        error: () => toast('Network error', 'error')
    });
}

function assignToMe() {
    if (!currentConvId) return;
    Swal.fire({
        title: 'Assign to me?',
        icon: 'question',
        showCancelButton: true,
        confirmButtonColor: '#0a3358'
    }).then(r => {
        if (!r.isConfirmed) return;

        $.ajax({
            url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true},
            data: { action:'assign_to_me', conversation_id: currentConvId, csrf_token: CSRF_TOKEN },
            success: res => {
                if (res.success) {
                    const c = allConvs.find(x => x.id == currentConvId);
                    if (c) {
                        c.assigned_staff_id = STAFF_ID;
                        c.assigned_to = STAFF_NAME;
                    }
                    $('#chatStatus').html('<i class="fas fa-user-check" style="color:var(--orange);"></i> Assigned to you');
                    renderConvList();
                    toast('Assigned to you', 'success');
                    $('#infoPanel').removeClass('show');
                } else {
                    toast('Assign failed: ' + (res.error || ''), 'error');
                }
            },
            error: () => toast('Network error', 'error')
        });
    });
}

/* ============================================================
   BULK ACTIONS
   ============================================================ */
function markAllRead() {
    const unreadConvs = allConvs.filter(c => (parseInt(c.unread_count) || 0) > 0);
    if (!unreadConvs.length) { toast('Nothing to mark read', 'warn'); return; }

    Swal.fire({
        title: 'Mark all as read?',
        text: unreadConvs.length + ' conversation(s)',
        icon: 'question',
        showCancelButton: true,
        confirmButtonColor: '#0a3358'
    }).then(r => {
        if (!r.isConfirmed) return;

        let done = 0;
        unreadConvs.forEach(c => {
            $.ajax({
                url: API_URL, method:'POST', xhrFields:{withCredentials:true},
                data: { action:'mark_read', conversation_id: c.id, csrf_token: CSRF_TOKEN },
                complete: () => {
                    c.unread_count = 0;
                    done++;
                    if (done === unreadConvs.length) {
                        renderConvList();
                        updateBadge();
                        toast('All marked read', 'success');
                    }
                }
            });
        });
    });
}

function exportCsv() {
    if (!allConvs.length) { toast('No conversations to export', 'warn'); return; }
    let csv = 'id,phone,name,priority,status,assigned_to,unread,last_message,last_message_time\n';
    allConvs.forEach(c => {
        const row = [
            c.id,
            c.customer_phone || '',
            c.customer_name || '',
            c.priority || 'normal',
            c.status || 'active',
            c.assigned_to || '',
            c.unread_count || 0,
            (c.last_message || '').replace(/"/g, '""'),
            c.last_message_time || ''
        ].map(v => `"${v}"`).join(',');
        csv += row + '\n';
    });
    const blob = new Blob([csv], { type: 'text/csv' });
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = 'whatsapp_conversations_' + Date.now() + '.csv';
    a.click();
    toast('Exported ' + allConvs.length + ' conversations', 'success');
}

/* ============================================================
   DRAFTS
   ============================================================ */
let draftTimer = null;
function saveDraft(convId, text) {
    if (!convId) return;
    clearTimeout(draftTimer);
    draftTimer = setTimeout(() => {
        if (text.trim()) localStorage.setItem('wa_draft_' + convId, text);
        else localStorage.removeItem('wa_draft_' + convId);
    }, 400);
}
function clearDraft(convId) {
    if (convId) localStorage.removeItem('wa_draft_' + convId);
}

/* ============================================================
   POLLING
   ============================================================ */
function startPolling() {
    if (pollTimer) clearInterval(pollTimer);
    pollTimer = setInterval(function() {
        if (currentConvId) {
            $.ajax({
                url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true},
                data: {
                    action: 'check_new',
                    conversation_id: currentConvId,
                    last_id: lastMsgId,
                    csrf_token: CSRF_TOKEN
                },
                success: r => {
                    if (r.has_new) {
                        // Count unread
                        const newInbound = (r.messages || []).filter(m => m.direction === 'incoming').length;
                        if (newInbound > 0 && !isNearBottom()) {
                            unreadSinceScroll += newInbound;
                            playPing();
                            notifyDesktop(newInbound);
                        } else if (newInbound > 0 && document.visibilityState !== 'visible') {
                            playPing();
                            notifyDesktop(newInbound);
                        }
                        loadMessages(currentConvId);
                    }
                    markSessionHealthy();
                },
                error: () => markSessionStale()
            });
        }
        refreshConvs();
    }, 5000);
}

function refreshConvs() {
    $.ajax({
        url: API_URL, method:'POST', dataType:'json', xhrFields:{withCredentials:true}, timeout: 5000,
        data: { action:'get_conversations', csrf_token: CSRF_TOKEN },
        success: r => {
            if (r.success && r.conversations) {
                allConvs = r.conversations;
                renderConvList();
                updateBadge();
                markSessionHealthy();
            }
        },
        error: () => markSessionStale()
    });
}

function updateBadge() {
    const total = allConvs.reduce((s,c) => s + (parseInt(c.unread_count)||0), 0);
    const b = $('#globalBadge');
    if (total > 0) {
        if (b.length) b.text(total > 99 ? '99+' : total);
        else $('.user-profile').append(`<span class="notif-badge" id="globalBadge">${total > 99 ? '99+' : total}</span>`);
        document.title = `(${total}) WhatsApp CRM`;
    } else {
        b.remove();
        document.title = 'WhatsApp CRM — Paktia Travel';
    }
}

/* ============================================================
   SESSION HEALTH INDICATOR
   ============================================================ */
let lastSuccess = Date.now();
function markSessionHealthy() {
    lastSuccess = Date.now();
    pollFailures = 0;
    $('#sessionDot').removeClass('stale offline');
    $('#sessionText').text('Connected');
}
function markSessionStale() {
    pollFailures++;
    const elapsed = Math.floor((Date.now() - lastSuccess) / 1000);
    if (pollFailures > 3 || elapsed > 30) {
        $('#sessionDot').addClass('offline').removeClass('stale');
        $('#sessionText').text('Offline');
    } else {
        $('#sessionDot').addClass('stale').removeClass('offline');
        $('#sessionText').text('Reconnecting...');
    }
}

/* ============================================================
   DESKTOP NOTIFICATIONS
   ============================================================ */
function notifyDesktop(count) {
    if (!('Notification' in window)) return;
    if (Notification.permission !== 'granted') return;
    if (document.visibilityState === 'visible') return;

    try {
        new Notification('New WhatsApp message', {
            body: count + ' new message' + (count > 1 ? 's' : ''),
            icon: '/roundlogo.png',
            tag: 'wa-' + currentConvId,
            silent: true
        });
    } catch (e) { /* silent */ }
}

// Ask for notification permission on first user interaction
$(document).one('click', function() {
    if ('Notification' in window && Notification.permission === 'default') {
        setTimeout(() => Notification.requestPermission(), 1000);
    }
});
</script>

</body>
</html>