<?php
session_start();
if (!isset($_SESSION['oms_user'])) { header('Location: login.php'); exit; }
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
$SESSION_USER = $_SESSION['oms_user'];
$userInitials = strtoupper(substr($SESSION_USER['name'], 0, 1));
if (strpos($SESSION_USER['name'], ' ') !== false) {
    $parts = explode(' ', $SESSION_USER['name']);
    $userInitials = strtoupper(substr($parts[0],0,1) . substr(end($parts),0,1));
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Filo Hevis OMS">
<meta name="theme-color" content="#0f172a">
<title>Filo Hevis OMS</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
* { box-sizing: border-box; }
body { font-family: 'Plus Jakarta Sans', 'Inter', sans-serif; background: #F5F6F8; }
:root {
  --bg-app: #F5F6F8;
  --bg-card: #FFFFFF;
  --accent-highlight: #E8F7AA;
  --accent-teal: #518A87;
  --accent-dark: #111827;
  --text-primary: #1F2937;
  --text-secondary: #9CA3AF;
  --border-light: #E5E7EB;
  --shadow-soft: 0 4px 20px rgba(0,0,0,0.03);
}
/* Smooth all transitions - Doherty Threshold */
*, *::before, *::after { transition-timing-function: cubic-bezier(0.4,0,0.2,1); }
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }

/* Sidebar */
#sidebar { background: #111827; width: 260px; min-width: 260px; transition: all 0.3s cubic-bezier(0.4,0,0.2,1); box-shadow: 2px 0 12px rgba(0,0,0,0.1); }
#sidebar.collapsed { width: 0; min-width: 0; overflow: hidden; }
.nav-item { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: 50px; cursor: pointer; transition: all 0.18s; color: #9CA3AF; font-size: 13px; font-weight: 500; white-space: nowrap; margin: 2px 4px; }
.nav-item:hover { background: rgba(255,255,255,0.08); color: #E5E7EB; transform: translateX(0); }
.nav-item.active-nav { background: var(--accent-highlight); color: var(--text-primary); border-left: none; font-weight: 700; }
.nav-item i { width: 20px; text-align: center; font-size: 15px; flex-shrink: 0; }
.nav-section-label { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: #4B5563; padding: 8px 18px 4px; }

/* Status badges */
.badge { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 99px; font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
.badge-done    { background: #dcfce7; color: #15803d; box-shadow: 0 0 0 1px #bbf7d0; }
.badge-cancel  { background: #fee2e2; color: #b91c1c; box-shadow: 0 0 0 1px #fecaca; }
.badge-pending { background: #fef3c7; color: #92400e; box-shadow: 0 0 0 1px #fde68a; }
.badge-busy    { background: #dbeafe; color: #1d4ed8; }
.badge-np      { background: #ffedd5; color: #c2410c; }
.badge-so      { background: #f3e8ff; color: #7e22ce; }
.badge-ni      { background: #f1f5f9; color: #475569; }
.badge-hold    { background: #fce7f3; color: #be185d; }
.badge-default { background: #f3f4f6; color: #374151; }
.badge-unassigned { background: #e0e7ff; color: #3730a3; }

/* Status colors for backward compat */
.status-Done    { background: #dcfce7; color: #15803d; }
.status-Cancel  { background: #fee2e2; color: #b91c1c; }
.status-Pending { background: #fef9c3; color: #a16207; }
.status-Busy    { background: #dbeafe; color: #1d4ed8; }
.status-NP      { background: #ffedd5; color: #c2410c; }
.status-SO      { background: #f3e8ff; color: #7e22ce; }
.status-NI      { background: #f1f5f9; color: #475569; }
.status-Default { background: #f3f4f6; color: #374151; }
.status-badge   { padding: 3px 10px; border-radius: 99px; font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }

/* Cards */
.card { background: var(--bg-card); border-radius: 24px; border: 1px solid rgba(255,255,255,0.5); box-shadow: var(--shadow-soft); }
.card:hover { box-shadow: 0 6px 24px rgba(0,0,0,0.06); }
.card-sm { background: var(--bg-card); border-radius: 16px; border: 1px solid var(--border-light); }

/* Stat pill */
.stat-pill { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 10px 18px; border-radius: 12px; border: 1px solid #e2e8f0; background: #fff; cursor: pointer; transition: all 0.2s; min-width: 80px; }
.stat-pill:hover { border-color: var(--accent-teal); box-shadow: 0 0 0 3px rgba(81,138,135,0.1); }
.stat-val { font-size: 22px; font-weight: 800; line-height: 1.1; }
.stat-lbl { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: #94a3b8; margin-top: 2px; }

/* Table */
.data-table { width: 100%; border-collapse: collapse; }
.data-table th { padding: 11px 16px; text-align: left; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-secondary); background: #F9FAFB; border-bottom: 2px solid var(--border-light); white-space: nowrap; }
.data-table td { padding: 13px 16px; border-bottom: 1px solid #f1f5f9; font-size: 13px; color: #334155; }
.data-table tbody tr { cursor: pointer; transition: background 0.12s; }
.data-table tbody tr:hover { background: #F5F6F8; }
.data-table tbody tr.dup-row { background: #fffbeb; }
.data-table tbody tr.dup-row:hover { background: #fef3c7; }

/* Sticky */
.sticky-left { position: sticky; left: 0; z-index: 20; background: #fff; border-right: 1px solid #e2e8f0; }
th.sticky-left { background: #f8fafc !important; }

/* Inputs & Selects */
.form-input { height: 36px; padding: 0 12px; border: 1.5px solid var(--border-light); border-radius: 12px; font-size: 13px; color: var(--text-primary); background: #fff; outline: none; font-family: inherit; transition: all 0.15s; }
.form-input:focus { border-color: var(--accent-teal); box-shadow: 0 0 0 3px rgba(81,138,135,0.12); }
.form-select { height: 36px; padding: 0 32px 0 12px; border: 1px solid var(--border-light); border-radius: 12px; font-size: 13px; color: var(--text-primary); background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 10px center; appearance: none; outline: none; cursor: pointer; font-family: inherit; transition: all 0.15s; }
.form-select:focus { border-color: var(--accent-teal); box-shadow: 0 0 0 3px rgba(81,138,135,0.12); }

/* Buttons */
.btn { display: inline-flex; align-items: center; gap: 6px; padding: 0 20px; height: 38px; border-radius: 30px; font-size: 13px; font-weight: 600; cursor: pointer; border: none; transition: all 0.15s; font-family: inherit; white-space: nowrap; letter-spacing: 0.01em; }
.btn:active { transform: scale(0.97); }
.btn-primary { background: var(--accent-dark); color: #fff; }
.btn-primary:hover { opacity: 0.85; background: var(--accent-dark); }
.btn-success { background: var(--accent-teal); color: #fff; }
.btn-success:hover { opacity: 0.9; background: var(--accent-teal); }
.btn-danger  { background: #ef4444; color: #fff; }
.btn-danger:hover { background: #dc2626; }
.btn-ghost { background: transparent; color: #6B7280; border: 1px solid var(--border-light); }
.btn-ghost:hover { background: var(--bg-app); color: var(--text-primary); }
.btn-sm { height: 30px; padding: 0 14px; font-size: 12px; border-radius: 30px; }

/* Tag chips */
.tag-chip { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 99px; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; border: 1px solid; }
.tag-high   { background: #fee2e2; color: #b91c1c; border-color: #fecaca; }
.tag-medium { background: #fef3c7; color: #92400e; border-color: #fde68a; }
.tag-low    { background: #dcfce7; color: #166534; border-color: #bbf7d0; }
.tag-red    { background: #fee2e2; color: #b91c1c; border-color: #fecaca; }
.tag-repeat { background: #ede9fe; color: #5b21b6; border-color: #ddd6fe; }
.tag-ppcod  { background: #ede9fe; color: #5b21b6; border-color: #ddd6fe; }
.tag-upi    { background: #d1fae5; color: #065f46; border-color: #a7f3d0; }
.tag-cod    { background: #dbeafe; color: #1e3a8a; border-color: #bfdbfe; }
.tag-hold   { background: #fce7f3; color: #9d174d; border-color: #fbcfe8; }
.tag-cancel { background: #fee2e2; color: #b91c1c; border-color: #fecaca; }
.tag-default{ background: #f1f5f9; color: #475569; border-color: #cbd5e1; }

/* Toast */
#toast-container { position: fixed; top: 20px; right: 20px; z-index: 9999; display: flex; flex-direction: column; gap: 8px; pointer-events: none; }
.toast { min-width: 300px; padding: 14px 18px; border-radius: 14px; background: #ffffff; color: #1f2937; box-shadow: 0 8px 24px rgba(0,0,0,0.12); display: flex; align-items: center; gap: 12px; font-size: 13px; font-weight: 600; pointer-events: all; animation: toastIn 0.35s cubic-bezier(0.16,1,0.3,1); border-left: 4px solid; }
.toast-success { border-color: #10b981; background: #f0fdf4; color: #14532d; }
.toast-error   { border-color: #ef4444; background: #fef2f2; color: #7f1d1d; }
.toast-info    { border-color: #6366f1; background: #eef2ff; color: #3730a3; }
@keyframes toastIn { from { transform: translateX(110%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes toastOut { from { opacity: 1; } to { opacity: 0; transform: translateX(110%); } }

/* Modal backdrop */
.modal-backdrop { position: fixed; inset: 0; background: rgba(15,23,42,0.6); backdrop-filter: blur(4px); z-index: 50; display: flex; align-items: center; justify-content: center; padding: 16px; }

/* Loader */
#loader { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; background: rgba(240,242,247,0.9); z-index: 40; backdrop-filter: blur(2px); }
.spinner { width: 44px; height: 44px; border: 3px solid #e2e8f0; border-top-color: var(--accent-dark); border-radius: 50%; animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Pagination */
.page-btn { width: 32px; height: 32px; border-radius: 8px; border: 1px solid #e2e8f0; background: #fff; color: #64748b; font-size: 13px; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: all 0.15s; }
.page-btn:hover:not(:disabled) { background: var(--accent-highlight); border-color: #acd94a; color: var(--text-primary); }
.page-btn.active { background: var(--accent-dark); color: #fff; border-color: var(--accent-dark); }
.page-btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* Count badges */
.count-badge { display: flex; flex-direction: column; align-items: center; justify-content: center; background: white; border: 1px solid #e2e8f0; border-radius: 10px; padding: 8px 14px; min-width: 72px; cursor: pointer; transition: all 0.2s; }
.count-badge:hover { border-color: var(--accent-teal); box-shadow: 0 0 0 3px rgba(81,138,135,0.1); }
.count-value { font-size: 20px; font-weight: 800; color: #1e293b; line-height: 1; }
.count-label { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: #94a3b8; margin-top: 3px; }

/* Animations */
.fade-up { animation: fadeUp 0.35s cubic-bezier(0.16,1,0.3,1); }
@keyframes fadeUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }

/* Scan cards */
.scan-card-found  { background: #f0fdf4; border: 1px solid #bbf7d0; }
.scan-card-notfound{ background: #fffbeb; border: 1px solid #fde68a; }

/* Misc */
.truncate-2 { overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
input[type="date"] { cursor: pointer; }
input[type="date"]::-webkit-calendar-picker-indicator { opacity: 0; position: absolute; width: 100%; height: 100%; cursor: pointer; }
input[type="date"] { position: relative; }
.view-section { display: none; }
.view-section.active { display: flex; flex-direction: column; }
.selected-row td { background: #eef2ff !important; }
.selected-row td:first-child { border-left: 3px solid #6366f1; }

/* MOBILE RESPONSIVE */
@media(max-width:768px){aside#sidebar{position:fixed!important;left:-220px!important;top:0;bottom:0;width:200px!important;z-index:200;transition:left 0.25s ease;box-shadow:4px 0 24px rgba(0,0,0,.18)}aside#sidebar.mobile-open{left:0!important}#sidebar-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:199}#sidebar-overlay.active{display:block}main{margin-left:0!important;width:100%!important}#content-area{padding:10px 8px!important}.card{border-radius:10px!important}.data-table,table{min-width:500px}.overflow-auto{overflow-x:auto!important;-webkit-overflow-scrolling:touch}.count-badge{min-width:58px!important;padding:6px 10px!important}.count-value{font-size:20px!important}.grid.grid-cols-2{grid-template-columns:1fr!important}.max-w-2xl{max-width:100%!important}.modal-backdrop>div{width:96vw!important;max-height:90vh!important;overflow-y:auto!important;margin:5vh auto!important}.nav-item{font-size:12px!important;padding:9px 10px!important;gap:8px!important}input[type=date]{font-size:12px!important}#view-returns .overflow-auto{max-height:55vh!important}}@media(min-width:769px)and(max-width:1024px){aside#sidebar{width:200px!important;min-width:200px!important}.nav-item{font-size:12px!important;padding:9px 10px!important}}
/* ── Mobile app-like enhancements (additive — desktop untouched) ── */
@media(max-width:768px){
  /* Inline-styled stat grids: stack 2-up instead of squeezing 3-5 tiny columns */
  div[style*="repeat(5,1fr)"],div[style*="repeat(5, 1fr)"],
  div[style*="repeat(4,1fr)"],div[style*="repeat(4, 1fr)"],
  div[style*="repeat(3,1fr)"],div[style*="repeat(3, 1fr)"]{grid-template-columns:repeat(2,1fr)!important}
  .grid-cols-4,.grid-cols-3{grid-template-columns:repeat(2,1fr)!important}
  /* Header wraps cleanly; search shrinks */
  header{height:auto!important;min-height:56px;flex-wrap:wrap;padding:8px 10px!important;row-gap:6px}
  header input{min-width:0!important;width:150px!important}
  /* Content never causes page-level sideways scroll; wide content scrolls inside its card */
  #content-area{overflow-x:hidden!important}
  #content-area .card{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}
  /* Order Lifecycle Tracker becomes a full-screen app sheet */
  #lifecycleModal{padding:0!important}
  #lifecycleModal>div{max-width:100vw!important;width:100vw!important;min-height:100vh!important;border-radius:0!important;margin:0!important}
  #lifecycleModal div[style*="overflow-x:auto"]{-webkit-overflow-scrolling:touch}
  /* Touch friendliness: 16px inputs stop iOS auto-zoom; bigger tap targets */
  input[type=text],input[type=search],input[type=password],input[type=number],input[type=date],select,textarea{font-size:16px!important}
  .btn{min-height:38px}
  .nav-item{min-height:42px}
  /* Filter bars wrap instead of overflowing */
  .flex.items-center.gap-3{flex-wrap:wrap}
}
/* When added to home screen (standalone), feel like a native app */
@media all and (display-mode: standalone){
  body{-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}
  input,textarea,[contenteditable]{-webkit-user-select:text;user-select:text}
}
/* ── Device-based mobile rules: apply on real phones even if browser reports a desktop viewport ── */
body.is-mobile aside#sidebar{position:fixed!important;left:-240px!important;top:0;bottom:0;width:220px!important;z-index:200;transition:left 0.25s ease;box-shadow:4px 0 24px rgba(0,0,0,.18)}
body.is-mobile aside#sidebar.mobile-open{left:0!important}
body.is-mobile #sidebar-overlay.active{display:block}
body.is-mobile main{margin-left:0!important;width:100%!important;max-width:100vw!important}
body.is-mobile #content-area{padding:10px 8px!important;overflow-x:hidden!important}
body.is-mobile #content-area .card{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;border-radius:10px!important}
body.is-mobile div[style*="repeat(5,1fr)"],body.is-mobile div[style*="repeat(5, 1fr)"],
body.is-mobile div[style*="repeat(4,1fr)"],body.is-mobile div[style*="repeat(4, 1fr)"],
body.is-mobile div[style*="repeat(3,1fr)"],body.is-mobile div[style*="repeat(3, 1fr)"]{grid-template-columns:repeat(2,1fr)!important}
body.is-mobile .grid-cols-4,body.is-mobile .grid-cols-3{grid-template-columns:repeat(2,1fr)!important}
body.is-mobile .grid.grid-cols-2{grid-template-columns:1fr!important}
body.is-mobile header{height:auto!important;min-height:56px;flex-wrap:wrap;padding:8px 10px!important;row-gap:6px}
body.is-mobile header input{min-width:0!important;width:150px!important}
body.is-mobile .max-w-2xl{max-width:100%!important}
body.is-mobile .modal-backdrop>div{width:96vw!important;max-height:90vh!important;overflow-y:auto!important;margin:5vh auto!important}
body.is-mobile #lifecycleModal{padding:0!important}
body.is-mobile #lifecycleModal>div{max-width:100vw!important;width:100vw!important;min-height:100vh!important;border-radius:0!important;margin:0!important}
body.is-mobile #lifecycleModal div[style*="overflow-x:auto"]{-webkit-overflow-scrolling:touch}
body.is-mobile .nav-item{font-size:13px!important;padding:10px 12px!important;gap:8px!important;min-height:42px}
body.is-mobile input[type=text],body.is-mobile input[type=search],body.is-mobile input[type=password],body.is-mobile input[type=number],body.is-mobile input[type=date],body.is-mobile select,body.is-mobile textarea{font-size:16px!important}
body.is-mobile .btn{min-height:38px}
body.is-mobile .flex.items-center.gap-3{flex-wrap:wrap}

/* ── Upload Slots ── */
.upload-slot-card { background:#fff; border-radius:12px; border:1px solid #e2e8f0; overflow:hidden; box-shadow:0 1px 4px rgba(0,0,0,0.06); transition:box-shadow 0.2s; }
.upload-slot-card:hover { box-shadow:0 4px 12px rgba(0,0,0,0.1); }
.upload-slot-card.uploaded { border-color:#10b981; }
.upload-slot-header { padding:10px 14px; color:#fff; font-size:12px; font-weight:700; display:flex; align-items:center; gap:8px; }
.upload-slot-body { padding:12px 14px; }
.upload-slot-desc { font-size:11px; color:#64748b; margin-bottom:8px; line-height:1.4; }
.upload-slot-status { font-size:11px; color:#94a3b8; margin-bottom:10px; min-height:16px; }
.upload-slot-status.loaded { color:#059669; font-weight:600; }
.upload-slot-status.error { color:#dc2626; }
.upload-slot-btn { display:inline-flex; align-items:center; gap:6px; padding:6px 14px; background:#f1f5f9; color:#374151; border-radius:8px; font-size:11px; font-weight:600; cursor:pointer; border:1px solid #e2e8f0; transition:background 0.15s; }
.upload-slot-btn:hover { background:#e2e8f0; }

</style>
</head>
<body class="h-screen flex overflow-hidden">
<script>
// Detect a real mobile device (works even when "Request Desktop Site" reports a wide viewport)
(function(){
  var ua = navigator.userAgent || '';
  // Genuine phone/tablet user agents only
  var isPhoneUA = /Android.*Mobile|iPhone|iPod|Windows Phone|BlackBerry|Opera Mini|IEMobile/i.test(ua);
  var isTabletUA = /iPad|Android(?!.*Mobile)|Tablet/i.test(ua);
  // A desktop OS UA must never be treated as mobile, even on touchscreen laptops
  var isDesktopOS = /Windows NT|Macintosh|Mac OS X|CrOS|Linux x86/i.test(ua) && !/Android|Mobile/i.test(ua);
  // Only consider screen-size as a fallback for very small, non-desktop devices
  var trulySmall = Math.min(screen.width, screen.height) <= 480;
  if (!isDesktopOS && (isPhoneUA || isTabletUA || trulySmall)) document.body.classList.add('is-mobile');
})();
</script>
<script>
// Width-based mobile class is intentionally NOT auto-applied here.
// The CSS @media(max-width:768px) rules already handle narrow widths responsively,
// and genuine phones/tablets are detected by user-agent above. This avoids
// false 'mobile' triggers on desktops viewed via remote-desktop tools or odd viewports.
</script>

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

<!-- ═══════════════════════════════════════════════════════
     SIDEBAR
     ═══════════════════════════════════════════════════════ -->
<div id="sidebar-overlay" onclick="closeMobileSidebar()" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:199"></div>
<aside id="sidebar" class="flex flex-col shadow-2xl z-30 flex-shrink-0 overflow-hidden">
  <!-- Logo -->
  <div class="flex items-center gap-3 px-5 py-5 border-b border-white/5">
    <div class="w-9 h-9 rounded-xl flex items-center justify-center flex-shrink-0" style="background:linear-gradient(135deg,#E8F7AA,#c5e86f);box-shadow:0 4px 12px rgba(81,138,135,0.25)">
      <i class="fas fa-box-open text-white text-sm"></i>
    </div>
    <div>
      <div class="text-white font-bold text-sm tracking-tight leading-none">Filo Hevis</div>
      <div style="color:#4ade80;font-size:10px;font-weight:600;letter-spacing:0.1em;text-transform:uppercase;margin-top:2px">OMS</div>
    </div>
  </div>

  <!-- Nav -->
  <nav class="flex-1 px-3 py-4 overflow-y-auto space-y-1">
    <div class="nav-section-label">Menu</div>
    <div onclick="switchTab('admin')"    id="btn-admin"    class="nav-item hidden"><i class="fas fa-chart-line"></i><span>Live Activity</span></div>
    <div onclick="switchTab('raw')"      id="btn-raw"      class="nav-item hidden"><i class="fas fa-database"></i><span>Master File</span></div>
    <div onclick="switchTab('assign')"   id="btn-assign"   class="nav-item hidden"><i class="fas fa-user-plus"></i><span>Assign Callers</span></div>
    <div onclick="switchTab('agent')"    id="btn-agent"    class="nav-item hidden"><i class="fas fa-headset"></i><span>Agent View</span></div>
    <div onclick="switchTab('updates')"  id="btn-updates"  class="nav-item hidden"><i class="fas fa-clock-rotate-left"></i><span>Recent Updates</span></div>
    <div onclick="switchTab('scan')"     id="btn-scan"     class="nav-item hidden"><i class="fas fa-barcode"></i><span>Dispatch & Scan</span></div>
    <div onclick="switchTab('analytics')"id="btn-analytics"class="nav-item hidden"><i class="fas fa-chart-pie"></i><span>Analytics</span></div>
    <div onclick="switchTab('agentanalytics')" id="btn-agentanalytics" class="nav-item hidden"><i class="fas fa-chart-column" style="color:#f59e0b"></i><span>Agent Analytics</span></div>
    <div onclick="switchTab('users')"    id="btn-users"    class="nav-item hidden"><i class="fas fa-users-cog"></i><span>User Management</span></div>
    <div onclick="switchTab('delivery')"  id="btn-delivery" class="nav-item hidden"><i class="fas fa-shipping-fast"></i><span>Delivery Report</span></div>
    <div onclick="switchTab('training')"  id="btn-training" class="nav-item hidden"><i class="fas fa-graduation-cap"></i><span>Training</span></div>
    <div onclick="switchTab('uploads')"    id="btn-uploads"  class="nav-item hidden"><i class="fas fa-cloud-upload-alt" style="color:#0ea5e9"></i><span>Upload Files</span></div>
    <div onclick="switchTab('returns')"   id="btn-returns"  class="nav-item hidden"><i class="fas fa-rotate-left" style="color:#f97316"></i><span>Returns Ledger</span></div>
    <div onclick="openLifecycleModal()" id="btn-lifecycle" class="nav-item hidden"><i class="fas fa-route" style="color:#6366f1"></i><span>Order Lifecycle</span></div>
    <div onclick="switchTab('ndr')" id="btn-ndr" class="nav-item hidden"><i class="fas fa-truck-loading" style="color:#0891b2"></i><span>NDR</span></div>
  </nav>

  <!-- Dev credit -->
  <div class="px-4 py-2 text-center">
    <p class="text-[10px] text-slate-700 font-medium">Built by <span style="color:#4ade80;font-weight:600">Atul Kumar</span></p>
  </div>

  <!-- User -->
  <div class="px-4 py-4 border-t border-white/5">
    <div class="flex items-center gap-3">
      <div class="w-9 h-9 rounded-xl flex items-center justify-center text-xs font-bold flex-shrink-0" style="background:var(--accent-highlight);color:var(--text-primary)"><?= $userInitials ?></div>
      <div class="flex-1 min-w-0">
        <div id="user-display-name" class="text-white text-sm font-semibold truncate"><?= htmlspecialchars($SESSION_USER['name']) ?></div>
        <div class="text-slate-500 text-[10px] capitalize"><?= htmlspecialchars($SESSION_USER['role']) ?></div>
      </div>
      <button onclick="doLogout()" title="Logout" class="text-slate-600 hover:text-red-400 transition p-1.5 rounded-lg hover:bg-white/5">
        <i class="fas fa-arrow-right-from-bracket text-sm"></i>
      </button>
    </div>
  </div>
</aside>

<!-- ═══════════════════════════════════════════════════════
     MAIN CONTENT
     ═══════════════════════════════════════════════════════ -->
<main class="flex-1 flex flex-col overflow-hidden min-w-0">

  <!-- Header -->
  <header class="bg-white h-14 flex items-center px-4 gap-3 flex-shrink-0 z-10" style="border-bottom:1px solid var(--border-light);box-shadow:0 1px 0 var(--border-light);">
    <button onclick="(window.innerWidth<=768||document.body.classList.contains('is-mobile'))?toggleMobileSidebar():toggleSidebar()" class="w-8 h-8 flex items-center justify-center text-slate-400 hover:text-indigo-600 hover:bg-indigo-50 rounded-lg transition">
      <i class="fas fa-bars text-sm" id="sidebar-icon"></i>
    </button>
    <h2 id="page-title" class="text-base font-bold tracking-tight mr-auto" style="color:var(--text-primary)"></h2>

    <div id="auto-refresh-badge" class="hidden items-center gap-1.5 px-3 h-7 rounded-full text-xs font-bold border" style="background:#f0fdf4;color:#15803d;border-color:#bbf7d0">
      <span class="relative flex h-1.5 w-1.5"><span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span><span class="relative inline-flex rounded-full h-1.5 w-1.5 bg-emerald-500"></span></span>
      Syncing
    </div>

    <div class="relative">
      <i class="fas fa-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-xs pointer-events-none"></i>
      <input type="text" id="searchBar" placeholder="Search orders..." class="form-input pl-8 w-56" style="border-radius:99px" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" name="oms_order_search_nofill" data-form-type="other" role="searchbox" aria-label="Search orders">
    </div>

    <button onclick="manualRefresh()" class="btn btn-ghost">
      <i class="fas fa-rotate-right text-indigo-500"></i>
      <span class="hidden sm:inline">Refresh</span>
    </button>
  </header>

  <!-- Content -->
  <div id="content-area" class="flex-1 overflow-auto p-5 relative" style="background:var(--bg-app);">
    <div id="loader" class="rounded-2xl">
      <div class="spinner"></div>
      <p class="mt-4 text-sm text-slate-500 font-medium">Loading data...</p>
    </div>

    <!-- ── LIVE ACTIVITY ── -->
    <div id="view-admin" class="view-section h-full fade-up">
      <div class="card overflow-hidden flex flex-col h-full">
        <div class="px-5 py-3.5 border-b border-slate-100 flex items-center justify-between flex-shrink-0 bg-slate-50">
          <span class="font-bold text-slate-700 text-sm flex items-center gap-2"><i class="fas fa-chart-line text-indigo-500"></i> Live Activity Monitor</span>
          <div class="flex gap-2">
            <select id="adminAgentFilter" class="form-select text-xs" style="height:32px" onchange="renderAdminView()"><option value="All">All Agents</option></select>
            <select id="adminStatusFilter" class="form-select text-xs" style="height:32px" onchange="renderAdminView()"><option value="All">All Statuses</option><option>Pending</option><option>Done</option><option>Cancel</option><option>Busy</option><option>NP</option><option>SO</option><option>NI</option><option>Hold</option></select>
          </div>
        </div>
        <div class="overflow-auto flex-1">
          <table class="data-table">
            <thead><tr><th>Order ID</th><th>Customer</th><th>Agent</th><th>Status</th><th>Remark</th></tr></thead>
            <tbody id="admin-table-body"></tbody>
          </table>
        </div>
        <div id="admin-pagination" class="px-4 py-3 border-t border-slate-100 flex justify-between items-center flex-shrink-0"></div>
      </div>
    </div>

    <!-- ── MASTER FILE ── -->
    <div id="view-raw" class="view-section h-full fade-up">
      <div class="card overflow-hidden flex flex-col h-full">
        <div class="px-4 py-3 border-b border-slate-100 bg-slate-50 flex flex-wrap gap-2 items-center flex-shrink-0">
          <span class="font-bold text-slate-700 text-sm flex items-center gap-2"><i class="fas fa-database text-indigo-500"></i> Master Data</span>
          <input type="date" id="raw-date-start" onchange="renderRawView()" class="form-input text-xs" style="height:32px">
          <input type="date" id="raw-date-end"   onchange="renderRawView()" class="form-input text-xs" style="height:32px">
          <button onclick="resetDates('raw')" class="btn btn-ghost btn-sm">Reset</button>
          <select id="raw-vendor"  onchange="renderRawView()" class="form-select text-xs" style="height:32px"><option value="">All Vendors</option></select>
          <select id="raw-payment" onchange="renderRawView()" class="form-select text-xs" style="height:32px"><option value="">All Payments</option><option value="paid">Paid</option><option value="pending">Pending</option></select>
          <input type="text" id="rawSearch" placeholder="Search..." onkeyup="renderRawView()" class="form-input text-xs flex-1 min-w-28" style="height:32px">
          <button onclick="downloadMasterData()" class="btn btn-success btn-sm ml-auto"><i class="fas fa-download"></i> Export</button>
          <span class="text-xs text-slate-400 font-medium">Rows: <b class="text-slate-600" id="raw-count">0</b> | Orders: <b class="text-slate-600" id="unique-count">0</b></span>
        </div>
        <div class="overflow-auto flex-1">
          <table class="data-table min-w-max">
            <thead id="raw-head"></thead>
            <tbody id="raw-body"><tr><td class="p-10 text-center text-slate-400"><i class="fas fa-spinner fa-spin text-xl text-indigo-400 mr-2"></i> Loading...</td></tr></tbody>
          </table>
        </div>
        <div id="raw-pagination" class="px-4 py-3 border-t border-slate-100 flex justify-center gap-2"></div>
      </div>
    </div>

    <!-- ── ASSIGN CALLERS ── -->
    <div id="view-assign" class="view-section fade-up">
      <div class="max-w-2xl mx-auto w-full space-y-4">
        <div class="card p-5">
          <h3 class="font-bold text-slate-800 mb-4 flex items-center gap-2"><i class="fas fa-user-plus text-indigo-500"></i> Assign Callers</h3>
          <div class="grid grid-cols-2 gap-3 mb-4">
            <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Vendor</label><select id="assign-vendor" onchange="toggleAssignDates()" class="form-select w-full"><option value="">-- Choose Vendor --</option></select></div>
            <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Agent</label><select id="assign-agent" class="form-select w-full"><option value="">⚠ Select a specific agent</option></select></div>
            <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Date From</label><input type="date" id="assign-start" disabled class="form-input w-full disabled:opacity-40"></div>
            <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Date To</label><input type="date" id="assign-end" disabled class="form-input w-full disabled:opacity-40"></div>
            <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Payment Type</label><select id="assign-paytype" class="form-select w-full"><option value="cod">COD Only</option><option value="paid">Paid Only</option><option value="both">COD + Paid</option></select></div>
          </div>
          <div class="flex gap-2">
            <button onclick="loadUnassigned()" class="btn btn-primary flex-1"><i class="fas fa-search"></i> Load Unassigned Orders</button>
            <button onclick="pullBackPending()" class="btn btn-danger"><i class="fas fa-rotate-left"></i> Pull Back</button>
          </div>
        </div>

        <div id="assign-step-2" class="hidden card p-5 space-y-4">
          <div class="flex gap-3 flex-wrap">
            <div class="count-badge"><span class="count-value text-slate-700" id="assign-total-received">0</span><span class="count-label">Total Orders</span></div>
            <div class="count-badge"><span class="count-value text-emerald-600" id="assign-paid">0</span><span class="count-label">Paid</span></div>
            <div class="count-badge"><span class="count-value text-orange-500" id="assign-cod">0</span><span class="count-label">COD</span></div>
            <div class="count-badge"><span class="count-value text-indigo-600" id="assign-total">0</span><span class="count-label">Assignable</span></div>
            <div class="count-badge" style="border-color:#22c55e;background:#f0fdf4"><span class="count-value text-green-600" id="assign-selected">0</span><span class="count-label">Selected</span></div>
          </div>
          <div>
            <label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-2">Select Categories</label>
            <div id="tag-checkboxes" class="grid grid-cols-2 gap-2"></div>
          </div>
          <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Limit (optional)</label><input type="number" id="assign-limit" placeholder="Leave blank for all" class="form-input w-full"></div>
          <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Current Load</label><div id="assign-current-load" class="flex flex-wrap gap-2 text-xs"></div></div>
          <button onclick="submitAssignment()" class="btn btn-success w-full justify-center"><i class="fas fa-user-check"></i> Assign Orders</button>
        </div>
      </div>
    </div>

    <!-- ── AGENT VIEW ── -->
    <div id="view-agent" class="view-section h-full fade-up">
      <div class="card overflow-hidden flex flex-col h-full">
        <!-- Toolbar -->
        <div class="px-4 py-3 border-b border-slate-100 bg-white flex flex-wrap gap-2 items-center flex-shrink-0">
          <div class="flex items-center gap-2">
            <div style="display:flex;border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;background:#f8fafc;height:32px">
              <button id="filter-by-assign" onclick="setAgentDateMode('assign')" style="padding:0 10px;font-size:11px;font-weight:700;background:#16a34a;color:#fff;border:none;cursor:pointer">Assign Date</button>
              <button id="filter-by-order" onclick="setAgentDateMode('order')" style="padding:0 10px;font-size:11px;font-weight:600;background:transparent;color:#64748b;border:none;cursor:pointer">Order Date</button>
            </div>
            <input type="date" id="agent-date-start" onchange="renderAgentView()" class="form-input text-xs" style="height:32px">
            <span class="text-slate-300 text-xs">→</span>
            <input type="date" id="agent-date-end"   onchange="renderAgentView()" class="form-input text-xs" style="height:32px">
            <button onclick="resetDates('agent')" class="btn btn-ghost btn-sm px-2 text-slate-400">✕</button>
          </div>
          <select id="statusFilter" onchange="renderAgentView()" class="form-select text-xs" style="height:32px"><option value="All">All Status</option><option>Pending</option><option>Done</option><option>Cancel</option><option>Busy</option><option>NP</option><option>SO</option><option>NI</option><option>Hold</option></select>

          <!-- Agent dropdown (moved up — right after Status) -->
          <div class="relative" id="agentFilterWrapper">
            <button onclick="document.getElementById('agentDropdownMenu').classList.toggle('hidden')" class="btn btn-ghost btn-sm gap-2 min-w-32">
              <i class="fas fa-users text-indigo-400 text-xs"></i>
              <span id="agentFilterText" class="text-xs">All Agents</span>
              <i class="fas fa-chevron-down text-slate-300 text-xs ml-auto"></i>
            </button>
            <div id="agentDropdownMenu" class="hidden absolute top-full left-0 mt-1 w-48 bg-white border border-slate-200 rounded-xl shadow-xl z-30 p-2 max-h-60 overflow-auto">
              <div id="agentFilterOptions"></div>
            </div>
          </div>

          <div class="relative" id="tagFilterWrapper">
            <button onclick="document.getElementById('tagDropdownMenu').classList.toggle('hidden')" class="btn btn-ghost btn-sm gap-2 min-w-32">
              <i class="fas fa-tags text-indigo-400 text-xs"></i>
              <span id="tagFilterText" class="text-xs">All Tags</span>
              <i class="fas fa-chevron-down text-slate-300 text-xs ml-auto"></i>
            </button>
            <div id="tagDropdownMenu" class="hidden absolute top-full left-0 mt-1 w-52 bg-white border border-slate-200 rounded-xl shadow-xl z-30 p-2 max-h-64 overflow-auto">
              <div id="tagFilterOptions"></div>
            </div>
          </div>

          <!-- Payment Status dropdown (COD / Paid) -->
          <div class="relative" id="payFilterWrapper">
            <button onclick="document.getElementById('payDropdownMenu').classList.toggle('hidden')" class="btn btn-ghost btn-sm gap-2 min-w-32">
              <i class="fas fa-wallet text-cyan-500 text-xs"></i>
              <span id="payFilterText" class="text-xs">All Payments</span>
              <i class="fas fa-chevron-down text-slate-300 text-xs ml-auto"></i>
            </button>
            <div id="payDropdownMenu" class="hidden absolute top-full left-0 mt-1 w-48 bg-white border border-slate-200 rounded-xl shadow-xl z-30 p-2" style="z-index:35">
              <label style="display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;cursor:pointer;font-size:12px;font-weight:600;color:#1e293b;background:#f8fafc;margin-bottom:4px"><input type="radio" name="pay-filter" class="pay-filter-rb" value="all" checked onchange="onPayFilterChange()"> All Payments</label>
              <hr style="border:none;border-top:1px solid #e2e8f0;margin:4px 0">
              <label style="display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:12px;color:#475569" onmouseover="this.style.background='#f1f5f9'" onmouseout="this.style.background=''"><input type="radio" name="pay-filter" class="pay-filter-rb" value="paid" onchange="onPayFilterChange()"> 💳 Paid (Prepaid)</label>
              <label style="display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:12px;color:#475569" onmouseover="this.style.background='#f1f5f9'" onmouseout="this.style.background=''"><input type="radio" name="pay-filter" class="pay-filter-rb" value="cod" onchange="onPayFilterChange()"> 💵 COD</label>
            </div>
          </div>

          <div class="relative" id="priceFilterWrapper">
            <button onclick="document.getElementById('priceDropdownMenu').classList.toggle('hidden')" class="btn btn-ghost btn-sm gap-2 min-w-32">
              <i class="fas fa-tag text-green-400 text-xs"></i>
              <span id="priceFilterText" class="text-xs">All Prices</span>
              <i class="fas fa-chevron-down text-slate-300 text-xs ml-auto"></i>
            </button>
            <div id="priceDropdownMenu" class="hidden absolute top-full left-0 mt-1 w-48 bg-white border border-slate-200 rounded-xl shadow-xl z-30 p-2" style="z-index:35">
              <label style="display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;cursor:pointer;font-size:12px;font-weight:600;color:#1e293b;background:#f8fafc;margin-bottom:4px"><input type="radio" name="price-filter" class="price-filter-rb" value="all" checked onchange="onPriceFilterChange()"> All Prices</label>
              <hr style="border:none;border-top:1px solid #e2e8f0;margin:4px 0">
              <label style="display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:12px;color:#475569" onmouseover="this.style.background='#f1f5f9'" onmouseout="this.style.background=''"><input type="radio" name="price-filter" class="price-filter-rb" value="lt1000" onchange="onPriceFilterChange()"> Less than ₹1000</label>
              <label style="display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:12px;color:#475569" onmouseover="this.style.background='#f1f5f9'" onmouseout="this.style.background=''"><input type="radio" name="price-filter" class="price-filter-rb" value="1000to1500" onchange="onPriceFilterChange()"> ₹1000 – ₹1500</label>
              <label style="display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:12px;color:#475569" onmouseover="this.style.background='#f1f5f9'" onmouseout="this.style.background=''"><input type="radio" name="price-filter" class="price-filter-rb" value="gt1500" onchange="onPriceFilterChange()"> Above ₹1500</label>
            </div>
          </div>

          <button onclick="downloadAgentData()" class="btn btn-success btn-sm"><i class="fas fa-download"></i> Export</button>
          <div id="btn-bulk-done" class="hidden items-center gap-2 btn btn-sm" style="background:#6366f1;color:#fff" onclick="executeBulkDone()">
            <i class="fas fa-check-double"></i> Force Done (<span id="bulk-count">0</span>)
          </div>
        </div>

        <!-- Stat counters -->
        <div id="agent-counts-container" class="px-4 py-2.5 flex gap-2 flex-wrap border-b border-slate-100 bg-white flex-shrink-0"></div>

        <!-- Table -->
        <div class="overflow-auto flex-1">
          <table class="data-table">
            <thead>
              <tr>
                <th class="w-8"></th>
                <th class="w-8">#</th>
                <th>Order ID</th>
                <th>Order Date</th>
                <th id="th-assign-date">Assign Date</th>
                <th>Customer</th>
                <th>Amount</th>
                <th>Phone</th>
                <th>Agent</th>
                <th>Remark</th>
                <th class="text-right">Status</th>
              </tr>
            </thead>
            <tbody id="agent-cards"></tbody>
          </table>
        </div>
        <div id="pagination-controls" class="px-4 py-3 border-t border-slate-100 flex justify-center items-center gap-2 flex-shrink-0"></div>
      </div>
    </div>

    <!-- ── RECENT UPDATES ── -->
    <div id="view-updates" class="view-section h-full fade-up">
      <div class="card overflow-hidden flex flex-col h-full">
        <div class="px-4 py-3 border-b border-slate-100 bg-slate-50 flex gap-2 items-center flex-shrink-0">
          <span class="font-bold text-slate-700 text-sm flex items-center gap-2"><i class="fas fa-clock-rotate-left text-indigo-500"></i> Recent Updates</span>
          <input type="date" id="upd-start" onchange="renderUpdatesView()" class="form-input text-xs" style="height:32px">
          <input type="date" id="upd-end"   onchange="renderUpdatesView()" class="form-input text-xs" style="height:32px">
          <button onclick="resetDates('updates')" class="btn btn-ghost btn-sm">Reset</button>
        </div>
        <div class="overflow-auto flex-1">
          <table class="data-table">
            <thead><tr><th>Timestamp</th><th>Order</th><th>Agent / Status</th><th style="min-width:200px">Remark</th><th>Dispatch</th><th>Delivery</th></tr></thead>
            <tbody id="updates-body" class="divide-y divide-slate-50"></tbody>
          </table>
        </div>
      </div>
    </div>

    <!-- ── DISPATCH & SCAN ── -->
    <div id="view-scan" class="view-section fade-up flex-col gap-4">
      <!-- Summary -->
      <div class="flex gap-3 items-center">
        <input type="date" id="scan-sum-start" onchange="loadScanHistoryRange(this.value, document.getElementById('scan-sum-end').value); renderScanSummary()" class="form-input text-xs" style="height:32px">
        <input type="date" id="scan-sum-end"   onchange="loadScanHistoryRange(document.getElementById('scan-sum-start').value, this.value); renderScanSummary()" class="form-input text-xs" style="height:32px">
      </div>
      <div id="scan-summary-cards" class="grid grid-cols-2 md:grid-cols-4 gap-3" style="grid-template-columns:repeat(4,1fr)"></div>

      <!-- Sub tabs -->
      <div class="border-b border-slate-200 flex gap-0 flex-shrink-0">
        <button id="subtab-stage"   onclick="switchScanTab('stage')"   class="px-5 py-2.5 text-sm font-semibold border-b-2 border-indigo-600 text-indigo-600 transition">Scan Orders</button>
        <button id="subtab-history" onclick="switchScanTab('history')" class="px-5 py-2.5 text-sm font-semibold border-b-2 border-transparent text-slate-500 transition">Scan History</button>
      </div>

      <!-- Stage -->
      <div id="scan-stage-container" class="flex flex-col gap-4">
        <div class="card p-5">
          <div class="flex gap-3 mb-4 flex-wrap">
            <select id="scanAction" class="form-select" style="min-width:160px">
              <option value="Dispatched">-- Action: Dispatch --</option>
              <option value="Dispatched">Dispatch</option>
              <option value="Returned">Return</option>
              <option value="Cancelled">Cancel</option>
            </select>
            <select id="scanCourier" class="form-select flex-1">
              <option value="">-- Select Courier --</option>
              <option>Delhivery</option><option>Bluedart</option><option>DTDC</option>
              <option>Xpressbees</option><option>Ecom Express</option><option>Shadowfax</option>
              <option>Ekart</option><option>Amazon</option><option>ShipRocket</option><option>Others</option>
            </select>
            <input type="text" id="scanInput" placeholder="Scan barcode or enter Order ID / AWB..." class="form-input flex-1" style="min-width:250px">
            <button onclick="addToStaged()" class="btn btn-primary"><i class="fas fa-plus"></i> Add</button>
            <div style="display:flex;align-items:center;gap:8px">
              <span id="staged-count-badge" style="display:none;background:#6366f1;color:#fff;border-radius:99px;padding:4px 14px;font-size:12px;font-weight:700;white-space:nowrap">0 staged</span>
              <button onclick="processStagedScans()" class="btn btn-success"><i class="fas fa-paper-plane"></i> Submit Scans</button>
            </div>
          </div>
          <div id="scan-live-counter" style="display:none;padding:10px 16px;background:#f0fdf4;border-radius:10px;border:1px solid #bbf7d0;margin-bottom:10px;flex-wrap:wrap;gap:12px;align-items:center"></div>
          <div id="staged-scan-list" class="space-y-2 max-h-72 overflow-auto"></div>
        </div>
      </div>

      <!-- History -->
      <div id="scan-history-container" class="hidden flex-col gap-3">
        <!-- Filters row -->
        <div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
          <input type="date" id="scan-hist-start" onchange="loadScanHistoryRange(this.value, document.getElementById('scan-hist-end').value); renderScanHistory()" class="form-input text-xs" style="height:32px">
          <input type="date" id="scan-hist-end"   onchange="loadScanHistoryRange(document.getElementById('scan-hist-start').value, this.value); renderScanHistory()" class="form-input text-xs" style="height:32px">
          <div style="position:relative;display:flex;align-items:center">
            <i class="fas fa-search" style="position:absolute;left:9px;color:#94a3b8;font-size:11px;pointer-events:none"></i>
            <input type="text" id="scan-hist-search" oninput="scanHistPage=1;renderScanHistory()" placeholder="Search order / customer..." class="form-input text-xs" style="height:32px;padding-left:28px;min-width:200px">
          </div>
          <select id="scan-hist-courier" onchange="renderScanHistory()" class="form-select text-xs" style="height:32px;min-width:140px">
            <option value="">All Couriers</option>
            <option>Xpressbees</option><option>Shadowfax</option><option>Ekart</option>
            <option>Bluedart</option><option>Delhivery</option><option>DTDC</option>
            <option>Amazon</option><option>Ecom Express</option><option>ShipRocket</option><option>Others</option>
          </select>
          <select id="scan-hist-status" onchange="renderScanHistory()" class="form-select text-xs" style="height:32px;min-width:130px">
            <option value="">All Status</option>
            <option value="Dispatched">Dispatched</option>
            <option value="Returned">Returned</option>
            <option value="Cancelled">Cancelled</option>
          </select>
          <select id="scan-hist-perpage" onchange="scanHistPage=1;renderScanHistory()" class="form-select text-xs" style="height:32px;min-width:110px">
            <option value="50">Show 50</option>
            <option value="100">Show 100</option>
            <option value="200">Show 200</option>
            <option value="500">Show 500</option>
            <option value="99999">Show All</option>
          </select>
          <button onclick="downloadScanHistoryExcel()" class="btn btn-success btn-sm" style="height:32px">
            <i class="fas fa-file-excel"></i> Export CSV
          </button>
          <?php if(in_array($SESSION_USER['role'], ['admin','dispatch'])): ?>
          <button onclick="openScanImportModal()" class="btn btn-sm" style="background:#6366f1;color:#fff;height:32px">
            <i class="fas fa-file-upload"></i> Bulk Import
          </button>
          <?php endif; ?>
        </div>
        <!-- Count cards -->
        <div id="scan-hist-counts" style="display:grid;grid-template-columns:repeat(4,1fr);gap:12px"></div>
        <!-- Summary bar -->
        <div id="scan-hist-summary" style="display:flex;align-items:center;gap:8px;padding:10px 16px;background:#f8fafc;border-radius:10px;border:1px solid #e2e8f0;flex-wrap:wrap;min-height:38px"></div>
        <!-- Table -->
        <div class="card overflow-hidden">
          <div class="overflow-auto">
            <table class="data-table">
              <thead><tr><th>Timestamp</th><th>Order ID</th><th>Customer</th><th>Courier</th><th>Status</th><th style="text-align:right">Action</th></tr></thead>
              <tbody id="scan-history-body"></tbody>
            </table>
          </div>
          <div id="scan-hist-pagination" class="px-4 py-3 border-t border-slate-100 flex justify-between items-center"></div>
        </div>
      </div>
    </div>

    <!-- ── ANALYTICS ── -->
    <div id="view-analytics" class="view-section fade-up flex-col gap-4" style="overflow-x:hidden;min-width:0;max-width:100%;padding:4px 2px">

      <!-- Analytics sub-navigation -->
      <div class="flex gap-3 flex-wrap mb-2">
        <button onclick="toggleAnalyticsView('default')" class="btn btn-ghost btn-sm active:scale-95" id="an-btn-default" style="border-color:#16a34a;color:#16a34a"><i class="fas fa-chart-pie"></i> Overview</button>
        <button onclick="toggleAnalyticsView('pnl')" class="btn btn-ghost btn-sm" id="an-btn-pnl"><i class="fas fa-chart-line"></i> P&amp;L Report</button>
        <button onclick="toggleAnalyticsView('ai')" class="btn btn-ghost btn-sm" id="an-btn-ai" style="border-color:#7c3aed;color:#6d28d9"><i class="fas fa-robot"></i> AI Ops Report</button>
      </div>

      <!-- Default analytics section -->
      <div id="default-analytics-section" style="display:flex;flex-direction:column;gap:16px">
      <!-- Date filter -->
      <div class="flex items-center gap-3 flex-wrap">
        <span class="text-sm font-semibold text-slate-500">Filter by Order Date:</span>
        <input type="date" id="an-start" onchange="renderAnalyticsView()" class="form-input text-xs" style="height:32px">
        <input type="date" id="an-end"   onchange="renderAnalyticsView()" class="form-input text-xs" style="height:32px">
        <span class="text-sm font-semibold text-slate-500" style="margin-left:6px">Agent:</span>
        <select id="an-agent-filter" onchange="renderAnalyticsView()" class="form-input text-xs" style="height:32px;min-width:150px">
          <option value="All">All Agents</option>
        </select>
        <button onclick="document.getElementById('an-start').value='';document.getElementById('an-end').value='';document.getElementById('an-agent-filter').value='All';renderAnalyticsView()" class="btn btn-ghost btn-sm">All Time</button>
        <button onclick="openLifecycleModal()" class="btn btn-sm ml-auto" style="background:linear-gradient(135deg,#7c3aed,#6366f1);color:#fff;gap:6px;height:34px;padding:0 16px;box-shadow:0 4px 12px rgba(99,102,241,0.3)">
          <i class="fas fa-route"></i> Order Lifecycle Tracker
        </button>
      </div>

      <!-- KPI Row -->
      <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:12px;min-width:0;max-width:100%">
        <div class="card p-4" style="border-left:4px solid #10b981;min-width:0;overflow:hidden">
          <div class="text-xs font-bold text-slate-400 uppercase tracking-wide mb-1">Confirmed Orders</div>
          <div id="an-conf" class="text-3xl font-black text-emerald-500">0</div>
          <div id="an-conf-sub" class="text-xs text-slate-400 mt-1"></div>
        </div>
        <div class="card p-4" style="border-left:4px solid #6366f1;min-width:0;overflow:hidden">
          <div class="text-xs font-bold text-slate-400 uppercase tracking-wide mb-1">Pending Dispatch</div>
          <div id="an-disp-pend" class="text-3xl font-black text-indigo-500">0</div>
          <div id="an-disp-sub" class="text-xs text-slate-400 mt-1"></div>
        </div>
        <div class="card p-4" style="border-left:4px solid #ef4444;min-width:0;overflow:hidden">
          <div class="text-xs font-bold text-slate-400 uppercase tracking-wide mb-1">Cancelled</div>
          <div id="an-canc" class="text-3xl font-black text-red-500">0</div>
          <div id="an-canc-sub" class="text-xs text-slate-400 mt-1"></div>
        </div>
        <div class="card p-4" style="border-left:4px solid #8b5cf6;min-width:0;overflow:hidden">
          <div class="text-xs font-bold text-slate-400 uppercase tracking-wide mb-1">Conversion Rate</div>
          <div id="an-conv" class="text-3xl font-black text-purple-500">0%</div>
          <div id="an-conv-sub" class="text-xs text-slate-400 mt-1"></div>
        </div>
      </div>

      <!-- Row 2: Agent Performance + Payment Split -->
      <div style="display:grid;grid-template-columns:1fr 300px;gap:16px;min-width:0;max-width:100%;overflow:hidden">
        <div class="card p-5" style="min-width:0;overflow:hidden">
          <h3 class="font-bold text-slate-700 mb-3 text-sm flex items-center gap-2"><i class="fas fa-users" style="color:#16a34a"></i> Agent Performance</h3>
          <div>
            <table style="width:100%;border-collapse:collapse">
              <thead><tr>
                <th style="padding:8px 12px;text-align:left;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#64748b;background:#f8fafc;border-bottom:1px solid #e2e8f0">Agent</th>
                <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#64748b;background:#f8fafc;border-bottom:1px solid #e2e8f0">Assigned</th>
                <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#10b981;background:#f0fdf4;border-bottom:1px solid #e2e8f0">Done</th>
                <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#ef4444;background:#fef2f2;border-bottom:1px solid #e2e8f0">Cancel</th>
                <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#f59e0b;background:#fffbeb;border-bottom:1px solid #e2e8f0">Pending</th>
                <th style="padding:8px 12px;text-align:right;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#64748b;background:#f8fafc;border-bottom:1px solid #e2e8f0">Conv %</th>
              </tr></thead>
              <tbody id="an-agent-body"></tbody>
            </table>
          </div>
        </div>
        <div class="card p-5" style="min-width:0;overflow:hidden">
          <h3 class="font-bold text-slate-700 mb-3 text-sm flex items-center gap-2"><i class="fas fa-credit-card" style="color:#16a34a"></i> Payment Split</h3>
          <div id="an-payment-split" style="display:flex;flex-direction:column;gap:8px;max-height:300px;overflow-y:auto;padding-right:4px"></div>
        </div>
      </div>

      <!-- Row 3: Status distribution + Top products -->
      <div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;min-width:0;max-width:100%;overflow:hidden">
        <div class="card p-5">
          <h3 class="font-bold text-slate-700 mb-3 text-sm flex items-center gap-2"><i class="fas fa-chart-pie text-indigo-500"></i> Order Status Distribution</h3>
          <div style="height:220px"><canvas id="statusChart"></canvas></div>
        </div>
        <div class="card p-5">
          <h3 class="font-bold text-slate-700 mb-3 text-sm flex items-center gap-2"><i class="fas fa-box text-indigo-500"></i> Top Products</h3>
          <div style="height:220px"><canvas id="productChart"></canvas></div>
        </div>
      </div>

      <!-- Row 4: Business Insights -->
      <div class="card" style="padding:20px;overflow:hidden">
        <h3 style="font-weight:700;color:#1e293b;font-size:14px;margin-bottom:14px;display:flex;align-items:center;gap:8px"><i class="fas fa-lightbulb" style="color:#f59e0b"></i> Business Insights</h3>
        <div id="an-insights" style="display:grid;grid-template-columns:repeat(3,1fr);gap:10px;min-width:0"></div>
      </div>

      </div><!-- end default-analytics-section -->

      <!-- P&L Report Section -->
      <div id="pnl-report-section" class="hidden">
        <div class="card overflow-hidden">
          <div style="padding:14px 20px;border-bottom:1px solid #f1f5f9;background:#f8fafc">
            <div style="display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin-bottom:12px">
              <h3 style="font-weight:700;color:#1e293b;font-size:14px;display:flex;align-items:center;gap:8px"><i class="fas fa-chart-line" style="color:#6366f1"></i> P&L Report</h3>
              <div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap">
                <select id="pnl-vendor" class="form-select text-xs" style="height:34px"><option value="">All Vendors</option><option value="Filohevis.com">Filohevis.com</option><option value="Filohevis.in">Filohevis.in</option></select>
                <input type="date" id="pnl-start" class="form-input text-xs" style="height:34px">
                <input type="date" id="pnl-end" class="form-input text-xs" style="height:34px">
                <button onclick="fetchPnLReport()" class="btn btn-sm" style="background:#6366f1;color:#fff"><i class="fas fa-search"></i> Generate</button>
                <button onclick="openCogsModal()" class="btn btn-ghost btn-sm" style="border:1px solid #6366f1;color:#6366f1"><i class="fas fa-sliders-h"></i> Manage COGS</button>
                <button onclick="exportPnLReport()" class="btn btn-success btn-sm"><i class="fas fa-file-excel"></i> Export</button>
              </div>
            </div>
            <!-- Ad spend per account (auto-sums) + CPA inputs -->
            <div style="display:flex;flex-wrap:wrap;gap:10px;align-items:end">
              <div><label style="font-size:9px;font-weight:700;color:#64748b;text-transform:uppercase;display:block;margin-bottom:2px">FB ac2 ₹</label><input type="number" id="ad-fb2" oninput="pnlSumAdSpend()" placeholder="0" class="pnl-ad" style="width:90px;border:1px solid #e2e8f0;border-radius:6px;padding:5px 8px;font-size:12px"></div>
              <div><label style="font-size:9px;font-weight:700;color:#64748b;text-transform:uppercase;display:block;margin-bottom:2px">FB ac6 ₹</label><input type="number" id="ad-fb6" oninput="pnlSumAdSpend()" placeholder="0" class="pnl-ad" style="width:90px;border:1px solid #e2e8f0;border-radius:6px;padding:5px 8px;font-size:12px"></div>
              <div><label style="font-size:9px;font-weight:700;color:#64748b;text-transform:uppercase;display:block;margin-bottom:2px">Filo ₹</label><input type="number" id="ad-filo" oninput="pnlSumAdSpend()" placeholder="0" class="pnl-ad" style="width:90px;border:1px solid #e2e8f0;border-radius:6px;padding:5px 8px;font-size:12px"></div>
              <div><label style="font-size:9px;font-weight:700;color:#64748b;text-transform:uppercase;display:block;margin-bottom:2px">Filo ac3 ₹</label><input type="number" id="ad-filo3" oninput="pnlSumAdSpend()" placeholder="0" class="pnl-ad" style="width:90px;border:1px solid #e2e8f0;border-radius:6px;padding:5px 8px;font-size:12px"></div>
              <div><label style="font-size:9px;font-weight:700;color:#64748b;text-transform:uppercase;display:block;margin-bottom:2px">Google ₹</label><input type="number" id="ad-google" oninput="pnlSumAdSpend()" placeholder="0" class="pnl-ad" style="width:90px;border:1px solid #e2e8f0;border-radius:6px;padding:5px 8px;font-size:12px"></div>
              <div><label style="font-size:9px;font-weight:700;color:#64748b;text-transform:uppercase;display:block;margin-bottom:2px">WhatsApp ₹</label><input type="number" id="ad-whatsapp" oninput="pnlSumAdSpend()" placeholder="0" class="pnl-ad" style="width:90px;border:1px solid #e2e8f0;border-radius:6px;padding:5px 8px;font-size:12px"></div>
              <div style="border-left:2px solid #e2e8f0;padding-left:10px"><label style="font-size:9px;font-weight:800;color:#6366f1;text-transform:uppercase;display:block;margin-bottom:2px">Total Ad Spend ₹</label><input type="number" id="pnl-ad-spend" readonly placeholder="0" style="width:120px;border:1px solid #c7d2fe;background:#eef2ff;border-radius:6px;padding:5px 8px;font-size:13px;font-weight:700;color:#4338ca"></div>
              <div><label style="font-size:9px;font-weight:800;color:#9a3412;text-transform:uppercase;display:block;margin-bottom:2px">Total Orders Received</label><input type="number" id="pnl-orders-received" placeholder="e.g. 5402" style="width:120px;border:1px solid #fed7aa;background:#fff7ed;border-radius:6px;padding:5px 8px;font-size:13px;font-weight:700;color:#9a3412"></div>
              <div><label style="font-size:9px;font-weight:800;color:#5b21b6;text-transform:uppercase;display:block;margin-bottom:2px">Office Exp ₹</label><input type="number" id="pnl-office-exp" value="480000" style="width:120px;border:1px solid #ddd6fe;background:#f5f3ff;border-radius:6px;padding:5px 8px;font-size:13px;font-weight:700;color:#5b21b6"></div>
            </div>
          </div>
          <div style="overflow-x:auto;max-height:calc(100vh - 220px)">
            <table style="width:100%;border-collapse:collapse;font-size:11px;text-align:center;white-space:nowrap">
              <thead style="position:sticky;top:0;z-index:10">
                <!-- Section band -->
                <tr>
                  <th rowspan="2" style="padding:8px 10px;text-align:left;background:#f8fafc;border-bottom:2px solid #e2e8f0;border-right:2px solid #cbd5e1;font-size:10px;font-weight:800;text-transform:uppercase;color:#334155;position:sticky;left:0;z-index:11">Article</th>
                  <th rowspan="2" style="padding:8px 8px;background:#fef2f2;color:#b91c1c;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">COGS</th>
                  <th rowspan="2" style="padding:8px 8px;background:#f0fdf4;color:#15803d;border-bottom:2px solid #e2e8f0;border-right:2px solid #cbd5e1;font-size:9px;font-weight:700">SP</th>
                  <th colspan="14" style="padding:6px;background:#fff7ed;color:#9a3412;border-bottom:1px solid #fed7aa;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:0.05em;border-right:2px solid #cbd5e1">💵 Cash On Delivery</th>
                  <th colspan="12" style="padding:6px;background:#eff6ff;color:#1e40af;border-bottom:1px solid #bfdbfe;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:0.05em;border-right:2px solid #cbd5e1">💳 Prepaid</th>
                  <th colspan="6" style="padding:6px;background:#f5f3ff;color:#5b21b6;border-bottom:1px solid #ddd6fe;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:0.05em">📊 Combined (COD + Prepaid)</th>
                </tr>
                <tr>
                  <!-- COD section (14 cols) -->
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Ave Order</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Order Recd</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Line Item Recd</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">CPA × E/F</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Dispatch COD</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Total Del</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Del %</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Revenue</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">COGS</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">CPA</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Courier</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Off Exp</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">P&L Bef Exp</th>
                  <th style="padding:7px 6px;background:#fff7ed;color:#9a3412;border-bottom:2px solid #e2e8f0;border-right:2px solid #cbd5e1;font-size:9px;font-weight:700">PP/COD %</th>
                  <!-- Prepaid section (12 cols) -->
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Order Recd</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Line Item Recd</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Dispatch</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Delivery</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Del %</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Revenue</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">COGS</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">CPA</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Courier</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Off Exp</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;border-right:2px solid #cbd5e1;font-size:9px;font-weight:700">P&L Bef Exp</th>
                  <th style="padding:7px 6px;background:#eff6ff;color:#1e40af;border-bottom:2px solid #e2e8f0;border-right:2px solid #cbd5e1;font-size:9px;font-weight:700">&nbsp;</th>
                  <!-- Combined section (6 cols) -->
                  <th style="padding:7px 6px;background:#f5f3ff;color:#5b21b6;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Line Item Recd</th>
                  <th style="padding:7px 6px;background:#f5f3ff;color:#5b21b6;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Total Del</th>
                  <th style="padding:7px 6px;background:#f5f3ff;color:#5b21b6;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Total Dispatch</th>
                  <th style="padding:7px 6px;background:#f5f3ff;color:#5b21b6;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">Del %</th>
                  <th style="padding:7px 6px;background:#f5f3ff;color:#5b21b6;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:700">CPA/Unit</th>
                  <th style="padding:7px 6px;background:#f5f3ff;color:#5b21b6;border-bottom:2px solid #e2e8f0;font-size:9px;font-weight:800">P&L</th>
                </tr>
              </thead>
              <tbody id="pnl-report-body" style="font-size:12px">
                <tr><td colspan="38" style="padding:32px;text-align:center;color:#94a3b8">Enter Total Ad Spend, select dates, and click Generate.</td></tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>

      <!-- AI OPS REPORT SECTION -->
      <div id="ai-report-section" style="display:none">
        <div class="card overflow-hidden" style="border:1px solid #ede9fe">
          <div style="padding:14px 20px;border-bottom:1px solid #ede9fe;background:linear-gradient(135deg,#f5f3ff,#fafafa);display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px">
            <h3 style="font-weight:800;color:#1e293b;font-size:15px;display:flex;align-items:center;gap:8px"><i class="fas fa-robot" style="color:#7c3aed"></i> AI Ops Report <span style="font-size:11px;color:#94a3b8;font-weight:400">powered by Claude</span></h3>
            <button onclick="opsRunReport()" style="background:#7c3aed;color:#fff;border:none;border-radius:8px;padding:7px 16px;font-size:12px;font-weight:700;cursor:pointer;display:flex;align-items:center;gap:6px"><i class="fas fa-sync-alt"></i> Regenerate</button>
          </div>
          <div style="padding:12px 20px;border-bottom:1px solid #f1f5f9;background:#f8fafc;display:flex;gap:10px;flex-wrap:wrap;align-items:center">
            <div style="flex:1;min-width:160px;border:1px solid #e2e8f0;border-radius:8px;padding:8px 12px;background:#fff;display:flex;align-items:center;gap:8px">
              <i class="fas fa-database" style="color:#7c3aed;font-size:12px"></i>
              <div><div style="font-size:10px;font-weight:700;color:#94a3b8;text-transform:uppercase">Last Year Orders</div><div style="font-size:11px;font-weight:600" id="ops-ly-status">Loading from database...</div></div>
            </div>
            <div style="flex:1;min-width:160px;border:1px solid #e2e8f0;border-radius:8px;padding:8px 12px;background:#fff;display:flex;align-items:center;gap:8px">
              <i class="fas fa-bolt" style="color:#10b981;font-size:12px"></i>
              <div><div style="font-size:10px;font-weight:700;color:#94a3b8;text-transform:uppercase">Shopify Latest</div><div style="font-size:11px;font-weight:600" id="ops-webhook-status">Loading from OMS data...</div></div>
            </div>
            <div style="flex:1;min-width:160px">
              <div style="font-size:10px;font-weight:700;color:#94a3b8;text-transform:uppercase;margin-bottom:4px"><i class="fas fa-satellite-dish" style="margin-right:4px"></i>Clickpost Live</div>
              <div style="border:1.5px solid #cbd5e1;border-radius:8px;padding:8px 12px;cursor:pointer;position:relative;background:#f8fafc" id="ops-slot-cp" onclick="opsLoadClickpost()">
                <div style="font-size:11px;color:#64748b" id="ops-slot-cp-name">🔄 Click to load live Clickpost data</div>
              </div>
            </div>
          </div>
          <div style="padding:12px 20px;border-bottom:1px solid #f1f5f9;display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end;background:#fff">
            <div><div style="font-size:10px;font-weight:700;color:#94a3b8;text-transform:uppercase;margin-bottom:4px">From date</div><input type="date" id="ops-from" class="form-input text-xs" style="height:34px"></div>
            <div><div style="font-size:10px;font-weight:700;color:#94a3b8;text-transform:uppercase;margin-bottom:4px">To date</div><input type="date" id="ops-to" class="form-input text-xs" style="height:34px"></div>
            <div><div style="font-size:10px;font-weight:700;color:#94a3b8;text-transform:uppercase;margin-bottom:4px">Order status</div><select id="ops-status" class="form-select text-xs" style="height:34px"><option value="unfulfilled">Unfulfilled</option><option value="fulfilled">Fulfilled</option></select></div>
            <button onclick="opsRunReport()" style="background:#1e293b;color:#fff;border:none;border-radius:8px;padding:8px 18px;font-size:13px;font-weight:700;cursor:pointer;height:34px;display:flex;align-items:center">Run report</button>
          </div>
          <div id="ops-main" style="padding:20px;overflow-y:auto;max-height:65vh">
            <div style="display:flex;flex-direction:column;align-items:center;justify-content:center;padding:56px;color:#94a3b8;gap:12px;text-align:center">
              <i class="fas fa-chart-bar" style="font-size:40px;color:#e2e8f0"></i>
              <p style="font-size:13px">Select date range and click <strong style="color:#475569">Run report</strong>.<br>Shopify Latest loads automatically from your OMS data.</p>
            </div>
          </div>
          <div style="padding:8px 20px;background:#f8fafc;border-top:1px solid #f1f5f9;font-size:10px;color:#94a3b8;text-align:right">Last Year data from PostgreSQL &nbsp;•&nbsp; Latest from Webhook &nbsp;•&nbsp; <i class="fas fa-lock"></i> All processing is local</div>
        </div>
      </div>

    </div><!-- end view-analytics -->

    <!-- ── AGENT ANALYTICS VIEW ── -->
    <div id="view-agentanalytics" class="view-section fade-up flex-col gap-4" style="overflow-x:hidden;min-width:0;max-width:100%;padding:4px 2px">
      <!-- Filter bar -->
      <div class="flex items-center gap-3 flex-wrap">
        <span class="text-sm font-semibold text-slate-500">Filter by Order Date:</span>
        <input type="date" id="aa-start" onchange="renderAgentAnalyticsView()" class="form-input text-xs" style="height:32px">
        <input type="date" id="aa-end"   onchange="renderAgentAnalyticsView()" class="form-input text-xs" style="height:32px">
        <span class="text-sm font-semibold text-slate-500" style="margin-left:6px">Agent:</span>
        <select id="aa-agent-filter" onchange="renderAgentAnalyticsView()" class="form-input text-xs" style="height:32px;min-width:150px">
          <option value="All">All Agents</option>
        </select>
        <button onclick="document.getElementById('aa-start').value='';document.getElementById('aa-end').value='';document.getElementById('aa-agent-filter').value='All';renderAgentAnalyticsView()" class="btn btn-ghost btn-sm">All Time</button>
      </div>

      <!-- KPI Row -->
      <div style="display:grid;grid-template-columns:repeat(5,1fr);gap:12px;min-width:0;max-width:100%">
        <div class="card p-4" style="border-left:4px solid #6366f1;min-width:0;overflow:hidden">
          <div class="text-xs font-bold text-slate-400 uppercase tracking-wide mb-1">Assigned</div>
          <div id="aa-assigned" class="text-3xl font-black text-indigo-500">0</div>
          <div id="aa-assigned-sub" class="text-xs text-slate-400 mt-1"></div>
        </div>
        <div class="card p-4" style="border-left:4px solid #10b981;min-width:0;overflow:hidden">
          <div class="text-xs font-bold text-slate-400 uppercase tracking-wide mb-1">Done</div>
          <div id="aa-done" class="text-3xl font-black text-emerald-500">0</div>
          <div id="aa-done-sub" class="text-xs text-slate-400 mt-1"></div>
        </div>
        <div class="card p-4" style="border-left:4px solid #ef4444;min-width:0;overflow:hidden">
          <div class="text-xs font-bold text-slate-400 uppercase tracking-wide mb-1">Cancel</div>
          <div id="aa-cancel" class="text-3xl font-black text-red-500">0</div>
          <div id="aa-cancel-sub" class="text-xs text-slate-400 mt-1"></div>
        </div>
        <div class="card p-4" style="border-left:4px solid #f59e0b;min-width:0;overflow:hidden">
          <div class="text-xs font-bold text-slate-400 uppercase tracking-wide mb-1">Pending</div>
          <div id="aa-pending" class="text-3xl font-black text-amber-500">0</div>
          <div id="aa-pending-sub" class="text-xs text-slate-400 mt-1"></div>
        </div>
        <div class="card p-4" style="border-left:4px solid #8b5cf6;min-width:0;overflow:hidden">
          <div class="text-xs font-bold text-slate-400 uppercase tracking-wide mb-1">Conversion</div>
          <div id="aa-conv" class="text-3xl font-black text-purple-500">0%</div>
          <div id="aa-conv-sub" class="text-xs text-slate-400 mt-1"></div>
        </div>
      </div>

      <!-- Agent Performance table -->
      <div class="card p-5" style="min-width:0;overflow:hidden">
        <h3 class="font-bold text-slate-700 mb-3 text-sm flex items-center gap-2"><i class="fas fa-chart-column" style="color:#f59e0b"></i> Agent Wise Performance</h3>
        <div style="overflow-x:auto">
          <table style="width:100%;border-collapse:collapse">
            <thead><tr>
              <th style="padding:8px 12px;text-align:left;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#64748b;background:#f8fafc;border-bottom:1px solid #e2e8f0">Agent</th>
              <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#64748b;background:#f8fafc;border-bottom:1px solid #e2e8f0">Assigned</th>
              <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#10b981;background:#f0fdf4;border-bottom:1px solid #e2e8f0">Done</th>
              <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#ef4444;background:#fef2f2;border-bottom:1px solid #e2e8f0">Cancel</th>
              <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#f97316;background:#fff7ed;border-bottom:1px solid #e2e8f0">NP</th>
              <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#3b82f6;background:#eff6ff;border-bottom:1px solid #e2e8f0">Busy</th>
              <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#64748b;background:#f8fafc;border-bottom:1px solid #e2e8f0">Other</th>
              <th style="padding:8px 12px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#f59e0b;background:#fffbeb;border-bottom:1px solid #e2e8f0">Pending</th>
              <th style="padding:8px 12px;text-align:right;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#64748b;background:#f8fafc;border-bottom:1px solid #e2e8f0">Conv %</th>
            </tr></thead>
            <tbody id="aa-agent-body">
              <tr><td colspan="9" style="text-align:center;padding:30px;color:#94a3b8;font-size:13px">Loading…</td></tr>
            </tbody>
          </table>
        </div>
      </div>
    </div><!-- end view-agentanalytics -->

    <!-- ── NDR AUTOMATION VIEW ── -->
    <div id="view-ndr" class="view-section fade-up flex-col gap-4" style="overflow-x:hidden;min-width:0;max-width:100%;padding:4px 2px">
      <!-- Action bar -->
      <div class="card p-4" style="display:flex;align-items:center;gap:12px;flex-wrap:wrap">
        <div style="flex:1;min-width:200px">
          <h3 class="font-bold text-slate-700 text-sm flex items-center gap-2"><i class="fas fa-truck-loading" style="color:#0891b2"></i> NDR Automation</h3>
          <p class="text-xs text-slate-400 mt-0.5">Upload Clickpost NDR (Raw2) in Upload Files, then Run Full Refresh. Delivered status is read automatically from the live Clickpost webhook.</p>
        </div>
        <button onclick="ndrRunRefresh()" id="ndr-refresh-btn" class="btn btn-sm" style="background:#0891b2;color:#fff;height:34px"><i class="fas fa-sync"></i> Run Full Refresh</button>
        <button onclick="ndrLoadData()" class="btn btn-ghost btn-sm" style="height:34px"><i class="fas fa-rotate"></i> Reload</button>
        <button onclick="ndrExportFiltered()" class="btn btn-success btn-sm" style="height:34px"><i class="fas fa-file-excel"></i> Export</button>
        <div style="display:flex;gap:6px">
          <button onclick="ndrExportReattempt('DTDC')"      class="btn btn-ghost btn-sm" style="height:34px;border:1px solid #f59e0b;color:#b45309"><i class="fas fa-file-export"></i> DTDC</button>
          <button onclick="ndrExportReattempt('Bluedart')"  class="btn btn-ghost btn-sm" style="height:34px;border:1px solid #f59e0b;color:#b45309"><i class="fas fa-file-export"></i> Bluedart</button>
          <button onclick="ndrExportReattempt('Delhivery')" class="btn btn-ghost btn-sm" style="height:34px;border:1px solid #f59e0b;color:#b45309"><i class="fas fa-file-export"></i> Delhivery</button>
        </div>
      </div>

      <!-- Dashboard KPIs -->
      <div id="ndr-dash" style="display:grid;grid-template-columns:repeat(6,1fr);gap:10px;min-width:0;max-width:100%"></div>

      <!-- Tabs: NDR | RTO -->
      <div class="card p-0" style="min-width:0;overflow:hidden">
        <div style="display:flex;border-bottom:1px solid #e2e8f0">
          <button id="ndr-tab-ndr" onclick="ndrSwitchTable('ndr')" class="ndr-subtab" style="flex:0 0 auto;padding:10px 18px;font-size:13px;font-weight:700;color:#0891b2;border-bottom:2px solid #0891b2;background:none;cursor:pointer">NDR Working <span id="ndr-count" style="font-size:11px;color:#94a3b8">(0)</span></button>
          <button id="ndr-tab-rto" onclick="ndrSwitchTable('rto')" class="ndr-subtab" style="flex:0 0 auto;padding:10px 18px;font-size:13px;font-weight:600;color:#94a3b8;border-bottom:2px solid transparent;background:none;cursor:pointer">RTO Working <span id="rto-count" style="font-size:11px;color:#cbd5e1">(0)</span></button>
          <div style="flex:1;display:flex;align-items:center;justify-content:flex-end;padding:6px 12px">
            <input type="text" id="ndr-search" oninput="ndrFilter()" placeholder="Search AWB / Order / Phone…" class="form-input text-xs" style="height:30px;max-width:240px">
          </div>
        </div>
        <div style="overflow-x:auto;max-height:calc(100vh - 360px);overflow-y:auto">
          <table style="width:100%;border-collapse:collapse;font-size:12px">
            <thead id="ndr-thead" style="position:sticky;top:0;z-index:5"></thead>
            <tbody id="ndr-tbody"></tbody>
          </table>
        </div>
      </div>
    </div><!-- end view-ndr -->


    <!-- ── USER MANAGEMENT ── -->
    <div id="view-users" class="view-section fade-up flex-col gap-4">

      <!-- Header with Add button -->
      <div class="flex items-center justify-between">
        <div>
          <h2 style="font-size:20px;font-weight:800;color:#1e293b">User Management</h2>
          <p style="font-size:13px;color:#64748b;margin-top:2px">Add, edit and manage agent accounts</p>
        </div>
        <button onclick="openUserModal()" class="btn btn-primary gap-2" style="height:40px;padding:0 20px">
          <i class="fas fa-user-plus"></i> Add New User
        </button>
      </div>

      <!-- Stats row -->
      <div class="grid grid-cols-2 md:grid-cols-4 gap-3" id="user-stats-row"></div>

      <!-- Users table -->
      <div class="card overflow-hidden">
        <div style="padding:14px 20px;border-bottom:1px solid #f1f5f9;display:flex;align-items:center;gap:10px">
          <i class="fas fa-users" style="color:#16a34a"></i>
          <span style="font-weight:700;color:#1e293b;font-size:14px">All Users</span>
          <input type="text" id="user-search" placeholder="Search users..." onkeyup="renderUsersTable()" class="form-input text-xs ml-auto" style="height:32px;width:200px">
        </div>
        <div class="overflow-auto">
          <table class="data-table">
            <thead>
              <tr>
                <th style="width:40px">#</th>
                <th>Name</th>
                <th>Username</th>
                <th>Role</th>
                <th style="text-align:center">Status</th>
                <th>Created</th>
                <th style="text-align:right">Actions</th>
              </tr>
            </thead>
            <tbody id="users-table-body">
              <tr><td colspan="7" style="text-align:center;padding:40px;color:#94a3b8">
                <i class="fas fa-spinner fa-spin text-2xl" style="color:#16a34a"></i>
                <div style="margin-top:8px;font-size:13px">Loading users...</div>
              </td></tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>


    <!-- ── DELIVERY REPORT ── -->
    <div id="view-delivery" class="view-section fade-up flex-col gap-4">
      <div class="card p-4 flex flex-wrap gap-4 items-end">
        <div><label class="block text-xs font-bold text-slate-500 uppercase mb-1.5">Start Date</label><input type="date" id="del-start" class="form-input" style="height:36px"></div>
        <div><label class="block text-xs font-bold text-slate-500 uppercase mb-1.5">End Date</label><input type="date" id="del-end" class="form-input" style="height:36px"></div>
        <button onclick="resetDates('delivery')" class="btn btn-ghost">Reset</button>
        <button onclick="renderDeliveryView()" class="btn btn-primary"><i class="fas fa-filter"></i> Filter</button>
      </div>
      <div id="delivery-cards" class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-3"></div>
      <div class="card overflow-hidden">
        <div style="padding:14px 20px;border-bottom:1px solid #f1f5f9;display:flex;justify-content:space-between;align-items:center;background:#f8fafc">
          <h3 style="font-weight:700;color:#1e293b;font-size:14px" id="delivery-list-title">All Orders</h3>
          <span style="font-size:11px;background:#fff;border:1px solid #e2e8f0;padding:3px 10px;border-radius:99px;color:#64748b;font-weight:600" id="delivery-list-count">0</span>
        </div>
        <div style="overflow-x:auto;max-height:500px">
          <table class="data-table">
            <thead><tr><th>Order ID</th><th>Created</th><th>Customer</th><th>Courier</th><th>AWB</th><th>Status</th><th>Delivery Status</th></tr></thead>
            <tbody id="delivery-list-body"></tbody>
          </table>
        </div>
      </div>
    </div>


    <!-- ── TRAINING ── -->
    <div id="view-training" class="view-section fade-up h-full">
      <div class="card overflow-hidden flex flex-col h-full">
        <div style="padding:14px 20px;border-bottom:1px solid #f1f5f9;display:flex;justify-content:space-between;align-items:center;background:#f8fafc">
          <h3 style="font-weight:700;color:#1e293b;font-size:14px;display:flex;align-items:center;gap:8px"><i class="fas fa-graduation-cap" style="color:#16a34a"></i> Training Materials</h3>
          <div style="display:flex;gap:8px">
            <?php if(in_array($SESSION_USER['role'],['admin','writer'])): ?>
            <button onclick="openTrainingEditor()" class="btn btn-sm" style="background:#16a34a;color:#fff;gap:6px"><i class="fas fa-plus"></i> Add Material</button>
            <?php endif; ?>
            <button onclick="loadTrainingData()" class="btn btn-ghost btn-sm"><i class="fas fa-sync-alt"></i> Refresh</button>
          </div>
        </div>
        <div style="flex:1;overflow:auto;background:#f8fafc;display:flex">
          <div id="training-headers" style="width:220px;flex-shrink:0;border-right:1px solid #e2e8f0;background:#fff;overflow-y:auto"></div>
          <div id="training-subs" style="width:240px;flex-shrink:0;border-right:1px solid #e2e8f0;background:#f8fafc;overflow-y:auto;display:none"></div>
          <div id="training-detail" style="flex:1;overflow-y:auto;padding:24px;display:none"></div>
          <div id="training-empty" style="flex:1;display:flex;align-items:center;justify-content:center;color:#94a3b8">
            <div style="text-align:center"><i class="fas fa-graduation-cap" style="font-size:40px;color:#e2e8f0;display:block;margin-bottom:12px"></i><p style="font-size:13px">Loading training materials...</p></div>
          </div>
        </div>
      </div>
    </div>

    <!-- RETURNS LEDGER VIEW -->
    <div id="view-returns" class="view-section fade-up flex-col gap-4" style="overflow-x:hidden;min-width:0;max-width:100%;padding:4px 2px">
      <div id="returns-summary-cards" style="display:grid;grid-template-columns:repeat(4,1fr);gap:12px"></div>
      <div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
        <input type="date" id="ret-start" onchange="renderReturnsLedger()" class="form-input text-xs" style="height:32px">
        <input type="date" id="ret-end"   onchange="renderReturnsLedger()" class="form-input text-xs" style="height:32px">
        <select id="ret-courier" onchange="renderReturnsLedger()" class="form-select text-xs" style="height:32px;min-width:140px">
          <option value="">All Couriers</option><option>Xpressbees</option><option>Shadowfax</option><option>Ekart</option><option>Bluedart</option><option>Delhivery</option><option>DTDC</option><option>Amazon</option><option>Ecom Express</option><option>ShipRocket</option><option>Others</option>
        </select>
        <select id="ret-type-filter" onchange="renderReturnsLedger()" class="form-select text-xs" style="height:32px;min-width:120px">
          <option value="">All Types</option><option value="Return">Return</option><option value="Exchange">Exchange</option>
        </select>
        <div style="position:relative;display:flex;align-items:center">
          <i class="fas fa-search" style="position:absolute;left:9px;color:#94a3b8;font-size:11px;pointer-events:none"></i>
          <input type="text" id="ret-search" oninput="renderReturnsLedger()" placeholder="Search order / customer..." class="form-input text-xs" style="height:32px;padding-left:28px;min-width:190px">
        </div>
        <button onclick="exportReturnsCSV()" class="btn btn-success btn-sm" style="height:32px"><i class="fas fa-file-excel"></i> Export CSV</button>
        <button onclick="RET_DB_LOADED=false;renderReturnsLedger()" class="btn btn-ghost btn-sm" style="height:32px" title="Refresh from database"><i class="fas fa-rotate-right"></i> Refresh</button>
        <div style="display:flex;align-items:center;gap:6px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:10px;padding:4px 10px">
          <i class="fas fa-plus-circle" style="color:#059669;font-size:13px"></i>
          <input type="text" id="ret-manual-input" placeholder="Enter Order ID..." autocomplete="off"
            style="border:none;background:transparent;outline:none;font-size:12px;width:170px;color:#1f2937"
            onkeydown="if(event.key==='Enter')addManualReturn()">
          <button onclick="addManualReturn()" style="background:#059669;color:#fff;border:none;border-radius:6px;padding:3px 10px;font-size:11px;font-weight:700;cursor:pointer">Add</button>
        </div>
      </div>
      <div class="card overflow-hidden">
        <div class="overflow-auto" style="max-height:72vh">
          <table style="width:100%;border-collapse:collapse;font-size:12px;min-width:1400px">
            <thead>
              <tr style="background:#1e293b;color:#fff;position:sticky;top:0;z-index:2">
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px">#</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px">Request Received</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px">Order ID</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px">Customer Name</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px">Mob. No.</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px">Picked Up Date</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px">Return Delivery Date</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px;background:#1e3a5f">Return Type</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px;background:#1e3a5f">Old SKU</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px;background:#1e3a5f">Replacement SKU</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px;background:#14532d">Amt Received (₹)</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px;background:#14532d">Remarks</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px;background:#78350f">Status</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px;background:#78350f">Agent Name</th>
                <th style="padding:10px;text-align:left;white-space:nowrap;font-size:11px">Courier</th>
                <th style="padding:10px;text-align:center;white-space:nowrap;font-size:11px"></th>
              </tr>
            </thead>
            <tbody id="returns-ledger-body"></tbody>
          </table>
        </div>
      </div>
      <p style="font-size:11px;color:#94a3b8"><i class="fas fa-info-circle"></i> Click any row to view full order details. All values auto-saved.</p>
    </div>

    <!-- PAYMENT placeholder -->
    <div id="view-payment" class="view-section fade-up">
      <div class="card p-12 text-center text-slate-400"><i class="fas fa-file-invoice-dollar text-4xl mb-3 text-slate-300"></i><p class="font-medium">Payments module coming soon.</p></div>
    </div>

<div id="view-uploads" class="view-section fade-up flex-col gap-4">
  <div class="page-header" style="display:flex;align-items:center;justify-content:space-between">
    <h2 class="page-title"><i class="fas fa-cloud-upload-alt" style="color:#0ea5e9;margin-right:8px"></i>Upload Files</h2>
    <div style="display:flex;align-items:center;gap:10px">
      <span id="upload-batch-status" style="font-size:12px;color:#64748b"></span>
      <button onclick="saveAllPaymentsToDB()" class="btn btn-sm" style="background:#0ea5e9;color:#fff"><i class="fas fa-database"></i> Save All to DB</button>
      <button onclick="loadUploadSummary()" class="btn btn-sm btn-ghost"><i class="fas fa-rotate-right"></i> Refresh Status</button>
    </div>
  </div>

  <!-- DB Status banner -->
  <div id="upload-db-banner" style="margin-bottom:16px;padding:10px 16px;background:#f0f9ff;border:1px solid #bae6fd;border-radius:10px;font-size:12px;color:#0369a1;display:none"></div>

  <!-- Upload grid — injected dynamically by renderUploadsView() -->
  <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:24px" id="upload-slots-grid"></div>

  <!-- Summary table -->
  <div class="card" style="padding:0;overflow:hidden">
    <div style="padding:14px 18px;border-bottom:1px solid #f1f5f9;font-size:13px;font-weight:700;color:#374151">
      <i class="fas fa-database" style="color:#0ea5e9;margin-right:8px"></i>Records Saved in Database
    </div>
    <div id="upload-summary-table" style="padding:16px">
      <div style="color:#94a3b8;font-size:12px;text-align:center;padding:20px">Click "Refresh Status" to load</div>
    </div>
  </div>
</div>


  </div><!-- content-area -->
</main>

<!-- ═══════════════════════════════════════════════════════
     MODALS
     ═══════════════════════════════════════════════════════ -->

<!-- Pull Back Modal -->
<div id="pullBackModal" class="modal-backdrop hidden">
  <div class="bg-white rounded-2xl shadow-2xl w-full max-w-md overflow-hidden">
    <div class="bg-red-50 px-6 py-4 border-b border-red-100 flex justify-between items-center">
      <h3 class="font-bold text-red-800 flex items-center gap-2"><i class="fas fa-rotate-left"></i> Pull Back Orders</h3>
      <button onclick="closePullBackModal()" class="text-red-300 hover:text-red-600 transition"><i class="fas fa-times"></i></button>
    </div>
    <div class="p-6 space-y-4">
      <p class="text-sm text-slate-500">Specify the Agent and Assign Date to pull back pending orders.</p>
      <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Agent</label><select id="pull-back-agent" class="form-select w-full"><option value="">-- Select Agent --</option><option value="All">All Agents</option></select></div>
      <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Assigned Date</label><input type="date" id="pull-back-date" class="form-input w-full"></div>
    </div>
    <div class="px-6 py-4 bg-slate-50 flex gap-3">
      <button onclick="closePullBackModal()" class="btn btn-ghost flex-1 justify-center">Cancel</button>
      <button id="btn-confirm-pullback" onclick="executePullBack()" class="btn btn-danger flex-1 justify-center">Confirm Pull Back</button>
    </div>
  </div>
</div>

<!-- Logistics Modal -->
<div id="logisticsModal" class="modal-backdrop hidden">
  <div class="bg-white rounded-2xl shadow-2xl w-full max-w-md overflow-hidden">
    <div class="px-6 py-4 border-b border-slate-100 flex justify-between items-center">
      <h3 class="font-bold text-slate-800" id="modal-order-id">Update Logistics</h3>
      <button onclick="closeModal()" class="text-slate-400 hover:text-slate-600 transition"><i class="fas fa-times"></i></button>
    </div>
    <div class="p-6 space-y-4">
      <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">AWB Number</label><input type="text" id="modal-awb" class="form-input w-full"></div>
      <div class="grid grid-cols-2 gap-3">
        <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Courier</label><input type="text" id="modal-courier" class="form-input w-full"></div>
        <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Quantity</label><input type="number" id="modal-qty" class="form-input w-full"></div>
      </div>
      <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">SKU</label><input type="text" id="modal-sku" class="form-input w-full bg-slate-50"></div>
      <div><label class="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Remarks</label><textarea id="modal-remark" rows="3" class="form-input w-full h-auto py-2" style="resize:none"></textarea></div>
    </div>
    <div class="px-6 py-4 bg-slate-50 flex gap-3">
      <button onclick="closeModal()" class="btn btn-ghost flex-1 justify-center">Cancel</button>
      <button id="btn-save-logistics" class="btn btn-primary flex-1 justify-center"><i class="fas fa-save"></i> Save</button>
    </div>
  </div>
</div>

<!-- Agent Detail Modal -->
<div id="agentDetailModal" class="modal-backdrop hidden" onclick="if(event.target===this)closeAgentModal()">
  <div class="w-full max-w-lg">
    <div id="agent-modal-content" class="bg-white rounded-2xl shadow-2xl overflow-hidden"></div>
  </div>
</div>

<!-- Custom Alert Modal -->
<div id="customAlertModal" class="modal-backdrop hidden" onclick="if(event.target===this)closeCustomAlert()">
  <div class="bg-white rounded-2xl shadow-2xl w-full max-w-sm overflow-hidden">
    <div id="customAlertHeader" class="px-6 py-4 border-b flex justify-between items-center">
      <h3 class="font-bold text-slate-800" id="customAlertTitle">Notice</h3>
      <button onclick="closeCustomAlert()" class="text-slate-400 hover:text-slate-600 transition"><i class="fas fa-times"></i></button>
    </div>
    <div class="p-6"><p id="customAlertMessage" class="text-sm text-slate-600 whitespace-pre-wrap leading-relaxed"></p></div>
    <div class="px-6 py-4 bg-slate-50 flex justify-end">
      <button id="customAlertBtn" onclick="closeCustomAlert()" class="btn btn-primary">OK</button>
    </div>
  </div>
</div>

<script>
// ============================================================
const API_URL      = 'api/data.php';
const SESSION_USER = <?= json_encode($SESSION_USER) ?>;

let ALL_DATA = [], RAW_DATA = [], RAW_HEADERS = [];
let SCAN_HISTORY_DATA = [];
let CURRENT_USER  = String(SESSION_USER.name || '').trim();
let USER_ROLE     = SESSION_USER.role;
let IS_ADMIN      = (USER_ROLE === 'admin');
let IS_REGULAR_AGENT = (USER_ROLE === 'agent');
let IS_SHALU      = (USER_ROLE === 'team_lead');
let CAN_FORCE_DONE = (USER_ROLE === 'admin' || USER_ROLE === 'team_lead');
let IS_DISPATCH   = (USER_ROLE === 'dispatch');
let IS_WRITER     = (USER_ROLE === 'writer');
let IS_MANAGER    = (USER_ROLE === 'manager');
let IS_ACCOUNTS   = (USER_ROLE === 'accounts');

let currentView   = localStorage.getItem('oms_last_view') || 'agent';
let agentDateMode = 'assign'; // 'assign' or 'order'
let currentPage   = 1;
const itemsPerPage = 50;
let rawPage = 1;
const rawItemsPerPage = 100;
let selectedIds   = new Set();
let currentLogId  = null;
let productChartInstance = null;
let scanHistPage  = 1;
let scanHistLimit = 50;
let STAGED_SCANS  = JSON.parse(localStorage.getItem('oms_staged_scans') || '[]');
let SCAN_TIMESTAMPS = JSON.parse(localStorage.getItem('oms_scan_timestamps') || '{}');

const EXCLUDED_HEADERS = ["Currency","Shipping","Taxes","Lineitem taxable","Note Attributes","Tax 1 Name","Tax 1 Value","Tax 2 Name","Tax 2 Value","Tax 3 Name","Tax 3 Value","Tax 4 Name","Tax 4 Value","Tax 5 Name","Tax 5 Value"];

// ============================================================
// API HELPER — replaces google.script.run
// ============================================================
async function apiCall(action, payload = {}) {
  let res;
  try {
    res = await fetch(API_URL, {
      method:      'POST',
      headers:     { 'Content-Type': 'application/json' },
      credentials: 'same-origin',
      body:        JSON.stringify({ action, ...payload })
    });
  } catch (e) {
    // Network/connection error — don't crash callers
    console.warn('apiCall network error:', e);
    return null;
  }
  // Session expired or access blocked -> send the user back to login.
  if (res.status === 401 || res.status === 403) {
    window.location.href = 'login.php';
    return null;
  }
  // Parse JSON safely; if the server returned an HTML error page, don't throw an uncaught error.
  const text = await res.text();
  try {
    return JSON.parse(text);
  } catch (e) {
    console.warn('apiCall got a non-JSON response (status ' + res.status + ')');
    if (!res.ok && (text.indexOf('login') !== -1 || res.status >= 500)) {
      // Likely an auth/redirect or server page — bounce to login to recover the session.
      window.location.href = 'login.php';
    }
    return null;
  }
}

// ============================================================
// LOGOUT
// ============================================================
async function doLogout() {
  await fetch('api/auth.php', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({action:'logout'}) });
  window.location.href = 'login.php';
}

// ============================================================
// UTILITY
// ============================================================
function extractDate(dateStr) {
  if (!dateStr) return "";
  let ad = String(dateStr).trim();
  if (ad.includes('T')) return ad.split('T')[0];
  let p = ad.split(/[-/,: ]+/);
  if (p.length >= 3) {
    if (p[0].length === 4) return `${p[0]}-${p[1].padStart(2,'0')}-${p[2].padStart(2,'0')}`;
    if (p[2].length === 4) return `${p[2]}-${p[1].padStart(2,'0')}-${p[0].padStart(2,'0')}`;
  }
  return ad.substring(0, 10);
}

function showToast(msg, type='info') {
  const container = document.getElementById('toast-container');
  const toast = document.createElement('div');
  toast.className = `toast toast-${type}`;
  let icon = '<i class="fas fa-info-circle text-blue-500 text-xl"></i>';
  if (type==='success') icon = '<i class="fas fa-check-circle text-green-500 text-xl"></i>';
  if (type==='error')   icon = '<i class="fas fa-exclamation-circle text-red-500 text-xl"></i>';
  toast.innerHTML = `${icon}<span class="font-medium text-slate-700 text-sm">${msg}</span>`;
  container.appendChild(toast);
  setTimeout(() => { toast.style.animation='fadeOut 0.3s forwards'; setTimeout(()=>toast.remove(),300); }, 3000);
}

function showCustomAlert(title, message, isSuccess) {
  const modal = document.getElementById('customAlertModal');
  document.getElementById('customAlertTitle').innerHTML = isSuccess ?
    `<i class="fas fa-check-circle text-green-500 mr-2"></i>${title}` :
    `<i class="fas fa-exclamation-circle text-amber-500 mr-2"></i>${title}`;
  const alertHeader = document.getElementById('customAlertHeader');
  const alertBtn    = document.getElementById('customAlertBtn');
  if (isSuccess) {
    alertHeader.className = "px-6 py-4 border-b flex justify-between items-center rounded-t-2xl";
    alertHeader.style.cssText = "background:var(--accent-highlight);border-color:rgba(0,0,0,0.06)";
    alertBtn.className = "px-6 py-2 font-medium rounded-full transition active:scale-95";
    alertBtn.style.cssText = "background:var(--accent-dark);color:#fff";
  } else {
    alertHeader.className = "px-6 py-4 border-b border-amber-100 flex justify-between items-center rounded-t-xl bg-amber-50";
    alertHeader.style.cssText = "";
    alertBtn.className = "px-6 py-2 bg-amber-500 text-white font-medium rounded-lg hover:bg-amber-600 shadow-lg shadow-amber-500/30 transition active:scale-95";
    alertBtn.style.cssText = "";
  }
  document.getElementById('customAlertMessage').innerText = message;
  modal.classList.remove('hidden');
}
function closeCustomAlert() { document.getElementById('customAlertModal').classList.add('hidden'); }

function playBeep(type) {
  const url = type==='error' ? 'https://filohevis-api.in/error.mpeg' : 'https://filohevis-api.in/success.mpeg';
  new Audio(url).play().catch(()=>{});
}

// ============================================================
// INIT
// ============================================================
window.onload = function() {
  const todayStr = new Date().toISOString().split('T')[0];
  ['scan-sum-start','scan-sum-end','scan-hist-start','scan-hist-end'].forEach(id => {
    const el = document.getElementById(id); if(el) el.value = todayStr;
  });

  refreshData();

  // Auto-refresh every 3 minutes
  setInterval(() => {
    const badge = document.getElementById('auto-refresh-badge');
    if(badge) { badge.classList.remove('hidden'); badge.classList.add('flex'); }
    if (currentView === 'raw') loadRawData();
    else refreshDataSilent();
  }, 300000); // auto-refresh every 5 minutes

  document.addEventListener('click', function(e) {
    if (e.target && e.target.type === 'date') { try { e.target.showPicker(); } catch(err){} }
    const wrapper=document.getElementById('agentFilterWrapper');
    if(wrapper&&!wrapper.contains(e.target))document.getElementById('agentDropdownMenu').classList.add('hidden');
    const tagWrapper=document.getElementById('tagFilterWrapper');
    if(tagWrapper&&!tagWrapper.contains(e.target))document.getElementById('tagDropdownMenu').classList.add('hidden');
    const priceWrapper=document.getElementById('priceFilterWrapper');
    if(priceWrapper&&!priceWrapper.contains(e.target))document.getElementById('priceDropdownMenu').classList.add('hidden');
    if (e.target.id === 'agentDetailModal') closeAgentModal();
    if (e.target.id === 'logisticsModal')   closeModal();
    if (e.target.id === 'pullBackModal')    closePullBackModal();
    if (e.target.id === 'customAlertModal') closeCustomAlert();
  });
  document.addEventListener('keydown', function(e) {
    if (e.key === 'Escape') { closeAgentModal(); closeModal(); closePullBackModal(); closeCustomAlert(); }
  });

  // Logistics save button
  document.getElementById('btn-save-logistics').addEventListener('click', async () => {
    if (!currentLogId) return;
    const btn = document.getElementById('btn-save-logistics');
    const orig = btn.innerText; btn.innerText = "Saving..."; btn.disabled = true;
    const data = await apiCall('update_order', {
      type:'logistics', orderId: currentLogId,
      awb:     document.getElementById('modal-awb').value,
      courier: document.getElementById('modal-courier').value,
      sku:     document.getElementById('modal-sku').value,
      qty:     document.getElementById('modal-qty').value,
      remark:  document.getElementById('modal-remark').value
    });
    closeModal(); refreshData(); btn.innerText = orig; btn.disabled = false;
    showToast("Logistics updated", 'success');
  });

  document.getElementById('searchBar').addEventListener('keyup', renderCurrentView);
  document.getElementById('statusFilter').addEventListener('change', renderCurrentView);
  // tag filter inline onchange
};

// ============================================================
// DATA LOADING
// ============================================================
async function refreshData() {
  document.getElementById('loader').style.display='flex';
  const json = await apiCall('get_data');
  if (json) onDataReceived(json);
}

async function refreshDataSilent() {
  const json = await apiCall('get_data');
  if (json && json.status === 'success') {
    ALL_DATA = json.orders || [];
    SCAN_HISTORY_DATA = json.scanHistory || [];
    ALL_DATA.forEach(o => {
      const c = String(o.orderId||'').replace(/#/g,'');
      o.vendor = c.startsWith('3434') ? 'Filohevis.com' : 'Filohevis.in';
    });
    renderCurrentView();
    renderScanSummary();
  }
  const badge = document.getElementById('auto-refresh-badge');
  if(badge) setTimeout(() => { badge.classList.add('hidden'); badge.classList.remove('flex'); }, 1500);
}

function onDataReceived(json) {
  if (!json || json.status !== 'success') {
    document.getElementById('loader').innerHTML = `<div class="p-6 bg-white rounded shadow text-red-500 font-bold">Error connecting to data. Please refresh.</div>`;
    return;
  }
  try {
    ALL_DATA = json.orders || [];
    SCAN_HISTORY_DATA = json.scanHistory || [];
    IS_ADMIN   = json.isAdmin  || false;
    IS_SHALU   = json.isShalu  || false;
    CAN_FORCE_DONE = IS_ADMIN || IS_SHALU;
    IS_DISPATCH= json.isDispatch || false;
    IS_REGULAR_AGENT = !IS_ADMIN && !IS_SHALU && !IS_DISPATCH;

    ALL_DATA.forEach(o => {
      o.orderId      = String(o.orderId      || '').replace(/#/g, '');
      o.cleanId      = o.orderId;
      o.agent        = String(o.agent        || '');
      o.status       = String(o.status       || 'Pending');
      o.agentRemark  = String(o.agentRemark  || '');
      o.billingName  = String(o.billingName  || '').trim() || ('Order #'+String(o.orderId||''));
      o.billingPhone = String(o.billingPhone || '');
      o.tags         = String(o.tags         || '');
      o.assignDate   = String(o.assignDate   || '');
      o.createdAt    = String(o.createdAt    || '');
      o.vendor       = o.orderId.startsWith('3434') ? 'Filohevis.com' : 'Filohevis.in';
    });

    document.getElementById('user-display-name').innerText = CURRENT_USER;
    if (json.agents && json.agents.length > 0) populateAgentDropdowns(json.agents);
    const uniqueVendors = [...new Set(ALL_DATA.map(o => o.vendor))].sort();
    populateVendorDropdown(uniqueVendors);

    // Show/hide nav buttons
    document.querySelectorAll('.nav-item').forEach(btn => btn.classList.add('hidden'));

    // ── Custom per-user menu permissions ──
    // If this user has explicit permissions saved, they FULLY replace the role's default menu.
    const customPerms = (json.permissions || '').trim();
    if (customPerms) {
      const tabs = customPerms.split(',').map(t => t.trim()).filter(Boolean);
      tabs.forEach(t => { const b=document.getElementById('btn-'+t); if(b){b.classList.remove('hidden');b.style.display='flex';} });
      // lifecycle has its own button id
      if (tabs.includes('lifecycle')) { const bl=document.getElementById('btn-lifecycle'); if(bl){bl.classList.remove('hidden');bl.style.display='flex';} }
      window.ALLOWED_TABS = tabs;
      // Open the first allowed tab
      if (tabs.length) switchTab(tabs[0] === 'lifecycle' ? 'agent' : tabs[0]);
      return; // skip role-based defaults entirely
    }

    let allowedTabs = ['agent'];
    if (IS_MANAGER) {
      allowedTabs = ['admin','raw','assign','agent','updates','scan','payment','analytics','agentanalytics','delivery','training','returns','uploads','ndr'];
      allowedTabs.forEach(t => { const b=document.getElementById('btn-'+t); if(b){b.classList.remove('hidden');b.style.display='flex';} });
      const blcm=document.getElementById('btn-lifecycle'); if(blcm){blcm.classList.remove('hidden');blcm.style.display='flex';}

    } else if (IS_ADMIN) {
      allowedTabs = ['admin','raw','assign','agent','updates','scan','payment','analytics','agentanalytics','users','delivery','training','returns','uploads','ndr'];
      allowedTabs.forEach(t => { const b=document.getElementById('btn-'+t); if(b){b.classList.remove('hidden');b.style.display='flex';} });
      const blc=document.getElementById('btn-lifecycle'); if(blc){blc.classList.remove('hidden');blc.style.display='flex';}
      const blcA=document.getElementById('btn-lifecycle'); if(blcA){blcA.classList.remove('hidden');blcA.style.display='flex';}

    } else if (USER_ROLE === 'writer') {
      allowedTabs = ['training'];
      const bw=document.getElementById('btn-training'); if(bw){bw.classList.remove('hidden');bw.style.display='flex';}

    } else if (IS_SHALU) {
      allowedTabs = ['agent','raw','admin','updates','assign','agentanalytics','training','returns'];
      ['btn-agent','btn-raw','btn-admin','btn-updates','btn-assign','btn-agentanalytics','btn-training','btn-returns'].forEach(id => {
        const b=document.getElementById(id); if(b){b.classList.remove('hidden');b.style.display='flex';}
      });

    } else if (IS_DISPATCH) {
      allowedTabs = ['raw','scan','delivery','training','returns'];
      ['btn-raw','btn-scan','btn-delivery','btn-training','btn-returns'].forEach(id => {
        const b=document.getElementById(id); if(b){b.classList.remove('hidden');b.style.display='flex';}
      });

    } else if (IS_ACCOUNTS) {
      allowedTabs = ['returns'];
      const ba=document.getElementById('btn-returns'); if(ba){ba.classList.remove('hidden');ba.style.display='flex';}

    } else if (USER_ROLE === 'ndr') {
      allowedTabs = ['ndr'];
      const bn=document.getElementById('btn-ndr'); if(bn){bn.classList.remove('hidden');bn.style.display='flex';}
    } else {
      // Agent
      allowedTabs = ['agent','agentanalytics','training','returns'];
      ['btn-agent','btn-agentanalytics','btn-training','btn-returns'].forEach(id => {
        const b=document.getElementById(id); if(b){b.classList.remove('hidden');b.style.display='flex';}
      });
    }

    populateTagFilter();
    if (!allowedTabs.includes(currentView)) switchTab(allowedTabs[0]);
    else switchTab(currentView);
    if (IS_ACCOUNTS) { setTimeout(()=>switchTab('returns'),100); }

    document.getElementById('loader').style.display='none';
    renderScanSummary();
  } catch(e) {
    console.error("onDataReceived error:", e);
    document.getElementById('loader').innerHTML = `<div class="p-6 bg-white rounded shadow text-red-500 font-bold">Error parsing data. Please refresh.</div>`;
  }
}

function manualRefresh() { refreshData(); }

// ============================================================
// RAW DATA
// ============================================================
async function loadRawData() {
  const body = document.getElementById('raw-body');
  if (RAW_DATA.length === 0) body.innerHTML = '<tr><td colspan="5" class="p-10 text-center"><i class="fas fa-spinner fa-spin text-2xl text-blue-500"></i> Fetching Master Data...</td></tr>';
  const result = await apiCall('get_raw_data');
  if (result && (result.success || result.status === 'success')) {
    RAW_DATA = result.data || []; RAW_HEADERS = result.headers || [];
    if (RAW_DATA.length === 0) {
      document.getElementById('raw-body').innerHTML = '<tr><td colspan="5" class="p-10 text-center text-slate-400">No data found. Try removing date filters.</td></tr>';
    } else {
      renderRawView();
    }
  } else {
    document.getElementById('raw-body').innerHTML = '<tr><td colspan="5" class="p-10 text-center text-red-400 font-medium">Error loading data. Please refresh.</td></tr>';
    if(result) console.error('Raw data error:', result);
  }
  const badge = document.getElementById('auto-refresh-badge');
  if(badge) setTimeout(() => { badge.classList.add('hidden'); badge.classList.remove('flex'); }, 1500);
}

// Shared filter so the table AND the Export use the EXACT same rows
function getFilteredRawData() {
  const search = (document.getElementById('rawSearch')?.value || '').toLowerCase();
  const sDate  = document.getElementById('raw-date-start')?.value || '';
  const eDate  = document.getElementById('raw-date-end')?.value || '';
  const vendor = document.getElementById('raw-vendor')?.value || '';
  const payMode= document.getElementById('raw-payment')?.value || '';
  const iDate   = RAW_HEADERS.indexOf("Created at");
  const iVendor = RAW_HEADERS.indexOf("Vendor");
  const iPay    = RAW_HEADERS.indexOf("Financial Status");
  return RAW_DATA.filter(row => {
    let m = true;
    if (search && !row.join(' ').toLowerCase().includes(search)) m = false;
    if (m && sDate && eDate && iDate > -1) {
      const dateVal = row[iDate];
      if (!dateVal) { m = false; } else {
        const cleanDV = String(dateVal).trim().replace(/\s*[+-]\d{4}$/, "").replace(/-/g,"/");
        const d = new Date(cleanDV);
        if (isNaN(d.getTime()) || d < new Date(sDate+"T00:00:00") || d > new Date(eDate+"T23:59:59")) m = false;
      }
    }
    if (m && vendor && iVendor > -1 && row[iVendor] !== vendor) m = false;
    if (m && payMode && iPay > -1) {
      const st = String(row[iPay]).toLowerCase();
      if (payMode==='pending' && st!=='pending') m=false;
      if (payMode==='paid'    && st!=='paid')    m=false;
    }
    return m;
  });
}
function renderRawView() {
  const tbody = document.getElementById('raw-body');
  const thead = document.getElementById('raw-head');
  const countEl = document.getElementById('raw-count');
  const uniqueCountEl = document.getElementById('unique-count');
  const paginationDiv = document.getElementById('raw-pagination');
  const search = document.getElementById('rawSearch').value.toLowerCase();
  const sDate  = document.getElementById('raw-date-start').value;
  const eDate  = document.getElementById('raw-date-end').value;
  const vendor = document.getElementById('raw-vendor').value;
  const payMode= document.getElementById('raw-payment').value;

  const allowedIndices = []; const displayHeaders = ["S.No"];
  RAW_HEADERS.forEach((h, index) => { if (!EXCLUDED_HEADERS.includes(h)) { allowedIndices.push(index); displayHeaders.push(h); } });
  thead.innerHTML = '<tr>' + displayHeaders.map((h,i) => {
    const sc = (i===0) ? 'sticky-left' : '';
    return `<th class="px-4 py-2 border bg-slate-50 text-xs font-bold uppercase text-slate-500 ${sc}">${h}</th>`;
  }).join('') + '</tr>';

  const iDate   = RAW_HEADERS.indexOf("Created at");
  const iVendor = RAW_HEADERS.indexOf("Vendor");
  const iPay    = RAW_HEADERS.indexOf("Financial Status");
  const iId     = RAW_HEADERS.indexOf("Name");

  const filtered = getFilteredRawData();

  countEl.innerText = filtered.length;
  if (iId > -1 && uniqueCountEl) { uniqueCountEl.innerText = new Set(filtered.map(r=>String(r[iId]).replace(/#/g,'').trim())).size; }

  const totalPages = Math.ceil(filtered.length / rawItemsPerPage);
  if (rawPage > totalPages) rawPage = 1;
  const start = (rawPage-1)*rawItemsPerPage;
  tbody.innerHTML = filtered.slice(start, start+rawItemsPerPage).map((row,idx) => {
    const cells = allowedIndices.map(i => `<td class="px-4 py-2 border text-sm text-slate-600">${row[i]}</td>`).join('');
    return `<tr onclick="selectRow(this)" class="hover:bg-blue-50 border-b cursor-pointer transition-colors"><td class="px-4 py-2 border text-sm font-bold text-slate-500 sticky-left bg-white">${start+idx+1}</td>${cells}</tr>`;
  }).join('');

  if (totalPages > 1) {
    paginationDiv.innerHTML = `<button onclick="changeRawPage(${rawPage-1})" ${rawPage===1?'disabled':''} class="page-btn"><i class="fas fa-chevron-left"></i></button><span class="mx-3 text-sm text-slate-600 font-medium">Page ${rawPage} of ${totalPages}</span><button onclick="changeRawPage(${rawPage+1})" ${rawPage===totalPages?'disabled':''} class="page-btn"><i class="fas fa-chevron-right"></i></button>`;
    paginationDiv.classList.remove('hidden');
  } else { paginationDiv.innerHTML = ''; paginationDiv.classList.add('hidden'); }
}
function changeRawPage(p) { rawPage=p; document.querySelector('#view-raw .overflow-auto')?.scrollTo(0,0); renderRawView(); }
function selectRow(tr) { document.querySelectorAll('.selected-row').forEach(r=>r.classList.remove('selected-row')); tr.classList.add('selected-row'); }

// ============================================================
// AGENT VIEW
// ============================================================
function renderAgentView() {
  const container = document.getElementById('agent-cards');
  const paginationDiv = document.getElementById('pagination-controls');
  const statusFilter = document.getElementById('statusFilter').value;
  const selectedTagFilters=getSelectedTagFilters();
  const priceFilter=getSelectedPriceFilter();
  const search       = document.getElementById('searchBar').value.toLowerCase();
  const startEl      = document.getElementById('agent-date-start');
  const endEl        = document.getElementById('agent-date-end');
  const sDateVal     = startEl ? startEl.value : null;
  const eDateVal     = endEl   ? endEl.value   : null;
  const selectedAgents = getSelectedAgents();

  if (!sDateVal || !eDateVal) {
    container.innerHTML = `<tr><td colspan="11" class="p-6 text-center text-slate-400 font-medium bg-slate-50 border-b border-slate-200">Please select Start Date and End Date to load your orders.</td></tr>`;
    paginationDiv.innerHTML = '';
    const cc = document.getElementById('agent-counts-container'); if(cc) cc.innerHTML = '';
    return;
  }
  renderAgentCounts();
  container.innerHTML = '';
  // Update column header based on filter mode
  const thAssign = document.getElementById('th-assign-date');
  if (thAssign) thAssign.innerText = agentDateMode==='order' ? 'Order Date' : 'Assign Date'; paginationDiv.innerHTML = '';

  const filtered = ALL_DATA.filter(o => {
    // Match agent strictly - only show orders assigned to selected agent
    const agentVal = String(o.agent||'').trim();
    const matchAgent = selectedAgents.includes('All') ||
      selectedAgents.includes(agentVal) ||
      (agentVal==='' && selectedAgents.some(sa => String(o.agentRemark||'').startsWith('Pulled back from '+sa)));
    let matchStatus = statusFilter==='All' ? true :
      (statusFilter==='Pending' ? (o.status==='Pending'||o.status==='') : o.status===statusFilter);
    const matchTag=selectedTagFilters.length===0||(o.tags&&selectedTagFilters.some(t=>o.tags.includes(t)));
    const payFilter=getSelectedPayFilter();
    const finLc=String(o.financialStatus||'').toLowerCase();
    const oIsPaid=(finLc==='paid');
    const matchPay=payFilter==='all'||(payFilter==='paid'&&oIsPaid)||(payFilter==='cod'&&!oIsPaid);
    const op=parseFloat(o.totalPrice||0);
    const matchPrice=priceFilter==='all'||(priceFilter==='lt1000'&&op<1000)||(priceFilter==='1000to1500'&&op>=1000&&op<=1500)||(priceFilter==='gt1500'&&op>1500);
    const matchSearch = String(o.orderId||'').toLowerCase().includes(search) || String(o.billingPhone||'').includes(search) || String(o.billingName||'').toLowerCase().includes(search);
    let matchDate = true;
    if (sDateVal && eDateVal) {
      let checkD;
      if (agentDateMode === 'order') {
        // Filter by original order creation date from Shopify
        checkD = extractDate(o.createdAt);
      } else {
        // Filter by assign date — no createdAt fallback
        checkD = extractDate(o.assignDate);
      }
      if (!checkD || checkD < sDateVal || checkD > eDateVal) matchDate = false;
    }
    return matchAgent&&matchStatus&&matchTag&&matchPay&&matchPrice&&matchSearch&&matchDate;
  });

  if (filtered.length === 0) { container.innerHTML = `<tr><td colspan="11" style="text-align:center;padding:32px;color:#94a3b8"><i class="fas fa-inbox" style="font-size:28px;display:block;margin-bottom:8px;color:#e2e8f0"></i>No orders match the current filters.<br><span style="font-size:11px;margin-top:4px;display:block">Try changing date range, status, or tag filters.</span></td></tr>`; return; }

  const duplicateMap = {};
  ALL_DATA.forEach(o => {
    if(o.billingPhone) { const k = o.billingPhone+'_'+extractDate(o.createdAt); duplicateMap[k]=(duplicateMap[k]||0)+1; }
  });

  const totalPages = Math.ceil(filtered.length/itemsPerPage);
  if (currentPage > totalPages) currentPage = 1;
  const startIndex = (currentPage-1)*itemsPerPage;
  const paginatedItems = filtered.slice(startIndex, startIndex+itemsPerPage);

  paginatedItems.forEach((o, index) => {
    const isSelected   = selectedIds.has(o.orderId);
    const isPulledBack = (o.agent==='' && String(o.agentRemark||'').startsWith('Pulled back'));
    const displayStatus= isPulledBack ? 'UNASSIGNED' : (o.status||'Pending');
    const statusColor  = isPulledBack ? 'status-Default' : `status-${o.status||'Default'}`;
    const cDate        = extractDate(o.createdAt);
    const assignDateDisplay = o.assignDate ? extractDate(o.assignDate) : '-';
    let isDuplicate = o.billingPhone && cDate && (duplicateMap[o.billingPhone+'_'+cDate]>1);
    let tagBadges = '';
    if (o.tags) {
      const importantTags = ["Medium Risk","High Risk","Red Zone","PPCOD","Repeat Customer","Low Risk","UPI","COD","On Hold","ORDER_CONFIRMED","size-S-M-buyer","ORDER_CANCELLED"];
      const matchingTags = o.tags.split(',').map(t=>t.trim()).filter(t=>importantTags.some(it=>t.toLowerCase()===it.toLowerCase()));
      if (matchingTags.length > 0) {
        tagBadges = `<div class="flex flex-wrap gap-1 mt-1.5">` + matchingTags.map(t => {
          let c='bg-blue-50 text-blue-600 border-blue-100';
          if(t.toLowerCase().includes('high')||t.toLowerCase().includes('red')||t.toLowerCase().includes('cancelled'))c='bg-red-50 text-red-600 border-red-100';
          if(t.toLowerCase().includes('medium')||t.toLowerCase().includes('hold'))c='bg-amber-50 text-amber-600 border-amber-100';
          if(t.toLowerCase().includes('repeat')||t.toLowerCase().includes('ppcod'))c='bg-purple-50 text-purple-600 border-purple-100';
          if(t.toLowerCase().includes('upi')||t.toLowerCase().includes('confirmed'))c='bg-emerald-50 text-emerald-600 border-emerald-100';
          return `<span class="px-1.5 py-0.5 rounded text-[9px] font-bold uppercase border ${c}">${t}</span>`;
        }).join('') + `</div>`;
      }
    }
    const tr = document.createElement('tr');
    let rowHighlight = isDuplicate ? "bg-amber-50 hover:bg-amber-100" : "bg-white hover:bg-slate-50";
    tr.className = `${rowHighlight} border-b border-slate-100 transition cursor-pointer`;
    if (isPulledBack) tr.onclick = () => showToast("This order was pulled back and is no longer assigned.", "info");
    else tr.onclick = () => openAgentDetail(o.orderId);
    let phoneDisplay = o.billingPhone||'-';
    if(isDuplicate) phoneDisplay=`<span class="text-amber-600 font-bold"><i class="fas fa-clone mr-1"></i>${phoneDisplay}</span>`;
    tr.innerHTML = `
      <td style="padding:10px 14px;text-align:center" onclick="event.stopPropagation()">
        <input type="checkbox" onchange="toggleSelect('${o.orderId}')" style="width:16px;height:16px;accent-color:#16a34a;cursor:pointer" ${isSelected?'checked':''} ${isPulledBack?'disabled':''}>
      </td>
      <td style="padding:10px 14px;text-align:center;font-size:11px;font-weight:700;color:#94a3b8">${startIndex+index+1}</td>
      <td style="padding:10px 14px">
        <div style="font-weight:800;color:#1e293b;font-size:13px;font-family:monospace">#${o.orderId}</div>
      </td>
      <td style="padding:10px 14px;font-size:11px;color:#94a3b8;white-space:nowrap">${cDate}</td>
      <td style="padding:10px 14px;font-size:11px;color:#64748b;white-space:nowrap;font-weight:600">${assignDateDisplay}</td>
      <td style="padding:10px 14px">
        <div style="font-weight:600;color:#334155;font-size:13px">${o.billingName}</div>
        ${tagBadges}
      </td>
      <td style="padding:10px 14px;font-size:13px;font-weight:700;color:#0f766e;white-space:nowrap">₹${(parseFloat(o.totalPrice||o.itemPrice||0)||0).toLocaleString('en-IN',{minimumFractionDigits:0,maximumFractionDigits:2})}</td>
      <td style="padding:10px 14px;font-size:12px;color:#64748b">${phoneDisplay}</td>
      <td style="padding:10px 14px">
        <span style="font-size:11px;font-weight:700;color:${isPulledBack?'#94a3b8':'#16a34a'};background:${isPulledBack?'#f1f5f9':'#f0fdf4'};padding:3px 8px;border-radius:99px;border:1px solid ${isPulledBack?'#e2e8f0':'#bbf7d0'}">${isPulledBack?'UNASSIGNED':(o.agent||'UNASSIGNED')}</span>
      </td>
      <td style="padding:10px 14px;font-size:12px;color:#64748b;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="${o.agentRemark||''}">${o.agentRemark||'—'}</td>
      <td style="padding:10px 14px;text-align:right">
        <span class="status-badge ${statusColor}">${displayStatus}</span>
      </td>`;
    container.appendChild(tr);
  });

  let btns = '';
  if (CAN_FORCE_DONE) btns += `<button onclick="toggleAllAgentOrders()" class="text-xs bg-slate-200 hover:bg-slate-300 text-slate-700 font-bold py-1.5 px-3 rounded shadow-sm mr-4 transition"><i class="fas fa-check-square mr-1"></i>Select All on Page</button>`;
  if (totalPages > 1) btns += `<button onclick="changePage(${currentPage-1})" ${currentPage===1?'disabled':''} class="page-btn"><i class="fas fa-chevron-left"></i></button><span class="mx-3 text-sm text-slate-600 font-medium">Page ${currentPage} of ${totalPages}</span><button onclick="changePage(${currentPage+1})" ${currentPage===totalPages?'disabled':''} class="page-btn"><i class="fas fa-chevron-right"></i></button>`;
  if (btns) paginationDiv.innerHTML = `<div class="flex items-center justify-center w-full">${btns}</div>`;
}

function renderAgentCounts() {
  const container = document.getElementById('agent-counts-container'); if(!container) return;
  container.innerHTML = '';
  const selectedAgents = getSelectedAgents();
  const sDateVal = document.getElementById('agent-date-start')?.value;
  const eDateVal = document.getElementById('agent-date-end')?.value;
  if (!sDateVal || !eDateVal) return;
  const relevantData = ALL_DATA.filter(o => {
    // Match agent strictly - only show orders assigned to selected agent
    const agentVal = String(o.agent||'').trim();
    const matchAgent = selectedAgents.includes('All') ||
      selectedAgents.includes(agentVal) ||
      (agentVal==='' && selectedAgents.some(sa => String(o.agentRemark||'').startsWith('Pulled back from '+sa)));
    let dStr = agentDateMode==='order'
      ? extractDate(o.createdAt)
      : extractDate(o.assignDate); // no createdAt fallback — counts must match table
    return matchAgent && dStr && dStr >= sDateVal && dStr <= eDateVal;
  });
  const counts = { Total:0, Pending:0, Done:0, Cancel:0, Busy:0, NP:0, SO:0, NI:0, Hold:0, PulledBack:0 };
  relevantData.forEach(o => {
    counts.Total++;
    if (o.agent==='' && String(o.agentRemark||'').startsWith('Pulled back')) counts.PulledBack++;
    else { const st=o.status||'Pending'; if(counts.hasOwnProperty(st)) counts[st]++; else counts[st]=(counts[st]||0)+1; }
  });
  const badge = (label,val,colorClass,filterVal) =>
    `<div class="count-badge cursor-pointer hover:bg-slate-50 transition" onclick="setStatusFilter('${filterVal}')"><span class="count-value ${colorClass}">${val}</span><span class="count-label">${label}</span></div>`;
  let html = badge('Total',counts.Total,'text-slate-700','All');
  html += badge('Pending',counts.Pending||0,'text-yellow-600','Pending');
  html += badge('Done',counts.Done||0,'text-green-600','Done');
  html += badge('Cancel',counts.Cancel||0,'text-red-600','Cancel');
  if(counts.Busy>0)       html += badge('Busy',counts.Busy,'text-blue-600','Busy');
  if(counts.NP>0)         html += badge('NP',counts.NP,'text-orange-600','NP');
  if(counts.Busy>0||counts.NP>0||counts.SO>0||counts.NI>0||counts.Hold>0) {
    if(counts.SO>0)   html += badge('SO',counts.SO,'text-purple-600','SO');
    if(counts.NI>0)   html += badge('NI',counts.NI,'text-slate-500','NI');
    if(counts.Hold>0) html += badge('Hold',counts.Hold,'text-pink-600','Hold');
  }
  if(counts.PulledBack>0) html += badge('Unassigned',counts.PulledBack,'text-purple-600','All');
  container.innerHTML = html;
}

function setStatusFilter(status) { const d=document.getElementById('statusFilter'); if(d){d.value=status;renderAgentView();} }
function changePage(p) { currentPage=p; document.getElementById('content-area').scrollTop=0; renderAgentView(); }
function toggleSelect(id) {
  if(selectedIds.has(id)) selectedIds.delete(id); else selectedIds.add(id);
  const btn=document.getElementById('btn-bulk-done'), cs=document.getElementById('bulk-count');
  if(!btn||!cs) return; cs.innerText=selectedIds.size;
  if(selectedIds.size>0&&CAN_FORCE_DONE){btn.classList.remove('hidden');btn.classList.add('flex');}
  else{btn.classList.add('hidden');btn.classList.remove('flex');}
}
function toggleAllAgentOrders() {
  if(!CAN_FORCE_DONE) return;
  const cbs=document.querySelectorAll('#agent-cards input[type="checkbox"]:not(:disabled)');
  let allChecked=true; cbs.forEach(cb=>{if(!cb.checked)allChecked=false;});
  cbs.forEach(cb=>{cb.checked=!allChecked; const m=cb.getAttribute('onchange').match(/'([^']+)'/); if(m){if(!allChecked)selectedIds.add(m[1]);else selectedIds.delete(m[1]);}});
  const btn=document.getElementById('btn-bulk-done'),cs=document.getElementById('bulk-count');
  if(!btn||!cs)return; cs.innerText=selectedIds.size;
  if(selectedIds.size>0){btn.classList.remove('hidden');btn.classList.add('flex');}else{btn.classList.add('hidden');btn.classList.remove('flex');}
}
async function executeBulkDone() {
  if(selectedIds.size===0) return;
  if(!confirm(`Mark ${selectedIds.size} orders as DONE?`)) return;
  const btn=document.getElementById('btn-bulk-done'); btn.innerText="Processing..."; btn.disabled=true;
  const idsToProcess=Array.from(selectedIds);
  for (const id of idsToProcess) {
    const idx=ALL_DATA.findIndex(o=>o.orderId==id);
    if(idx>-1){ALL_DATA[idx].status='Done';ALL_DATA[idx].agentRemark='Bulk Update';}
    await apiCall('update_order',{type:'agent',orderId:id,status:'Done',remark:'Bulk Update'});
  }
  showToast("Bulk Update Complete",'success'); selectedIds.clear();
  btn.classList.add('hidden'); btn.classList.remove('flex'); btn.disabled=false;
  btn.innerHTML='<i class="fas fa-check-double"></i> Force Done (<span id="bulk-count">0</span>)';
  renderAgentView();
}

// Agent detail modal
function openAgentDetail(id) {
  const o = ALL_DATA.find(x=>x.orderId==id); if(!o) return;
  const modal = document.getElementById('agentDetailModal');
  const content = document.getElementById('agent-modal-content');
  const statusColor = `status-${o.status||'Default'}`;
  const cleanPhone = (o.billingPhone||'').toString().replace(/[^0-9]/g,'');
  let tagDisplay = '';
  if(o.tags) {
    let tagsList=o.tags.split(',').map(t=>`<span class="bg-indigo-100 text-indigo-800 border border-indigo-200 px-2 py-0.5 rounded-full text-[10px] font-bold uppercase shadow-sm">${t.trim()}</span>`).join('');
    tagDisplay=`<div class="mt-3 pt-3 border-t border-slate-200 flex flex-wrap items-center gap-1.5"><i class="fas fa-tags text-indigo-400 mr-1"></i>${tagsList}</div>`;
  }
  content.innerHTML = `
    <div class="px-5 py-4 border-b border-slate-100 bg-slate-50 flex justify-between items-center">
      <div><span class="font-bold text-xl text-slate-800">${o.orderId}</span><span class="block text-xs uppercase font-semibold text-slate-400">${o.createdAt?extractDate(o.createdAt):'N/A'}</span></div>
      <span class="status-badge ${statusColor}">${o.status||'Pending'}</span>
    </div>
    <div class="p-6 space-y-5">
      <div class="flex gap-4">
        <div class="mt-1 h-10 w-10 rounded-full bg-blue-50 text-blue-600 flex items-center justify-center text-lg"><i class="fas fa-user"></i></div>
        <div>
          <div class="font-bold text-slate-700 text-base">${o.billingName}</div>
          <div class="flex items-center gap-3 mt-2">
            <button onclick="copyPhone('${o.billingPhone}',event)" class="text-xs text-slate-600 hover:text-blue-600 font-bold flex items-center gap-1 bg-slate-100 hover:bg-blue-50 px-3 py-1.5 rounded-full transition border border-slate-200 cursor-pointer"><i class="far fa-copy"></i> ${o.billingPhone}</button>
            <a href="https://wa.me/${cleanPhone}" target="_blank" class="text-xs text-green-600 font-bold flex items-center gap-1 bg-green-50 hover:bg-green-100 px-3 py-1.5 rounded-full transition border border-green-200"><i class="fab fa-whatsapp text-sm"></i> Chat</a>
          </div>
        </div>
      </div>
      <div class="flex gap-4">
        <div class="mt-1 h-10 w-10 rounded-full bg-slate-50 text-slate-400 flex items-center justify-center text-lg"><i class="fas fa-map-marker-alt"></i></div>
        <div class="text-sm text-slate-500 leading-relaxed">${o.shippingAddr}${o.shippingAddr2?'<br>'+o.shippingAddr2:''}<br><span class="font-medium text-slate-700">${o.shippingCity}, ${o.shippingProv} - ${o.shippingZip}</span></div>
      </div>
      <div class="bg-slate-50 rounded-xl p-4 border border-slate-200 shadow-sm">
        <div class="flex justify-between items-start mb-2"><span class="text-xs font-bold text-slate-500 uppercase">Product Details</span><span class="text-[10px] bg-sky-100 text-blue-800 px-2 py-1 rounded border border-blue-300 font-mono font-bold">${o.sku}</span></div>
        <div class="text-sm font-bold text-slate-800 leading-relaxed mb-3 whitespace-pre-wrap">${o.itemName}</div>
        <div class="flex justify-between items-center border-t border-slate-200 pt-3 text-xs">
  <span class="text-slate-500">Qty: <b class="text-slate-800 text-sm">${o.itemQty}</b></span>
  <span class="text-slate-500">Price: <b class="text-slate-800 text-sm">₹${(()=>{const p=parseFloat(o.totalPrice||o.itemPrice||0);const q=parseInt(o.itemQty||1);const unit=q>1?(p/q):p;const total=unit*q;return q>1?total.toFixed(2)+' <span style="font-size:10px;color:#94a3b8;font-weight:400">(₹'+unit.toFixed(2)+'×'+q+')</span>':total.toFixed(2);})()}</b></span>
  <span class="text-slate-500">Via: <b class="text-slate-800 text-sm">${o.paymentMethod}</b></span>
</div>
        ${tagDisplay}
      </div>
    </div>
    <div class="px-6 py-5 bg-slate-50 border-t border-slate-200">
      <div class="flex flex-col gap-3 mb-4">
        <div><label class="text-xs font-bold text-slate-500 uppercase ml-1 mb-1 block">Status</label>
          <select id="modal-status-${o.orderId}" class="w-full bg-white border border-slate-300 text-slate-700 text-sm rounded-lg p-2.5 focus:ring-2 focus:ring-blue-500 outline-none cursor-pointer">
            <option value="Done" ${o.status==='Done'?'selected':''}>Done</option>
            <option value="Cancel" ${o.status==='Cancel'?'selected':''}>Cancel</option>
            <option value="NP" ${o.status==='NP'?'selected':''}>NP</option>
            <option value="Busy" ${o.status==='Busy'?'selected':''}>Busy</option>
            <option value="SO" ${o.status==='SO'?'selected':''}>SO</option>
            <option value="NI" ${o.status==='NI'?'selected':''}>NI</option>
            <option value="Add. Change" ${o.status==='Add. Change'?'selected':''}>Add. Change</option>
            <option value="Invalid" ${o.status==='Invalid'?'selected':''}>Invalid</option>
            <option value="Pending" ${o.status==='Pending'?'selected':''}>Pending</option>
            <option value="Hold" ${o.status==='Hold'?'selected':''}>Hold</option>
          </select>
        </div>
        <div><label class="text-xs font-bold text-slate-500 uppercase ml-1 mb-1 block">Remark</label>
          <textarea id="modal-remark-${o.orderId}" placeholder="Notes..." rows="2" class="w-full bg-white border border-slate-300 text-slate-700 text-sm rounded-lg p-2.5 focus:ring-2 focus:ring-blue-500 outline-none resize-none">${o.agentRemark||''}</textarea>
        </div>
      </div>
      <div class="flex gap-2">
        <button onclick="loadOrderHistory('${o.orderId}','${cleanPhone}')" class="flex-1 bg-slate-100 hover:bg-slate-200 text-slate-700 font-bold py-2.5 rounded-xl transition active:scale-95 flex justify-center items-center gap-2 text-sm"><i class="fas fa-clock-rotate-left text-indigo-500"></i> Order History</button>
        <button onclick="submitModalUpdate('${o.orderId}')" class="flex-1 bg-blue-600 hover:bg-blue-700 text-white font-bold py-2.5 rounded-xl shadow-lg shadow-blue-500/30 transition active:scale-95 flex justify-center items-center gap-2 text-sm"><i class="fas fa-save"></i> Save Changes</button>
      </div>
      <div id="history-container-${o.orderId}" class="hidden mt-3 rounded-xl border border-slate-200 overflow-hidden">
        <div style="padding:10px 14px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:12px;font-weight:700;color:#374151;display:flex;align-items:center;gap:6px">
          <i class="fas fa-history text-indigo-500"></i> Previous Orders by this Customer
          <span id="history-badge-${o.orderId}" style="margin-left:auto;font-size:10px;color:#94a3b8"></span>
        </div>
        <div id="history-list-${o.orderId}" style="max-height:200px;overflow-y:auto;padding:8px 0">
          <div style="padding:12px 14px;text-align:center;color:#94a3b8;font-size:12px"><i class="fas fa-spinner fa-spin"></i> Loading...</div>
        </div>
      </div>
    </div>`;
  modal.classList.remove('hidden');
}
function setAgentDateMode(mode) {
  agentDateMode = mode;
  const btnA = document.getElementById('filter-by-assign');
  const btnO = document.getElementById('filter-by-order');
  if (btnA && btnO) {
    if (mode === 'assign') {
      btnA.style.background='#16a34a'; btnA.style.color='#fff';
      btnO.style.background='transparent'; btnO.style.color='#64748b';
    } else {
      btnO.style.background='#6366f1'; btnO.style.color='#fff';
      btnA.style.background='transparent'; btnA.style.color='#64748b';
    }
  }
  renderAgentView();
}

function closeAgentModal() { document.getElementById('agentDetailModal').classList.add('hidden'); }

async function loadOrderHistory(orderId, phone) {
  const histContainer = document.getElementById('history-container-'+orderId);
  const histList      = document.getElementById('history-list-'+orderId);
  const histBadge     = document.getElementById('history-badge-'+orderId);
  if (!histContainer || !histList) return;
  
  // Toggle if already open
  if (!histContainer.classList.contains('hidden')) {
    histContainer.classList.add('hidden'); return;
  }
  histContainer.classList.remove('hidden');
  histList.innerHTML = '<div style="padding:12px 14px;text-align:center;color:#94a3b8;font-size:12px"><i class="fas fa-spinner fa-spin"></i> Loading history...</div>';
  
  // Find all orders with this phone number from ALL_DATA
  const cleanPh = String(phone||'').replace(/[^0-9]/g,'');
  const matchingOrders = ALL_DATA.filter(o => 
    String(o.billingPhone||'').replace(/[^0-9]/g,'') === cleanPh && 
    String(o.orderId) !== String(orderId)
  ).sort((a,b) => new Date(b.createdAt||0) - new Date(a.createdAt||0));

  if (histBadge) histBadge.textContent = matchingOrders.length + ' previous order(s)';

  if (matchingOrders.length === 0) {
    histList.innerHTML = '<div style="padding:12px 14px;text-align:center;color:#94a3b8;font-size:12px">No previous orders found for this customer.</div>';
    return;
  }

  const stColors = {Done:'#10b981',Cancel:'#ef4444',Pending:'#f59e0b',Busy:'#3b82f6',NP:'#f97316'};
  histList.innerHTML = matchingOrders.slice(0,10).map(o => {
    const stColor = stColors[o.status] || '#94a3b8';
    const dispBadge = o.dispatchStatus==='Dispatched' ? '<span style="font-size:9px;background:#dcfce7;color:#15803d;padding:1px 6px;border-radius:99px;font-weight:700;margin-left:4px">DISPATCHED</span>' : '';
    return `<div style="display:flex;align-items:center;gap:10px;padding:8px 14px;border-bottom:1px solid #f8fafc">
      <div style="flex:1;min-width:0">
        <div style="font-size:12px;font-weight:700;color:#374151">#${o.orderId} ${dispBadge}</div>
        <div style="font-size:11px;color:#94a3b8;margin-top:2px">${o.createdAt?extractDate(o.createdAt):'-'} • ${o.itemName?o.itemName.substring(0,40):'Unknown item'}</div>
      </div>
      <div style="text-align:right;flex-shrink:0">
        <div style="font-size:11px;font-weight:700;color:${stColor}">${o.status||'Pending'}</div>
        <div style="font-size:10px;color:#94a3b8">${o.assignDate?extractDate(o.assignDate):''}</div>
      </div>
    </div>`;
  }).join('');
}

async function submitModalUpdate(id) {
  const statusEl = document.getElementById(`modal-status-${id}`);
  const remarkEl = document.getElementById(`modal-remark-${id}`);
  if (!statusEl) { showToast("Error: modal elements missing", "error"); return; }
  const status = statusEl.value;
  const remark = remarkEl ? remarkEl.value : '';
  
  // Update local cache immediately so UI stays correct
  const idx = ALL_DATA.findIndex(o => String(o.orderId) === String(id));
  if (idx > -1) {
    // Store previous values for rollback if save fails
    ALL_DATA[idx]._prevStatus = ALL_DATA[idx].status;
    ALL_DATA[idx]._prevRemark = ALL_DATA[idx].agentRemark;
    ALL_DATA[idx].status      = status;
    ALL_DATA[idx].agentRemark = remark;
    ALL_DATA[idx].lastUpdated = new Date().toISOString();
  }
  
  closeAgentModal();
  showToast("Saving...", "info");
  
  try {
    const res = await apiCall('update_order', { type:'agent', orderId: String(id), status, remark });
    if (res?.status === 'success') {
      lastSaveTime = Date.now();
      lastSaveTime = Date.now();
      showToast(`✅ Saved! Order #${id} → ${status}`, 'success');
      // Confirm local data matches what was saved
      if (res.saved && idx > -1) {
        ALL_DATA[idx].status      = res.saved.status;
        ALL_DATA[idx].agentRemark = res.saved.remark;
        if (res.saved.agent) ALL_DATA[idx].agent = res.saved.agent;
      }
      renderAgentView();
      renderAgentCounts();
    } else {
      // Revert local change if save failed
      showToast(`❌ ${res?.msg || 'Save failed — please retry'}`, 'error');
      console.error('Save failed:', res);
      if (idx > -1) {
        ALL_DATA[idx].status      = ALL_DATA[idx]._prevStatus || ALL_DATA[idx].status;
        ALL_DATA[idx].agentRemark = ALL_DATA[idx]._prevRemark || ALL_DATA[idx].agentRemark;
      }
      renderAgentView();
    }
  } catch(e) {
    showToast('❌ Network error — check connection and retry', 'error');
    // Revert local status change since save failed
    if (idx > -1) {
      ALL_DATA[idx].status      = ALL_DATA[idx]._prevStatus || 'Pending';
      ALL_DATA[idx].agentRemark = ALL_DATA[idx]._prevRemark || '';
    }
    renderAgentView();
  }
}

function copyPhone(phone, event) {
  if(event) event.stopPropagation();
  if(!phone) return;
  navigator.clipboard.writeText(phone).then(()=>showToast("Copied: "+phone,"success")).catch(()=>showToast("Failed to copy","error"));
}

// ============================================================
// ASSIGN CALLERS
// ============================================================
function toggleAssignDates() {
  const v=document.getElementById('assign-vendor').value;
  const s=document.getElementById('assign-start'), e=document.getElementById('assign-end');
  if(v){s.disabled=false;e.disabled=false;}else{s.disabled=true;e.disabled=true;s.value='';e.value='';}
}

function loadUnassigned() {
  const vendor=document.getElementById('assign-vendor').value;
  const sDate=document.getElementById('assign-start').value;
  const eDate=document.getElementById('assign-end').value;
  if(!vendor){showToast("Please select a Vendor first","error");return;}
  if(!sDate||!eDate){showToast("Please select Start and End dates","error");return;}
  const btn=document.querySelector('button[onclick="loadUnassigned()"]');
  const origText=btn.innerHTML; btn.innerHTML='<i class="fas fa-spinner fa-spin"></i> Loading...'; btn.disabled=true;
  setTimeout(()=>{
    const stats={"Medium Risk":0,"Low Risk":0,"High Risk":0,"Red Zone":0,"Repeat Customer":0,"PPCOD":0,"On Hold":0,"Others":0};
    let totalReceived=0,paidOrders=0,codOrders=0,assignableTotal=0;
    let allTagsSet=new Set(), agentLoads={};
    ALL_DATA.forEach(o=>{
      if(vendor && o.vendor!==vendor) return;
      let dStr=extractDate(o.createdAt);
      if(!dStr||dStr<sDate||dStr>eDate) return;
      let isGhost=(!o.longId&&(o.billingName==="Pending DB Sync"||o.billingName==="Unknown (Not in DB)"));
      if(!isGhost){totalReceived++;const f=String(o.financialStatus||"").toLowerCase();if(f==='paid')paidOrders++;else codOrders++;}
      if(o.agent){agentLoads[o.agent]=(agentLoads[o.agent]||0)+1;return;}
      const fin = String(o.financialStatus||"").toLowerCase();
      const payType = document.getElementById('assign-paytype')?.value || 'cod';
      const isPaidOrder = (fin==='paid');
      const isCodOrder  = (fin==='pending'||fin==='partially_paid');
      // Payment-type gate: COD-only, Paid-only, or both
      if(payType==='cod'  && !isCodOrder)  return;
      if(payType==='paid' && !isPaidOrder) return;
      if(payType==='both' && !isCodOrder && !isPaidOrder) return;
      if(['Done','Cancel','Dispatched','Returned'].includes(o.status)) return;
      const tags=String(o.tags||""),fulStatus=String(o.fulfillmentStatus||"").toLowerCase();
      let matched=false;
      if(tags)tags.split(',').forEach(t=>{const ct=t.trim();if(ct)allTagsSet.add(ct);});
      let isMedium=tags.includes("Medium Risk"),isLow=tags.includes("Low Risk"),isHigh=tags.includes("High Risk"),isRed=tags.includes("Red Zone"),isRepeat=tags.toLowerCase().includes("repeat"),isPpcod=tags.toLowerCase().includes("ppcod"),isOnHold=tags.toLowerCase().includes("on hold")||tags.toLowerCase().includes("onhold")||fulStatus.includes("hold");
      if(isMedium){stats["Medium Risk"]++;matched=true;}if(isLow){stats["Low Risk"]++;matched=true;}if(isHigh){stats["High Risk"]++;matched=true;}if(isRed){stats["Red Zone"]++;matched=true;}if(isRepeat){stats["Repeat Customer"]++;matched=true;}if(isPpcod){stats["PPCOD"]++;matched=true;}if(isOnHold){stats["On Hold"]++;matched=true;}if(!matched){stats["Others"]++;}
      assignableTotal++;
    });
    const trBox=document.getElementById('assign-total-received');if(trBox)trBox.innerText=totalReceived;
    const paidBox=document.getElementById('assign-paid');if(paidBox)paidBox.innerText=paidOrders;
    const codBox=document.getElementById('assign-cod');if(codBox)codBox.innerText=codOrders;
    document.getElementById('assign-total').innerText=assignableTotal;
    const tagContainer=document.getElementById('tag-checkboxes'); tagContainer.innerHTML='';
    for(const [tag,count] of Object.entries(stats)){if(count>0)tagContainer.innerHTML+=`<label class="flex items-center gap-3 p-3 border border-slate-200 rounded-lg cursor-pointer hover:bg-slate-50 transition"><input type="checkbox" value="${tag}" class="card-checkbox tag-cb" data-count="${count}" onchange="updateAssignLimit()"><div class="flex-1"><div class="font-bold text-slate-700">${tag}</div></div><span class="bg-blue-100 text-blue-800 text-xs font-bold px-2 py-1 rounded-full">${count}</span></label>`;}
    const loadContainer=document.getElementById('assign-current-load'); loadContainer.innerHTML='';
    for(const [agent,count] of Object.entries(agentLoads))loadContainer.innerHTML+=`<div class="bg-slate-100 px-3 py-2 rounded border border-slate-200"><span class="font-bold">${agent}:</span> <span class="text-blue-600 font-bold">${count}</span></div>`;
    document.getElementById('assign-step-2').classList.remove('hidden');
    btn.innerHTML=origText; btn.disabled=false;
    if(assignableTotal===0) showToast("✅ All orders are assigned — no unassigned orders in this date range.","success");
    else showToast(`Found ${assignableTotal} unassigned orders`,"success");
  },50);
}

function updateAssignLimit() {
  let sum=0; document.querySelectorAll('.tag-cb:checked').forEach(cb=>{sum+=parseInt(cb.getAttribute('data-count')||0);});
  const limitEl=document.getElementById('assign-limit'); if(limitEl) limitEl.value=sum>0?sum:'';
  const selEl=document.getElementById('assign-selected'); if(selEl) selEl.innerText=sum;
}

async function submitAssignment() {
  const vendor=document.getElementById('assign-vendor').value;
  const sDate=document.getElementById('assign-start').value;
  const eDate=document.getElementById('assign-end').value;
  let limitVal=document.getElementById('assign-limit').value;
  const limit=(limitVal&&limitVal.trim()!=='')?parseInt(limitVal,10):999999;
  const agentName=document.getElementById('assign-agent').value;
  const selectedTags=Array.from(document.querySelectorAll('.tag-cb:checked')).map(cb=>cb.value);
  if(!vendor){showToast("Please select a Vendor","error");return;}
  if(!agentName || agentName.toLowerCase()==='all' || agentName.toLowerCase()==='all agents'){
    showToast("Please select a specific agent — not 'All'","error"); return;
  }
  if(selectedTags.length===0){showToast("Please select at least one category","error");return;}

  const btn=document.querySelector('button[onclick="submitAssignment()"]');
  const origText=btn.innerHTML; btn.innerHTML='<i class="fas fa-spinner fa-spin"></i> Assigning...'; btn.disabled=true;

  let candidates=[];
  ALL_DATA.forEach(o=>{
    if(vendor&&o.vendor!==vendor) return;
    if(o.agent) return;
    let dStr=extractDate(o.assignDate||o.createdAt);
    if(!dStr||dStr<sDate||dStr>eDate) return;
    const finStatus=String(o.financialStatus||"").toLowerCase();
    const payTypeA = document.getElementById('assign-paytype')?.value || 'cod';
    const isPaidA = (finStatus==='paid');
    const isCodA  = (finStatus==='pending'||finStatus==='partially_paid');
    if(payTypeA==='cod'  && !isCodA)  return;
    if(payTypeA==='paid' && !isPaidA) return;
    if(payTypeA==='both' && !isCodA && !isPaidA) return;
    if(['Done','Cancel','Dispatched','Returned'].includes(o.status)) return;
    const tags=String(o.tags||""),fulStatus=String(o.fulfillmentStatus||"").toLowerCase();
    let shouldAssign=false;
    let isMedium=tags.includes("Medium Risk"),isLow=tags.includes("Low Risk"),isHigh=tags.includes("High Risk"),isRed=tags.includes("Red Zone"),isRepeat=tags.toLowerCase().includes("repeat"),isPpcod=tags.toLowerCase().includes("ppcod"),isOnHold=tags.toLowerCase().includes("on hold")||tags.toLowerCase().includes("onhold")||fulStatus.includes("hold");
    let isOthers=!isMedium&&!isLow&&!isHigh&&!isRed&&!isRepeat&&!isPpcod&&!isOnHold;
    if(selectedTags.includes("Medium Risk")&&isMedium)shouldAssign=true;if(selectedTags.includes("Low Risk")&&isLow)shouldAssign=true;if(selectedTags.includes("High Risk")&&isHigh)shouldAssign=true;if(selectedTags.includes("Red Zone")&&isRed)shouldAssign=true;if(selectedTags.includes("Repeat Customer")&&isRepeat)shouldAssign=true;if(selectedTags.includes("PPCOD")&&isPpcod)shouldAssign=true;if(selectedTags.includes("On Hold")&&isOnHold)shouldAssign=true;if(selectedTags.includes("Others")&&isOthers)shouldAssign=true;
    if(shouldAssign) candidates.push(o.orderId);
  });
  const finalIds=candidates.slice(0,limit);
  if(finalIds.length===0){btn.innerHTML=origText;btn.disabled=false;showToast("No orders found to assign","error");return;}

  showToast(`Assigning ${finalIds.length} orders...`,"info");
  const res=await apiCall('assign_agents',{orderIds:finalIds,agentName});
  btn.innerHTML=origText; btn.disabled=false;
  if(res?.status==='success'){
    showToast(`Successfully assigned ${finalIds.length} orders to ${agentName}`,"success");
    const nowIso=new Date().toISOString();
    finalIds.forEach(id=>{const idx=ALL_DATA.findIndex(x=>x.orderId==id);if(idx>-1){ALL_DATA[idx].agent=agentName;ALL_DATA[idx].assignDate=nowIso;if(!ALL_DATA[idx].status||ALL_DATA[idx].status==='')ALL_DATA[idx].status='Pending';}});
    updateLoadSummary(); loadUnassigned(); renderAgentView();
  } else { showToast("Assignment failed — please retry","error"); }
}

function pullBackPending() {
  const vendor=document.getElementById('assign-vendor').value;
  const sDate=document.getElementById('assign-start').value;
  const eDate=document.getElementById('assign-end').value;
  if(!vendor){showToast("Please select a Vendor first","error");return;}
  if(!sDate||!eDate){showToast("Please select Start and End dates","error");return;}
  document.getElementById('pull-back-date').value=new Date().toISOString().split('T')[0];
  document.getElementById('pullBackModal').classList.remove('hidden');
}
function closePullBackModal() { document.getElementById('pullBackModal').classList.add('hidden'); }

async function executePullBack() {
  const vendor=document.getElementById('assign-vendor').value;
  const agentName=document.getElementById('pull-back-agent').value;
  const assignDate=document.getElementById('pull-back-date').value;
  if(!agentName){showToast("Please select an Agent","error");return;}
  if(!assignDate){showToast("Please select an Assigned Date","error");return;}
  const btn=document.getElementById('btn-confirm-pullback');
  const origText=btn.innerHTML; btn.innerHTML='<i class="fas fa-spinner fa-spin"></i> Processing...'; btn.disabled=true;

  let pullbackIds=[];
  ALL_DATA.forEach(o=>{
    if(vendor&&o.vendor!==vendor) return;
    if(!o.agent) return;
    if(agentName!=='All'&&o.agent!==agentName) return;
    if(extractDate(o.assignDate)!==assignDate) return;
    if(o.status==='Pending'||o.status==='') pullbackIds.push(o.orderId);
  });

  if(pullbackIds.length===0){btn.innerHTML=origText;btn.disabled=false;closePullBackModal();showCustomAlert("Notice","No pending orders found for this Agent and Date.",false);return;}

  const res=await apiCall('pull_back',{orderIds:pullbackIds});
  btn.innerHTML=origText; btn.disabled=false; closePullBackModal();
  if(res?.status==='success'){
    showCustomAlert("Success",`Successfully pulled back ${pullbackIds.length} pending orders!`,true);
    pullbackIds.forEach(id=>{const idx=ALL_DATA.findIndex(x=>String(x.orderId).replace(/#/g,'')===String(id).replace(/#/g,''));if(idx>-1){const old=ALL_DATA[idx].agent;ALL_DATA[idx].agent='';ALL_DATA[idx].agentRemark='Pulled back from '+old;ALL_DATA[idx].assignDate='';}});
    loadUnassigned(); renderAgentView();
  } else { showCustomAlert("Error","Pull back failed — please retry.",false); }
}

function updateLoadSummary() {
  const step2=document.getElementById('assign-step-2'); if(step2) step2.classList.add('hidden');
  document.getElementById('assign-total').innerText='0';
  document.getElementById('tag-checkboxes').innerHTML='';
  document.getElementById('assign-current-load').innerHTML='';
}

// ============================================================
// SCAN / DISPATCH
// ============================================================
const scanInput = document.getElementById('scanInput');
const scanCourierSelect = document.getElementById('scanCourier');
if (scanCourierSelect) scanCourierSelect.addEventListener('change', function(){if(this.value&&scanInput)scanInput.focus();});
if (scanInput) {
  scanInput.addEventListener('keydown', function(e){
    if(e.key==='Enter'){e.preventDefault();addToStaged();}
  });
}

function addToStaged() {
  const actionEl  = document.getElementById('scanAction');
  const courierEl = document.getElementById('scanCourier');
  const inputEl   = document.getElementById('scanInput');
  const action    = actionEl  ? (actionEl.value  || 'Dispatched') : 'Dispatched';
  const courier   = courierEl ? courierEl.value : '';
  const barcode   = inputEl   ? inputEl.value.trim().toUpperCase().replace(/#/g,'') : '';
  if(!courier && action==='Dispatched'){showToast("Please select a courier first","error");playBeep('error');return;}
  if(!barcode){showToast("Please enter a barcode or order ID","error");playBeep('error');return;}
  // Check if already in staged list
  const inStaged = STAGED_SCANS.some(s=>String(s.orderId||s.displayId||'').replace(/#/g,'').toUpperCase()===barcode);
  if(inStaged){showToast("⚠ Already in staged list: #"+barcode,"error");playBeep('error');if(inputEl)inputEl.value='';return;}
  // Check if already submitted/dispatched today (in scan history)
  const prevScan=SCAN_HISTORY_DATA.find(s=>String(s.orderId||'').replace(/#/g,'').toUpperCase()===barcode);
  if(prevScan){
    const prevStatus=prevScan.dispatchStatus||'Dispatched';
    const allowRescan=(prevStatus==='Dispatched')&&(action==='Returned'||action==='Cancelled');
    if(!allowRescan){showToast(`⚠ Already scanned! #${barcode} — ${prevStatus} via ${prevScan.courierName||''} on ${prevScan.scanTimestamp?extractDate(prevScan.scanTimestamp):''}`,"error");playBeep('error');if(inputEl)inputEl.value='';return;}
  }
  const order=ALL_DATA.find(o=>String(o.orderId||'').replace(/#/g,'').toUpperCase()===barcode||String(o.awb||'').toUpperCase()===barcode||String(o.longId||'').replace(/#/g,'').toUpperCase()===barcode);
  const entry={orderId:barcode,displayId:barcode,courier,action,billingName:order?order.billingName:'Unknown',found:!!order,ts:new Date().toISOString()};
  STAGED_SCANS.push(entry); localStorage.setItem('oms_staged_scans',JSON.stringify(STAGED_SCANS));
  renderStagedScans(); playBeep('success'); if(inputEl)inputEl.value=''; if(inputEl)inputEl.focus();
}

function renderStagedScans() {
  const container=document.getElementById('staged-scan-list'); if(!container) return;
  
  // ── Live counter ──
  const lc = document.getElementById('scan-live-counter');
  if (lc) {
    if (STAGED_SCANS.length > 0) {
      const found    = STAGED_SCANS.filter(s=>s.found).length;
      const notFound = STAGED_SCANS.length - found;
      const byAction = {};
      STAGED_SCANS.forEach(s=>{ const a=s.action||'Dispatch'; byAction[a]=(byAction[a]||0)+1; });
      const actionBadges = Object.entries(byAction).map(([a,n])=>
        `<span style="background:#eef2ff;color:#3730a3;padding:3px 10px;border-radius:99px;font-size:11px;font-weight:700">${a}: ${n}</span>`
      ).join('');
      lc.style.display='flex';
      lc.innerHTML=`
        <span style="font-size:22px;font-weight:900;color:#15803d">${STAGED_SCANS.length}</span>
        <span style="font-size:12px;color:#64748b;font-weight:600">orders staged</span>
        <span style="width:1px;height:18px;background:#d1fae5"></span>
        <span style="font-size:12px;color:#10b981;font-weight:700">✓ ${found} found</span>
        ${notFound>0?`<span style="font-size:12px;color:#f59e0b;font-weight:700">⚠ ${notFound} unknown</span>`:''}
        <span style="width:1px;height:18px;background:#d1fae5"></span>
        ${actionBadges}`;
    } else {
      lc.style.display='none';
    }
  }
  // ── Update count badge on submit button ──
  const badge=document.getElementById('staged-count-badge');
  if(badge){if(STAGED_SCANS.length>0){badge.style.display='inline-flex';badge.textContent=STAGED_SCANS.length+(STAGED_SCANS.length===1?' order':' orders')+' staged';}else{badge.style.display='none';}}

  if(STAGED_SCANS.length===0){container.innerHTML='<div class="text-center text-slate-400 py-6 text-sm"><i class="fas fa-barcode text-3xl mb-2"></i><p>No scans staged yet</p></div>';return;}
  const actionColors={Dispatched:'green',Returned:'orange',Cancelled:'red'};
  container.innerHTML=STAGED_SCANS.map((s,i)=>{
    const ac=actionColors[s.action||'Dispatched']||'green';
    const bg=s.found?ac:'amber';
    return `<div style="display:flex;align-items:center;gap:10px;padding:10px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:10px">
      <i class="fas fa-${s.found?'check-circle':'exclamation-triangle'}" style="color:${s.found?'#10b981':'#f59e0b'}"></i>
      <div style="flex:1">
        <div style="font-weight:700;color:#374151;font-size:13px">${s.displayId||s.orderId}</div>
        <div style="font-size:11px;color:#64748b">${s.billingName} • ${s.courier||'No courier'} • <b style="color:#16a34a">${s.action||'Dispatch'}</b></div>
      </div>
      <button onclick="removeStagedScan('${s.orderId||s.displayId}')" style="color:#ef4444;background:none;border:none;cursor:pointer;padding:4px"><i class="fas fa-times"></i></button>
    </div>`;
  }).join('');
}

function removeStagedScan(orderId) {
  const cleanTarget=String(orderId).replace(/#/g,'').trim();
  STAGED_SCANS=STAGED_SCANS.filter(s=>String(s.displayId||s.orderId||'').replace(/#/g,'').trim()!==cleanTarget);
  localStorage.setItem('oms_staged_scans',JSON.stringify(STAGED_SCANS)); renderStagedScans();
}

async function processStagedScans() {
  if(STAGED_SCANS.length===0){showToast("No scans staged","error");return;}
  const total = STAGED_SCANS.length;
  showToast(`Dispatching ${total} orders...`,"info");
  let successCount=0;
  const CHUNK=200; // send up to 200 scans per request
  const ts=new Date().toISOString();
  for(let i=0;i<STAGED_SCANS.length;i+=CHUNK){
    const chunk=STAGED_SCANS.slice(i,i+CHUNK);
    const scans=chunk.map(scan=>({
      barcode: scan.orderId||scan.displayId,
      courierName: scan.courier,
      dispatchStatus: scan.action||'Dispatched',
      awb: scan.awb||''
    }));
    try {
      const res=await apiCall('barcode_scan_batch',{scans});
      if(res?.status==='success'){
        successCount += res.count || chunk.length;
        // Update local state for each scanned order
        chunk.forEach(scan=>{
          const key=String(scan.orderId||scan.displayId).replace(/#/g,'').trim();
          SCAN_TIMESTAMPS[key]=ts;
          const newStatus = (scan.action==='Returned'?'Returned':scan.action==='Cancelled'?'Cancelled':'Dispatched');
          const idx=ALL_DATA.findIndex(o=>String(o.orderId||'').replace(/#/g,'').toUpperCase()===key.toUpperCase());
          if(idx>-1){ALL_DATA[idx].dispatchStatus=newStatus;ALL_DATA[idx].scanTimestamp=ts;ALL_DATA[idx].courierName=scan.courier;}
          // Keep SCAN_HISTORY_DATA in sync so the summary/history show the correct status right away.
          // The scanning table is unique per order, so replace any existing row for this order.
          const keyU = key.toUpperCase();
          const sIdx = SCAN_HISTORY_DATA.findIndex(s=>String(s.orderId||'').replace(/#/g,'').toUpperCase()===keyU);
          const histRow = {orderId:key, billingName:(scan.billingName||(idx>-1?ALL_DATA[idx].billingName:'Unknown')),
                           dispatchStatus:newStatus, courierName:scan.courier, awb:scan.awb||'', scanTimestamp:ts};
          if(sIdx>-1) SCAN_HISTORY_DATA[sIdx]=histRow; else SCAN_HISTORY_DATA.push(histRow);
        });
      }
    } catch(e){ console.warn('Batch scan failed for chunk', i, e); }
    if (total > CHUNK) showToast(`Dispatched ${successCount} of ${total}...`,'info');
  }
  localStorage.setItem('oms_scan_timestamps',JSON.stringify(SCAN_TIMESTAMPS));
  playBeep('success');
  showToast(`Dispatched ${successCount} of ${total} orders`,'success');
  STAGED_SCANS=[]; localStorage.setItem('oms_staged_scans','[]');
  renderStagedScans(); renderScanSummary(); renderScanHistory();
}

function renderScanView() { renderStagedScans(); }

function normalizeCourier(name){
  if(!name)return'Others';const n=name.toLowerCase();
  if(n.includes('xpress'))return'Xpressbees';
  if(n.includes('shadow'))return'Shadowfax';
  if(n.includes('ekart'))return'Ekart';
  if(n.includes('amazon'))return'Amazon';
  if(n.includes('blue')||n.includes('dart'))return'Bluedart';
  if(n.includes('delhivery')||n.includes('delivery'))return'Delhivery';
  if(n.includes('dtdc'))return'DTDC';
  if(n.includes('ecom'))return'Ecom Express';
  if(n.includes('ship')||n.includes('rocket'))return'ShipRocket';
  return'Others';
}

// Collapse scan rows to the LATEST one per order (by timestamp). The scan team may scan the same
// order more than once (e.g. Dispatched then later Returned); the most recent scan is the truth.
function latestScansPerOrder(rows) {
  const byOrder = {};
  (rows||[]).forEach(s => {
    const k = String(s.orderId||'').replace(/#/g,'').trim().toUpperCase();
    if (!k) return;
    const prev = byOrder[k];
    if (!prev || String(s.scanTimestamp||'') >= String(prev.scanTimestamp||'')) byOrder[k] = s;
  });
  return Object.values(byOrder);
}

function renderScanSummary() {
  const sDate=document.getElementById('scan-sum-start')?.value;
  const eDate=document.getElementById('scan-sum-end')?.value;
  const cards=document.getElementById('scan-summary-cards'); if(!cards) return;

  const COURIERS=['Xpressbees','Shadowfax','Ekart','Bluedart','Delhivery','DTDC','Ecom Express','Amazon','ShipRocket','Others'];
  const cs={}; COURIERS.forEach(c=>{cs[c]={assigned:0,scanning:0,dispatched:0,cancelled:0,returned:0};});

  latestScansPerOrder(SCAN_HISTORY_DATA).forEach(s=>{
    const ts=s.scanTimestamp||'';
    if(sDate&&eDate){const d=extractDate(ts);if(!d||d<sDate||d>eDate)return;}
    const cn=normalizeCourier(s.courierName||'');
    if(!cs[cn])cs[cn]={assigned:0,scanning:0,dispatched:0,cancelled:0,returned:0};
    cs[cn].scanning++;
    if(s.dispatchStatus==='Dispatched')cs[cn].dispatched++;
    else if(s.dispatchStatus==='Cancelled')cs[cn].cancelled++;
    else if(s.dispatchStatus==='Returned')cs[cn].returned++;
  });

  ALL_DATA.forEach(o=>{
    if(!o.courierName)return;
    const cn=normalizeCourier(o.courierName);
    if(!cs[cn])cs[cn]={assigned:0,scanning:0,dispatched:0,cancelled:0,returned:0};
    cs[cn].assigned++;
  });

  const tot={assigned:0,scanning:0,dispatched:0,cancelled:0,returned:0};
  Object.values(cs).forEach(r=>{tot.assigned+=r.assigned;tot.scanning+=r.scanning;tot.dispatched+=r.dispatched;tot.cancelled+=r.cancelled;tot.returned+=r.returned;});

  const kpi=(label,val,bg,color,icon)=>`<div class="card p-4" style="display:flex;align-items:center;gap:12px"><div style="width:44px;height:44px;border-radius:12px;background:${bg};color:${color};display:flex;align-items:center;justify-content:center;font-size:20px;flex-shrink:0"><i class="fas fa-${icon}"></i></div><div><div style="font-size:30px;font-weight:900;color:${color};line-height:1">${val}</div><div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#94a3b8;margin-top:4px">${label}</div></div></div>`;

  const rows=Object.entries(cs).filter(([,r])=>r.assigned>0||r.scanning>0||r.dispatched>0).map(([name,r])=>`<tr>
    <td style="padding:7px 14px;font-weight:600;color:#374151;font-size:13px">${name}</td>
    <td style="padding:7px 14px;text-align:center;font-weight:700;color:#a16207;font-size:13px">${r.scanning}</td>
    <td style="padding:7px 14px;text-align:center;font-weight:700;color:#15803d;font-size:13px">${r.dispatched}</td>
    <td style="padding:7px 14px;text-align:center;font-weight:700;color:#b91c1c;font-size:13px">${r.cancelled}</td>
    <td style="padding:7px 14px;text-align:center;font-weight:700;color:#c2410c;font-size:13px">${r.returned}</td>
  </tr>`).join('');

  cards.innerHTML=
    kpi('Total Scanned',tot.scanning,'#f8fafc','#64748b','barcode')+
    kpi('Dispatched',tot.dispatched,'#f0fdf4','#10b981','truck')+
    kpi('Returned',tot.returned,'#fff7ed','#f97316','rotate-left')+
    kpi('Cancelled',tot.cancelled,'#fef2f2','#ef4444','times-circle')+
    `<div class="card" style="grid-column:1/-1;overflow:hidden;margin-top:4px">
      <div style="padding:14px 20px;border-bottom:1px solid #f1f5f9;display:flex;align-items:center;gap:8px">
        <i class="fas fa-table-cells" style="color:#16a34a"></i>
        <span style="font-weight:700;color:#1e293b;font-size:14px">Courier-wise Dispatch Summary</span>
        <span style="font-size:11px;color:#94a3b8;margin-left:auto">${sDate||'All'} ${eDate?'→ '+eDate:''}</span>
      </div>
      <div style="overflow-x:auto">
        <table style="width:100%;border-collapse:collapse">
          <thead>
            <tr style="background:#f8fafc">
              <th style="padding:10px 16px;text-align:left;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#64748b;border-bottom:1px solid #e2e8f0">Courier Partner</th>
              
              <th style="padding:10px 16px;text-align:center;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;background:#fef9c3;color:#a16207;border-bottom:1px solid #e2e8f0">Scan Data</th>
              <th style="padding:10px 16px;text-align:center;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;background:#dcfce7;color:#15803d;border-bottom:1px solid #e2e8f0">Dispatched</th>
              <th style="padding:10px 16px;text-align:center;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;background:#fee2e2;color:#b91c1c;border-bottom:1px solid #e2e8f0">Cancelled</th>
              <th style="padding:10px 16px;text-align:center;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;background:#ffedd5;color:#c2410c;border-bottom:1px solid #e2e8f0">Return</th>
            </tr>
          </thead>
          <tbody>${rows}
            <tr style="background:#f8fafc;border-top:2px solid #e2e8f0">
              <td style="padding:12px 16px;font-weight:800;color:#1e293b;font-size:13px">Total Order</td>
              <td style="padding:12px 16px;text-align:center;font-weight:800;color:#a16207;font-size:15px">${tot.scanning}</td>
              <td style="padding:12px 16px;text-align:center;font-weight:800;color:#15803d;font-size:15px">${tot.dispatched}</td>
              <td style="padding:12px 16px;text-align:center;font-weight:800;color:#b91c1c;font-size:15px">${tot.cancelled}</td>
              <td style="padding:12px 16px;text-align:center;font-weight:800;color:#c2410c;font-size:15px">${tot.returned}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>`;
}

// Fetch scan history for a date range from the DB on demand (older than the 60 days loaded at start),
// merge it into SCAN_HISTORY_DATA, then re-render the summary + history table.
let _scanRangeLoaded = '';
async function loadScanHistoryRange(sDate, eDate) {
  const key = (sDate||'')+'|'+(eDate||'');
  if (!sDate || !eDate || key === _scanRangeLoaded) return;
  _scanRangeLoaded = key;
  try {
    const res = await apiCall('scan_history', { start: sDate, end: eDate });
    if (res && res.status==='success' && Array.isArray(res.data)) {
      // Merge: replace SCAN_HISTORY_DATA rows in this range with the freshly fetched set, keep others.
      const inRange = s => { const d=extractDate(s.scanTimestamp||''); return d && d>=sDate && d<=eDate; };
      const kept = SCAN_HISTORY_DATA.filter(s => !inRange(s));
      SCAN_HISTORY_DATA = kept.concat(res.data);
      renderScanSummary();
      renderScanHistory();
    }
  } catch(e) { console.warn('scan_history fetch failed', e); }
}

function renderScanHistory() {
  const sDate=document.getElementById('scan-hist-start')?.value;
  const eDate=document.getElementById('scan-hist-end')?.value;
  const courier=(document.getElementById('scan-hist-courier')?.value||'').trim();
  const status=(document.getElementById('scan-hist-status')?.value||'').trim();
  const perpage=parseInt(document.getElementById('scan-hist-perpage')?.value||'50');
  const search=(document.getElementById('scan-hist-search')?.value||'').toLowerCase().trim();
  scanHistLimit=perpage;
  const tbody=document.getElementById('scan-history-body'); if(!tbody) return;
  let filtered=latestScansPerOrder(SCAN_HISTORY_DATA).sort((a,b)=>(b.scanTimestamp||'').localeCompare(a.scanTimestamp||'')).filter(s=>{
    if(sDate&&eDate){const d=extractDate(s.scanTimestamp||'');if(!d||d<sDate||d>eDate)return false;}
    if(courier&&courier!=='All Couriers'&&(s.courierName||'').toLowerCase()!==courier.toLowerCase())return false;
    if(status&&status!=='All Status'&&(s.dispatchStatus||'Dispatched')!==status)return false;
    if(search){const hay=(s.orderId||'')+' '+(s.billingName||'');if(!hay.toLowerCase().includes(search))return false;}
    return true;
  });
  const cntBox=document.getElementById('scan-hist-counts');
  if(cntBox){
    const total=filtered.length,disp=filtered.filter(s=>(s.dispatchStatus||'Dispatched')==='Dispatched').length,ret=filtered.filter(s=>(s.dispatchStatus||'')==='Returned').length,canc=filtered.filter(s=>(s.dispatchStatus||'')==='Cancelled').length;
    const card=(val,label,color,bg,border)=>`<div style="background:${bg};border:1px solid ${border};border-radius:12px;padding:14px 18px;text-align:center"><div style="font-size:26px;font-weight:900;color:${color};line-height:1">${val.toLocaleString()}</div><div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#64748b;margin-top:4px">${label}</div></div>`;
    cntBox.innerHTML=card(total,'Total Scans','#1e293b','#fff','#e2e8f0')+card(disp,'Dispatched','#15803d','#f0fdf4','#bbf7d0')+card(ret,'Returned','#c2410c','#fff7ed','#fed7aa')+card(canc,'Cancelled','#b91c1c','#fef2f2','#fecaca');
  }
  const totalPages=Math.ceil(filtered.length/scanHistLimit);
  if(scanHistPage>totalPages) scanHistPage=1;
  const start=(scanHistPage-1)*scanHistLimit;
  const page=filtered.slice(start,start+scanHistLimit);
  const stBadge = (st) => {
    const mp = {Dispatched:'#dcfce7|#15803d|#bbf7d0', Returned:'#ffedd5|#c2410c|#fed7aa', Cancelled:'#fee2e2|#b91c1c|#fecaca'};
    const [bg,col,bd] = (mp[st]||'#f1f5f9|#475569|#cbd5e1').split('|');
    return `<span style="background:${bg};color:${col};border:1px solid ${bd};padding:2px 10px;border-radius:99px;font-size:10px;font-weight:700;text-transform:uppercase">${st}</span>`;
  };
  tbody.innerHTML=page.map(s=>`<tr style="border-bottom:1px solid #f8fafc;transition:background 0.15s" onmouseover="this.style.background='#f8fafc'" onmouseout="this.style.background=''">
    <td style="padding:10px 14px;font-size:11px;font-family:monospace;color:#94a3b8">${s.scanTimestamp||'-'}</td>
    <td style="padding:10px 14px;font-weight:700;color:#1e293b;font-size:13px">#${s.orderId}</td>
    <td style="padding:10px 14px;font-size:13px;color:#475569">${s.billingName||'-'}</td>
    <td style="padding:10px 14px;font-size:13px;color:#475569">${s.courierName||'-'}</td>
    <td style="padding:10px 14px">${stBadge(s.dispatchStatus||'Dispatched')}</td>
    ${IS_ADMIN ? `<td style="padding:10px 14px;text-align:right">
      <button onclick="deleteScanRecord('${s.orderId}')" title="Delete scan record"
        style="background:#fef2f2;color:#ef4444;border:1px solid #fecaca;padding:4px 10px;border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;gap:4px;transition:all 0.15s"
        onmouseover="this.style.background='#fee2e2'" onmouseout="this.style.background='#fef2f2'">
        <i class="fas fa-trash-alt"></i> Delete
      </button>
    </td>` : '<td></td>'}
  </tr>`).join('');
  const pag=document.getElementById('scan-hist-pagination'); if(pag)pag.innerHTML=totalPages>1?`<span class="text-sm text-slate-500">${filtered.length} records</span><div class="flex gap-2"><button onclick="changeScanHistPage(${scanHistPage-1})" ${scanHistPage===1?'disabled':''} class="page-btn"><i class="fas fa-chevron-left"></i></button><span class="text-sm text-slate-600 font-bold">Page ${scanHistPage} of ${totalPages||1}</span><button onclick="changeScanHistPage(${scanHistPage+1})" ${scanHistPage===totalPages||totalPages===0?'disabled':''} class="page-btn"><i class="fas fa-chevron-right"></i></button></div>`:'';
}

function changeScanHistPage(p){scanHistPage=p;renderScanHistory();}

function downloadScanHistoryExcel() {
  const sDate  = document.getElementById('scan-hist-start')?.value;
  const eDate  = document.getElementById('scan-hist-end')?.value;
  const courier= document.getElementById('scan-hist-courier')?.value||'';
  const status = document.getElementById('scan-hist-status')?.value||'';
  let data = SCAN_HISTORY_DATA.filter(s=>{
    if(sDate&&eDate){const d=extractDate(s.scanTimestamp||'');if(!d||d<sDate||d>eDate)return false;}
    if(courier && normalizeCourier(s.courierName||'')!==courier) return false;
    if(status  && s.dispatchStatus!==status) return false;
    return true;
  });
  if(!data.length){showToast('No data to export','error');return;}
  const headers=['Timestamp','Order ID','Customer','Phone','Courier','AWB','Status'];
  const rows=data.map(s=>[s.scanTimestamp||'',s.orderId||'',s.billingName||'',s.billingPhone||'',s.courierName||'',s.awb||'',s.dispatchStatus||'']);
  const csv=[headers,...rows].map(r=>r.map(c=>'"'+String(c||'').replace(/"/g,'""')+'"').join(',')).join('\n');
  const blob=new Blob([csv],{type:'text/csv;charset=utf-8;'});
  const link=document.createElement('a');link.href=URL.createObjectURL(blob);
  link.download='ScanHistory_'+(sDate||'all')+'_'+(eDate||'all')+'.csv';
  document.body.appendChild(link);link.click();document.body.removeChild(link);
  showToast('Scan History exported!','success');
}

function downloadScanHistoryExcel() {
  const sDate  = document.getElementById('scan-hist-start')?.value;
  const eDate  = document.getElementById('scan-hist-end')?.value;
  const courier= document.getElementById('scan-hist-courier')?.value||'';
  const status = document.getElementById('scan-hist-status')?.value||'';
  let data = SCAN_HISTORY_DATA.filter(s=>{
    if(sDate&&eDate){const d=extractDate(s.scanTimestamp||'');if(!d||d<sDate||d>eDate)return false;}
    if(courier && normalizeCourier(s.courierName||'')!==courier) return false;
    if(status  && s.dispatchStatus!==status) return false;
    return true;
  });
  if(!data.length){showToast('No data to export','error');return;}
  const headers=['Timestamp','Order ID','Customer','Phone','Courier','AWB','Status'];
  const rows=data.map(s=>[
    s.scanTimestamp||'',
    s.orderId||'',
    s.billingName||'',
    s.billingPhone||'',
    s.courierName||'',
    s.awb||'',
    s.dispatchStatus||''
  ]);
  const csv=[headers,...rows].map(r=>r.map(c=>'"'+String(c||'').replace(/"/g,'""')+'"').join(',')).join('\n');
  const blob=new Blob([csv],{type:'text/csv;charset=utf-8;'});
  const link=document.createElement('a');
  link.href=URL.createObjectURL(blob);
  link.download='ScanHistory_'+(sDate||'all')+'_to_'+(eDate||'all')+'.csv';
  document.body.appendChild(link);link.click();document.body.removeChild(link);
  showToast('Scan History exported!','success');
}

async function deleteScanRecord(orderId) {
  if (!IS_ADMIN && !IS_MANAGER) { showToast("Admin access required", "error"); return; }
  if (!confirm('Delete scan record for order #' + orderId + '? This cannot be undone.')) return;
  showToast("Deleting...", "info");
  const res = await apiCall('delete_scan', { orderId });
  if (res?.status === 'success') {
    showToast("Scan record deleted", "success");
    // Remove from local scan history
    SCAN_HISTORY_DATA = SCAN_HISTORY_DATA.filter(s => s.orderId !== orderId);
    renderScanHistory();
    renderScanSummary();
  } else {
    showToast("Delete failed — please retry", "error");
  }
}

function switchScanTab(tab) {
  const stage=document.getElementById('scan-stage-container'), hist=document.getElementById('scan-history-container');
  const btnS=document.getElementById('subtab-stage'), btnH=document.getElementById('subtab-history');
  if(tab==='stage'){
    stage.classList.remove('hidden'); stage.classList.add('flex');
    hist.classList.add('hidden'); hist.classList.remove('flex');
    btnS.className='px-5 py-2.5 text-sm font-semibold border-b-2 transition';btnS.style.cssText='border-color:#16a34a;color:#16a34a';
    btnH.className='px-5 py-2.5 text-sm font-semibold border-b-2 border-transparent text-slate-500 transition';
    setTimeout(()=>{const i=document.getElementById('scanInput');if(i)i.focus();},10);
  } else {
    hist.classList.remove('hidden'); hist.classList.add('flex');
    stage.classList.add('hidden'); stage.classList.remove('flex');
    btnH.className='px-5 py-2.5 text-sm font-semibold border-b-2 transition';btnH.style.cssText='border-color:#16a34a;color:#16a34a';
    btnS.className='px-5 py-2.5 text-sm font-semibold border-b-2 border-transparent text-slate-500 transition';
    renderScanHistory();
  }
}

// ============================================================
// UPDATES VIEW
// ============================================================
function renderUpdatesView() {
  try {
    const tbody=document.getElementById('updates-body'); tbody.innerHTML='';
    const s=document.getElementById('upd-start').value, e=document.getElementById('upd-end').value;
    const search=document.getElementById('searchBar').value.toLowerCase();
    let filterStart=s?new Date(s+"T00:00:00"):new Date(); if(!s)filterStart.setDate(filterStart.getDate()-7); filterStart.setHours(0,0,0,0);
    let filterEnd=e?new Date(e+"T23:59:59"):new Date(); filterEnd.setHours(23,59,59,999);
    const sorted=[...ALL_DATA].sort((a,b)=>{const ap=(a.status==='Pending'||!a.status),bp=(b.status==='Pending'||!b.status);if(!ap&&bp)return -1;if(ap&&!bp)return 1;return new Date(b.lastUpdated||b.createdAt||0)-new Date(a.lastUpdated||a.createdAt||0);});
    const filtered=sorted.filter(o=>{if(!o.lastUpdated&&!o.createdAt)return false;const d=new Date(o.lastUpdated||o.createdAt);return !isNaN(d.getTime())&&d>=filterStart&&d<=filterEnd&&(!search||String(o.orderId||'').toLowerCase().includes(search)||String(o.billingPhone||'').includes(search)||String(o.billingName||'').toLowerCase().includes(search));});
    if(filtered.length===0){tbody.innerHTML=`<tr><td colspan="6" class="p-6 text-center text-slate-400">No updates found.</td></tr>`;return;}
    filtered.slice(0,100).forEach(o=>{const ts=new Date(o.lastUpdated||o.createdAt).toLocaleString();let sc="slate";if(o.status==="Done")sc="green";if(o.status==="Cancel")sc="red";if(o.status==="Pending")sc="yellow";tbody.innerHTML+=`<tr><td class="px-4 py-3 font-mono text-xs text-slate-400 whitespace-nowrap">${ts}</td><td class="px-4 py-3"><div class="font-bold text-slate-700">#${o.orderId}</div><div class="text-xs text-slate-400">${o.billingName}</div></td><td class="px-4 py-3"><div class="text-xs font-bold text-slate-700">${o.agent||"Unassigned"}</div><span class="inline-flex items-center px-2 py-0.5 rounded text-[10px] font-bold uppercase bg-${sc}-100 text-${sc}-700 mt-1">${o.status||"Pending"}</span></td><td class="px-4 py-3 remark-cell"><div class="text-xs text-slate-600">${o.agentRemark||"-"}</div></td><td class="px-4 py-3"><div class="text-xs font-bold text-slate-700">${o.dispatchStatus||"Pending"}</div><div class="text-[10px] text-slate-400 font-mono">${o.awb||""}</div></td><td class="px-4 py-3"><span class="text-xs bg-blue-50 text-blue-700 px-2 py-1 rounded border border-blue-100">${o.deliveryStatus||"Processing"}</span></td></tr>`;});
  } catch(err) {}
}

// ============================================================
// ADMIN VIEW
// ============================================================
let adminPage = 1; const adminPerPage = 100;
function renderAdminView() {
  const tbody=document.getElementById('admin-table-body');
  const af=document.getElementById('adminAgentFilter').value;
  const sf=document.getElementById('adminStatusFilter').value;
  const search=document.getElementById('searchBar').value.toLowerCase();
  tbody.innerHTML='';
  let filteredAdmin=ALL_DATA.filter(o=>{const ma=af==='All'||o.agent===af;const ms=sf==='All'||o.status===sf;const ms2=!search||String(o.orderId||'').toLowerCase().includes(search)||String(o.billingPhone||'').includes(search)||String(o.billingName||'').toLowerCase().includes(search);return ma&&ms&&ms2;});
  filteredAdmin.sort((a,b)=>{const ap=(a.status==='Pending'||!a.status),bp=(b.status==='Pending'||!b.status);if(!ap&&bp)return -1;if(ap&&!bp)return 1;return new Date(b.lastUpdated||b.createdAt||0)-new Date(a.lastUpdated||a.createdAt||0);});
  const totalPages=Math.ceil(filteredAdmin.length/adminPerPage);
  if(adminPage>totalPages) adminPage=1;
  const start=(adminPage-1)*adminPerPage;
  const pageData=filteredAdmin.slice(start, start+adminPerPage);
  const stClass={Done:'badge-done',Cancel:'badge-cancel',Pending:'badge-pending',Busy:'badge-busy',NP:'badge-np',SO:'badge-so',NI:'badge-ni'};
  pageData.forEach(o=>{
    tbody.innerHTML+=`<tr><td class="px-4 py-3 font-mono font-bold text-slate-700 text-sm">#${o.orderId}<div class="text-xs text-slate-400 font-normal">${o.createdAt?extractDate(o.createdAt):''}</div></td><td class="px-4 py-3"><div class="font-medium text-slate-700 text-sm">${o.billingName}</div><div class="text-xs text-slate-400">${o.billingPhone}</div></td><td class="px-4 py-3"><span class="badge badge-default">${o.agent||"Unassigned"}</span></td><td class="px-4 py-3"><span class="badge ${stClass[o.status]||'badge-default'}">${o.status||"Pending"}</span></td><td class="px-4 py-3 text-xs text-slate-500 max-w-[200px] truncate">${o.agentRemark||"-"}</td></tr>`;
  });
  const adminPag=document.getElementById('admin-pagination');
  if(adminPag){
    adminPag.innerHTML = totalPages>1 ?
      `<span class="text-xs text-slate-400">${filteredAdmin.length} orders</span>
       <div class="flex items-center gap-2">
         <button onclick="adminPage=Math.max(1,adminPage-1);renderAdminView()" ${adminPage===1?'disabled':''} class="page-btn"><i class="fas fa-chevron-left text-xs"></i></button>
         <span class="text-xs font-semibold text-slate-600">Page ${adminPage} of ${totalPages}</span>
         <button onclick="adminPage=Math.min(${totalPages},adminPage+1);renderAdminView()" ${adminPage===totalPages?'disabled':''} class="page-btn"><i class="fas fa-chevron-right text-xs"></i></button>
       </div>` : `<span class="text-xs text-slate-400">${filteredAdmin.length} orders</span>`;
  }
}

// ============================================================
// ANALYTICS
// ============================================================
let statusChartInstance = null;

function renderAnalyticsView() {
  const anStart = document.getElementById('an-start')?.value;
  const anEnd   = document.getElementById('an-end')?.value;
  const anAgent = document.getElementById('an-agent-filter')?.value || 'All';

  // Filter data by date if set
  let data = ALL_DATA;
  if (anStart && anEnd) {
    data = ALL_DATA.filter(o => {
      const d = extractDate(o.createdAt || '');
      return d && d >= anStart && d <= anEnd;
    });
  }
  // Agent-wise filter — narrows every KPI, chart and table below to one agent
  if (anAgent && anAgent !== 'All') {
    data = data.filter(o => (o.agent || '') === anAgent);
  }

  const total       = data.length;
  const totalDone   = data.filter(x=>x.status==='Done').length;
  const totalCancel = data.filter(x=>x.status==='Cancel').length;
  const totalPending= data.filter(x=>!x.status||x.status==='Pending').length;
  const totalBusy   = data.filter(x=>x.status==='Busy').length;
  const totalNP     = data.filter(x=>x.status==='NP').length;
  const dispatched  = data.filter(x=>x.dispatchStatus==='Dispatched').length;
  const pendingDispatch = Math.max(0, totalDone - dispatched);
  const conversion  = total > 0 ? ((totalDone/total)*100).toFixed(1) : 0;
  const cancelRate  = total > 0 ? ((totalCancel/total)*100).toFixed(1) : 0;
  const unassigned  = data.filter(x=>!x.agent).length;

  // KPI cards
  document.getElementById('an-conf').innerText      = totalDone.toLocaleString();
  document.getElementById('an-conf-sub').innerText  = `${conversion}% of ${total.toLocaleString()} total`;
  document.getElementById('an-disp-pend').innerText = pendingDispatch.toLocaleString();
  document.getElementById('an-disp-sub').innerText  = `${dispatched} already dispatched`;
  document.getElementById('an-canc').innerText      = totalCancel.toLocaleString();
  document.getElementById('an-canc-sub').innerText  = `${cancelRate}% cancel rate`;
  document.getElementById('an-conv').innerText      = conversion + '%';
  document.getElementById('an-conv-sub').innerText  = `${totalDone} confirmed of ${total}`;

  // Agent performance table
  const agentMap = {};
  data.forEach(o => {
    const ag = o.agent || 'Unassigned';
    if (!agentMap[ag]) agentMap[ag] = {total:0,done:0,cancel:0,pending:0};
    agentMap[ag].total++;
    if (o.status==='Done')    agentMap[ag].done++;
    if (o.status==='Cancel')  agentMap[ag].cancel++;
    if (!o.status||o.status==='Pending') agentMap[ag].pending++;
  });
  const abody = document.getElementById('an-agent-body'); abody.innerHTML='';
  Object.keys(agentMap).filter(k=>k!=='Unassigned').sort((a,b)=>agentMap[b].done-agentMap[a].done).forEach(k=>{
    const d=agentMap[k], rate=d.total>0?((d.done/d.total)*100).toFixed(0):0;
    const barW = Math.round(rate);
    const barColor = rate>=80?'#10b981':rate>=60?'#f59e0b':'#ef4444';
    abody.innerHTML+=`<tr>
      <td style="padding:10px 14px;font-weight:600;color:#374151">${k}</td>
      <td style="padding:10px 14px;text-align:center;color:#64748b">${d.total}</td>
      <td style="padding:10px 14px;text-align:center;font-weight:700;color:#10b981">${d.done}</td>
      <td style="padding:10px 14px;text-align:center;color:#ef4444">${d.cancel}</td>
      <td style="padding:10px 14px;text-align:center;color:#f59e0b">${d.pending}</td>
      <td style="padding:10px 14px;text-align:right">
        <div style="display:flex;align-items:center;gap:8px;justify-content:flex-end">
          <div style="width:60px;height:6px;background:#f1f5f9;border-radius:99px;overflow:hidden">
            <div style="width:${barW}%;height:100%;background:${barColor};border-radius:99px"></div>
          </div>
          <span style="font-weight:700;color:${barColor};font-size:13px">${rate}%</span>
        </div>
      </td>
    </tr>`;
  });
  if(agentMap['Unassigned']) {
    const d=agentMap['Unassigned'];
    abody.innerHTML+=`<tr style="background:#f8fafc;border-top:1px solid #e2e8f0">
      <td style="padding:10px 14px;font-weight:600;color:#94a3b8">Unassigned</td>
      <td style="padding:10px 14px;text-align:center;color:#94a3b8">${d.total}</td>
      <td colspan="4" style="padding:10px 14px;text-align:center;color:#94a3b8;font-size:12px">— not yet called —</td>
    </tr>`;
  }

  // Payment split
  const payMap={};
  data.forEach(o=>{const pm=o.paymentMethod||'COD';payMap[pm]=(payMap[pm]||0)+1;});
  const payDiv=document.getElementById('an-payment-split'); payDiv.innerHTML='';
  const payTotal=Object.values(payMap).reduce((a,b)=>a+b,0);
  const payColors={'COD':'#f97316','UPI':'#10b981','Prepaid':'#6366f1','Paid':'#6366f1'};
  Object.entries(payMap).sort((a,b)=>b[1]-a[1]).forEach(([pm,cnt])=>{
    const pct=payTotal>0?Math.min(100,((cnt/payTotal)*100)).toFixed(1):0;
    const color=payColors[pm]||'#6366f1';
    payDiv.innerHTML+=`<div style="min-width:0">
      <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:3px;gap:6px">
        <span style="font-size:12px;font-weight:600;color:#374151;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1">${pm}</span>
        <span style="font-size:12px;font-weight:700;color:${color};flex-shrink:0">${cnt} <span style="color:#94a3b8;font-weight:400;font-size:11px">(${pct}%)</span></span>
      </div>
      <div style="height:6px;background:#f1f5f9;border-radius:99px;overflow:hidden;width:100%">
        <div style="width:${pct}%;height:100%;background:${color};border-radius:99px;transition:width 0.6s ease"></div>
      </div>
    </div>`;
  });

  // Status distribution chart
  const statusData=[
    {label:'Done',val:totalDone,color:'#10b981'},
    {label:'Pending',val:totalPending,color:'#f59e0b'},
    {label:'Cancel',val:totalCancel,color:'#ef4444'},
    {label:'Busy',val:totalBusy,color:'#3b82f6'},
    {label:'NP',val:totalNP,color:'#f97316'},
    {label:'Other',val:total-totalDone-totalPending-totalCancel-totalBusy-totalNP,color:'#8b5cf6'},
  ].filter(x=>x.val>0);
  const sCtx=document.getElementById('statusChart');
  if(statusChartInstance)statusChartInstance.destroy();
  statusChartInstance=new Chart(sCtx,{type:'doughnut',data:{labels:statusData.map(x=>x.label),datasets:[{data:statusData.map(x=>x.val),backgroundColor:statusData.map(x=>x.color),borderWidth:2,borderColor:'#fff'}]},options:{responsive:true,maintainAspectRatio:false,cutout:'65%',plugins:{legend:{position:'right',labels:{boxWidth:10,font:{size:11},padding:12}},tooltip:{callbacks:{label:function(c){const pct=total>0?((c.raw/total)*100).toFixed(1):0;return ` ${c.label}: ${c.raw} (${pct}%)`;}}}}}});

  // Top products chart
  const prodMap={};
  data.forEach(o=>{if(o.status!=='Cancel'){const n=(o.itemName||'Unknown').split('•').filter(Boolean).map(s=>s.trim()).join(', ');if(n)prodMap[n]=(prodMap[n]||0)+1;}});
  const topProds=Object.entries(prodMap).sort((a,b)=>b[1]-a[1]).slice(0,6);
  const pCtx=document.getElementById('productChart');
  if(productChartInstance)productChartInstance.destroy();
  productChartInstance=new Chart(pCtx,{type:'bar',data:{labels:topProds.map(([k])=>k.length>25?k.substring(0,25)+'…':k),datasets:[{data:topProds.map(([,v])=>v),backgroundColor:['#6366f1','#10b981','#f59e0b','#ef4444','#8b5cf6','#06b6d4'],borderRadius:6,borderSkipped:false}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false},tooltip:{callbacks:{label:c=>{const pct=total>0?((c.raw/total)*100).toFixed(1):0;return ` ${c.raw} orders (${pct}%)`}}}}  ,scales:{x:{grid:{color:'#f1f5f9'},ticks:{font:{size:11}}},y:{grid:{display:false},ticks:{font:{size:10}}}}}});

  // Business Insights
  const insDiv=document.getElementById('an-insights'); insDiv.innerHTML='';
  const bestAgent=Object.keys(agentMap).filter(k=>k!=='Unassigned').sort((a,b)=>agentMap[b].done-agentMap[a].done)[0];
  const bestRate=bestAgent?((agentMap[bestAgent].done/agentMap[bestAgent].total)*100).toFixed(0):0;
  const worstAgent=Object.keys(agentMap).filter(k=>k!=='Unassigned'&&agentMap[k].total>50).sort((a,b)=>(agentMap[a].done/agentMap[a].total)-(agentMap[b].done/agentMap[b].total))[0];
  const unassignedPct=total>0?((unassigned/total)*100).toFixed(1):0;
  const dispatchPct=totalDone>0?((dispatched/totalDone)*100).toFixed(1):0;

  const insight=(icon,color,title,body)=>`<div class="card-sm p-4" style="border-left:3px solid ${color}">
    <div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
      <span style="font-size:20px">${icon}</span>
      <span style="font-size:12px;font-weight:700;color:#374151">${title}</span>
    </div>
    <div style="font-size:12px;color:#64748b;line-height:1.5">${body}</div>
  </div>`;

  insDiv.innerHTML=
    insight('🏆','#10b981','Top Performer',bestAgent?`<b style="color:#10b981">${bestAgent}</b> leads with <b>${agentMap[bestAgent]?.done}</b> confirmed orders at <b>${bestRate}%</b> conversion rate.`:'No data yet')+
    insight('📦','#6366f1','Dispatch Pipeline',`<b>${pendingDispatch}</b> confirmed orders are awaiting dispatch. <b>${dispatchPct}%</b> of confirmed orders have been dispatched so far.`)+
    insight('⚡','#f59e0b','Unassigned Orders',`<b style="color:#f59e0b">${unassigned}</b> orders (<b>${unassignedPct}%</b>) are still unassigned. Assign them to agents to improve conversion.`)+
    (worstAgent?insight('📉','#ef4444','Needs Attention',`<b style="color:#ef4444">${worstAgent}</b> has a low conversion rate of <b>${((agentMap[worstAgent].done/agentMap[worstAgent].total)*100).toFixed(0)}%</b>. Consider additional training or support.`)
    :insight('✅','#10b981','Cancel Rate',`Current cancel rate is <b style="color:#ef4444">${cancelRate}%</b>. ${parseFloat(cancelRate)<15?'This is within healthy range.':'Consider reviewing reasons for cancellation.'}`))+
    insight('💰','#8b5cf6','Revenue Signal',`<b>${totalDone}</b> orders confirmed. ${data.filter(x=>x.paymentMethod==='UPI'||x.paymentMethod==='Paid').length} were prepaid (lower risk of RTO).`)+
    insight('📊','#06b6d4','Today Summary',`Total orders in view: <b>${total}</b> | Done: <b>${totalDone}</b> | Pending: <b>${totalPending}</b> | Unassigned: <b>${unassigned}</b>`);
}

// ============================================================
// HELPERS
// ============================================================
function renderAgentAnalyticsView() {
  // Regular agents see only their own analytics — lock the dropdown to their name
  const aaSel = document.getElementById('aa-agent-filter');
  if (typeof IS_REGULAR_AGENT !== 'undefined' && IS_REGULAR_AGENT && aaSel) {
    if (![...aaSel.options].some(op => op.value === CURRENT_USER)) {
      const op = document.createElement('option'); op.value = CURRENT_USER; op.innerText = CURRENT_USER; aaSel.appendChild(op);
    }
    aaSel.value = CURRENT_USER;
    aaSel.disabled = true;
  }
  const aaStart = document.getElementById('aa-start')?.value;
  const aaEnd   = document.getElementById('aa-end')?.value;
  const aaAgent = document.getElementById('aa-agent-filter')?.value || 'All';

  let data = ALL_DATA;
  if (aaStart && aaEnd) {
    data = ALL_DATA.filter(o => {
      const d = extractDate(o.createdAt || '');
      return d && d >= aaStart && d <= aaEnd;
    });
  }
  // Only orders actually assigned to an agent
  const assignedData = data.filter(o => o.agent);

  // KPI scope: selected agent, or all assigned orders
  const scope = aaAgent !== 'All' ? assignedData.filter(o => o.agent === aaAgent) : assignedData;
  const t  = scope.length;
  const dn = scope.filter(x => x.status === 'Done').length;
  const cn = scope.filter(x => x.status === 'Cancel').length;
  const pd = scope.filter(x => !x.status || x.status === 'Pending').length;
  const conv = t > 0 ? ((dn / t) * 100).toFixed(1) : 0;
  const lbl = aaAgent !== 'All' ? aaAgent : 'all agents';
  const set = (id, v) => { const el = document.getElementById(id); if (el) el.innerText = v; };
  set('aa-assigned', t.toLocaleString());      set('aa-assigned-sub', 'orders for ' + lbl);
  set('aa-done', dn.toLocaleString());          set('aa-done-sub', t > 0 ? ((dn/t)*100).toFixed(1) + '% of assigned' : '');
  set('aa-cancel', cn.toLocaleString());        set('aa-cancel-sub', t > 0 ? ((cn/t)*100).toFixed(1) + '% cancel rate' : '');
  set('aa-pending', pd.toLocaleString());       set('aa-pending-sub', 'awaiting call/update');
  set('aa-conv', conv + '%');                   set('aa-conv-sub', dn + ' confirmed of ' + t);

  // Agent-wise table (all agents in date range; selected agent highlighted)
  const map = {};
  assignedData.forEach(o => {
    const a = o.agent;
    if (!map[a]) map[a] = {total:0,done:0,cancel:0,np:0,busy:0,pending:0,other:0};
    const m = map[a]; m.total++;
    const st = o.status || 'Pending';
    if (st === 'Done') m.done++;
    else if (st === 'Cancel') m.cancel++;
    else if (st === 'NP') m.np++;
    else if (st === 'Busy') m.busy++;
    else if (st === 'Pending') m.pending++;
    else m.other++;
  });
  const tbody = document.getElementById('aa-agent-body');
  if (!tbody) return;
  const names = Object.keys(map).sort((a,b) => map[b].done - map[a].done);
  if (!names.length) {
    tbody.innerHTML = '<tr><td colspan="9" style="text-align:center;padding:30px;color:#94a3b8;font-size:13px">No assigned orders in this range</td></tr>';
    return;
  }
  tbody.innerHTML = names.map(a => {
    const m = map[a];
    const cv = m.total > 0 ? ((m.done / m.total) * 100).toFixed(1) : '0.0';
    const isSel = aaAgent !== 'All' && a === aaAgent;
    return `<tr style="border-bottom:1px solid #f8fafc;${isSel ? 'background:#fffbeb' : ''}" onmouseover="this.style.background='#f8fafc'" onmouseout="this.style.background='${isSel ? '#fffbeb' : ''}'">
      <td style="padding:9px 12px;font-weight:700;color:#1e293b;font-size:13px">${a}${isSel ? ' <span style="font-size:10px;background:#fde68a;color:#92400e;padding:1px 6px;border-radius:99px;font-weight:700">SELECTED</span>' : ''}</td>
      <td style="padding:9px 12px;text-align:center;font-size:13px;color:#374151;font-weight:600">${m.total}</td>
      <td style="padding:9px 12px;text-align:center;font-size:13px;color:#10b981;font-weight:700;background:#f0fdf408">${m.done}</td>
      <td style="padding:9px 12px;text-align:center;font-size:13px;color:#ef4444;font-weight:700">${m.cancel}</td>
      <td style="padding:9px 12px;text-align:center;font-size:13px;color:#f97316;font-weight:600">${m.np}</td>
      <td style="padding:9px 12px;text-align:center;font-size:13px;color:#3b82f6;font-weight:600">${m.busy}</td>
      <td style="padding:9px 12px;text-align:center;font-size:13px;color:#64748b;font-weight:600">${m.other}</td>
      <td style="padding:9px 12px;text-align:center;font-size:13px;color:#f59e0b;font-weight:700">${m.pending}</td>
      <td style="padding:9px 12px;text-align:right;font-size:13px;font-weight:800;color:${parseFloat(cv) >= 50 ? '#10b981' : parseFloat(cv) >= 25 ? '#f59e0b' : '#ef4444'}">${cv}%</td>
    </tr>`;
  }).join('');
}

function populateAgentDropdowns(agents) {
  ['assign-agent','adminAgentFilter','pull-back-agent','an-agent-filter','aa-agent-filter'].forEach(id=>{
    const select=document.getElementById(id); if(!select) return;
    const currentVal=select.value;
    select.innerHTML=id==='pull-back-agent'?'<option value="">-- Select Agent --</option><option value="All">All Agents</option>':'<option value="All">All Agents</option>';
    agents.forEach(a=>{const opt=document.createElement('option');opt.value=a;opt.innerText=a;select.appendChild(opt);});
    if(currentVal&&agents.includes(currentVal))select.value=currentVal;
  });
  const container=document.getElementById('agentFilterOptions'); if(!container) return;
  let html='';
  if(IS_REGULAR_AGENT){
    html+=`<label class="hidden flex items-center gap-3 p-2 hover:bg-slate-50 rounded cursor-pointer text-sm"><input type="checkbox" value="All" class="agent-cb w-4 h-4 text-blue-600 rounded" onchange="handleAgentCbChange(this)"> <span class="font-bold">All Agents</span></label>`;
    agents.forEach(a=>{const checked=a===CURRENT_USER?'checked':'';html+=`<label class="flex items-center gap-3 p-2 hover:bg-slate-50 rounded cursor-pointer text-sm"><input type="checkbox" value="${a}" class="agent-cb w-4 h-4 text-blue-600 rounded" onchange="handleAgentCbChange(this)" ${checked}> <span>${a}</span></label>`;});
  } else {
    html+=`<label class="flex items-center gap-3 p-2 hover:bg-slate-50 rounded cursor-pointer text-sm"><input type="checkbox" value="All" class="agent-cb w-4 h-4 text-blue-600 rounded" onchange="handleAgentCbChange(this)" checked> <span class="font-bold">All Agents</span></label>`;
    agents.forEach(a=>{html+=`<label class="flex items-center gap-3 p-2 hover:bg-slate-50 rounded cursor-pointer text-sm"><input type="checkbox" value="${a}" class="agent-cb w-4 h-4 text-blue-600 rounded" onchange="handleAgentCbChange(this)"> <span>${a}</span></label>`;});
  }
  container.innerHTML=html; updateAgentFilterText();
}

function handleAgentCbChange(clickedCb) {
  const allCbs=document.querySelectorAll('.agent-cb');
  if(clickedCb.value==='All'&&clickedCb.checked){allCbs.forEach(cb=>{if(cb.value!=='All')cb.checked=false;});}
  else if(clickedCb.checked){const a=document.querySelector('.agent-cb[value="All"]');if(a)a.checked=false;}
  const checked=Array.from(document.querySelectorAll('.agent-cb:checked')).map(cb=>cb.value);
  if(checked.length===0){const a=document.querySelector('.agent-cb[value="All"]');if(a)a.checked=true;}
  updateAgentFilterText(); renderAgentView();
}
function updateAgentFilterText() {
  const checked=Array.from(document.querySelectorAll('.agent-cb:checked')).map(cb=>cb.value);
  const textEl=document.getElementById('agentFilterText'); if(!textEl) return;
  if(checked.includes('All')||checked.length===0) textEl.innerText="All Agents";
  else if(checked.length===1) textEl.innerText=checked[0];
  else textEl.innerText=checked.length+" Selected";
}
function getSelectedAgents() {
  const cbs=document.querySelectorAll('.agent-cb:checked');
  if(cbs.length===0) return['All'];
  return Array.from(cbs).map(cb=>cb.value);
}

function populateVendorDropdown(vendors) {
  ['raw-vendor','assign-vendor'].forEach(id=>{
    const select=document.getElementById(id); if(!select) return;
    const currentVal=select.value;
    select.innerHTML=id==='assign-vendor'?'<option value="">-- Choose Vendor --</option>':'<option value="">All Vendors</option>';
    vendors.forEach(v=>{const opt=document.createElement('option');opt.value=v;opt.innerText=v;select.appendChild(opt);});
    if(vendors.includes(currentVal))select.value=currentVal;
  });
}

function populateTagFilter(){
  const essentialTags=["Medium Risk","Low Risk","High Risk","Red Zone","Repeat Customer","PPCOD","On Hold","UPI","COD","ORDER_CONFIRMED","size-S-M-buyer","ORDER_CANCELLED"];
  const tagSet=new Set();
  ALL_DATA.forEach(o=>{if(o.tags){o.tags.split(',').forEach(t=>{const ct=t.trim();if(essentialTags.some(et=>et.toLowerCase()===ct.toLowerCase()))tagSet.add(ct);});}});
  const container=document.getElementById('tagFilterOptions'); if(!container) return;
  const tags=Array.from(tagSet).sort();
  container.innerHTML=`<label style="display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;cursor:pointer;font-size:12px;font-weight:600;color:#1e293b;background:#f8fafc;margin-bottom:4px"><input type="checkbox" class="tag-filter-cb" value="__all__" checked onchange="onTagFilterAllChange(this)">All Tags</label><hr style="border:none;border-top:1px solid #e2e8f0;margin:4px 0">${tags.map(tag=>`<label style="display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:12px;color:#475569" onmouseover="this.style.background='#f1f5f9'" onmouseout="this.style.background=''"><input type="checkbox" class="tag-filter-cb" value="${tag}" onchange="onTagFilterChange()"> ${tag}</label>`).join('')}`;
}
function onTagFilterAllChange(cb){document.querySelectorAll('.tag-filter-cb:not([value="__all__"])').forEach(c=>c.checked=false);cb.checked=true;updateTagFilterText();renderAgentView();}
function onTagFilterChange(){const all=document.querySelector('.tag-filter-cb[value="__all__"]');const any=Array.from(document.querySelectorAll('.tag-filter-cb:not([value="__all__"])')).some(c=>c.checked);if(all)all.checked=!any;updateTagFilterText();renderAgentView();}
function updateTagFilterText(){const sel=Array.from(document.querySelectorAll('.tag-filter-cb:not([value="__all__"])')).filter(c=>c.checked).map(c=>c.value);const el=document.getElementById('tagFilterText');if(!el)return;el.innerText=sel.length===0?'All Tags':sel.length===1?sel[0]:sel.length+' Tags';}
function getSelectedTagFilters(){return Array.from(document.querySelectorAll('.tag-filter-cb:not([value="__all__"])')).filter(c=>c.checked).map(c=>c.value);}
function onPriceFilterChange(){const el=document.getElementById('priceFilterText');if(!el)return;const val=document.querySelector('.price-filter-rb:checked')?.value||'all';const labels={'all':'All Prices','lt1000':'< ₹1000','1000to1500':'₹1000–1500','gt1500':'> ₹1500'};el.innerText=labels[val]||'All Prices';document.getElementById('priceDropdownMenu').classList.add('hidden');renderAgentView();}
function getSelectedPriceFilter(){return document.querySelector('.price-filter-rb:checked')?.value||'all';}
function onPayFilterChange(){const el=document.getElementById('payFilterText');if(!el)return;const val=document.querySelector('.pay-filter-rb:checked')?.value||'all';const labels={'all':'All Payments','paid':'💳 Paid','cod':'💵 COD'};el.innerText=labels[val]||'All Payments';document.getElementById('payDropdownMenu').classList.add('hidden');renderAgentView();}
function getSelectedPayFilter(){return document.querySelector('.pay-filter-rb:checked')?.value||'all';}

function switchTab(tab) {
  if(typeof closeMobileSidebar==='function')closeMobileSidebar();
  currentView=tab; localStorage.setItem('oms_last_view',tab);
  document.querySelectorAll('.view-section').forEach(el=>el.classList.remove('active'));
  const av=document.getElementById(`view-${tab}`); if(av)av.classList.add('active');
  document.querySelectorAll('.nav-item').forEach(el=>el.classList.remove('active-nav'));
  const ab=document.getElementById(`btn-${tab}`); if(ab)ab.classList.add('active-nav');
  const tabNames = {'admin':'Live Activity','raw':'Master File','assign':'Assign Callers','agent':'Agent View','updates':'Recent Updates','scan':'Dispatch & Scan','analytics':'Analytics','agentanalytics':'Agent Analytics','payment':'Payments','users':'User Management','delivery':'Delivery Report','training':'Training','returns':'Returns Ledger','uploads':'Upload Files','ndr':'NDR Automation'};
  const tName = tabNames[tab] || tab.toUpperCase();
  document.getElementById('page-title').innerText = tName;
  document.title = tName + ' — Filo Hevis OMS';
  if(tab==='agent'){
    const sEl=document.getElementById('agent-date-start'); if(sEl)sEl.value='';
    const eEl=document.getElementById('agent-date-end'); if(eEl)eEl.value='';
    const sf=document.getElementById('statusFilter'); if(sf)sf.value='All';
    document.querySelectorAll('.tag-filter-cb').forEach(c=>{c.checked=c.value==='__all__';});updateTagFilterText();
    const prb=document.querySelector('.price-filter-rb[value="all"]');if(prb){prb.checked=true;}onPriceFilterChange();
    const ss=document.getElementById('searchBar'); if(ss)ss.value='';
    const allCbs=document.querySelectorAll('.agent-cb');
    if(allCbs.length>0){
      if(IS_REGULAR_AGENT) allCbs.forEach(cb=>cb.checked=(cb.value===CURRENT_USER));
      else allCbs.forEach(cb=>cb.checked=(cb.value==='All'));
      updateAgentFilterText();
    }
  }
  if(tab==='raw') loadRawData();
  if(tab==='admin') renderAdminView();
  if(tab==='updates'){showToast("Loading Updates...","info");renderUpdatesView();}
  if(tab==='scan'){renderScanView();renderScanSummary();switchScanTab('stage');}
  if(tab==='assign'){
    const av2=document.getElementById('assign-vendor'); if(av2)av2.value='';
    const as=document.getElementById('assign-start'); if(as){as.value='';as.disabled=true;}
    const ae=document.getElementById('assign-end'); if(ae){ae.value='';ae.disabled=true;}
    updateLoadSummary();
  }
  if(tab==='analytics') renderAnalyticsView();
  if(tab==='agentanalytics') renderAgentAnalyticsView();
  if(tab==='ndr') ndrLoadData();
  if(tab==='uploads') renderUploadsView();
  if(tab==='returns') { RET_DB_LOADED=false; renderReturnsLedger(); }
  if(tab==='returns') { RET_DB_LOADED=false; renderReturnsLedger(); }
  if(tab==='users') { loadUsers(); }
  if(tab==='delivery') { renderDeliveryView(); }
  if(tab==='training') { loadTrainingData(); }
  renderCurrentView();
}

function renderCurrentView() {
  if(currentView==='agent') renderAgentView();
  else if(currentView==='analytics') renderAnalyticsView();
  else if(currentView==='agentanalytics') renderAgentAnalyticsView();
  else if(currentView==='updates') renderUpdatesView();
  else if(currentView==='raw'&&RAW_DATA.length===0) loadRawData();
  else if(currentView==='raw') renderRawView();
  else if(currentView==='admin') { if(ALL_DATA.length>0) renderAdminView(); }
  else if(currentView==='scan'){renderScanView();renderScanHistory();}
}

function resetDates(view) {
  if(view==='updates'){document.getElementById('upd-start').value='';document.getElementById('upd-end').value='';renderUpdatesView();}
  else if(view==='raw'){document.getElementById('raw-date-start').value='';document.getElementById('raw-date-end').value='';renderRawView();}
  else if(view==='agent'){const s=document.getElementById('agent-date-start'),e=document.getElementById('agent-date-end');if(s)s.value='';if(e)e.value='';renderAgentView();}
}

function openLogisticsModal(o) {
  currentLogId=o.orderId;
  document.getElementById('modal-order-id').innerText=`Update #${o.orderId}`;
  document.getElementById('modal-awb').value=o.awb||'';
  document.getElementById('modal-courier').value=o.courier||'';
  document.getElementById('modal-sku').value=o.skuCode||o.sku||'';
  document.getElementById('modal-qty').value=o.logQty||o.itemQty||'';
  document.getElementById('modal-remark').value=o.logRemark||'';
  document.getElementById('logisticsModal').classList.remove('hidden');
}
function closeModal() { document.getElementById('logisticsModal').classList.add('hidden'); currentLogId=null; }

function downloadMasterData() {
  const rows = getFilteredRawData();
  if(rows.length===0){showToast("No data to export","error");return;}
  const allowedIndices=[],displayHeaders=["S.No"];
  RAW_HEADERS.forEach((h,index)=>{if(!EXCLUDED_HEADERS.includes(h)){allowedIndices.push(index);displayHeaders.push(h);}});
  let csvRows=[]; csvRows.push(displayHeaders.join(","));
  rows.forEach((row,idx)=>{let rowData=[idx+1];allowedIndices.forEach(i=>{let cell=String(row[i]||"").replace(/"/g,'""');if(cell.search(/("|,|\n)/g)>=0)cell=`"${cell}"`;rowData.push(cell);});csvRows.push(rowData.join(","));});
  const blob=new Blob([csvRows.join("\n")],{type:'text/csv;charset=utf-8;'});
  const link=document.createElement("a");link.setAttribute("href",URL.createObjectURL(blob));link.setAttribute("download",`master_data_${new Date().toISOString().slice(0,10)}.csv`);link.style.visibility='hidden';document.body.appendChild(link);link.click();document.body.removeChild(link);
  showToast(`Exported ${rows.length} rows`,"success");
}

function downloadAgentData() {
  const selectedAgents=getSelectedAgents();
  const statusFilter=document.getElementById('statusFilter').value;
  const selectedTagFilters=getSelectedTagFilters();
  const priceFilter=getSelectedPriceFilter();
  const search=document.getElementById('searchBar').value.toLowerCase();
  const sDateVal=document.getElementById('agent-date-start')?.value;
  const eDateVal=document.getElementById('agent-date-end')?.value;
  const filtered=ALL_DATA.filter(o=>{
    const matchAgent=selectedAgents.includes('All')||selectedAgents.includes(o.agent)||(o.agent===''&&selectedAgents.some(sa=>String(o.agentRemark||'').startsWith('Pulled back from '+sa)));
    let matchStatus=statusFilter==='All'?true:(statusFilter==='Pending'?(o.status==='Pending'||o.status===''):o.status===statusFilter);
    const matchTag=selectedTagFilters.length===0||(o.tags&&selectedTagFilters.some(t=>o.tags.includes(t)));
    const payFilter=getSelectedPayFilter();
    const finLc=String(o.financialStatus||'').toLowerCase();
    const oIsPaid=(finLc==='paid');
    const matchPay=payFilter==='all'||(payFilter==='paid'&&oIsPaid)||(payFilter==='cod'&&!oIsPaid);
    const ep=parseFloat(o.totalPrice||0);
    const matchPrice=priceFilter==='all'||(priceFilter==='lt1000'&&ep<1000)||(priceFilter==='1000to1500'&&ep>=1000&&ep<=1500)||(priceFilter==='gt1500'&&ep>1500);
    const matchSearch=(o.orderId||'').toLowerCase().includes(search)||(o.billingPhone||'').includes(search)||(o.billingName||'').toLowerCase().includes(search);
    let matchDate=true;
    if(sDateVal&&eDateVal){let dStr=extractDate(o.assignDate||o.createdAt);if(!dStr||dStr<sDateVal||dStr>eDateVal)matchDate=false;}
    return matchAgent&&matchStatus&&matchTag&&matchPay&&matchPrice&&matchSearch&&matchDate;
  });
  if(filtered.length===0){showToast("No data to export","error");return;}
  const headers=["Order ID","Date","Customer","Phone","Item Name","Qty","Price","Payment","Address","City","State","Zip","Agent","Status","Remark","Tags"];
  let csvRows=[headers.join(",")];
  filtered.forEach(o=>{let isPulledBack=(o.agent===''&&String(o.agentRemark||'').startsWith('Pulled back'));let row=[o.orderId,o.createdAt?extractDate(o.createdAt):'',o.billingName,o.billingPhone,o.itemName,o.itemQty,o.itemPrice,o.paymentMethod,`${o.shippingAddr} ${o.shippingAddr2||''}`.trim(),o.shippingCity,o.shippingProv,o.shippingZip,isPulledBack?'UNASSIGNED':o.agent,isPulledBack?'UNASSIGNED':(o.status||'Pending'),o.agentRemark,o.tags];let esc=row.map(cell=>{let s=String(cell||'').replace(/"/g,'""');if(s.search(/("|,|\n)/g)>=0)s=`"${s}"`;return s;});csvRows.push(esc.join(","));});
  const blob=new Blob([csvRows.join("\n")],{type:'text/csv;charset=utf-8;'});
  const link=document.createElement("a");link.setAttribute("href",URL.createObjectURL(blob));link.setAttribute("download",`Agent_Export_${new Date().toISOString().slice(0,10)}.csv`);link.style.visibility='hidden';document.body.appendChild(link);link.click();document.body.removeChild(link);
  showToast(`Exported ${filtered.length} orders`,"success");
}

function renderLabelView() {}

// ═══════════════════════════════════════════
// LIFECYCLE PAYMENT UPLOAD
// ═══════════════════════════════════════════
window.LC_PAYMENT_DATA = [];

function lcHandlePaymentUpload(input) {
  const files = Array.from(input.files);
  if (!files.length) return;
  const statusEl = document.getElementById('lc-pay-status');
  if (statusEl) statusEl.textContent = '⏳ Parsing ' + files.length + ' file(s)…';
  let allRows = [];
  let processed = 0;
  files.forEach(function(file) {
    const name = file.name.toLowerCase();
    const reader = new FileReader();
    reader.onload = function(e) {
      try {
        const wb = XLSX.read(e.target.result, {type:'array', cellDates:false});
        const ws = wb.Sheets[wb.SheetNames[0]];
        const rows = XLSX.utils.sheet_to_json(ws, {defval:''});
        let parsed = [];
        if (name.includes('dtdc')) {
          // DTDC: 'ORDER ID' = '#3434336821_SP/...' — extract before '_'
          rows.forEach(function(r) {
            const rawOid = String(r['ORDER ID']||r['Order ID']||'').trim();
            const oid = rawOid.split('_')[0].replace(/#/g,'').trim();
            const awb = String(r['Consignment Numbar']||r['Consignment Number']||r['AWB']||'').trim();
            const amt = String(r['AMT']||r['Amount']||r['amt']||'').trim();
            if (oid||awb) parsed.push({orderId:oid, awb:awb, amount:amt, source:'DTDC', utr:String(r['UTR ']||r['UTR']||'')});
          });
        } else if (name.includes('shiprocket')) {
          // Shiprocket: 'Order Id' (no #), 'AWB' col
          rows.forEach(function(r) {
            const oid = String(r['Order Id']||r['ORDER ID']||'').replace(/#/g,'').trim();
            const awb = String(r['AWB']||r['Waybill']||'').trim();
            const amt = String(r['total_adjusted_amt']||r['Order Value']||'').trim();
            if (oid||awb) parsed.push({orderId:oid, awb:awb, amount:amt, source:'Shiprocket', utr:String(r['UTR']||'')});
          });
        } else if (name.includes('gokwik')) {
          // Gokwik CSV: 'Merchant Order Id' or 'Platform Order Id'
          rows.forEach(function(r) {
            const pid = String(r['Platform Order Id']||'').replace(/#/g,'').trim();
            const mid = String(r['Merchant Order Id']||'').replace(/#/g,'').trim();
            const oid = pid || mid;
            const amt = String(r['Credit']||r['Amount']||'').trim();
            const pg  = String(r['Settled By']||r['Payment Mode']||'').trim();
            if (oid) parsed.push({orderId:oid, awb:'', amount:amt, source:'Gokwik', utr:String(r['Settlement UTR']||''), paymentMode:pg});
          });
        } else {
          // Generic fallback
          rows.forEach(function(r) {
            const oid = String(r['Merchant Order Id']||r['Platform Order Id']||r['Order Id']||r['ORDER ID']||'').replace(/#/g,'').trim();
            const awb = String(r['AWB']||r['Waybill']||r['Consignment Numbar']||'').trim();
            const amt = String(r['Amount']||r['Credit']||r['total_adjusted_amt']||r['AMT']||'').trim();
            if (oid||awb) parsed.push({orderId:oid, awb:awb, amount:amt, source:file.name});
          });
        }
        allRows = allRows.concat(parsed);
      } catch(err) { console.warn('Payment parse error:', file.name, err); }
      processed++;
      if (processed === files.length) {
        window.LC_PAYMENT_DATA = allRows;
        if (statusEl) statusEl.textContent = '✅ ' + allRows.length + ' records loaded (' + files.length + ' files)';
        showToast('Payment data loaded: ' + allRows.length + ' records', 'success');
        input.value = '';
      }
    };
    reader.readAsArrayBuffer(file);
  });
}

function toggleMobileSidebar(){const sb=document.getElementById('sidebar'),ov=document.getElementById('sidebar-overlay');if(!sb)return;const o=sb.classList.contains('mobile-open');if(o){sb.classList.remove('mobile-open');if(ov)ov.style.display='none';}else{sb.classList.add('mobile-open');if(ov)ov.style.display='block';}}
function closeMobileSidebar(){const sb=document.getElementById('sidebar'),ov=document.getElementById('sidebar-overlay');if(sb)sb.classList.remove('mobile-open');if(ov)ov.style.display='none';}
function toggleSidebar() {
  const sidebar=document.getElementById('sidebar');
  sidebar.classList.toggle('collapsed');
}

// ============================================================
// USER MANAGEMENT
// ============================================================
const USERS_API = 'api/data.php';
let ALL_USERS = [];

async function loadUsers() {
  const tbody = document.getElementById('users-table-body'); if (!tbody) return;
  tbody.innerHTML = '<tr><td colspan="7" style="text-align:center;padding:40px;color:#94a3b8"><i class="fas fa-spinner fa-spin" style="font-size:24px;color:#16a34a"></i><div style="margin-top:8px;font-size:13px">Loading users...</div></td></tr>';
  try {
    const data = await apiCall('get_users');
    if (data && data.status === 'success') { ALL_USERS = data.users||[]; renderUsersStats(); renderUsersTable(); }
    else tbody.innerHTML = `<tr><td colspan="7" style="text-align:center;padding:40px;color:#ef4444">${data?.msg||'Error loading users'}</td></tr>`;
  } catch(e) { tbody.innerHTML = `<tr><td colspan="7" style="text-align:center;padding:40px;color:#ef4444">Error: ${e.message}</td></tr>`; }
}

function renderUsersStats() {
  const sr=document.getElementById('user-stats-row'); if(!sr) return;
  const total=ALL_USERS.length, active=ALL_USERS.filter(u=>u.is_active==='t'||u.is_active===true).length;
  const agents=ALL_USERS.filter(u=>u.role==='agent').length, admins=ALL_USERS.filter(u=>u.role==='admin').length;
  const stat=(label,val,color,icon,bg)=>`<div class="card p-4" style="display:flex;align-items:center;gap:12px;border-left:3px solid ${color}"><div style="width:40px;height:40px;border-radius:10px;background:${bg};color:${color};display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0"><i class="fas fa-${icon}"></i></div><div><div style="font-size:26px;font-weight:900;color:#1e293b;line-height:1">${val}</div><div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#94a3b8;margin-top:3px">${label}</div></div></div>`;
  sr.innerHTML=stat('Total Users',total,'#6366f1','users','#f0f0ff')+stat('Active',active,'#10b981','user-check','#f0fdf4')+stat('Agents',agents,'#f59e0b','headset','#fffbeb')+stat('Admins',admins,'#ef4444','shield-halved','#fef2f2');
}

function renderUsersTable() {
  const tbody=document.getElementById('users-table-body'); if(!tbody) return;
  const search=(document.getElementById('user-search')?.value||'').toLowerCase();
  const RS={admin:{bg:'#fef2f2',color:'#b91c1c',border:'#fecaca',label:'Admin'},manager:{bg:'#fff7ed',color:'#c2410c',border:'#fed7aa',label:'Manager'},team_lead:{bg:'#f3e8ff',color:'#7e22ce',border:'#e9d5ff',label:'Team Lead'},agent:{bg:'#dbeafe',color:'#1d4ed8',border:'#bfdbfe',label:'Agent'},dispatch:{bg:'#dcfce7',color:'#15803d',border:'#bbf7d0',label:'Dispatch'},writer:{bg:'#fdf4ff',color:'#a21caf',border:'#f5d0fe',label:'Writer'},accounts:{bg:'#ecfeff',color:'#0e7490',border:'#a5f3fc',label:'Accounts'},ndr:{bg:'#cffafe',color:'#0e7490',border:'#a5f3fc',label:'NDR'}};
  const filtered=ALL_USERS.filter(u=>!search||u.name.toLowerCase().includes(search)||u.username.toLowerCase().includes(search)||u.role.toLowerCase().includes(search));
  if(!filtered.length){tbody.innerHTML='<tr><td colspan="7" style="text-align:center;padding:40px;color:#94a3b8">No users found</td></tr>';return;}
  const cid=<?= intval($SESSION_USER['id']) ?>;
  tbody.innerHTML=filtered.map((u,i)=>{
    const act=u.is_active==='t'||u.is_active===true, rs=RS[u.role]||RS.agent, self=parseInt(u.id)===cid;
    const ini=u.name.split(' ').map(p=>p[0]).join('').substring(0,2).toUpperCase();
    const cd=u.created_at?u.created_at.substring(0,10):'—';
    return `<tr style="border-bottom:1px solid #f8fafc" onmouseover="this.style.background='#f8fafc'" onmouseout="this.style.background=''">
      <td style="padding:12px 16px;font-size:12px;color:#94a3b8;font-weight:700">${i+1}</td>
      <td style="padding:12px 16px"><div style="display:flex;align-items:center;gap:10px">
        <div style="width:36px;height:36px;border-radius:10px;background:linear-gradient(135deg,#16a34a,#15803d);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800;flex-shrink:0">${ini}</div>
        <div><div style="font-weight:700;color:#1e293b;font-size:13px">${u.name}${self?' <span style="font-size:10px;background:#dbeafe;color:#1d4ed8;padding:1px 6px;border-radius:99px;font-weight:700">YOU</span>':''}</div>
        ${act?'':'<div style="font-size:10px;color:#ef4444;font-weight:600">Deactivated</div>'}</div></div></td>
      <td style="padding:12px 16px;font-size:12px;color:#64748b;font-family:monospace">${u.username}</td>
      <td style="padding:12px 16px"><span style="background:${rs.bg};color:${rs.color};border:1px solid ${rs.border};padding:3px 10px;border-radius:99px;font-size:11px;font-weight:700;text-transform:uppercase">${rs.label}</span></td>
      <td style="padding:12px 16px;text-align:center">
        <button onclick="toggleUserActive(${u.id})" style="padding:4px 12px;border-radius:99px;font-size:11px;font-weight:700;cursor:pointer;border:1px solid ${act?'#bbf7d0':'#e2e8f0'};background:${act?'#dcfce7':'#f8fafc'};color:${act?'#15803d':'#94a3b8'};transition:all .15s">
          ${act?'<i class="fas fa-check"></i> Active':'<i class="fas fa-ban"></i> Inactive'}</button></td>
      <td style="padding:12px 16px;font-size:12px;color:#94a3b8">${cd}</td>
      <td style="padding:12px 16px;text-align:right"><div style="display:inline-flex;align-items:center;gap:6px">
        <button onclick="openResetModal(${u.id},'${u.name.replace(/'/g,'&#39;')}')" style="background:#fffbeb;color:#d97706;border:1px solid #fde68a;padding:5px 10px;border-radius:7px;font-size:11px;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;gap:4px" onmouseover="this.style.background='#fef3c7'" onmouseout="this.style.background='#fffbeb'"><i class="fas fa-key"></i> Pwd</button>
        <button onclick="openUserModal(${u.id})" style="background:#f0f9ff;color:#0369a1;border:1px solid #bae6fd;padding:5px 10px;border-radius:7px;font-size:11px;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;gap:4px" onmouseover="this.style.background='#e0f2fe'" onmouseout="this.style.background='#f0f9ff'"><i class="fas fa-pen"></i> Edit</button>
        ${!self?`<button onclick="deleteUser(${u.id},'${u.name.replace(/'/g,"&#39;")}')" style="background:#fef2f2;color:#ef4444;border:1px solid #fecaca;padding:5px 10px;border-radius:7px;font-size:11px;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;gap:4px" onmouseover="this.style.background='#fee2e2'" onmouseout="this.style.background='#fef2f2'"><i class="fas fa-trash-alt"></i></button>`:''}
      </div></td></tr>`;
  }).join('');
}

// Custom menu permission system
const UM_MENU_OPTIONS = [
  {key:'admin',label:'Live Activity'},{key:'raw',label:'Master File'},{key:'assign',label:'Assign Callers'},
  {key:'agent',label:'Agent View'},{key:'updates',label:'Recent Updates'},{key:'scan',label:'Dispatch & Scan'},
  {key:'analytics',label:'Analytics'},{key:'agentanalytics',label:'Agent Analytics'},{key:'users',label:'User Management'},
  {key:'delivery',label:'Delivery Report'},{key:'training',label:'Training'},{key:'uploads',label:'Upload Files'},
  {key:'returns',label:'Returns Ledger'},{key:'lifecycle',label:'Order Lifecycle'},{key:'ndr',label:'NDR'}
];
function umBuildPermsGrid(selected) {
  const sel = new Set((selected||'').split(',').map(s=>s.trim()).filter(Boolean));
  const g = document.getElementById('um-perms-checks');
  if (!g) return;
  g.innerHTML = UM_MENU_OPTIONS.map(o =>
    `<label style="display:flex;align-items:center;gap:6px;font-size:12px;color:#475569;cursor:pointer"><input type="checkbox" class="um-perm-cb" value="${o.key}" ${sel.has(o.key)?'checked':''} style="width:14px;height:14px">${o.label}</label>`
  ).join('');
}
function umToggleCustomPerms() {
  const on = document.getElementById('um-custom-toggle').checked;
  document.getElementById('um-perms-grid').style.display = on ? 'block' : 'none';
}

function openUserModal(userId=null) {
  const isEdit=userId!==null;
  ['um-id','um-name','um-username','um-password'].forEach(id=>{document.getElementById(id).value='';});
  document.getElementById('um-role').value='agent';
  document.getElementById('um-active').checked=true;
  document.getElementById('um-error').style.display='none';
  document.getElementById('um-username').disabled=false;
  if(isEdit){
    const u=ALL_USERS.find(x=>parseInt(x.id)===parseInt(userId)); if(!u) return;
    document.getElementById('user-modal-title').innerText='Edit User';
    document.getElementById('user-modal-sub').innerText='Update account details';
    document.getElementById('um-save-text').innerText='Save Changes';
    document.getElementById('um-pw-hint').innerText='(leave blank to keep current password)';
    document.getElementById('um-id').value=u.id;
    document.getElementById('um-name').value=u.name;
    document.getElementById('um-username').value=u.username;
    document.getElementById('um-role').value=u.role;
    document.getElementById('um-active').checked=(u.is_active==='t'||u.is_active===true);
    // Load custom permissions
    const perm = (u.permissions||'').trim();
    document.getElementById('um-custom-toggle').checked = !!perm;
    umBuildPermsGrid(perm);
    umToggleCustomPerms();
    // username editable by admin — no disabled
  } else {
    document.getElementById('user-modal-title').innerText='Add New User';
    document.getElementById('user-modal-sub').innerText='Create a new agent account';
    document.getElementById('um-save-text').innerText='Create User';
    document.getElementById('um-pw-hint').innerText='(min 6 characters)';
    document.getElementById('um-custom-toggle').checked=false;
    umBuildPermsGrid('');
    umToggleCustomPerms();
  }
  updateRoleHint();
  document.getElementById('userModal').classList.remove('hidden');
  setTimeout(()=>document.getElementById('um-name').focus(),100);
}
function closeUserModal(){document.getElementById('userModal').classList.add('hidden');document.getElementById('um-username').disabled=false;}
function updateRoleHint(){
  const hints={agent:'Can view and update their assigned orders only',team_lead:'Can view all orders, assign callers, pull back orders',dispatch:'Can access dispatch & scan module only',
    writer:'Can add and edit Training materials only',accounts:'Can view Returns Ledger only',manager:'Full access to all modules except User Management',admin:'Full access including User Management'};
  const el=document.getElementById('um-role-hint'); if(el) el.innerText=hints[document.getElementById('um-role').value]||'';
}
function toggleUMPassword(){const inp=document.getElementById('um-password'),eye=document.getElementById('um-pw-eye');inp.type=inp.type==='password'?'text':'password';eye.className=inp.type==='password'?'fas fa-eye':'fas fa-eye-slash';}

async function saveUser(){
  const id=document.getElementById('um-id').value, name=document.getElementById('um-name').value.trim();
  const username=document.getElementById('um-username').value.trim().toLowerCase(), role=document.getElementById('um-role').value;
  const password=document.getElementById('um-password').value, isActive=document.getElementById('um-active').checked;
  const isEdit=!!id, errDiv=document.getElementById('um-error'), errText=document.getElementById('um-error-text');
  const btn=document.getElementById('um-save-btn');
  errDiv.style.display='none';
  if(!name){errText.innerText='Full name is required';errDiv.style.display='flex';return;}
  if(!isEdit&&!username){errText.innerText='Username is required';errDiv.style.display='flex';return;}
  if(!isEdit&&!password){errText.innerText='Password is required';errDiv.style.display='flex';return;}
  if(password&&password.length<6){errText.innerText='Password must be at least 6 characters';errDiv.style.display='flex';return;}
  const orig=btn.innerHTML; btn.innerHTML='<i class="fas fa-spinner fa-spin"></i> Saving...'; btn.disabled=true;
  // Gather custom permissions (empty string = use role default)
  let permissions = '';
  if (document.getElementById('um-custom-toggle').checked) {
    permissions = Array.from(document.querySelectorAll('.um-perm-cb:checked')).map(c=>c.value).join(',');
    if (!permissions) { errText.innerText='Select at least one menu for custom access, or untick Custom Menu Access'; errDiv.style.display='flex'; btn.innerHTML=orig; btn.disabled=false; return; }
  }
  try {
    const payload=isEdit?{action:'update_user',id:parseInt(id),name,role,is_active:isActive?'1':'0',password,permissions}:{action:'create_user',username,name,role,password,permissions};
    // Send as URL-encoded form data — works on all PHP servers
    const data = await apiCall(payload.action, payload);
    if(data.status==='success'){closeUserModal();showToast(data.msg||(isEdit?'User updated!':'User created!'),'success');loadUsers();}
    else{errText.innerText=data.msg||'Something went wrong';errDiv.style.display='flex';}
  } catch(e){errText.innerText='Connection error';errDiv.style.display='flex';}
  btn.innerHTML=orig; btn.disabled=false;
}
async function toggleUserActive(userId){
  const data = await apiCall('toggle_active',{id:userId});
  if(data.status==='success'){showToast(data.msg,'success');loadUsers();}else showToast(data.msg||'Error','error');
}
async function deleteUser(userId,name){
  if(!confirm('Delete user "'+name+'"? This cannot be undone.')) return;
  const data = await apiCall('delete_user',{id:userId});
  if(data.status==='success'){showToast('User deleted','success');loadUsers();}else showToast(data.msg||'Error','error');
}
function openResetModal(userId,name){
  document.getElementById('rp-id').value=userId;
  document.getElementById('rp-name').innerText=name;
  document.getElementById('rp-password').value='';
  document.getElementById('resetPwModal').classList.remove('hidden');
  setTimeout(()=>document.getElementById('rp-password').focus(),100);
}
function closeResetModal(){document.getElementById('resetPwModal').classList.add('hidden');}
async function confirmResetPassword(){
  const id=document.getElementById('rp-id').value, password=document.getElementById('rp-password').value;
  if(!password||password.length<6){showToast('Password must be at least 6 characters','error');return;}
  const data = await apiCall('reset_password',{id:parseInt(id),new_password:password});
  if(data.status==='success'){closeResetModal();showToast('Password reset!','success');}else showToast(data.msg||'Error','error');
}



// ============================================================
// RETURNS LEDGER
// ============================================================
// RETURNS LEDGER — DB-backed storage
let RET_DB_CACHE = {}; // { orderId: { field: value } }
let RET_DB_LOADED = false;

let RET_MANUAL_ROWS = []; // manually added rows from DB

async function retLoadAll() {
  if (RET_DB_LOADED) return;
  try {
    const r = await apiCall('get_return_ledger');
    if (r && r.status==='success') {
      RET_MANUAL_ROWS = [];
      (r.data||[]).forEach(row => {
        const k = String(row.order_id||'').replace(/#/g,'');
        RET_DB_CACHE[k] = {
          pickup:       row.pickup_date||'',
          retdate:      row.return_date||'',
          type:         row.return_type||'',
          replsku:      row.replacement_sku||'',
          amt:          row.amt_received||'',
          remark:       row.remarks||'',
          status:       row.status||'',
          agent:        row.agent_name||'',
          awb:          row.awb||'',
          courier:      row.courier||'',
          cpStatus:     row.cp_status||'',
          scanReturned: row.scan_returned==='t'||row.scan_returned===true||row.scan_returned==='true',
          scanTs:       row.scan_timestamp||'',
          isManual:     row.is_manual==='t'||row.is_manual===true||row.is_manual==='true'
        };
        if (RET_DB_CACHE[k].isManual) {
          RET_MANUAL_ROWS.push({ orderId: k, ...RET_DB_CACHE[k] });
        }
      });
      RET_DB_LOADED = true;
    }
  } catch(e) { console.warn('retLoadAll error', e); }
}

function retGet(oid,field) {
  const k = String(oid).replace(/#/g,'');
  return (RET_DB_CACHE[k] && RET_DB_CACHE[k][field]!==undefined) ? String(RET_DB_CACHE[k][field]) : '';
}

async function retSave(oid,field,val) {
  const k = String(oid).replace(/#/g,'');
  if (!RET_DB_CACHE[k]) RET_DB_CACHE[k] = {};
  RET_DB_CACHE[k][field] = val;
  // Map field name to DB column
  const dbField = {pickup:'pickup_date',retdate:'return_date',type:'return_type',
                   replsku:'replacement_sku',amt:'amt_received',remark:'remarks',
                   status:'status',agent:'agent_name'}[field];
  if (!dbField) return;
  try { await apiCall('save_return_ledger',{order_id:k, field:dbField, value:val}); }
  catch(e) { console.warn('retSave error',e); }
}
function retInp(oid,field,ph,w,type){const val=retGet(oid,field).replace(/"/g,'&quot;');return `<input type="${type||'text'}" value="${val}" placeholder="${ph}" style="width:${w};border:1px solid #d1d5db;border-radius:6px;padding:4px 7px;font-size:11px;background:#fff;outline:none" onclick="event.stopPropagation()" oninput="retSave('${oid}','${field}',this.value)" onfocus="this.style.borderColor='#059669'" onblur="this.style.borderColor='#d1d5db'">`;}
function retSel(oid,field,opts,w){const val=retGet(oid,field);const o=opts.map(x=>`<option value="${x}" ${val===x?'selected':''}>${x}</option>`).join('');return `<select style="width:${w};border:1px solid #d1d5db;border-radius:6px;padding:4px 6px;font-size:11px;background:#fff" onclick="event.stopPropagation()" onchange="retSave('${oid}','${field}',this.value);renderReturnsLedger()"><option value="">--</option>${o}</select>`;}
async function deleteManualReturn(oid) {
  if (!confirm('Delete #'+oid+' from Returns Ledger?')) return;
  try {
    const r = await apiCall('delete_return_manual', {order_id: oid});
    if (r.status === 'success') {
      // Remove from local cache
      const k = String(oid).replace(/#/g,'');
      delete RET_DB_CACHE[k];
      RET_MANUAL_ROWS = RET_MANUAL_ROWS.filter(m=>String(m.orderId).replace(/#/g,'')!==k);
      showToast('Entry deleted', 'success');
      RET_DB_LOADED = false;
      await renderReturnsLedger();
    } else {
      showToast(r.msg||'Delete failed', 'error');
    }
  } catch(e) { showToast('Error: '+e.message, 'error'); }
}

async function addManualReturn() {
  const inp = document.getElementById('ret-manual-input');
  const oid = (inp?.value||'').trim().replace(/#/g,'');
  if (!oid) { showToast('Please enter an Order ID','error'); return; }
  inp.value = '';
  showToast('Looking up order #'+oid+'...','success');
  try {
    const r = await apiCall('add_return_manual', {order_id: oid});
    if (r.status === 'exists') { showToast('Order #'+oid+' already in Returns Ledger','error'); return; }
    if (r.status !== 'success') { showToast(r.msg||'Error adding order','error'); return; }
    // Add to local cache
    RET_DB_CACHE[oid] = {
      pickup:'', retdate:'', type:'', replsku:'', amt:'', remark:'', status:'', agent:'',
      awb: r.awb||'', courier: r.courier||'', cpStatus: r.cp_status||'',
      scanReturned: r.scan_returned===true||r.scan_returned==='true',
      scanTs: r.scan_ts||'', isManual: true
    };
    RET_MANUAL_ROWS.push({ orderId: oid, ...RET_DB_CACHE[oid] });
    showToast('Order #'+oid+' added'+( r.scan_returned ? ' — ✅ Scan found (Received)' : ' — AWB: '+(r.awb||'Not found')),'success');
    RET_DB_LOADED = false; // force reload
    await renderReturnsLedger();
  } catch(e) { showToast('Error: '+e.message,'error'); }
}

async function renderReturnsLedger(){
  // Load DB data first
  await retLoadAll();

  const sDate=(document.getElementById('ret-start')?.value||'').trim();
  const eDate=(document.getElementById('ret-end')?.value||'').trim();
  const courier=(document.getElementById('ret-courier')?.value||'').trim();
  const typeFilter=(document.getElementById('ret-type-filter')?.value||'').trim();
  const search=(document.getElementById('ret-search')?.value||'').toLowerCase().trim();
  const tbody=document.getElementById('returns-ledger-body'); if(!tbody) return;

  // Build set of AWBs scanned as Returned in scanning table
  const returnedAwbSet = new Set();
  const returnedOidSet = new Set();
  (SCAN_HISTORY_DATA||[]).forEach(s=>{
    if((s.dispatchStatus||'')==='Returned'){
      if(s.awb) returnedAwbSet.add(String(s.awb).trim().toUpperCase());
      if(s.orderId) returnedOidSet.add(String(s.orderId).replace(/#/g,'').trim().toUpperCase());
    }
  });

  // Merge: scan-based Returned orders + manually added orders
  const scanReturnedRows = [...SCAN_HISTORY_DATA]
    .filter(s=>(s.dispatchStatus||'')==='Returned')
    .map(s=>({ ...s, _source:'scan' }));

  // Manual rows — only those NOT already in scan history
  const scanOidSet = new Set(scanReturnedRows.map(s=>String(s.orderId||'').replace(/#/g,'').toUpperCase()));
  const manualOnlyRows = RET_MANUAL_ROWS
    .filter(m=>!scanOidSet.has(String(m.orderId||'').toUpperCase()))
    .map(m=>({
      orderId:       '#'+m.orderId,
      billingName:   ALL_DATA.find(o=>String(o.orderId)===m.orderId)?.billingName || 'Manual Entry',
      billingPhone:  ALL_DATA.find(o=>String(o.orderId)===m.orderId)?.billingPhone || '',
      courierName:   m.courier||'',
      dispatchStatus:'Returned',
      scanTimestamp: m.scanTs||m.retdate||'',
      awb:           m.awb||'',
      _source:       'manual'
    }));

  let rows = [...scanReturnedRows, ...manualOnlyRows]
    .sort((a,b)=>(b.scanTimestamp||'').localeCompare(a.scanTimestamp||''));
  if(sDate&&eDate) rows=rows.filter(s=>{const d=extractDate(s.scanTimestamp||'');return d&&d>=sDate&&d<=eDate;});
  if(courier) rows=rows.filter(s=>(s.courierName||'').toLowerCase()===courier.toLowerCase());
  if(typeFilter) rows=rows.filter(s=>retGet(s.orderId,'type')===typeFilter);
  if(search) rows=rows.filter(s=>{const o=ALL_DATA.find(x=>String(x.orderId)===String((s.orderId||'').replace(/#/g,'')));return((s.orderId||'')+' '+(o?.billingName||s.billingName||'')+' '+(o?.billingPhone||'')).toLowerCase().includes(search);});
  const cards=document.getElementById('returns-summary-cards');
  if(cards){
    const total=rows.length,totalVal=rows.reduce((sum,r)=>{const o=ALL_DATA.find(x=>String(x.orderId)===String((r.orderId||'').replace(/#/g,'')));return sum+parseFloat(o?.totalPrice||0);},0),totalRec=rows.reduce((sum,r)=>sum+(parseFloat(retGet(r.orderId,'amt'))||0),0),exchanges=rows.filter(r=>retGet(r.orderId,'type')==='Exchange').length;
    const card=(val,label,color,bg,border)=>`<div style="background:${bg};border:1px solid ${border};border-radius:12px;padding:14px 18px;text-align:center"><div style="font-size:22px;font-weight:900;color:${color};line-height:1">${val}</div><div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#64748b;margin-top:4px">${label}</div></div>`;
    cards.innerHTML=card(total,'Total Returns','#c2410c','#fff7ed','#fed7aa')+card(exchanges,'Exchanges','#1d4ed8','#eff6ff','#bfdbfe')+card('₹'+totalVal.toLocaleString('en-IN',{maximumFractionDigits:0}),'Total Order Value','#1e293b','#f8fafc','#e2e8f0')+card('₹'+totalRec.toLocaleString('en-IN',{maximumFractionDigits:0}),'Amount Received','#15803d','#f0fdf4','#bbf7d0');
  }
  if(rows.length===0){tbody.innerHTML='<tr><td colspan="15" style="text-align:center;padding:32px;color:#94a3b8">No returned orders found.</td></tr>';return;}
  const statusOpts=['Pending','In Transit','Received','Closed','Rejected'];
  tbody.innerHTML=rows.map((s,i)=>{
    const oid=s.orderId||'',cid=oid.replace(/#/g,'');
    const order=ALL_DATA.find(x=>String(x.orderId)===String(cid));
    const name=order?.billingName||s.billingName||'-',phone=order?.billingPhone||'-',sku=order?.sku||order?.skuCode||'-';
    const normOidRet = String(oid).replace(/#/g,'').trim().toUpperCase();
    const awbRet = String(s.awb||s._source==='manual'?RET_DB_CACHE[normOidRet]?.awb||'':'').trim().toUpperCase();
    const dbEntry = RET_DB_CACHE[normOidRet];
    // Scanned returned: from scan history (scanReturned in DB), or in returnedOidSet
    const isScannedRet = (dbEntry?.scanReturned) || returnedOidSet.has(normOidRet) || (awbRet && returnedAwbSet.has(awbRet)) || s._source==='scan';
    const isManualRet = s._source==='manual';
    const rowBg = isScannedRet ? '#f0fdf4' : isManualRet ? '#fef9f0' : '';
    const rowBorder = isScannedRet ? '2px solid #bbf7d0' : isManualRet ? '1px solid #fed7aa' : '1px solid #f1f5f9';
    return `<tr style="cursor:pointer;border-bottom:${rowBorder};background:${rowBg}" onmouseover="this.style.background='${isScannedRet?'#dcfce7':isManualRet?'#fff7ed':'#fff7ed'}'" onmouseout="this.style.background='${rowBg}'">
      <td style="padding:8px 10px;color:#94a3b8;font-size:11px" onclick="openAgentDetail('${cid}')">${i+1}</td>
      <td style="padding:8px 10px;font-size:11px;color:#94a3b8;white-space:nowrap;font-family:monospace" onclick="openAgentDetail('${cid}')">${s.scanTimestamp||'-'}</td>
      <td style="padding:8px 10px;font-weight:700;color:#ea580c" onclick="openAgentDetail('${cid}')">${oid}</td>
      <td style="padding:8px 10px;font-weight:600;color:#0f172a;white-space:nowrap" onclick="openAgentDetail('${cid}')">${name}</td>
      <td style="padding:8px 10px;font-family:monospace;font-size:11px;color:#475569" onclick="openAgentDetail('${cid}')">${phone}</td>
      <td style="padding:6px 8px">${retInp(oid,'pickup','dd-mm-yyyy','110px','date')}</td>
      <td style="padding:6px 8px">${retInp(oid,'retdate','dd-mm-yyyy','110px','date')}</td>
      <td style="padding:6px 8px;background:#eff6ff">${retSel(oid,'type',['Return','Exchange'],'100px')}</td>
      <td style="padding:8px 10px;background:#eff6ff;font-size:11px;color:#334155">${sku}</td>
      <td style="padding:6px 8px;background:#eff6ff">${retInp(oid,'replsku','Replacement SKU','130px')}</td>
      <td style="padding:6px 8px;background:#f0fdf4">${retInp(oid,'amt','0','90px','number')}</td>
      <td style="padding:6px 8px;background:#f0fdf4">${retInp(oid,'remark','Remarks...','140px')}</td>
      <td style="padding:6px 8px;background:#fff7ed">
        ${isScannedRet&&s._source==='manual'
          ? '<div style="margin-bottom:3px"><span style="background:#dcfce7;color:#15803d;border:1px solid #bbf7d0;padding:1px 7px;border-radius:99px;font-size:10px;font-weight:700">✅ Received</span></div>'+retSel(oid,'status',statusOpts,'105px')
          : retSel(oid,'status',statusOpts,'105px')}
      </td>
      <td style="padding:6px 8px;background:#fff7ed">${retInp(oid,'agent','Agent name','100px')}</td>
      <td style="padding:8px 10px;font-size:11px;color:#64748b;white-space:nowrap">${s.courierName||'-'}</td>
      ${isManualRet&&IS_ADMIN
        ? `<td style="padding:6px 8px;text-align:center"><button onclick="event.stopPropagation();deleteManualReturn('${cid}')" style="background:#fee2e2;color:#b91c1c;border:1px solid #fecaca;border-radius:6px;padding:3px 8px;font-size:11px;cursor:pointer;font-weight:700" title="Delete entry">🗑</button></td>`
        : isManualRet ? '<td style="padding:6px 8px"></td>' : '<td></td>'}
    </tr>`;
  }).join('');
}
function exportReturnsCSV(){
  const rows=[...SCAN_HISTORY_DATA].filter(s=>(s.dispatchStatus||'')==='Returned').sort((a,b)=>(b.scanTimestamp||'').localeCompare(a.scanTimestamp||''));
  let csv='Return Date,Order ID,Customer,Phone,Courier,Return Type,Old SKU,Replacement SKU,Amt Received,Remarks,Status,Agent\n';
  rows.forEach(s=>{const o=ALL_DATA.find(x=>String(x.orderId)===String((s.orderId||'').replace(/#/g,'')));csv+=`"${s.scanTimestamp||''}","${s.orderId||''}","${o?.billingName||s.billingName||''}","${o?.billingPhone||''}","${s.courierName||''}","${retGet(s.orderId,'type')}","${o?.sku||o?.skuCode||''}","${retGet(s.orderId,'replsku')}","${retGet(s.orderId,'amt')}","${retGet(s.orderId,'remark')}","${retGet(s.orderId,'status')}","${retGet(s.orderId,'agent')}"\n`;});
  const a=document.createElement('a');a.href='data:text/csv;charset=utf-8,'+encodeURIComponent(csv);a.download='returns_ledger_'+new Date().toISOString().split('T')[0]+'.csv';a.click();
}

// P&L REPORT
// ============================================================
let CURRENT_PNL_DATA = [];

function toggleAnalyticsView(viewType) {
  ['default-analytics-section','pnl-report-section','ai-report-section'].forEach(id=>{
    const el=document.getElementById(id); if(el) el.style.display='none';
  });
  ['an-btn-default','an-btn-pnl','an-btn-ai'].forEach(id=>{
    const el=document.getElementById(id);
    if(el){el.style.borderColor='';el.style.color='';el.style.background='';}
  });
  if(viewType==='pnl') {
    const el=document.getElementById('pnl-report-section'); if(el) el.style.display='block';
    const btn=document.getElementById('an-btn-pnl'); if(btn){btn.style.background='#6366f1';btn.style.color='#fff';btn.style.borderColor='#6366f1';}
    const today=new Date().toISOString().split('T')[0];
    const ps=document.getElementById('pnl-start'),pe=document.getElementById('pnl-end');
    if(ps&&!ps.value)ps.value=today; if(pe&&!pe.value)pe.value=today;
  } else if(viewType==='ai') {
    const el=document.getElementById('ai-report-section'); if(el) el.style.display='block';
    const btn=document.getElementById('an-btn-ai'); if(btn){btn.style.background='#7c3aed';btn.style.color='#fff';btn.style.borderColor='#7c3aed';}
    opsInit();
  } else {
    const el=document.getElementById('default-analytics-section'); if(el) el.style.display='block';
    const btn=document.getElementById('an-btn-default'); if(btn){btn.style.borderColor='#16a34a';btn.style.color='#16a34a';}
  }
}

window.PNL_MODE = window.PNL_MODE || 'paid';

// COGS lookup by short SKU (upper-case)
// ── COGS data (loaded from DB cogs_master) ──
window.COGS_DATA = window.COGS_DATA || {};   // article(upper) -> {sp, cogs}

// Extract article code from a SKU: F-109-White-XL -> F-109 ; FP-156-Wine-L -> FP-156
function extractArticle(sku) {
  if (!sku) return '';
  let s = String(sku).trim().toUpperCase();
  if (!s) return '';

  // Normalise the COGS article keys once (e.g. "CUFFLINKS", "COMBO F-511", "F-109")
  const cogsKeys = window.COGS_KEYS_UPPER || (window.COGS_KEYS_UPPER =
    Object.values(window.COGS_DATA||{}).map(x => String(x.article||'').trim().toUpperCase()).filter(Boolean));

  // 1) Exact match to a COGS article
  if (cogsKeys.indexOf(s) !== -1) return s;

  // 2) Longest COGS key that is a prefix of this SKU (most reliable when COGS is well-populated)
  //    e.g. "F-109-WHITE-XL" -> "F-109", "CUFFLINKS-A" -> "CUFFLINKS", "BUNDLE-F-511-BLACK" -> "BUNDLE-F-511"
  let best = '';
  for (const k of cogsKeys) {
    if (k && (s === k || s.startsWith(k + '-') || s.startsWith(k + ' ')) && k.length > best.length) best = k;
  }
  if (best) return best;

  // 3) Code pattern: a (possibly word) prefix + number, e.g. F-109, FP-156, BUNDLE-F-511, COMBO-F-543
  //    Capture letters/hyphenated-letters up to and including the first numeric group.
  let m = s.match(/^([A-Z]+(?:-[A-Z]+)*-\d+)/);
  if (m) {
    const code = m[1];                                   // e.g. BUNDLE-F-511
    if (cogsKeys.indexOf(code) !== -1) return code;
    const spaced = code.replace(/^(BUNDLE|COMBO)-/, '$1 '); // "BUNDLE F-511" / "COMBO F-511"
    if (cogsKeys.indexOf(spaced) !== -1) return spaced;
    return code;
  }

  // 4) Fallback: strip a trailing short variant token (CUFFLINKS-A -> CUFFLINKS)
  const parts = s.split(/[-\s]+/);
  if (parts.length >= 2) {
    const last = parts[parts.length-1];
    if (/^[A-Z]{1,3}$/.test(last)) return parts.slice(0, -1).join('-');
    return parts[0] + '-' + parts[1];
  }
  return s;
}

async function ensureCogsLoaded(force) {
  if (!force && Object.keys(window.COGS_DATA).length) return;
  try {
    const r = await apiCall('cogs_get');
    if (r && r.status === 'success' && r.data) {
      window.COGS_DATA = {};
      r.data.forEach(row => {
        window.COGS_DATA[String(row.article).trim().toUpperCase()] = {
          sp: parseFloat(row.sp) || 0, cogs: parseFloat(row.cogs) || 0, id: row.id, article: row.article
        };
      });
      window.COGS_KEYS_UPPER = null; // rebuild on next extractArticle call
    }
  } catch(e) { console.warn('COGS load failed', e); }
}

function pnlSumAdSpend() {
  const ids = ['ad-fb2','ad-fb6','ad-filo','ad-filo3','ad-google','ad-whatsapp'];
  let sum = 0;
  ids.forEach(id => { const v = parseFloat(document.getElementById(id)?.value||0); if(!isNaN(v)) sum += v; });
  const total = document.getElementById('pnl-ad-spend');
  if (total) total.value = sum ? sum : '';
}

async function fetchPnLReport() {
  const sDate   = document.getElementById('pnl-start')?.value;
  const eDate   = document.getElementById('pnl-end')?.value;
  pnlSumAdSpend();
  const adSpend = document.getElementById('pnl-ad-spend')?.value;
  const ordersReceivedInput = document.getElementById('pnl-orders-received')?.value;
  const officeExpInput = document.getElementById('pnl-office-exp')?.value;
  const tbody   = document.getElementById('pnl-report-body');
  if (!sDate||!eDate) { showToast('Please select Start and End dates','error'); return; }
  if (!adSpend)       { showToast('Please enter at least one Ad Spend amount','error'); return; }
  if (!ordersReceivedInput) { showToast('Please enter Total Orders Received (CPA denominator)','error'); return; }
  tbody.innerHTML = '<tr><td colspan="38" style="text-align:center;padding:32px;color:#6366f1;font-weight:700"><i class="fas fa-spinner fa-spin" style="margin-right:8px"></i>Generating P&L Report...</td></tr>';

  try {
    await ensureCogsLoaded(false);
    const adSpendNum = parseFloat(adSpend) || 0;

    const vendorSel = document.getElementById('pnl-vendor')?.value || '';

    // Fetch orders for the selected range DIRECTLY from the DB (shopify_orders + last_year_orders).
    // ALL_DATA only holds the latest ~5000 orders, so older months would otherwise collapse to UNKNOWN-ITEM.
    let pnlOrders = [];
    try {
      const por = await apiCall('pnl_orders', { start: sDate, end: eDate });
      if (por && por.status==='success' && Array.isArray(por.data)) pnlOrders = por.data;
    } catch(e) { console.warn('pnl_orders fetch failed, falling back to loaded orders', e); }

    // Fallback to in-memory orders if the endpoint returns nothing
    if (!pnlOrders.length) {
      pnlOrders = ALL_DATA.filter(o => {
        const d = extractDate(o.createdAt||'');
        return d && d >= sDate && d <= eDate;
      });
    }

    const filteredRaw = pnlOrders.filter(o => {
      const d = extractDate(o.createdAt||'');
      if (!(d && d >= sDate && d <= eDate)) return false;
      if (vendorSel && o.vendor !== vendorSel) return false;
      return true;
    });
    // Safety net: collapse any duplicate orders (same order id) that could slip in from the two
    // source tables, so each order is counted exactly once per article.
    const _seenOrder = new Set();
    const filtered = filteredRaw.filter(o => {
      const k = String(o.orderId||'').replace(/#/g,'').trim().toUpperCase();
      if (!k || _seenOrder.has(k)) return false;
      _seenOrder.add(k);
      return true;
    });
    if (filtered.length===0) {
      tbody.innerHTML = '<tr><td colspan="38" style="text-align:center;padding:32px;color:#94a3b8">No orders found in this date range.</td></tr>';
      return;
    }

    // Auto-load Clickpost (delivered) + Payment (COD received) from DB if needed
    if (!OPS_CP_DATA || OPS_CP_DATA.length === 0) {
      try { const cpr = await apiCall('get_clickpost');
        if (cpr && cpr.status==='success' && cpr.data) OPS_CP_DATA = cpr.data.map(r=>({'Waybill':r.waybill||'','Order ID':r.order_id||'','Courier':r.courier_name||'','Status':r.status||''}));
      } catch(e){}
    }
    // Always reload payment data from DB so COD + Prepaid revenue is fresh and complete
    try {
      const pr = await apiCall('get_payment_data');
      if (pr && pr.status==='success' && pr.data && pr.data.length) {
        window.LC_PAYMENT_DATA = pr.data.map(row=>({orderId:row.order_id||'',awb:row.awb||'',amount:String(row.amount||''),gateway:row.gateway||row.payment_method||''}));
      }
    } catch(e){}

    const normId = v => String(v||'').replace(/#/g,'').trim().toUpperCase();

    // Order-level lookups
    const dispatchedSet = new Set();
    (SCAN_HISTORY_DATA || []).forEach(s => { if (String(s.dispatchStatus||'')==='Dispatched'){ const k=normId(s.orderId); if(k) dispatchedSet.add(k); }});
    const deliveredSet = new Set();
    (OPS_CP_DATA || []).forEach(c => { const st=String(c['Status']||'').toLowerCase();
      if (st.indexOf('delivered')!==-1 && st.indexOf('rto')===-1){ const oid=normId(c['Order ID']); if(oid)deliveredSet.add(oid); const wb=String(c['Waybill']||'').trim().toUpperCase(); if(wb)deliveredSet.add(wb);} });
    // Revenue source = uploaded payment files. Match by Order Number OR AWB and SUM all matching lines.
    const payAmtMap = {};
    (window.LC_PAYMENT_DATA || []).forEach(r => {
      const amt = parseFloat(String(r.amount||'').replace(/[^0-9.\-]/g,'')) || 0;
      if (!amt) return;
      const keys = new Set();
      const ko = normId(r.orderId); if (ko) keys.add(ko);
      const ka = normId(r.awb);     if (ka) keys.add(ka);
      keys.forEach(k => { payAmtMap[k] = (payAmtMap[k]||0) + amt; });
    });

    // Build an Order ID -> AWB map from Clickpost so payment rows that only carry an AWB still match.
    const cpAwbByOrder = {};
    (OPS_CP_DATA || []).forEach(c => {
      const oid = normId(c['Order ID']); const wb = String(c['Waybill']||'').trim().toUpperCase();
      if (oid && wb && !cpAwbByOrder[oid]) cpAwbByOrder[oid] = wb;
    });

    // ── Constants matching Excel ──
    // CPA per order received = (Total Ad Spend / Total Orders Received) * 1.18   [Excel $H$76]
    // Total Orders Received is the manually-entered period figure (Excel B75 = 5402), not the filtered count.
    const totalOrdersReceived = parseFloat(ordersReceivedInput) || 0;
    const cpaPerOrder = totalOrdersReceived > 0 ? (adSpendNum / totalOrdersReceived) * 1.18 : 0;

    // Group by ARTICLE (extracted from SKU). Split COD vs Prepaid per order.
    const art = {};   // article -> {cod:{...}, pp:{...}}
    const blank = () => ({orderSet:new Set(), lineItems:0, dispSet:new Set(), delSet:new Set(), revenue:0});
    function getA(article) {
      if (!art[article]) art[article] = { cod: blank(), pp: blank() };
      return art[article];
    }

    filtered.forEach(o => {
      // Build the list of {article, qty} for this order from its line items
      let lines = [];
      if (Array.isArray(o.skuList) && o.skuList.length) {
        // Backend gives a rough article + raw sku; re-run the COGS-aware extractor to collapse variants.
        lines = o.skuList.map(x => ({article: extractArticle(String(x.raw || x.a || '')), qty: parseInt(x.q||1)||1}));
      } else {
        // Fallback: parse the combined sku string, qty unknown -> 1 each
        const skus = String(o.sku||'').split(',').map(s=>s.trim()).filter(Boolean);
        if (skus.length) lines = skus.map(s => ({article: extractArticle(s), qty: 1}));
        else { const a = extractArticle(String(o.itemName||'')); if(a) lines=[{article:a, qty:parseInt(o.itemQty||1)||1}]; }
      }
      if (!lines.length) return;

      const price = parseFloat(o.totalPrice||o.itemPrice||0) || 0;
      const fin   = String(o.financialStatus||'').toLowerCase();
      const tagsL = String(o.tags||'').toLowerCase();
      const pmL   = String(o.paymentMethod||'').toLowerCase();
      // Note: cancelled orders ARE counted as received — if an order came in, it counts even if
      // it was cancelled later. So no cancellation exclusion here.
      // COD vs Prepaid — driven by the order tags Shopify/GoKwik set:
      //   COD orders carry a "COD" tag; prepaid orders carry "PREPAID-DISCOUNT".
      //   PPCOD/Gokwik UPI-advance orders are COD even though Shopify marks them paid.
      const hasCodTag     = /(^|[,\s])cod([,\s]|$)/.test(tagsL);
      const hasPrepaidTag = tagsL.includes('prepaid');
      const isPpcod = tagsL.includes('ppcod') || tagsL.includes('gokwik_ppcod')
                   || pmL.includes('ppcod') || pmL.includes('gokwik_ppcod');
      let isPaid;
      if (hasCodTag || isPpcod) isPaid = false;            // COD (incl. PPCOD)
      else if (hasPrepaidTag)   isPaid = true;             // Prepaid
      else                      isPaid = (fin === 'paid'); // fallback to financial status
      const bucket = isPaid ? 'pp' : 'cod';
      const oidKey = normId(o.orderId);
      const longKey = normId(o.longId);
      const awbKey = String(o.awb||'').trim().toUpperCase() || cpAwbByOrder[oidKey] || '';
      const isDispatched = dispatchedSet.has(oidKey) || (awbKey && dispatchedSet.has(awbKey)) || o.dispatchStatus==='Dispatched';
      const isDelivered  = deliveredSet.has(oidKey) || (awbKey && deliveredSet.has(awbKey));
      // Revenue match: try clean order id, long Shopify id, then AWB (own or from Clickpost)
      let payAmt;
      if (payAmtMap[oidKey]!==undefined) payAmt = payAmtMap[oidKey];
      else if (longKey && payAmtMap[longKey]!==undefined) payAmt = payAmtMap[longKey];
      else if (awbKey && payAmtMap[awbKey]!==undefined) payAmt = payAmtMap[awbKey];

      // Distinct articles in this order (so order/dispatch/delivery/revenue counted once per article)
      const distinctArticles = [...new Set(lines.map(l => l.article).filter(Boolean))];
      // Revenue = matched payment from uploaded files (Order No / AWB). Fall back to order price only if no payment match.
      const revenueForOrder = (payAmt !== undefined) ? payAmt : (isPaid ? price : 0);
      const revenueShare = distinctArticles.length ? (revenueForOrder / distinctArticles.length) : 0;

      // Line items: each line adds its qty to its article
      lines.forEach(l => {
        if (!l.article) return;
        const a = getA(l.article)[bucket];
        a.lineItems += l.qty;
      });
      // Order-level metrics: once per distinct article in the order
      distinctArticles.forEach(article => {
        const a = getA(article)[bucket];
        if (!a.orderSet.has(oidKey)) {
          a.orderSet.add(oidKey);
          a.revenue += revenueShare;
        }
        if (isDispatched) a.dispSet.add(oidKey);
        if (isDelivered)  a.delSet.add(oidKey);
      });
    });

    // Office Exp per line item = Office Exp total / total combined line items  [Excel $B$77]
    let totalCombinedLineItems = 0;
    Object.values(art).forEach(x => { totalCombinedLineItems += x.cod.lineItems + x.pp.lineItems; });
    const officeExpTotal = parseFloat(officeExpInput) || 480000;
    const officeExpPerItem = totalCombinedLineItems > 0 ? (officeExpTotal / totalCombinedLineItems) : 0;

    // Build rows
    CURRENT_PNL_DATA = Object.keys(art).sort().map(article => {
      const x = art[article];
      const cg = window.COGS_DATA[article.toUpperCase()] || {sp:0, cogs:0};
      const cogs = cg.cogs, sp = cg.sp;

      // ── COD section ──
      const E = x.cod.orderSet.size;      // Total Order Received (COD)
      const F = x.cod.lineItems;          // Total Line Item received (COD)
      const H = x.cod.dispSet.size;       // Total Dispatch COD
      const I = x.cod.delSet.size;        // Total Del (COD)
      const K = x.cod.revenue;            // Revenue (COD)
      const cod_aveOrder = I>0 ? (K/I) : null;
      const cod_cpaEF    = F>0 ? (cpaPerOrder*E/F) : 0;
      const cod_delPct   = H>0 ? (I/H*100) : 0;
      const cod_cogs     = I*cogs;        // L = I*B
      const cod_cpa      = cpaPerOrder*E; // M = H76*E
      const cod_courier  = 125*H;         // N = 125*H
      const cod_offExp   = officeExpPerItem*F; // O = B77*F
      const cod_pnl      = K - cod_cogs - cod_cpa - cod_courier - cod_offExp; // P

      // ── Prepaid section ──
      const R = x.pp.orderSet.size;       // Total Order received (PP)
      const S = x.pp.lineItems;           // Total Line Item received (PP)
      const T = x.pp.dispSet.size;        // Total Dispatch (PP)
      const U = x.pp.delSet.size;         // Delivery (PP)
      const W = x.pp.revenue;             // Revenue (PP)
      const pp_delPct  = T>0 ? (U/T*100) : 0;
      const pp_cogs    = U*cogs;          // X = U*B
      const pp_cpa     = cpaPerOrder*R;   // Y = H76*R
      const pp_courier = 80*T;            // Z = 80*T
      const pp_offExp  = officeExpPerItem*S; // AA = B77*S
      const pp_pnl     = W - pp_cogs - pp_cpa - pp_courier - pp_offExp; // AB

      const ppCodPct = (F+S)>0 ? (S/(F+S)*100) : 0;  // Q = S/(F+S)*100

      // ── Combined ──
      const c_lineItems = F + S;          // AC
      const c_del       = I + U;          // AD
      const c_disp      = H + T;          // AE
      const c_delPct    = c_disp>0 ? (c_del/c_disp*100) : 0; // AF
      const c_cpaUnit   = c_delPct>0 ? (cpaPerOrder*100/c_delPct) : 0; // AG
      const c_pnl       = cod_pnl + pp_pnl; // AH

      return { article, cogs, sp,
        cod_aveOrder, E, F, cod_cpaEF, H, I, cod_delPct, K, cod_cogs, cod_cpa, cod_courier, cod_offExp, cod_pnl, ppCodPct,
        R, S, T, U, pp_delPct, W, pp_cogs, pp_cpa, pp_courier, pp_offExp, pp_pnl,
        c_lineItems, c_del, c_disp, c_delPct, c_cpaUnit, c_pnl };
    }).filter(r => (r.E + r.R) > 0);

    if (CURRENT_PNL_DATA.length === 0) {
      tbody.innerHTML = '<tr><td colspan="38" style="text-align:center;padding:32px;color:#94a3b8">No data found.</td></tr>'; return;
    }

    const n0 = v => (Math.round(v)).toLocaleString('en-IN');
    const n1 = v => (Number(v).toFixed(1));
    const td = (v,bg,col,bold) => `<td style="padding:7px 8px;background:${bg||'#fff'};color:${col||'#334155'};font-weight:${bold?'800':'600'};text-align:center;white-space:nowrap">${v}</td>`;

    tbody.innerHTML = CURRENT_PNL_DATA.map(r => {
      const pnlCol = v => v>=0 ? '#15803d' : '#dc2626';
      return `<tr style="border-bottom:1px solid #f1f5f9" onmouseover="this.style.background='#fafafa'" onmouseout="this.style.background=''">
        <td style="padding:7px 10px;font-weight:700;color:#1e293b;text-align:left;position:sticky;left:0;background:#fff;border-right:2px solid #e2e8f0">${r.article}</td>
        ${td('₹'+n0(r.cogs),'#fef2f2','#b91c1c')}
        <td style="padding:7px 8px;background:#f0fdf4;color:#15803d;font-weight:600;text-align:center;border-right:2px solid #e2e8f0">₹${n0(r.sp)}</td>
        ${td(r.cod_aveOrder===null?'—':'₹'+n0(r.cod_aveOrder),'#fff7ed','#9a3412')}
        ${td(r.E,'#fff7ed','#9a3412')}
        ${td(r.F,'#fff7ed','#9a3412')}
        ${td('₹'+n0(r.cod_cpaEF),'#fff7ed','#9a3412')}
        ${td(r.H,'#fff7ed','#9a3412')}
        ${td(r.I,'#fff7ed','#9a3412')}
        ${td(n1(r.cod_delPct)+'%','#fff7ed','#9a3412')}
        ${td('₹'+n0(r.K),'#fff7ed','#9a3412')}
        ${td('₹'+n0(r.cod_cogs),'#fff7ed','#9a3412')}
        ${td('₹'+n0(r.cod_cpa),'#fff7ed','#9a3412')}
        ${td('₹'+n0(r.cod_courier),'#fff7ed','#9a3412')}
        ${td('₹'+n0(r.cod_offExp),'#fff7ed','#9a3412')}
        ${td('₹'+n0(r.cod_pnl),'#fff7ed',pnlCol(r.cod_pnl),true)}
        <td style="padding:7px 8px;background:#fff7ed;color:#9a3412;font-weight:600;text-align:center;border-right:2px solid #e2e8f0">${n1(r.ppCodPct)}%</td>
        ${td(r.R,'#eff6ff','#1e40af')}
        ${td(r.S,'#eff6ff','#1e40af')}
        ${td(r.T,'#eff6ff','#1e40af')}
        ${td(r.U,'#eff6ff','#1e40af')}
        ${td(n1(r.pp_delPct)+'%','#eff6ff','#1e40af')}
        ${td('₹'+n0(r.W),'#eff6ff','#1e40af')}
        ${td('₹'+n0(r.pp_cogs),'#eff6ff','#1e40af')}
        ${td('₹'+n0(r.pp_cpa),'#eff6ff','#1e40af')}
        ${td('₹'+n0(r.pp_courier),'#eff6ff','#1e40af')}
        ${td('₹'+n0(r.pp_offExp),'#eff6ff','#1e40af')}
        ${td('₹'+n0(r.pp_pnl),'#eff6ff',pnlCol(r.pp_pnl),true)}
        <td style="background:#eff6ff;border-right:2px solid #e2e8f0"></td>
        ${td(r.c_lineItems,'#f5f3ff','#5b21b6')}
        ${td(r.c_del,'#f5f3ff','#5b21b6')}
        ${td(r.c_disp,'#f5f3ff','#5b21b6')}
        ${td(n1(r.c_delPct)+'%','#f5f3ff','#5b21b6')}
        ${td('₹'+n0(r.c_cpaUnit),'#f5f3ff','#5b21b6')}
        ${td('₹'+n0(r.c_pnl),'#f5f3ff',pnlCol(r.c_pnl),true)}
      </tr>`;
    }).join('');
    showToast('P&L Report Generated!','success');
  } catch(e) {
    tbody.innerHTML = `<tr><td colspan="38" style="text-align:center;padding:32px;color:#ef4444">Error: ${e.message}</td></tr>`;
    console.error(e);
  }
}

function exportPnLReport() {
  if(!CURRENT_PNL_DATA.length){showToast('No data to export. Generate the report first.','error');return;}
  const headers = ['Article','COGS','SP',
    'COD Ave Order','COD Order Recd','COD Line Item','COD CPA*E/F','COD Dispatch','COD Total Del','COD Del%','COD Revenue','COD COGS','COD CPA','COD Courier','COD Off Exp','COD P&L Bef Exp','PP/COD%',
    'PP Order Recd','PP Line Item','PP Dispatch','PP Delivery','PP Del%','PP Revenue','PP COGS','PP CPA','PP Courier','PP Off Exp','PP P&L Bef Exp',
    'Comb Line Item','Comb Total Del','Comb Dispatch','Comb Del%','Comb CPA/Unit','Comb P&L'];
  const rows = CURRENT_PNL_DATA.map(r=>[r.article,r.cogs,r.sp,
    r.cod_aveOrder===null?'':Math.round(r.cod_aveOrder),r.E,r.F,Math.round(r.cod_cpaEF),r.H,r.I,r.cod_delPct.toFixed(1),Math.round(r.K),Math.round(r.cod_cogs),Math.round(r.cod_cpa),Math.round(r.cod_courier),Math.round(r.cod_offExp),Math.round(r.cod_pnl),r.ppCodPct.toFixed(1),
    r.R,r.S,r.T,r.U,r.pp_delPct.toFixed(1),Math.round(r.W),Math.round(r.pp_cogs),Math.round(r.pp_cpa),Math.round(r.pp_courier),Math.round(r.pp_offExp),Math.round(r.pp_pnl),
    r.c_lineItems,r.c_del,r.c_disp,r.c_delPct.toFixed(1),Math.round(r.c_cpaUnit),Math.round(r.c_pnl)]);
  try {
    const ws = XLSX.utils.aoa_to_sheet([headers,...rows]);
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, 'P&L Report');
    XLSX.writeFile(wb, 'PnL_Report_'+new Date().toISOString().slice(0,10)+'.xlsx');
    showToast('P&L Report exported!','success');
  } catch(e) { showToast('Export failed: '+e.message,'error'); }
}

// ── COGS management modal ──
function closeCogsModal() {
  const m = document.getElementById('cogsModal');
  if (m) m.remove();
}
async function openCogsModal() {
  await ensureCogsLoaded(true);
  let modal = document.getElementById('cogsModal');
  if (!modal) {
    modal = document.createElement('div');
    modal.id = 'cogsModal';
    modal.className = 'modal-backdrop';
    modal.style.cssText = 'position:fixed;inset:0;background:rgba(15,23,42,0.5);z-index:1000;display:flex;align-items:center;justify-content:center;padding:20px';
    modal.onclick = e => { if (e.target===modal) closeCogsModal(); };
    modal.innerHTML = `<div style="background:#fff;border-radius:14px;width:100%;max-width:640px;max-height:88vh;display:flex;flex-direction:column;overflow:hidden">
      <div style="padding:16px 20px;border-bottom:1px solid #e2e8f0;display:flex;justify-content:space-between;align-items:center">
        <h3 style="font-weight:800;color:#1e293b;font-size:15px"><i class="fas fa-sliders-h" style="color:#6366f1;margin-right:8px"></i>Manage COGS &amp; Selling Price</h3>
        <button onclick="closeCogsModal()" style="background:none;border:none;font-size:18px;color:#94a3b8;cursor:pointer">&times;</button>
      </div>
      <div style="padding:12px 20px;border-bottom:1px solid #f1f5f9;display:flex;gap:8px;align-items:end;flex-wrap:wrap">
        <div><label style="font-size:10px;font-weight:700;color:#64748b;text-transform:uppercase">Article</label><input id="cogs-new-article" placeholder="e.g. F-160" style="display:block;border:1px solid #e2e8f0;border-radius:6px;padding:6px 10px;font-size:13px;width:130px"></div>
        <div><label style="font-size:10px;font-weight:700;color:#64748b;text-transform:uppercase">SP ₹</label><input id="cogs-new-sp" type="number" placeholder="899" style="display:block;border:1px solid #e2e8f0;border-radius:6px;padding:6px 10px;font-size:13px;width:90px"></div>
        <div><label style="font-size:10px;font-weight:700;color:#64748b;text-transform:uppercase">COGS ₹</label><input id="cogs-new-cogs" type="number" placeholder="335" style="display:block;border:1px solid #e2e8f0;border-radius:6px;padding:6px 10px;font-size:13px;width:90px"></div>
        <button onclick="cogsSaveNew()" class="btn btn-sm" style="background:#6366f1;color:#fff;height:34px"><i class="fas fa-plus"></i> Add / Update</button>
        <input id="cogs-search" oninput="cogsRenderList()" placeholder="Search article…" style="margin-left:auto;border:1px solid #e2e8f0;border-radius:6px;padding:6px 10px;font-size:13px;width:150px">
      </div>
      <div style="overflow-y:auto;flex:1"><table style="width:100%;border-collapse:collapse;font-size:13px"><thead style="position:sticky;top:0;background:#f8fafc;z-index:2"><tr>
        <th style="padding:8px 12px;text-align:left;font-size:10px;font-weight:700;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0">Article</th>
        <th style="padding:8px 12px;text-align:right;font-size:10px;font-weight:700;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0">SP ₹</th>
        <th style="padding:8px 12px;text-align:right;font-size:10px;font-weight:700;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0">COGS ₹</th>
        <th style="padding:8px 12px;border-bottom:1px solid #e2e8f0"></th>
      </tr></thead><tbody id="cogs-list-body"></tbody></table></div>
    </div>`;
    document.body.appendChild(modal);
  }
  modal.classList.remove('hidden');
  cogsRenderList();
}

function cogsRenderList() {
  const body = document.getElementById('cogs-list-body');
  if (!body) return;
  const q = (document.getElementById('cogs-search')?.value||'').toLowerCase().trim();
  let items = Object.values(window.COGS_DATA);
  if (q) items = items.filter(i => String(i.article).toLowerCase().includes(q));
  items.sort((a,b)=>String(a.article).localeCompare(String(b.article)));
  body.innerHTML = items.map(i => {
    const art = String(i.article).replace(/"/g,'&quot;');
    return `<tr style="border-bottom:1px solid #f8fafc">
      <td style="padding:6px 12px;font-weight:600;color:#334155">${i.article}</td>
      <td style="padding:6px 12px;text-align:right"><input type="number" value="${i.sp}" onchange="cogsInlineSave('${art}','sp',this.value)" style="width:80px;text-align:right;border:1px solid #e2e8f0;border-radius:5px;padding:3px 6px;font-size:12px"></td>
      <td style="padding:6px 12px;text-align:right"><input type="number" value="${i.cogs}" onchange="cogsInlineSave('${art}','cogs',this.value)" style="width:80px;text-align:right;border:1px solid #e2e8f0;border-radius:5px;padding:3px 6px;font-size:12px"></td>
      <td style="padding:6px 12px;text-align:center"><button onclick="cogsDelete('${art}')" style="background:#fef2f2;color:#dc2626;border:1px solid #fecaca;border-radius:5px;padding:3px 8px;font-size:11px;cursor:pointer"><i class="fas fa-trash"></i></button></td>
    </tr>`;
  }).join('') || '<tr><td colspan="4" style="padding:24px;text-align:center;color:#94a3b8">No articles. Add one above.</td></tr>';
}

async function cogsSaveNew() {
  const article = (document.getElementById('cogs-new-article')?.value||'').trim();
  const sp = document.getElementById('cogs-new-sp')?.value;
  const cogs = document.getElementById('cogs-new-cogs')?.value;
  if (!article) { showToast('Enter an article code','error'); return; }
  const r = await apiCall('cogs_save', {article, sp:parseFloat(sp)||0, cogs:parseFloat(cogs)||0});
  if (r && r.status==='success') {
    window.COGS_DATA[article.toUpperCase()] = {sp:parseFloat(sp)||0, cogs:parseFloat(cogs)||0, article};
    document.getElementById('cogs-new-article').value='';
    document.getElementById('cogs-new-sp').value='';
    document.getElementById('cogs-new-cogs').value='';
    cogsRenderList();
    showToast('Saved '+article,'success');
  } else showToast('Save failed: '+((r&&r.msg)||'error'),'error');
}

async function cogsInlineSave(article, field, value) {
  const rec = window.COGS_DATA[article.toUpperCase()] || {sp:0,cogs:0,article};
  rec[field] = parseFloat(value)||0;
  const r = await apiCall('cogs_save', {article, sp:rec.sp, cogs:rec.cogs});
  if (r && r.status==='success') { window.COGS_DATA[article.toUpperCase()]=rec; showToast('Updated','success'); }
  else showToast('Save failed','error');
}

async function cogsDelete(article) {
  if (!confirm('Delete '+article+'?')) return;
  const r = await apiCall('cogs_delete', {article});
  if (r && r.status==='success') { delete window.COGS_DATA[article.toUpperCase()]; cogsRenderList(); showToast('Deleted '+article,'success'); }
  else showToast('Delete failed','error');
}

// ============================================================
// DELIVERY REPORT
// ============================================================
function renderDeliveryView() {
  const sDate = document.getElementById('del-start')?.value;
  const eDate = document.getElementById('del-end')?.value;
  const cards = document.getElementById('delivery-cards');
  const tbody = document.getElementById('delivery-list-body');
  const countEl = document.getElementById('delivery-list-count');
  const titleEl = document.getElementById('delivery-list-title');

  let filtered = ALL_DATA.filter(o => o.dispatchStatus==='Dispatched' || o.deliveryStatus);
  if(sDate&&eDate) {
    filtered = filtered.filter(o=>{
      const d=extractDate(o.scanTimestamp||o.createdAt||'');
      return d&&d>=sDate&&d<=eDate;
    });
  }
  if(countEl) countEl.textContent=filtered.length+' orders';
  if(titleEl) titleEl.textContent=(sDate&&eDate)?`Orders (${sDate} → ${eDate})`:'All Dispatched Orders';

  // Status counts
  const statMap={};
  filtered.forEach(o=>{const s=o.deliveryStatus||o.dispatchStatus||'Processing';statMap[s]=(statMap[s]||0)+1;});
  const statColors={'Dispatched':'#3b82f6','Delivered':'#10b981','Returned':'#f97316','Cancelled':'#ef4444','Processing':'#94a3b8','In Transit':'#8b5cf6'};
  if(cards) {
    cards.innerHTML=Object.entries(statMap).sort((a,b)=>b[1]-a[1]).map(([status,count])=>{
      const c=statColors[status]||'#64748b';
      return `<div class="card p-3 text-center" style="border-top:3px solid ${c}">
        <div style="font-size:22px;font-weight:900;color:${c}">${count}</div>
        <div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;color:#94a3b8;margin-top:3px">${status}</div>
      </div>`;
    }).join('');
  }
  if(tbody) {
    if(filtered.length===0){tbody.innerHTML='<tr><td colspan="7" style="text-align:center;padding:32px;color:#94a3b8">No dispatched orders found.</td></tr>';return;}
    const stColors={'Delivered':'#10b981','Returned':'#f97316','Cancelled':'#ef4444','Dispatched':'#3b82f6'};
    tbody.innerHTML=filtered.slice(0,500).map(o=>{
      const c=stColors[o.deliveryStatus||o.dispatchStatus]||'#94a3b8';
      return `<tr style="border-bottom:1px solid #f8fafc" onmouseover="this.style.background='#f8fafc'" onmouseout="this.style.background=''">
        <td style="padding:10px 14px;font-weight:700;font-family:monospace;color:#1e293b;font-size:13px">#${o.orderId}</td>
        <td style="padding:10px 14px;font-size:12px;color:#94a3b8">${o.createdAt?extractDate(o.createdAt):'—'}</td>
        <td style="padding:10px 14px;font-size:13px;color:#374151;font-weight:600">${o.billingName||'—'}</td>
        <td style="padding:10px 14px;font-size:12px;color:#64748b">${o.courierName||o.courier||'—'}</td>
        <td style="padding:10px 14px;font-size:11px;font-family:monospace;color:#64748b">${o.awb||'—'}</td>
        <td style="padding:10px 14px"><span style="background:${c}15;color:${c};padding:2px 10px;border-radius:99px;font-size:10px;font-weight:700;text-transform:uppercase;border:1px solid ${c}30">${o.dispatchStatus||'—'}</span></td>
        <td style="padding:10px 14px"><span style="background:${c}15;color:${c};padding:2px 10px;border-radius:99px;font-size:10px;font-weight:700;text-transform:uppercase;border:1px solid ${c}30">${o.deliveryStatus||'Processing'}</span></td>
      </tr>`;
    }).join('');
  }
}

// ============================================================
// TRAINING TAB
// ============================================================
function formatDriveImageUrl(url) {
  if(!url) return '';
  let str=String(url).trim();
  let m=str.match(/\/file\/d\/([a-zA-Z0-9_-]+)/);
  if(m&&m[1]) return 'https://drive.google.com/uc?export=view&id='+m[1];
  let m2=str.match(/id=([a-zA-Z0-9_-]+)/);
  if(m2&&m2[1]) return 'https://drive.google.com/uc?export=view&id='+m2[1];
  return str;
}
function ensureAbsoluteUrl(url) {
  if(!url) return '';
  let t=String(url).trim();
  return (!t.startsWith('http://')&&!t.startsWith('https://')) ? 'https://'+t : t;
}

async function loadTrainingData() {
  const headersEl=document.getElementById('training-headers');
  const subsEl=document.getElementById('training-subs');
  const detailEl=document.getElementById('training-detail');
  const emptyEl=document.getElementById('training-empty');
  if(!headersEl) return;
  headersEl.innerHTML='<div style="padding:16px;color:#94a3b8;font-size:13px"><i class="fas fa-spinner fa-spin" style="margin-right:6px"></i>Loading...</div>';
  subsEl.style.display='none'; detailEl.style.display='none'; emptyEl.style.display='flex';

  try {
    const res = await fetch('api/training.php', {credentials:'same-origin'});
    if(!res.ok) throw new Error('HTTP '+res.status);
    const data = await res.json();
    if(data.status==='success') renderTrainingAccordion(data.data||[]);
    else { headersEl.innerHTML='<div style="padding:16px;color:#ef4444;font-size:13px;font-weight:700">Error: '+data.msg+'</div>'; }
  } catch(e) {
    headersEl.innerHTML='<div style="padding:16px;color:#ef4444;font-size:13px;font-weight:700">Failed to load training data. Check api/training.php</div>';
  }
}

function renderTrainingAccordion(data) {
  const headersEl=document.getElementById('training-headers');
  const subsEl=document.getElementById('training-subs');
  const detailEl=document.getElementById('training-detail');
  const emptyEl=document.getElementById('training-empty');
  headersEl.innerHTML=''; subsEl.innerHTML=''; detailEl.innerHTML='';
  if(!data||data.length===0){
    emptyEl.style.display='flex';
    emptyEl.innerHTML='<div style="text-align:center"><i class="fas fa-graduation-cap" style="font-size:40px;color:#e2e8f0;display:block;margin-bottom:12px"></i><p style="font-size:13px;color:#94a3b8">No training materials found.</p></div>';
    return;
  }
  emptyEl.style.display='none';
  data.forEach((item,idx)=>{
    const headerName=item.header||('Item '+(idx+1));
    const btn=document.createElement('button');
    btn.style.cssText='width:100%;text-align:left;padding:12px 16px;border-bottom:1px solid #f1f5f9;font-size:13px;font-weight:600;color:#374151;background:none;border-left:none;border-right:none;border-top:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;transition:all 0.15s';
    btn.innerHTML='<span>'+headerName+'</span><i class="fas fa-chevron-right" style="font-size:10px;color:#cbd5e1"></i>';
    btn.onmouseover=()=>{if(!btn.classList.contains('active'))btn.style.background='#f0fdf4';};
    btn.onmouseout=()=>{if(!btn.classList.contains('active'))btn.style.background='';};
    btn.onclick=()=>{
      headersEl.querySelectorAll('button').forEach(b=>{b.classList.remove('active');b.style.background='';b.style.color='#374151';});
      btn.classList.add('active'); btn.style.background='#16a34a'; btn.style.color='#fff';
      showTrainingSubheadings(item,data);
    };
    headersEl.appendChild(btn);
  });
  if(data.length>0) headersEl.querySelector('button').click();
}

function showTrainingSubheadings(item,allData) {
  const subsEl=document.getElementById('training-subs');
  const detailEl=document.getElementById('training-detail');
  subsEl.innerHTML=''; const subs=item.subheadings||[];
  if(subs.length===0){subsEl.style.display='none';showTrainingDetail(item.header||'',null,item);return;}
  subsEl.style.display='block'; detailEl.style.display='flex'; detailEl.style.alignItems='center'; detailEl.style.justifyContent='center';
  detailEl.innerHTML='<div style="color:#94a3b8;font-size:13px"><i class="fas fa-arrow-left" style="margin-right:6px"></i>Select a topic</div>';
  const title=document.createElement('div');
  title.style.cssText='padding:10px 16px;background:#16a34a;color:#fff;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em';
  title.textContent=item.header||'Topics'; subsEl.appendChild(title);
  subs.forEach((s,i)=>{
    const subName=s.sub||('Topic '+(i+1));
    const btn=document.createElement('button');
    btn.style.cssText='width:100%;text-align:left;padding:11px 16px;border-bottom:1px solid #f1f5f9;font-size:12px;color:#475569;background:none;border-left:none;border-right:none;border-top:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;transition:all 0.15s';
    btn.innerHTML='<span>'+subName+'</span><i class="fas fa-chevron-right" style="font-size:10px;color:#cbd5e1"></i>';
    btn.onclick=()=>{
      subsEl.querySelectorAll('button:not(:first-child)').forEach(b=>{b.style.background='';b.style.color='#475569';b.style.fontWeight='400';});
      btn.style.background='#f0fdf4'; btn.style.color='#15803d'; btn.style.fontWeight='700';
      showTrainingDetail(item.header||'',s,item);
    };
    subsEl.appendChild(btn);
  });
  if(subs.length>0){const btns=subsEl.querySelectorAll('button:not(:first-child)');if(btns.length>0)btns[0].click();}
}

function showTrainingDetail(headerName,sub,item) {
  const detailEl=document.getElementById('training-detail');
  detailEl.style.display='block'; detailEl.style.alignItems=''; detailEl.style.justifyContent='';
  const bodyText=(sub&&sub.body)?sub.body:'';
  const subTitle=(sub&&sub.sub)?sub.sub:'';
  const imageUrl=formatDriveImageUrl(item.image||'');
  const videoUrl=ensureAbsoluteUrl(item.video||'');
  let imageHtml='';
  if(imageUrl){imageHtml='<div style="margin-bottom:16px;border-radius:12px;overflow:hidden;border:1px solid #e2e8f0;background:#f8fafc"><img src="'+imageUrl+'" alt="'+subTitle+'" style="width:100%;max-height:280px;object-fit:cover" onerror="this.parentElement.innerHTML=\'<div style=\\\'padding:32px;text-align:center;color:#94a3b8;font-size:13px\\\'>Image unavailable</div>\'"></div>';}
  let videoHtml='';
  if(videoUrl){const yt=videoUrl.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/);if(yt){videoHtml='<div style="margin-bottom:16px;border-radius:12px;overflow:hidden;border:1px solid #e2e8f0;aspect-ratio:16/9"><iframe src="https://www.youtube.com/embed/'+yt[1]+'" style="width:100%;height:100%;border:none" allowfullscreen></iframe></div>';}else{videoHtml='<div style="margin-bottom:16px"><a href="'+videoUrl+'" target="_blank" rel="noopener" style="display:flex;align-items:center;justify-content:center;gap:8px;background:#fef2f2;color:#ef4444;border:1px solid #fecaca;padding:12px;border-radius:12px;font-size:13px;font-weight:700;text-decoration:none"><i class="fab fa-youtube" style="font-size:18px"></i>Watch Video</a></div>';}}
  const bodyHtml=bodyText?'<div style="font-size:14px;color:#475569;line-height:1.7;white-space:pre-wrap">'+bodyText+'</div>':'<p style="color:#94a3b8;font-size:13px;font-style:italic">No description provided.</p>';
  detailEl.innerHTML='<div style="font-size:10px;font-weight:700;color:#16a34a;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:6px">'+headerName+'</div><h2 style="font-size:17px;font-weight:800;color:#1e293b;margin-bottom:16px;line-height:1.3">'+(subTitle||headerName)+'</h2>'+imageHtml+videoHtml+bodyHtml;
}

// ============================================================
// AI OPS REPORT
// ============================================================
let OPS_CP_DATA   = null;
  let OPS_LY_DATA   = null;   // populated by opsLoadLYFromDB()
  let OPS_LY_LOADED = false;  // true once DB fetch completes
  let OPS_INITED    = false;

  // Auto-load Clickpost data if not already loaded
  async function opsAutoLoadClickpost() {
      if (!OPS_CP_DATA || OPS_CP_DATA.length === 0) {
          await opsLoadClickpost();
      }
  }

  // Auto-load Clickpost data if not already loaded
  async function opsAutoLoadClickpost() {
      if (!OPS_CP_DATA || OPS_CP_DATA.length === 0) {
          await opsLoadClickpost();
      }
  }

  function opsInit() {
      if (OPS_INITED) return;
      OPS_INITED = true;

      // Set default dates (last 12 days → today)
      const today  = new Date().toISOString().split('T')[0];
      const d12ago = new Date(); d12ago.setDate(d12ago.getDate() - 12);
      const fromEl = document.getElementById('ops-from');
      const toEl   = document.getElementById('ops-to');
      if (fromEl && !fromEl.value) fromEl.value = d12ago.toISOString().split('T')[0];
      if (toEl   && !toEl.value)   toEl.value   = today;

      // Fetch Last Year data from DB (non-blocking)
      opsLoadLYFromDB();

      // Show webhook status
      opsRefreshWebhookStatus();
  }

  function opsLoadLYFromDB() {
      const lyEl = document.getElementById('ops-ly-status');
      if (lyEl) { lyEl.textContent = '⏳ Fetching from database...'; lyEl.style.color = '#d97706'; }

      const url = 'https://filohevis-api.in/api.php?table=last_year_orders&limit=300000&nocache=' + Date.now();
      fetch(url)
          .then(function(r) { return r.json(); })
          .then(function(json) {
              if (json.status === 'success' && Array.isArray(json.data)) {
                  OPS_LY_DATA   = json.data;   // already slim {d, s, q} from PHP
                  OPS_LY_LOADED = true;
                  if (lyEl) {
                      lyEl.textContent = '✅ ' + json.total_rows + ' rows loaded';
                      lyEl.style.color = '#16a34a';
                  }
              } else {
                  throw new Error(json.message || 'DB error');
              }
          })
          .catch(function(err) {
              OPS_LY_DATA   = [];
              OPS_LY_LOADED = true;
              if (lyEl) {
                  lyEl.textContent = '❌ ' + err.message;
                  lyEl.style.color = '#dc2626';
              }
          });
  }

  function opsRefreshWebhookStatus() {
      const el = document.getElementById('ops-webhook-status');
      if (!el) return;
      const count = (typeof ALL_DATA !== 'undefined') ? ALL_DATA.length : 0;
      if (count > 0) {
          el.textContent = '✅ ' + count + ' orders loaded from Webhook';
          el.className = 'text-xs text-green-700 font-semibold';
      } else {
          el.textContent = '⏳ No Webhook data yet — refresh OMS';
          el.className = 'text-xs text-amber-600 font-semibold';
      }
  }

  async function opsLoadClickpost() {
      var nameEl = document.getElementById('ops-slot-cp-name');
      var slotEl = document.getElementById('ops-slot-cp');
      if (nameEl) nameEl.textContent = '⏳ Loading from database…';
      try {
          const result = await apiCall('get_clickpost');
          if (result && result.status === 'success') {
              // Map DB rows to the format opsRenderFulfilled expects
              OPS_CP_DATA = (result.data || []).map(function(r) {
                  return {
                      'Waybill':         r.waybill || '',
                      'Order ID':        r.order_id || '',
                      'Courier':         r.courier_name || '',
                      'Status':          r.status || '',
                      'Updated At':      r.updated_at || ''
                  };
              });
              if (slotEl) { slotEl.style.borderColor = '#16a34a'; slotEl.style.background = '#f0fdf4'; }
              if (nameEl) nameEl.textContent = '✅ ' + OPS_CP_DATA.length + ' records loaded from Clickpost live';
              showToast('Clickpost data loaded: ' + OPS_CP_DATA.length + ' records', 'success');
          } else {
              if (slotEl) { slotEl.style.borderColor = '#dc2626'; slotEl.style.background = '#fef2f2'; }
              if (nameEl) nameEl.textContent = '❌ Failed to load Clickpost data';
              showToast('Could not load Clickpost data', 'error');
          }
      } catch(err) {
          if (slotEl) { slotEl.style.borderColor = '#dc2626'; slotEl.style.background = '#fef2f2'; }
          if (nameEl) nameEl.textContent = '❌ ' + err.message;
          showToast('Error: ' + err.message, 'error');
      }
  }
  function opsHandleUpload(key, input) {
      // Legacy: kept for compatibility but Clickpost now loads from DB
      if (key !== 'cp') return;
  }

  function opsRunReport() {
      opsInit();
      opsRefreshWebhookStatus();
      opsAutoLoadClickpost();
      opsAutoLoadClickpost();
      const status   = document.getElementById('ops-status').value;
      const fromDate = document.getElementById('ops-from').value;
      const toDate   = document.getElementById('ops-to').value;
      if (!fromDate || !toDate) { showToast('Please select a date range', 'error'); return; }
      const main = document.getElementById('ops-main');
      if (!main) return;
      if (status === 'unfulfilled') opsRenderUnfulfilled(main, fromDate, toDate);
      else                          opsRenderFulfilled(main, fromDate, toDate);
  }

  // ---- HELPERS ----
  function opsFmtD(dateStr) {
      try { const d = new Date(dateStr); return d.getDate() + ' ' + d.toLocaleString('en-IN',{month:'short'}); } catch(e) { return dateStr; }
  }
  function opsFmtRange(f, t) {
      try {
          const fd = new Date(f), td = new Date(t);
          return fd.getDate() + '–' + td.getDate() + ' ' + td.toLocaleString('en-IN',{month:'short'}) + ' ' + td.getFullYear();
      } catch(e) { return f + ' to ' + t; }
  }
  function opsReasonBadge(reason) {
      const styles = {
          'No AWB':        'background:#fee2e2;color:#b91c1c;border:1px solid #fecaca;',
          'OOS':           'background:#ffedd5;color:#c2410c;border:1px solid #fed7aa;',
          'Pending verify':'background:#fef9c3;color:#a16207;border:1px solid #fde047;',
          'No label':      'background:#f3e8ff;color:#7e22ce;border:1px solid #e9d5ff;',
          'Hold':          'background:#f1f5f9;color:#475569;border:1px solid #cbd5e1;'
      };
      const st = styles[reason] || 'background:#f3f4f6;color:#374151;';
      return '<span style="' + st + 'padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;">' + reason + '</span>';
  }

  // ---- Get Latest data from Webhook (ALL_DATA) filtered by date ----
  function opsGetLatestOrders(fromDate, toDate) {
      if (typeof ALL_DATA === 'undefined' || !ALL_DATA || ALL_DATA.length === 0) return [];
      var from = new Date(fromDate);
      var to   = new Date(toDate); to.setHours(23,59,59,999);
      return ALL_DATA.filter(function(o) {
          var raw = o.createdAt || o.orderDate || '';
          var d   = new Date(raw);
          return d >= from && d <= to;
      });
  }

  // ---- UNFULFILLED ----
  function opsRenderUnfulfilled(main, fromDate, toDate) {
      const latest  = opsGetLatestOrders(fromDate, toDate);
      const orders  = opsParseUnfulfilledFromWebhook(latest, fromDate, toDate);
      const noAWB   = orders.filter(function(o){return o.reason==='No AWB';}).length;
      const pend    = orders.filter(function(o){return o.reason==='Pending verify';}).length;
      const oos     = orders.filter(function(o){return o.reason==='OOS';}).length;
      const noLabel = orders.filter(function(o){return o.reason==='No label';}).length;
      const range   = opsFmtRange(fromDate, toDate);

      // ---- Group by SKU ----
      var skuMap = {};
      orders.forEach(function(o) {
          if (!skuMap[o.sku]) skuMap[o.sku] = { sku:o.sku, product:o.product, qty:0, cod:0, prepaid:0, reasons:{} };
          skuMap[o.sku].qty     += parseInt(o.qty)||1;
          skuMap[o.sku].reasons[o.reason] = (skuMap[o.sku].reasons[o.reason]||0) + (parseInt(o.qty)||1);
          if (o.payment==='COD') skuMap[o.sku].cod     += parseInt(o.qty)||1;
          else                   skuMap[o.sku].prepaid += parseInt(o.qty)||1;
      });
      var skuRows = Object.values(skuMap).sort(function(a,b){ return b.qty - a.qty; });

      var rows = '';
      skuRows.forEach(function(r) {
          var rsplit = Object.entries(r.reasons).map(function(e){
              return opsReasonBadge(e[0]) + ' <span style="font-size:11px;font-weight:700;">×'+e[1]+'</span>';
          }).join(' ');
          rows +=
              '<tr class="hover:bg-slate-50 transition">' +
              '<td style="padding:10px 14px;font-family:monospace;font-size:12px;font-weight:600;color:#334155;">' + r.sku + '</td>' +
              '<td style="padding:10px 14px;font-size:13px;">' + r.product + '</td>' +
              '<td style="padding:10px 14px;font-size:15px;font-weight:800;color:#2563eb;">' + r.qty + '</td>' +
              '<td style="padding:10px 14px;">' +
                  (r.cod     ? '<span style="padding:2px 7px;border-radius:4px;font-size:11px;font-weight:600;background:#fef9c3;color:#a16207;border:1px solid #fde047;margin-right:4px;">COD ×'+r.cod+'</span>' : '') +
                  (r.prepaid ? '<span style="padding:2px 7px;border-radius:4px;font-size:11px;font-weight:600;background:#e0f2fe;color:#0369a1;border:1px solid #bae6fd;">Prepaid ×'+r.prepaid+'</span>' : '') +
              '</td>' +
              '<td style="padding:10px 14px;">' + rsplit + '</td>' +
              '</tr>';
      });
      if (!rows) rows = '<tr><td colspan="5" style="padding:32px;text-align:center;color:#94a3b8;">No unfulfilled orders found in this date range.</td></tr>';

      // Unique SKU count for stat card
      var uniqueSkus = skuRows.length;

      main.innerHTML =
          '<div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-5">' +
          [['#2563eb', orders.length,  'Unfulfilled orders', range],
           ['#7c3aed', uniqueSkus,     'Unique SKUs',        'across all unfulfilled'],
           ['#dc2626', noAWB,          'No AWB assigned',    'label not generated'],
           ['#d97706', pend,           'Payment pending',    'COD verification']].map(function(x){
              return '<div class="bg-white rounded-xl border border-slate-200 shadow-sm p-4">' +
                  '<div style="font-size:28px;font-weight:700;color:'+x[0]+';line-height:1;margin-bottom:4px;">'+x[1]+'</div>' +
                  '<div style="font-size:12px;font-weight:600;color:#475569;">'+x[2]+'</div>' +
                  '<div style="font-size:10px;color:#94a3b8;margin-top:2px;">'+x[3]+'</div>' +
              '</div>';
          }).join('') +
          '</div>' +
          '<div class="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden mb-5">' +
              '<div style="padding:12px 16px;border-bottom:1px solid #f1f5f9;background:#f8fafc;display:flex;justify-content:space-between;align-items:center;">' +
                  '<span style="font-size:13px;font-weight:700;color:#334155;">Unfulfilled — SKU wise &nbsp;<span style="font-size:11px;color:#94a3b8;font-weight:400;">'+range+'</span></span>' +
                  '<span style="font-size:11px;color:#94a3b8;">'+uniqueSkus+' SKUs &nbsp;|&nbsp; '+orders.length+' units total</span>' +
              '</div>' +
              '<div style="overflow-x:auto;">' +
                  '<table style="width:100%;border-collapse:collapse;font-size:13px;">' +
                      '<thead>' +
                          '<tr style="font-size:11px;color:#94a3b8;background:#f8fafc;">' +
                          '<th style="padding:8px 14px;text-align:left;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">SKU</th>' +
                          '<th style="padding:8px 14px;text-align:left;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Product</th>' +
                          '<th style="padding:8px 14px;text-align:left;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Total Qty</th>' +
                          '<th style="padding:8px 14px;text-align:left;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Payment Split</th>' +
                          '<th style="padding:8px 14px;text-align:left;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Reason</th>' +
                          '</tr>' +
                      '</thead>' +
                      '<tbody style="border-top:1px solid #f1f5f9;">' + rows + '</tbody>' +
                  '</table>' +
              '</div>' +
          '</div>' +
          '<div class="flex gap-3 mb-4 flex-wrap" id="ops-action-btns">' +
              '<button onclick="opsShowProd()" id="ops-btn-prod" class="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition" style="border:1.5px solid #e2e8f0;background:#fff;color:#334155;">' +
                  '<i class="fas fa-industry text-xs"></i> Production order' +
              '</button>' +
              '<button onclick="opsShowAIReport()" id="ops-btn-ai" class="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition" style="border:1.5px solid #7c3aed;background:#f5f3ff;color:#6d28d9;">' +
                  '<i class="fas fa-robot text-xs"></i> AI Text Report' +
              '</button>' +
          '</div>' +
          '<div id="ops-sub-sku" style="display:none;"></div>' +
          '<div id="ops-sub-prod" style="display:none;"></div>' +
          '<div id="ops-sub-ai" style="display:none;"></div>';

      window._opsOrders   = orders;
      window._opsFromDate = fromDate;
      window._opsToDate   = toDate;
  }

  function opsParseUnfulfilledFromWebhook(latest, fromDate, toDate) {
      var result = [];
      latest.forEach(function(o) {
          var st = (o.status || '').toString();
          if (st === 'Done' || st === 'Cancel') return;

          var reason = (!o.awb || o.awb === '') ? 'No AWB'
                     : (st === 'Pending' || st === '') ? 'Pending verify'
                     : 'No label';

          var dateStr = (o.createdAt || o.orderDate || fromDate).substring(0, 10);
          var payment = String(o.paymentMethod || '').toLowerCase().includes('cod') ? 'COD' : 'Prepaid';

          // SKU may be comma-joined e.g. "F-511-Teal-Blue-XL, F-103-Black-L"
          // Split into individual SKUs and create one row per SKU
          var skuRaw = o.sku || o.skuCode || '';
          if(!skuRaw && o.itemName) skuRaw=String(o.itemName).replace(/^[•\s]+/,'').split('\n')[0].trim().substring(0,40);
          var skuList = skuRaw ? skuRaw.split(',').map(function(s){return s.trim();}).filter(Boolean) : ['Unknown SKU'];
          var totalQty = parseInt(o.itemQty || 1);
          var perSkuQty = skuList.length > 1 ? 1 : totalQty; // distribute qty evenly

          skuList.forEach(function(singleSku) {
              result.push({
                  id:      '#' + String(o.orderId || '').replace('#', ''),
                  date:    dateStr,
                  sku:     singleSku,
                  product: String(o.itemName || 'Unknown').replace(/^•\s*/,'').split('\n')[0].substring(0, 28),
                  qty:     perSkuQty,
                  payment: payment,
                  reason:  reason
              });
          });
      });

      if (result.length === 0) {
          result = opsGetDemoUnfulfilled(fromDate, toDate);
      }
      return result;
  }

  function opsShowSKU() {
      var skuBtn  = document.getElementById('ops-btn-sku');
      var prodBtn = document.getElementById('ops-btn-prod');
      if (skuBtn)  { skuBtn.style.background = '#1e293b'; skuBtn.style.color = '#fff'; skuBtn.style.borderColor = '#1e293b'; }
      if (prodBtn) { prodBtn.style.background = '#fff'; prodBtn.style.color = '#334155'; prodBtn.style.borderColor = '#e2e8f0'; }

      var orders = window._opsOrders || [];
      var skuMap = {};
      orders.forEach(function(o) {
          if (!skuMap[o.sku]) skuMap[o.sku] = { sku:o.sku, product:o.product, qty:0, reasons:{} };
          skuMap[o.sku].qty += parseInt(o.qty) || 1;
          skuMap[o.sku].reasons[o.reason] = (skuMap[o.sku].reasons[o.reason]||0) + (parseInt(o.qty)||1);
      });
      var rows = Object.values(skuMap).sort(function(a,b){return b.qty-a.qty;});
      var range = opsFmtRange(window._opsFromDate, window._opsToDate);

      var tbody = '';
      rows.forEach(function(r) {
          var parts = r.sku.split('-');
          var size  = parts.length >= 3 ? parts[parts.length-2] : '—';
          var color = parts.length >= 2 ? parts[parts.length-1] : '—';
          var rsplit = Object.entries(r.reasons).map(function(e){ return opsReasonBadge(e[0]) + ' <span style="font-size:11px;font-weight:700;">×' + e[1] + '</span>'; }).join(' ');
          tbody += '<tr class="hover:bg-slate-50 transition">' +
              '<td class="px-4 py-2" style="font-family:monospace;font-size:12px;font-weight:600;">' + r.sku + '</td>' +
              '<td class="px-4 py-2">' + r.product + '</td>' +
              '<td class="px-4 py-2 text-slate-500">' + size + '</td>' +
              '<td class="px-4 py-2 text-slate-500">' + color + '</td>' +
              '<td class="px-4 py-2 font-bold" style="color:#2563eb;">' + r.qty + '</td>' +
              '<td class="px-4 py-2">' + rsplit + '</td>' +
              '</tr>';
      });

      var el = document.getElementById('ops-sub-sku');
      document.getElementById('ops-sub-prod').style.display = 'none';
      el.style.display = 'block';
      el.innerHTML =
          '<div class="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden mb-4">' +
              '<div class="px-4 py-3 border-b border-slate-100 bg-slate-50">' +
                  '<span class="text-sm font-bold text-slate-700">Unfulfilled — SKU wise </span>' +
                  '<span class="text-xs text-slate-400">(' + range + ')</span>' +
              '</div>' +
              '<div class="overflow-x-auto"><table class="min-w-full text-sm text-left">' +
                  '<thead style="font-size:11px;" class="text-slate-500 bg-slate-50"><tr>' +
                  '<th class="px-4 py-2">SKU</th><th class="px-4 py-2">Product</th><th class="px-4 py-2">Size</th><th class="px-4 py-2">Color</th><th class="px-4 py-2">Unfulfilled Qty</th><th class="px-4 py-2">Reason Split</th>' +
                  '</tr></thead>' +
                  '<tbody class="divide-y divide-slate-100">' + tbody + '</tbody>' +
              '</table></div>' +
          '</div>';
  }

  function opsShowProd() {
      var prodBtn = document.getElementById('ops-btn-prod');
      var aiBtn   = document.getElementById('ops-btn-ai');
      if (prodBtn) { prodBtn.style.background='#1e293b'; prodBtn.style.color='#fff'; prodBtn.style.borderColor='#1e293b'; }
      if (aiBtn)   { aiBtn.style.background='#f5f3ff'; aiBtn.style.color='#6d28d9'; aiBtn.style.borderColor='#7c3aed'; }

      var orders = window._opsOrders || [];
      var toDate = window._opsToDate;
      var skuMap = {};
      orders.forEach(function(o) {
          if (!skuMap[o.sku]) skuMap[o.sku] = { sku: o.sku, product: o.product, A: 0 };
          skuMap[o.sku].A += parseInt(o.qty) || 1;
      });

      var items = Object.values(skuMap).map(function(item) {
          var B = opsCalcB(item.sku, toDate);
          var C = opsCalcC(item.sku, toDate);
          return Object.assign({}, item, { B: B, C: C, required: Math.round(item.A + (B + C) / 2) });
      }).sort(function(a, b) { return b.required - a.required; });

      // Store for export
      window._opsProdItems = items;

      var td   = new Date(toDate);
      var b15s = new Date(td); b15s.setDate(td.getDate() - 15);
      var lyE  = new Date(td); lyE.setFullYear(lyE.getFullYear() - 1);
      var lyS  = new Date(lyE); lyS.setDate(lyE.getDate() - 15);

      function fmtShort(d) { return d.getDate() + ' ' + d.toLocaleString('en-IN', { month: 'short' }) + ' ' + d.getFullYear(); }
      function fmtMon(d)   { return d.getDate() + ' ' + d.toLocaleString('en-IN', { month: 'short' }); }

      var bLabel = fmtMon(b15s) + '–' + fmtMon(td);
      var cLabel = fmtMon(lyS)  + '–' + fmtMon(lyE);

      // Build table rows
      var tbody = '';
      items.forEach(function(item, idx) {
          var formula = item.A + ' + (' + item.B + '+' + item.C + ')/2 = ' + item.required;
          var trendColor = item.C > 0 ? (item.B >= item.C ? '#16a34a' : '#dc2626') : '#94a3b8';
          var trendIcon  = item.C > 0 ? (item.B >= item.C ? '▲' : '▼') : '—';
          tbody +=
              '<tr style="border-bottom:1px solid #f1f5f9;' + (idx%2===0?'background:#fff;':'background:#fafafa;') + '">' +
              '<td style="padding:10px 12px;font-size:12px;font-weight:700;color:#94a3b8;text-align:center;">' + (idx+1) + '</td>' +
              '<td style="padding:10px 12px;font-family:monospace;font-size:11px;color:#475569;white-space:nowrap;">' + item.sku + '</td>' +
              '<td style="padding:10px 12px;font-size:13px;color:#1e293b;font-weight:500;">' + item.product + '</td>' +
              '<td style="padding:10px 12px;font-size:20px;font-weight:800;color:#2563eb;text-align:right;">' + item.required + '</td>' +
              '<td style="padding:10px 12px;font-size:14px;font-weight:700;color:#334155;text-align:right;">' + item.A + '</td>' +
              '<td style="padding:10px 12px;font-size:14px;font-weight:700;color:#334155;text-align:right;">' + item.B + '</td>' +
              '<td style="padding:10px 12px;font-size:14px;font-weight:700;color:#334155;text-align:right;">' + item.C + '</td>' +
              '<td style="padding:10px 12px;font-size:11px;font-weight:600;color:' + trendColor + ';text-align:center;">' + trendIcon + '</td>' +
              '<td style="padding:10px 12px;font-family:monospace;font-size:11px;color:#2563eb;white-space:nowrap;">' + formula + '</td>' +
              '</tr>';
      });

      if (!tbody) tbody = '<tr><td colspan="9" style="padding:32px;text-align:center;color:#94a3b8;">No unfulfilled SKU data available.</td></tr>';

      var el = document.getElementById('ops-sub-prod');
      document.getElementById('ops-sub-sku').style.display = 'none';
      document.getElementById('ops-sub-ai').style.display  = 'none';
      el.style.display = 'block';
      el.innerHTML =
          // Header row with title + Export button
          '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;flex-wrap:wrap;gap:8px;">' +
              '<div>' +
                  '<div style="font-size:14px;font-weight:700;color:#1e293b;">Production order recommendation — as on ' + fmtShort(td) + '</div>' +
                  '<div style="font-size:11px;color:#94a3b8;margin-top:2px;">' + items.length + ' SKUs &nbsp;|&nbsp; Total required: ' + items.reduce(function(s,i){return s+i.required;},0) + ' units</div>' +
              '</div>' +
              '<button onclick="opsExportProdExcel()" style="display:flex;align-items:center;gap:6px;background:#16a34a;color:#fff;border:none;border-radius:8px;padding:8px 16px;font-size:13px;font-weight:700;cursor:pointer;">' +
                  '<i class="fas fa-file-excel"></i> Export Excel' +
              '</button>' +
          '</div>' +
          // Formula info box
          '<div style="background:#eff6ff;border:1px solid #bfdbfe;border-radius:8px;padding:10px 14px;margin-bottom:14px;font-size:12px;color:#1e40af;line-height:1.7;">' +
              '<strong>Formula: Required = A + (B + C) / 2</strong> &nbsp;|&nbsp; ' +
              'A = Unfulfilled now &nbsp;|&nbsp; ' +
              'B = Last 15d orders (' + bLabel + ') &nbsp;|&nbsp; ' +
              'C = Same 15d last year (' + cLabel + ')' +
          '</div>' +
          // Table
          '<div style="background:#fff;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,0.06);">' +
              '<div style="overflow-x:auto;">' +
                  '<table style="width:100%;border-collapse:collapse;font-size:13px;">' +
                      '<thead>' +
                          '<tr style="background:#f8fafc;border-bottom:2px solid #e2e8f0;font-size:11px;color:#64748b;text-transform:uppercase;letter-spacing:.5px;">' +
                          '<th style="padding:10px 12px;text-align:center;font-weight:600;">#</th>' +
                          '<th style="padding:10px 12px;text-align:left;font-weight:600;">SKU</th>' +
                          '<th style="padding:10px 12px;text-align:left;font-weight:600;">Product</th>' +
                          '<th style="padding:10px 12px;text-align:right;font-weight:600;color:#2563eb;">Required</th>' +
                          '<th style="padding:10px 12px;text-align:right;font-weight:600;">A Unfulfilled</th>' +
                          '<th style="padding:10px 12px;text-align:right;font-weight:600;">B Last 15d</th>' +
                          '<th style="padding:10px 12px;text-align:right;font-weight:600;">C LY 15d</th>' +
                          '<th style="padding:10px 12px;text-align:center;font-weight:600;">Trend</th>' +
                          '<th style="padding:10px 12px;text-align:left;font-weight:600;">Formula</th>' +
                          '</tr>' +
                      '</thead>' +
                      '<tbody>' + tbody + '</tbody>' +
                      // Footer totals
                      '<tfoot>' +
                          '<tr style="background:#f8fafc;border-top:2px solid #e2e8f0;font-weight:700;">' +
                          '<td colspan="3" style="padding:10px 12px;font-size:12px;color:#475569;">TOTAL (' + items.length + ' SKUs)</td>' +
                          '<td style="padding:10px 12px;text-align:right;font-size:16px;color:#2563eb;">' + items.reduce(function(s,i){return s+i.required;},0) + '</td>' +
                          '<td style="padding:10px 12px;text-align:right;color:#334155;">' + items.reduce(function(s,i){return s+i.A;},0) + '</td>' +
                          '<td style="padding:10px 12px;text-align:right;color:#334155;">' + items.reduce(function(s,i){return s+i.B;},0) + '</td>' +
                          '<td style="padding:10px 12px;text-align:right;color:#334155;">' + items.reduce(function(s,i){return s+i.C;},0) + '</td>' +
                          '<td colspan="2"></td>' +
                          '</tr>' +
                      '</tfoot>' +
                  '</table>' +
              '</div>' +
          '</div>';
  }

  function opsExportProdExcel() {
      var items = window._opsProdItems || [];
      if (!items.length) { showToast('No data to export', 'error'); return; }

      var toDate = window._opsToDate || new Date().toISOString().split('T')[0];
      var td   = new Date(toDate);
      var b15s = new Date(td); b15s.setDate(td.getDate()-15);
      var lyE  = new Date(td); lyE.setFullYear(lyE.getFullYear()-1);
      var lyS  = new Date(lyE); lyS.setDate(lyE.getDate()-15);
      function fmtD(d){ return d.getDate()+' '+d.toLocaleString('en-IN',{month:'short'})+' '+d.getFullYear(); }

      // Build CSV content
      var lines = [];
      lines.push('Production Order Recommendation — as on ' + fmtD(td));
      lines.push('Formula: Required = A + (B + C) / 2');
      lines.push('A = Current unfulfilled | B = Last 15d (' + fmtD(b15s) + '–' + fmtD(td) + ') | C = Same 15d LY (' + fmtD(lyS) + '–' + fmtD(lyE) + ')');
      lines.push('');
      lines.push(['#','SKU','Product','Required Qty','A (Unfulfilled)','B (Last 15d)','C (LY 15d)','Trend (B vs C)','Formula'].join(','));

      items.forEach(function(item, idx) {
          var trend = item.C > 0 ? (item.B >= item.C ? 'Growing' : 'Declining') : 'No LY data';
          var formula = item.A + ' + (' + item.B + '+' + item.C + ')/2 = ' + item.required;
          lines.push([
              idx+1,
              '"' + item.sku + '"',
              '"' + item.product.replace(/"/g,"'") + '"',
              item.required,
              item.A,
              item.B,
              item.C,
              '"' + trend + '"',
              '"' + formula + '"'
          ].join(','));
      });

      // Totals row
      lines.push([
          'TOTAL','','',
          items.reduce(function(s,i){return s+i.required;},0),
          items.reduce(function(s,i){return s+i.A;},0),
          items.reduce(function(s,i){return s+i.B;},0),
          items.reduce(function(s,i){return s+i.C;},0),
          '','Formula totals'
      ].join(','));

      var csvContent = '\uFEFF' + lines.join('\r\n'); // BOM for Excel UTF-8
      var blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
      var url  = URL.createObjectURL(blob);
      var a    = document.createElement('a');
      a.href     = url;
      a.download = 'Production_Order_' + toDate + '.csv';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
      showToast('Production order exported!', 'success');
  }

  function opsShowAIReport() {
      // Highlight button
      ['ops-btn-sku','ops-btn-prod'].forEach(function(id) {
          var b = document.getElementById(id);
          if (b) { b.style.background='#fff'; b.style.color='#334155'; b.style.borderColor='#e2e8f0'; }
      });
      var aiBtn = document.getElementById('ops-btn-ai');
      if (aiBtn) { aiBtn.style.background='#7c3aed'; aiBtn.style.color='#fff'; aiBtn.style.borderColor='#7c3aed'; }

      document.getElementById('ops-sub-sku').style.display  = 'none';
      document.getElementById('ops-sub-prod').style.display = 'none';
      var el = document.getElementById('ops-sub-ai');
      el.style.display = 'block';

      // Don't re-generate if already loaded
      if (el.dataset.loaded === '1') return;
      el.dataset.loaded = '0';

      el.innerHTML =
          '<div style="background:#fff;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;">' +
              '<div style="background:linear-gradient(to right,#f5f3ff,#f8fafc);padding:14px 18px;border-bottom:1px solid #ede9fe;display:flex;justify-content:space-between;align-items:center;">' +
                  '<div style="font-weight:700;color:#1e293b;display:flex;align-items:center;gap:8px;">' +
                      '<i class="fas fa-robot" style="color:#7c3aed;"></i> AI Operations Analysis' +
                      '<span style="font-size:10px;color:#94a3b8;font-weight:400;">powered by Claude</span>' +
                  '</div>' +
                  '<button onclick="opsGenerateAIReport(true)" style="background:#7c3aed;color:#fff;border:none;border-radius:6px;padding:6px 14px;font-size:12px;font-weight:700;cursor:pointer;display:flex;align-items:center;gap:6px;">' +
                      '<i class="fas fa-sync-alt"></i> Regenerate' +
                  '</button>' +
              '</div>' +
              '<div id="ops-ai-loading" style="display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px;gap:12px;">' +
                  '<div style="position:relative;width:48px;height:48px;">' +
                      '<div style="position:absolute;inset:0;border-radius:50%;border:3px solid #ede9fe;border-top-color:#7c3aed;animation:spin 0.8s linear infinite;"></div>' +
                      '<i class="fas fa-robot" style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#7c3aed;font-size:18px;"></i>' +
                  '</div>' +
                  '<div style="text-align:center;">' +
                      '<div style="font-weight:700;color:#334155;font-size:14px;">Claude is analysing your data…</div>' +
                      '<div style="color:#94a3b8;font-size:12px;margin-top:4px;">Usually takes 5–10 seconds</div>' +
                  '</div>' +
              '</div>' +
              '<div id="ops-ai-error" style="display:none;margin:16px;padding:12px 16px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px;color:#dc2626;font-size:13px;font-weight:600;"></div>' +
              '<div id="ops-ai-output" style="padding:20px 24px;display:none;line-height:1.75;font-size:13px;color:#334155;"></div>' +
          '</div>';

      // Add spin keyframe if not present
      if (!document.getElementById('ops-spin-style')) {
          var st = document.createElement('style');
          st.id = 'ops-spin-style';
          st.textContent = '@keyframes spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}';
          document.head.appendChild(st);
      }

      opsGenerateAIReport(false);
  }

  function opsGenerateAIReport(forceRegen) {
      var el = document.getElementById('ops-sub-ai');
      if (!el) return;
      if (forceRegen) {
          el.dataset.loaded = '0';
          var out = document.getElementById('ops-ai-output');
          var err = document.getElementById('ops-ai-error');
          var ldr = document.getElementById('ops-ai-loading');
          if (out) { out.innerHTML = ''; out.style.display = 'none'; }
          if (err) { err.style.display = 'none'; }
          if (ldr) ldr.style.display = 'flex';
      }

      // Build data payload from current orders + production calcs
      var orders   = window._opsOrders   || [];
      var fromDate = window._opsFromDate  || '';
      var toDate   = window._opsToDate    || '';

      // SKU summary
      var skuMap = {};
      orders.forEach(function(o) {
          if (!skuMap[o.sku]) skuMap[o.sku] = { sku:o.sku, product:o.product, A:0, reasons:{} };
          skuMap[o.sku].A += parseInt(o.qty)||1;
          skuMap[o.sku].reasons[o.reason] = (skuMap[o.sku].reasons[o.reason]||0) + (parseInt(o.qty)||1);
      });

      var items = Object.values(skuMap).map(function(item) {
          var B = opsCalcB(item.sku, toDate);
          var C = opsCalcC(item.sku, toDate);
          return Object.assign({}, item, { B:B, C:C, required: Math.round(item.A+(B+C)/2) });
      }).sort(function(a,b){ return b.required-a.required; });

      // Reason breakdown
      var noAWB  = orders.filter(function(o){return o.reason==='No AWB';}).length;
      var pend   = orders.filter(function(o){return o.reason==='Pending verify';}).length;
      var oos    = orders.filter(function(o){return o.reason==='OOS';}).length;
      var noLbl  = orders.filter(function(o){return o.reason==='No label';}).length;

      // Top 10 production SKUs for prompt
      var prodLines = items.slice(0,10).map(function(it) {
          return it.product + ' (' + it.sku + '): A=' + it.A + ', B=' + it.B + ', C=' + it.C + ', Required=' + it.required;
      }).join('\n');

      var td   = new Date(toDate);
      var lyE  = new Date(td); lyE.setFullYear(lyE.getFullYear()-1);
      var lyS  = new Date(lyE); lyS.setDate(lyE.getDate()-15);
      var b15s = new Date(td); b15s.setDate(td.getDate()-15);

      var prompt =
          'You are an Operations Manager of a D2C apparel brand in India called Filo Hevis.\n\n' +
          'Analyse the following unfulfilled order and production planning data and provide a structured report.\n\n' +
          '=== DATE RANGE ===\n' +
          'Selected period: ' + fromDate + ' to ' + toDate + '\n' +
          'B period (last 15 days avg): ' + b15s.toISOString().split('T')[0] + ' to ' + toDate + '\n' +
          'C period (same 15 days last year): ' + lyS.toISOString().split('T')[0] + ' to ' + lyE.toISOString().split('T')[0] + '\n\n' +
          '=== UNFULFILLED ORDER SUMMARY ===\n' +
          'Total unfulfilled: ' + orders.length + '\n' +
          'No AWB (label not generated): ' + noAWB + '\n' +
          'Pending COD verification: ' + pend + '\n' +
          'Out of stock: ' + oos + '\n' +
          'No label: ' + noLbl + '\n\n' +
          '=== PRODUCTION ORDER DATA (Formula: Required = A + (B+C)/2) ===\n' +
          'A = Current unfulfilled | B = Last 15 days orders | C = Same 15 days last year\n\n' +
          prodLines + '\n\n' +
          'Please provide:\n' +
          '1. **Executive Summary** — 3-4 sentences on the current situation\n' +
          '2. **Urgent Actions** — What needs to be done TODAY (AWB generation, COD verification, stock issues)\n' +
          '3. **Production Priorities** — Top 5 SKUs to prioritise and why\n' +
          '4. **Demand Trend Analysis** — Compare B vs C to identify growing or declining SKUs\n' +
          '5. **Risk Flags** — Any SKUs with unusually high unfulfilled or zero last-year data\n\n' +
          'Be direct, specific, and actionable. Use ₹ context where relevant. Keep it concise.';

      fetch('https://api.anthropic.com/v1/messages', {
          method: 'POST',
          headers: {
              'Content-Type': 'application/json',
              'x-api-key': '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',
              'anthropic-version': '2023-06-01',
              'anthropic-dangerous-direct-browser-access': 'true'
          },
          body: JSON.stringify({
              model: 'claude-sonnet-4-6',
              max_tokens: 1500,
              messages: [{ role: 'user', content: prompt }]
          })
      })
      .then(function(r) { return r.json(); })
      .then(function(data) {
          var ldr = document.getElementById('ops-ai-loading');
          var out = document.getElementById('ops-ai-output');
          var err = document.getElementById('ops-ai-error');
          if (ldr) ldr.style.display = 'none';
          if (data.error) throw new Error(data.error.message || 'API error');
          var text = (data.content && data.content[0]) ? data.content[0].text : '';
          if (out) {
              out.style.display = 'block';
              out.innerHTML = opsFormatAIText(text);
              el.dataset.loaded = '1';
          }
      })
      .catch(function(e) {
          var ldr = document.getElementById('ops-ai-loading');
          var err = document.getElementById('ops-ai-error');
          if (ldr) ldr.style.display = 'none';
          if (err) { err.textContent = '❌ ' + e.message; err.style.display = 'block'; }
      });
  }

  function opsFormatAIText(text) {
      // Convert markdown to styled HTML
      return text
          .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
          .replace(/^### (.+)$/gm, '<h4 style="font-size:13px;font-weight:700;color:#1e293b;margin:16px 0 6px;border-left:3px solid #7c3aed;padding-left:8px;">$1</h4>')
          .replace(/^## (.+)$/gm,  '<h3 style="font-size:15px;font-weight:700;color:#1e293b;margin:20px 0 8px;padding-bottom:4px;border-bottom:1px solid #ede9fe;">$1</h3>')
          .replace(/^# (.+)$/gm,   '<h2 style="font-size:17px;font-weight:700;color:#1e293b;margin:16px 0 8px;">$1</h2>')
          .replace(/^\d+\.\s\*\*(.+?)\*\*/gm, '<div style="margin:12px 0 4px;"><span style="display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;background:#7c3aed;color:#fff;border-radius:50%;font-size:10px;font-weight:700;margin-right:6px;flex-shrink:0;">•</span><strong>$1</strong></div>')
          .replace(/^[-•]\s(.+)$/gm, '<div style="display:flex;gap:8px;margin:4px 0;"><span style="color:#7c3aed;flex-shrink:0;">›</span><span>$1</span></div>')
          .replace(/\n\n/g, '<div style="height:10px;"></div>')
          .replace(/\n/g, '<br>');
  }
  function opsCalcB(sku, toDate) {
      if (typeof ALL_DATA === 'undefined' || !ALL_DATA || ALL_DATA.length === 0) return 0;
      var to      = new Date(toDate);
      var from    = new Date(to); from.setDate(to.getDate() - 15);
      var fromStr = from.toISOString().split('T')[0];
      var toStr   = to.toISOString().split('T')[0];
      var total   = 0;
      ALL_DATA.forEach(function(o) {
          var raw = (o.createdAt || o.orderDate || '').substring(0, 10);
          if (raw < fromStr || raw > toStr) return;
          // SKU may be comma-joined — check if any part matches
          var skuRaw  = o.sku || '';
          var skuList = skuRaw.split(',').map(function(s){ return s.trim(); });
          if (skuList.indexOf(sku) > -1) {
              total += parseInt(o.itemQty || 1);
          }
      });
      return total > 0 ? total : 0; // return 0 if genuinely no data (not demo fallback)
  }

  function opsCalcC(sku, toDate) {
      if (!OPS_LY_DATA || OPS_LY_DATA.length === 0) return 0;
      var to      = new Date(toDate); to.setFullYear(to.getFullYear() - 1);
      var from    = new Date(to); from.setDate(to.getDate() - 15);
      var fromStr = from.toISOString().split('T')[0];
      var toStr   = to.toISOString().split('T')[0];
      var total   = 0;
      for (var i = 0; i < OPS_LY_DATA.length; i++) {
          var row     = OPS_LY_DATA[i];
          var rowDate = row.d || '';
          var rowSku  = row.s || '';
          if (rowSku === sku && rowDate >= fromStr && rowDate <= toStr) {
              total += row.q || 1;
          }
      }
      return total; // 0 is valid — means no orders last year for this SKU in this window
  }

  // ---- FULFILLED ----
  function opsRenderFulfilled(main, fromDate, toDate) {
      // Get fulfilled orders from Webhook (Done + Dispatched)
      var latest    = opsGetLatestOrders(fromDate, toDate);
      var fulfilled = latest.filter(function(o){ return o.status === 'Done'; });
      var total     = fulfilled.length || 0;
      var cpRows    = OPS_CP_DATA || [];
      // Clickpost status values from DB: Delivered, InTransit, RTO, RTO Delivered, etc.
      var delivered = cpRows.length > 0
          ? cpRows.filter(function(r){
              var s = String(r['Status']||r['Delivery Status']||'').toLowerCase();
              return s.includes('deliver') && !s.includes('rto');
            }).length
          : fulfilled.filter(function(o){ return (o.dispatchStatus||'').toLowerCase().includes('deliver'); }).length;
      var inTransit = cpRows.filter(function(r){
          return String(r['Status']||'').toLowerCase().includes('transit');
      }).length;
      var rtoCount = cpRows.length > 0
          ? cpRows.filter(function(r){
              var s = String(r['Status']||'').toLowerCase();
              return s.includes('rto');
            }).length
          : fulfilled.filter(function(o){ return (o.dispatchStatus||'').toLowerCase().includes('rto'); }).length;
      var delRate = total > 0 ? ((delivered/total)*100).toFixed(1) : '—';
      var rtoRate = total > 0 ? ((rtoCount/total)*100).toFixed(1) : '—';
      var range   = opsFmtRange(fromDate, toDate);

      main.innerHTML =
          '<div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-5">' +
          [['#2563eb', total,    'Total fulfilled',  range],
           ['#16a34a', delRate+(total?'%':''), 'Delivery rate', 'all couriers'],
           ['#d97706', '3.2d',  'Avg actual TAT',   'vs 2.8d SLA'],
           ['#dc2626', rtoCount,'RTO initiated',    rtoRate+'% RTO rate']].map(function(x) {
              return '<div class="bg-white rounded-xl border border-slate-200 shadow-sm p-4">' +
                  '<div style="font-size:28px;font-weight:700;color:' + x[0] + ';line-height:1;margin-bottom:4px;">' + x[1] + '</div>' +
                  '<div style="font-size:12px;font-weight:600;color:#475569;">' + x[2] + '</div>' +
                  '<div style="font-size:10px;color:#94a3b8;margin-top:2px;">' + x[3] + '</div></div>';
          }).join('') +
          '</div>' +
          '<div class="flex gap-2 mb-4 flex-wrap" id="ops-courier-tabs">' +
          ['bluedart','delhivery','dtdc','overall'].map(function(c) {
              var colors={bluedart:'#e02020',delhivery:'#0066cc',dtdc:'#ff8c00',overall:'#16a34a'};
              var labels={bluedart:'Bluedart',delhivery:'Delhivery',dtdc:'DTDC',overall:'Overall (consolidated)'};
              return '<button onclick="opsShowCourier(\'' + c + '\')" id="ops-ctab-' + c + '" ' +
                  'style="display:flex;align-items:center;gap:7px;padding:7px 16px;border-radius:50px;border:1.5px solid #e2e8f0;background:#fff;font-size:13px;font-weight:600;cursor:pointer;">' +
                  '<span style="width:8px;height:8px;border-radius:50%;background:' + colors[c] + ';display:inline-block;"></span>' +
                  labels[c] + '</button>';
          }).join('') +
          '</div>' +
          '<div id="ops-courier-detail"></div>';

      window._opsFromDate = fromDate;
      window._opsToDate   = toDate;
      opsShowCourier('bluedart');
  }

  function opsShowCourier(courier) {
      var colors={bluedart:'#e02020',delhivery:'#0066cc',dtdc:'#ff8c00',overall:'#16a34a'};
      var bgMap={bluedart:'#fef2f2',delhivery:'#eff6ff',dtdc:'#fff7ed',overall:'#f0fdf4'};
      ['bluedart','delhivery','dtdc','overall'].forEach(function(c) {
          var el=document.getElementById('ops-ctab-'+c);
          if(!el) return;
          if(c===courier){ el.style.borderColor=colors[c]; el.style.color=colors[c]; el.style.background=bgMap[c]; }
          else { el.style.borderColor='#e2e8f0'; el.style.color='#334155'; el.style.background='#fff'; }
      });
      var d = opsGetDemoCourier(courier);
      var labels={bluedart:'Bluedart',delhivery:'Delhivery',dtdc:'DTDC',overall:'Overall — Consolidated'};
      var range = opsFmtRange(window._opsFromDate, window._opsToDate);
      var el = document.getElementById('ops-courier-detail');
      if (!el) return;
      el.innerHTML =
          '<div style="font-size:13px;font-weight:700;color:#334155;margin-bottom:12px;display:flex;align-items:center;gap:8px;">' +
              '<span style="width:10px;height:10px;border-radius:50%;background:' + colors[courier] + ';display:inline-block;"></span>' +
              labels[courier] + ' — Delivery Report (' + range + ')' +
          '</div>' +
          '<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px;">' +
              opsCourierPanel('COD ORDERS', d.cod, colors[courier]) +
              opsCourierPanel('PREPAID ORDERS', d.prepaid, colors[courier]) +
          '</div>' +
          (courier==='overall' ? opsConsolidatedTable() : '');
  }

  function opsCourierPanel(title, d, color) {
      var breach  = d.avgTAT > d.slaTAT;
      var tatPct  = Math.min(100, (d.avgTAT / d.slaTAT) * 100);
      var tatColor= breach ? '#dc2626' : '#16a34a';
      return '<div class="bg-white rounded-xl border border-slate-200 shadow-sm p-4">' +
          '<div style="font-size:11px;font-weight:700;color:#94a3b8;text-transform:uppercase;letter-spacing:.5px;margin-bottom:12px;">' + title + ' (' + d.total + ')</div>' +
          '<div style="display:flex;justify-content:space-between;align-items:center;padding:6px 0;border-bottom:1px solid #f1f5f9;">' +
              '<span style="font-size:13px;color:#64748b;">Delivered</span>' +
              '<span style="font-size:13px;font-weight:700;color:#16a34a;">' + d.deliveryRate + '% (' + d.delivered + '/' + d.total + ')</span>' +
          '</div>' +
          '<div style="display:flex;justify-content:space-between;align-items:center;padding:6px 0;border-bottom:1px solid #f1f5f9;">' +
              '<span style="font-size:13px;color:#64748b;">In transit</span>' +
              '<span style="font-size:13px;font-weight:600;">' + d.inTransit + '</span>' +
          '</div>' +
          '<div style="display:flex;justify-content:space-between;align-items:center;padding:6px 0;border-bottom:1px solid #f1f5f9;">' +
              '<span style="font-size:13px;color:#64748b;">RTO initiated</span>' +
              '<span style="font-size:13px;font-weight:600;color:#dc2626;">' + d.rto + ' (' + d.rtoRate + '%)</span>' +
          '</div>' +
          '<div style="padding-top:10px;">' +
              '<div style="display:flex;justify-content:space-between;font-size:13px;margin-bottom:4px;">' +
                  '<span style="color:#64748b;">Actual TAT</span><span style="font-weight:700;color:' + tatColor + ';">' + d.avgTAT + 'd</span>' +
              '</div>' +
              '<div style="height:4px;background:#f1f5f9;border-radius:2px;">' +
                  '<div style="height:4px;width:' + tatPct + '%;background:' + tatColor + ';border-radius:2px;"></div>' +
              '</div>' +
          '</div>' +
          '<div style="display:flex;justify-content:space-between;align-items:center;padding-top:8px;font-size:13px;">' +
              '<span style="color:#64748b;">Courier SLA</span><span style="font-weight:600;">' + d.slaTAT + 'd</span>' +
          '</div>' +
      '</div>';
  }

  function opsConsolidatedTable() {
      var couriers=[['Bluedart','bluedart'],['Delhivery','delhivery'],['DTDC','dtdc']];
      var tbody='';
      couriers.forEach(function(pair) {
          var cd=opsGetDemoCourier(pair[1]);
          var tot=cd.cod.total+cd.prepaid.total;
          var del=cd.cod.delivered+cd.prepaid.delivered;
          var rto=cd.cod.rto+cd.prepaid.rto;
          var tat=((cd.cod.avgTAT+cd.prepaid.avgTAT)/2).toFixed(1);
          var delPct=((del/tot)*100).toFixed(1);
          var rtoPct=((rto/tot)*100).toFixed(1);
          var badge=parseFloat(delPct)>85 ? 'background:#dcfce7;color:#15803d;border:1px solid #bbf7d0;' : 'background:#fef9c3;color:#a16207;border:1px solid #fde047;';
          tbody+='<tr class="hover:bg-slate-50 transition">' +
              '<td class="px-4 py-2 font-bold">' + pair[0] + '</td>' +
              '<td class="px-4 py-2">' + tot + '</td>' +
              '<td class="px-4 py-2 font-semibold" style="color:#16a34a;">' + del + '</td>' +
              '<td class="px-4 py-2"><span style="' + badge + 'padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;">' + delPct + '%</span></td>' +
              '<td class="px-4 py-2" style="color:#dc2626;">' + rto + '</td>' +
              '<td class="px-4 py-2">' + rtoPct + '%</td>' +
              '<td class="px-4 py-2" style="font-family:monospace;font-size:12px;">' + tat + 'd</td>' +
          '</tr>';
      });
      return '<div class="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden">' +
          '<div class="px-4 py-3 border-b border-slate-100 bg-slate-50"><span class="text-sm font-bold text-slate-700">Consolidated Courier Comparison</span></div>' +
          '<div class="overflow-x-auto"><table class="min-w-full text-sm text-left">' +
              '<thead style="font-size:11px;" class="text-slate-500 bg-slate-50"><tr>' +
              '<th class="px-4 py-2">Courier</th><th class="px-4 py-2">Total</th><th class="px-4 py-2">Delivered</th><th class="px-4 py-2">Del %</th><th class="px-4 py-2">RTO</th><th class="px-4 py-2">RTO %</th><th class="px-4 py-2">Avg TAT</th>' +
              '</tr></thead>' +
              '<tbody class="divide-y divide-slate-100">' + tbody + '</tbody>' +
          '</table></div>' +
      '</div>';
  }

  // ---- DEMO DATA ----
  function opsGetDemoUnfulfilled(fromDate, toDate) {
      var all=[
          {id:'#FH-10421',date:'2026-05-01',sku:'FH-KRTSH-S-BLK',product:'Kurta Shirt S Black',qty:2,payment:'Prepaid',reason:'No AWB'},
          {id:'#FH-10432',date:'2026-05-01',sku:'FH-LINEN-M-WHT',product:'Linen Shirt M White',qty:1,payment:'COD',reason:'Pending verify'},
          {id:'#FH-10445',date:'2026-05-02',sku:'FH-JOGGER-L-NVY',product:'Jogger L Navy',qty:3,payment:'Prepaid',reason:'No AWB'},
          {id:'#FH-10461',date:'2026-05-02',sku:'FH-KRTSH-M-WHT',product:'Kurta Shirt M White',qty:1,payment:'Prepaid',reason:'OOS'},
          {id:'#FH-10478',date:'2026-05-03',sku:'FH-POLO-S-GRN',product:'Polo S Green',qty:2,payment:'COD',reason:'No AWB'},
          {id:'#FH-10490',date:'2026-05-03',sku:'FH-LINEN-L-BEI',product:'Linen Shirt L Beige',qty:1,payment:'Prepaid',reason:'No label'},
          {id:'#FH-10503',date:'2026-05-04',sku:'FH-JOGGER-M-BLK',product:'Jogger M Black',qty:2,payment:'Prepaid',reason:'OOS'},
          {id:'#FH-10517',date:'2026-05-05',sku:'FH-KRTSH-L-BLU',product:'Kurta Shirt L Blue',qty:1,payment:'COD',reason:'No AWB'}
      ];
      var from=new Date(fromDate), to=new Date(toDate); to.setHours(23,59,59);
      return all.filter(function(o){ return new Date(o.date)>=from && new Date(o.date)<=to; });
  }
  var _OPS_B={'FH-KRTSH-S-BLK':72,'FH-KRTSH-M-WHT':65,'FH-LINEN-M-WHT':68,'FH-LINEN-L-BEI':54,'FH-JOGGER-L-NVY':78,'FH-JOGGER-M-BLK':58,'FH-POLO-S-GRN':45,'FH-KRTSH-L-BLU':38};
  var _OPS_C={'FH-KRTSH-S-BLK':88,'FH-KRTSH-M-WHT':80,'FH-LINEN-M-WHT':82,'FH-LINEN-L-BEI':64,'FH-JOGGER-L-NVY':92,'FH-JOGGER-M-BLK':82,'FH-POLO-S-GRN':65,'FH-KRTSH-L-BLU':52};
  function opsGetDemoB(sku){ return _OPS_B[sku]||45; }
  function opsGetDemoC(sku){ return _OPS_C[sku]||50; }
  function opsGetDemoCourier(courier){
      var d={
          bluedart: {cod:{total:58,delivered:52,inTransit:2,rto:4,rtoRate:'6.9',deliveryRate:'89.7',avgTAT:2.4,slaTAT:2.0},prepaid:{total:82,delivered:76,inTransit:3,rto:3,rtoRate:'3.7',deliveryRate:'92.7',avgTAT:2.1,slaTAT:2.0}},
          delhivery:{cod:{total:74,delivered:61,inTransit:5,rto:8,rtoRate:'10.8',deliveryRate:'82.4',avgTAT:3.8,slaTAT:3.0},prepaid:{total:96,delivered:84,inTransit:6,rto:6,rtoRate:'6.3',deliveryRate:'87.5',avgTAT:3.2,slaTAT:3.0}},
          dtdc:     {cod:{total:34,delivered:27,inTransit:3,rto:4,rtoRate:'11.8',deliveryRate:'79.4',avgTAT:4.1,slaTAT:3.5},prepaid:{total:42,delivered:35,inTransit:3,rto:4,rtoRate:'9.5',deliveryRate:'83.3',avgTAT:3.7,slaTAT:3.5}},
          overall:  {cod:{total:166,delivered:140,inTransit:10,rto:16,rtoRate:'9.6',deliveryRate:'84.3',avgTAT:3.4,slaTAT:2.8},prepaid:{total:220,delivered:195,inTransit:12,rto:13,rtoRate:'5.9',deliveryRate:'88.6',avgTAT:2.9,slaTAT:2.8}}
      };
      return d[courier]||d.overall;
  }
  // ===================== END CLAUDE AI REPORT =====================

// ============================================================
// TRAINING EDITOR (Writer + Admin)
// ============================================================
function openTrainingEditor(id=null) {
  ['te-id','te-header','te-sub','te-body','te-image','te-video'].forEach(i=>{const el=document.getElementById(i);if(el)el.value='';});
  document.getElementById('te-error').style.display='none';
  document.getElementById('te-title').innerText = id ? 'Edit Training Material' : 'Add Training Material';
  document.getElementById('te-save-text').innerText = id ? 'Save Changes' : 'Save Material';
  document.getElementById('trainingEditorModal').classList.remove('hidden');
  document.getElementById('te-header').focus();
}
function closeTrainingEditor() { document.getElementById('trainingEditorModal').classList.add('hidden'); }

async function saveTrainingMaterial() {
  const header = document.getElementById('te-header').value.trim();
  const sub    = document.getElementById('te-sub').value.trim();
  const body   = document.getElementById('te-body').value.trim();
  const image  = document.getElementById('te-image').value.trim();
  const video  = document.getElementById('te-video').value.trim();
  const errDiv = document.getElementById('te-error');
  const errText= document.getElementById('te-error-text');
  const btn    = document.getElementById('te-save-btn');
  errDiv.style.display='none';
  if(!header){errText.innerText='Header/Category is required';errDiv.style.display='block';return;}
  const orig=btn.innerHTML; btn.innerHTML='<i class="fas fa-spinner fa-spin"></i> Saving...'; btn.disabled=true;
  try {
    const res = await fetch('api/training.php', {
      method:'POST', headers:{'Content-Type':'application/json'}, credentials:'same-origin',
      body: JSON.stringify({action:'save_material', header, subheading:sub, bodytext:body, image, video})
    });
    const data = await res.json();
    if(data.status==='success'){
      closeTrainingEditor();
      showToast('Training material saved!','success');
      loadTrainingData();
    } else { errText.innerText=data.msg||'Save failed'; errDiv.style.display='block'; }
  } catch(e){ errText.innerText='Connection error'; errDiv.style.display='block'; }
  btn.innerHTML=orig; btn.disabled=false;
}


// ============================================================
// SCAN BULK IMPORT (Admin only)
// ============================================================
let importParsedData = [];

function openScanImportModal() {
  document.getElementById('scanImportModal').classList.remove('hidden');
  document.getElementById('import-preview').style.display='none';
  document.getElementById('import-error').style.display='none';
  document.getElementById('import-progress').style.display='none';
  document.getElementById('import-file').value='';
  importParsedData=[];
}
function closeScanImportModal() { document.getElementById('scanImportModal').classList.add('hidden'); }

function downloadImportTemplate() {
  const csv = 'order_id,courier_name,dispatch_status,scan_date\n3434354140,DTDC,Dispatched,2026-05-21\n3434354141,Delhivery,Dispatched,2026-05-21\n';
  const blob=new Blob([csv],{type:'text/csv'});
  const link=document.createElement('a');link.href=URL.createObjectURL(blob);
  link.download='scan_import_template.csv';document.body.appendChild(link);link.click();document.body.removeChild(link);
}

function previewImport() {
  const fileEl = document.getElementById('import-file');
  const errDiv = document.getElementById('import-error');
  const prevDiv= document.getElementById('import-preview');
  const prevBody=document.getElementById('import-preview-body');
  errDiv.style.display='none';prevDiv.style.display='none';
  if(!fileEl.files.length){errDiv.innerText='Please select a CSV file first';errDiv.style.display='block';return;}
  const file=fileEl.files[0];
  const reader=new FileReader();
  reader.onload=function(e){
    const text=e.target.result;
    const lines=text.split('\n').filter(l=>l.trim());
    if(lines.length<2){errDiv.innerText='File appears empty or invalid';errDiv.style.display='block';return;}
    // Parse CSV (skip header)
    const defCourier=document.getElementById('import-default-courier').value||'Others';
    const defStatus =document.getElementById('import-default-status').value||'Dispatched';
    importParsedData=[];
    lines.slice(1).forEach(line=>{
      const cols=line.split(',').map(c=>c.trim().replace(/^"|"$/g,''));
      if(!cols[0]) return;
      const orderId  = cols[0].replace(/#/g,'').trim();
      const courier  = cols[1]||defCourier;
      const status   = cols[2]||defStatus;
      const scanDate = cols[3]||new Date().toISOString().split('T')[0];
      if(orderId) importParsedData.push({orderId,courier,status,scanDate});
    });
    prevBody.innerHTML=importParsedData.slice(0,20).map(r=>`<tr style="border-bottom:1px solid #f8fafc">
      <td style="padding:6px 12px;font-family:monospace;font-size:12px">#${r.orderId}</td>
      <td style="padding:6px 12px;font-size:12px">${r.courier}</td>
      <td style="padding:6px 12px"><span style="background:#dcfce7;color:#15803d;padding:1px 8px;border-radius:99px;font-size:10px;font-weight:700">${r.status}</span></td>
      <td style="padding:6px 12px;font-size:12px;color:#64748b">${r.scanDate}</td>
    </tr>`).join('');
    if(importParsedData.length>20) prevBody.innerHTML+=`<tr><td colspan="4" style="padding:8px 12px;text-align:center;color:#94a3b8;font-size:12px">... and ${importParsedData.length-20} more rows</td></tr>`;
    prevDiv.style.display='block';
    document.getElementById('import-progress').innerText=`Ready to import ${importParsedData.length} records`;
    document.getElementById('import-progress').style.display='block';
  };
  reader.readAsText(file);
}

async function submitImport() {
  if(!importParsedData.length){
    document.getElementById('import-error').innerText='Please preview first';
    document.getElementById('import-error').style.display='block'; return;
  }
  const btn=document.getElementById('import-submit-btn');
  const prog=document.getElementById('import-progress');
  const orig=btn.innerHTML; btn.innerHTML='<i class="fas fa-spinner fa-spin"></i> Importing...'; btn.disabled=true;
  prog.style.display='block'; prog.innerText='Importing '+importParsedData.length+' records...';

  let success=0, failed=0, lastErr='';
  // Send in large batches (500/request) so thousands of rows import in a few calls, not hundreds.
  const CHUNK=500;
  const batches=[];
  for(let i=0;i<importParsedData.length;i+=CHUNK) batches.push(importParsedData.slice(i,i+CHUNK));

  for(const batch of batches){
    try {
      const res = await apiCall('bulk_import_scans', {records: batch});
      if(res?.status==='success'){ success+=res.imported||0; failed+=res.failed||0; if(res.errors&&res.errors.length) lastErr=res.errors[0]; }
      else { failed+=batch.length; if(res?.msg){ lastErr=res.msg; console.warn('Import error:', res.msg); } }
    } catch(e){ failed+=batch.length; lastErr=String(e); console.warn('Import batch failed', e); }
    prog.innerText=`Imported ${success}/${importParsedData.length}...`;
    await new Promise(r=>setTimeout(r,0)); // let the UI repaint between batches
  }

  btn.innerHTML=orig; btn.disabled=false;
  if(failed===0){
    prog.innerText=`✅ Successfully imported ${success} records!`;
    showToast(`Imported ${success} scan records!`,'success');
    setTimeout(()=>{
      closeScanImportModal();
      // Force a fresh DB reload of scan history so the imported (latest) statuses show right away,
      // not the possibly-stale page-load copy.
      _scanRangeLoaded = '';
      const ss=document.getElementById('scan-sum-start')?.value, se=document.getElementById('scan-sum-end')?.value;
      const hs=document.getElementById('scan-hist-start')?.value, he=document.getElementById('scan-hist-end')?.value;
      if(hs&&he) loadScanHistoryRange(hs,he);
      else if(ss&&se) loadScanHistoryRange(ss,se);
      else { refreshDataSilent(); renderScanHistory(); }
    },1500);
  } else {
    prog.innerText=`⚠ Imported ${success}, failed ${failed}`;
    showToast(`Imported ${success}, failed ${failed}`,'error');
    if(lastErr){
      const errDiv=document.getElementById('import-error');
      if(errDiv){ errDiv.innerText='Reason: '+lastErr; errDiv.style.display='block'; }
    }
  }
}

// ============================================================
// ORDER LIFECYCLE TRACKER
// ============================================================
let LIFECYCLE_DATA = [];

function openLifecycleModal() {
  const modal = document.getElementById('lifecycleModal');
  modal.classList.remove('hidden');

  // Pre-fill today's date range
  const today = new Date().toISOString().split('T')[0];
  const monthAgo = new Date(Date.now() - 30*24*60*60*1000).toISOString().split('T')[0];
  const lcStart = document.getElementById('lc-start');
  const lcEnd   = document.getElementById('lc-end');
  if (lcStart && !lcStart.value) lcStart.value = monthAgo;
  if (lcEnd   && !lcEnd.value)   lcEnd.value   = today;

  // Populate agent filter
  const lcAgent = document.getElementById('lc-agent');
  if (lcAgent && lcAgent.options.length <= 1) {
    const agents = [...new Set(ALL_DATA.filter(o=>o.agent).map(o=>o.agent))].sort();
    agents.forEach(a => { const opt=document.createElement('option'); opt.value=a; opt.innerText=a; lcAgent.appendChild(opt); });
  }

  // Don't auto-run — let user click Run Report
}

function closeLifecycleModal() {
  document.getElementById('lifecycleModal').classList.add('hidden');
}

function diffHours(d1, d2) {
  if (!d1 || !d2) return null;
  const t1 = new Date(String(d1).replace(' ','T')).getTime();
  const t2 = new Date(String(d2).replace(' ','T')).getTime();
  if (isNaN(t1) || isNaN(t2)) return null;
  return Math.max(0, (t2 - t1) / (1000 * 60 * 60));
}

function formatDuration(hours) {
  if (hours === null || isNaN(hours)) return '—';
  if (hours < 1)  return Math.round(hours * 60) + ' min';
  if (hours < 24) return hours.toFixed(1) + ' hrs';
  return (hours / 24).toFixed(1) + ' days';
}

function formatDurationShort(hours) {
  if (hours === null || isNaN(hours)) return '—';
  if (hours < 24) return hours.toFixed(1) + 'h';
  return (hours / 24).toFixed(1) + 'd';
}

function durationColor(hours) {
  if (hours === null) return '#94a3b8';
  if (hours <= 4)  return '#10b981'; // green - fast
  if (hours <= 24) return '#f59e0b'; // yellow - ok
  if (hours <= 72) return '#f97316'; // orange - slow
  return '#ef4444';                  // red - very slow
}

function lcLoadMoreRows() {
  const rows = window._lcAllRows || [];
  const tbody = document.getElementById('lc-table-body');
  if (!tbody || !rows.length) return;
  window._lcRenderAll = true;
  runLifecycleReport();
}

// ── Per-column header filters for the Lifecycle table ──
window.LC_COL_FILTERS = window.LC_COL_FILTERS || {};

// Add a funnel icon to every header cell (call after the table body is rendered)
function lcInjectColumnFilters() {
  const table = document.getElementById('lc-table-body')?.closest('table');
  if (!table) return;
  const ths = table.querySelectorAll('thead th');
  ths.forEach((th, idx) => {
    if (th.querySelector('.lc-col-funnel')) return; // already injected
    const active = window.LC_COL_FILTERS[idx] && window.LC_COL_FILTERS[idx].size > 0;
    const btn = document.createElement('span');
    btn.className = 'lc-col-funnel';
    btn.style.cssText = 'cursor:pointer;margin-left:6px;font-size:10px;opacity:0.75;display:inline-block';
    btn.innerHTML = active ? '<i class="fas fa-filter" style="color:#6366f1"></i>' : '<i class="fas fa-filter" style="color:#cbd5e1"></i>';
    btn.onclick = function(e){ e.stopPropagation(); lcOpenColumnFilter(idx, btn); };
    th.appendChild(btn);
  });
}

function lcOpenColumnFilter(colIndex, anchorEl) {
  // Close any existing popover
  document.querySelectorAll('.lc-col-popover').forEach(p => p.remove());
  // Collect unique values from this column across all rows
  const rows = document.querySelectorAll('#lc-table-body tr');
  const valueCounts = {};
  rows.forEach(tr => {
    const tds = tr.querySelectorAll('td');
    if (!tds[colIndex]) return;
    let v = tds[colIndex].textContent.trim();
    if (v === '') v = '—';
    valueCounts[v] = (valueCounts[v]||0) + 1;
  });
  const values = Object.keys(valueCounts).sort((a,b)=>a.localeCompare(b));
  const sel = window.LC_COL_FILTERS[colIndex] || new Set();

  const pop = document.createElement('div');
  pop.className = 'lc-col-popover';
  pop.style.cssText = 'position:fixed;z-index:9999;background:#fff;border:1px solid #e2e8f0;border-radius:10px;box-shadow:0 8px 28px rgba(0,0,0,0.18);width:240px;max-height:340px;display:flex;flex-direction:column;font-size:12px';
  const rect = anchorEl.getBoundingClientRect();
  let left = rect.left; if (left + 240 > window.innerWidth) left = window.innerWidth - 250;
  pop.style.left = left + 'px';
  pop.style.top  = (rect.bottom + 4) + 'px';

  const optsHtml = values.map(v => {
    const checked = sel.has(v) ? 'checked' : '';
    const safe = v.replace(/"/g,'&quot;');
    return `<label style="display:flex;align-items:center;gap:8px;padding:5px 10px;cursor:pointer;border-radius:6px" onmouseover="this.style.background='#f1f5f9'" onmouseout="this.style.background=''"><input type="checkbox" class="lc-colf-cb" value="${safe}" ${checked} style="width:14px;height:14px"> <span style="flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="${safe}">${v}</span><span style="color:#94a3b8;font-size:10px">${valueCounts[v]}</span></label>`;
  }).join('');

  pop.innerHTML =
    '<div style="padding:8px 10px;border-bottom:1px solid #f1f5f9;display:flex;gap:6px;align-items:center">' +
      '<input type="text" placeholder="Search…" class="lc-colf-search" style="flex:1;border:1px solid #e2e8f0;border-radius:6px;padding:4px 8px;font-size:12px;outline:none">' +
    '</div>' +
    '<div class="lc-colf-list" style="overflow-y:auto;padding:4px">' + optsHtml + '</div>' +
    '<div style="padding:8px 10px;border-top:1px solid #f1f5f9;display:flex;gap:8px">' +
      '<button class="lc-colf-clear" style="flex:1;background:#f1f5f9;color:#475569;border:none;border-radius:6px;padding:6px;font-size:12px;font-weight:600;cursor:pointer">Clear</button>' +
      '<button class="lc-colf-apply" style="flex:1;background:#6366f1;color:#fff;border:none;border-radius:6px;padding:6px;font-size:12px;font-weight:600;cursor:pointer">Apply</button>' +
    '</div>';

  document.body.appendChild(pop);

  // Live search within the popover
  pop.querySelector('.lc-colf-search').addEventListener('input', function(){
    const q = this.value.toLowerCase();
    pop.querySelectorAll('.lc-colf-list label').forEach(l => {
      l.style.display = l.textContent.toLowerCase().includes(q) ? '' : 'none';
    });
  });
  pop.querySelector('.lc-colf-apply').onclick = function(){
    const chosen = new Set();
    pop.querySelectorAll('.lc-colf-cb:checked').forEach(cb => chosen.add(cb.value));
    if (chosen.size === 0) delete window.LC_COL_FILTERS[colIndex];
    else window.LC_COL_FILTERS[colIndex] = chosen;
    pop.remove();
    lcFilterTable();
    lcRefreshFunnelIcons();
  };
  pop.querySelector('.lc-colf-clear').onclick = function(){
    delete window.LC_COL_FILTERS[colIndex];
    pop.remove();
    lcFilterTable();
    lcRefreshFunnelIcons();
  };
  // Close on outside click
  setTimeout(() => {
    const closer = function(ev){ if (!pop.contains(ev.target)) { pop.remove(); document.removeEventListener('mousedown', closer); } };
    document.addEventListener('mousedown', closer);
  }, 0);
}

function lcRefreshFunnelIcons() {
  const table = document.getElementById('lc-table-body')?.closest('table');
  if (!table) return;
  table.querySelectorAll('thead th').forEach((th, idx) => {
    const f = th.querySelector('.lc-col-funnel');
    if (!f) return;
    const active = window.LC_COL_FILTERS[idx] && window.LC_COL_FILTERS[idx].size > 0;
    f.innerHTML = active ? '<i class="fas fa-filter" style="color:#6366f1"></i>' : '<i class="fas fa-filter" style="color:#cbd5e1"></i>';
  });
}

function lcFilterTable() {
  const q   = (document.getElementById('lc-search')?.value||'').toLowerCase().trim();
  const cpf = (document.getElementById('lc-cp-status')?.value||'').toLowerCase().trim();
  const awbf = (document.getElementById('lc-awb-filter')?.value||'');
  const rows = document.querySelectorAll('#lc-table-body tr');
  let shown = 0;
  rows.forEach(tr => {
    const text = tr.textContent.toLowerCase();
    const matchSearch = !q || text.includes(q);
    // Clickpost Status column is the 16th td (index 15)
    const tds = tr.querySelectorAll('td');
    const cpCell = tds[15] ? tds[15].textContent.toLowerCase().trim() : '';
    const matchCp = !cpf || cpCell.includes(cpf);
    // AWB No. column is the 13th td (index 12) — blank cells show '—'
    const awbCell = tds[12] ? tds[12].textContent.trim() : '';
    const hasAwb = awbCell !== '' && awbCell !== '—';
    // Dispatch Date column is the 15th td (index 14) — blank/— if not dispatched
    const dispCell = tds[14] ? tds[14].textContent.trim() : '';
    const isDispatched = dispCell !== '' && dispCell !== '—';
    let matchAwb = true;
    if (awbf === 'generated')         matchAwb = hasAwb;
    else if (awbf === 'notgenerated') matchAwb = !hasAwb;
    else if (awbf === 'gen_not_disp') matchAwb = hasAwb && !isDispatched;
    // Per-column header filters (LC_COL_FILTERS: {colIndex: Set(values)})
    let matchCols = true;
    if (window.LC_COL_FILTERS) {
      for (const ci in window.LC_COL_FILTERS) {
        const sel = window.LC_COL_FILTERS[ci];
        if (!sel || sel.size === 0) continue;
        const cellVal = tds[ci] ? tds[ci].textContent.trim() : '';
        const norm = (cellVal === '' ) ? '—' : cellVal;
        if (!sel.has(norm)) { matchCols = false; break; }
      }
    }
    if (matchSearch && matchCp && matchAwb && matchCols) { tr.style.display = ''; shown++; }
    else { tr.style.display = 'none'; }
  });
  const cnt = document.getElementById('lc-search-count');
  if (cnt && (q||cpf||awbf)) { cnt.textContent = shown + ' match' + (shown!==1?'es':''); cnt.style.color = shown===0?'#ef4444':'#94a3b8'; }
  else if (cnt) cnt.textContent = '';
}

async function runLifecycleReport() {
  const isLoadMore = window._lcRenderAll === true;
  window._lcRenderAll = false;
  // A direct Run Report must always recompute from the current date range — never reuse cached rows
  if (!isLoadMore) window._lcAllRows = null;
  if (!isLoadMore) window.LC_COL_FILTERS = {};

  const sDate    = document.getElementById('lc-start')?.value;
  const eDate    = document.getElementById('lc-end')?.value;
  const agentFlt = document.getElementById('lc-agent')?.value || 'All';
  const tbody    = document.getElementById('lc-table-body');
  const kpisDiv  = document.getElementById('lc-kpis');
  const tlDiv    = document.getElementById('lc-timeline');
  const badge    = document.getElementById('lc-count-badge');

  tbody.innerHTML = '<tr><td colspan="20" style="text-align:center;padding:30px;color:#94a3b8"><i class="fas fa-spinner fa-spin" style="font-size:20px;color:#6366f1"></i><div style="margin-top:8px;font-size:13px">'+(isLoadMore?'Rendering all rows...':'Loading Clickpost & calculating...')+'</div></td></tr>';

  if (!isLoadMore) {
    const lcSrch = document.getElementById('lc-search'); if(lcSrch) lcSrch.value='';
    const lcCp = document.getElementById('lc-cp-status'); if(lcCp) lcCp.value='';
    const lcAwbF = document.getElementById('lc-awb-filter'); if(lcAwbF) lcAwbF.value='';
    const lcCnt = document.getElementById('lc-search-count'); if(lcCnt) lcCnt.textContent='';
    // Auto-load Clickpost from DB only once
  if (!OPS_CP_DATA || OPS_CP_DATA.length === 0) {
    try {
      const cpResult = await apiCall('get_clickpost');
      if (cpResult && cpResult.status === 'success') {
        OPS_CP_DATA = (cpResult.data || []).map(function(r) {
          return { 'Waybill': r.waybill||'', 'Order ID': r.order_id||'', 'Courier': r.courier_name||'', 'Status': r.status||'', 'Updated At': r.updated_at||'' };
        });
        // Update the slot UI too
        const nameEl = document.getElementById('ops-slot-cp-name');
        const slotEl = document.getElementById('ops-slot-cp');
        if (slotEl) { slotEl.style.borderColor='#16a34a'; slotEl.style.background='#f0fdf4'; }
        if (nameEl) nameEl.textContent = '✅ ' + OPS_CP_DATA.length + ' records loaded from Clickpost live';
      }
    } catch(e) { console.warn('Clickpost auto-load failed:', e); }
    }
  }

  // Auto-load Payment data from DB (payment_files table) only once
  if (!window.LC_PAYMENT_DATA || window.LC_PAYMENT_DATA.length === 0) {
    try {
      const pr = await apiCall('get_payment_data');
      if (pr && pr.status === 'success' && pr.data && pr.data.length) {
        window.LC_PAYMENT_DATA = pr.data.map(function(row) {
          return {orderId:row.order_id||'', awb:row.awb||'', amount:String(row.amount||''), gateway:row.gateway||row.payment_method||'', paymentMethod:row.payment_method||''};
        });
        const ps = document.getElementById('lc-pay-status');
        if (ps) ps.textContent = '✅ ' + window.LC_PAYMENT_DATA.length + ' records from DB';
      }
    } catch(e) { console.warn('Payment auto-load failed:', e); }
  }

  // Fetch ALL orders in the date range directly from the DB (enriched with agent/scan data).
  // ALL_DATA only holds the latest ~5000-6000 orders, so older orders in the range were missing.
  let lcOrders = [];
  if (sDate && eDate && !isLoadMore) {
    try {
      const lor = await apiCall('lifecycle_orders', { start: sDate, end: eDate });
      if (lor && lor.status==='success' && Array.isArray(lor.data)) lcOrders = lor.data;
    } catch(e) { console.warn('lifecycle_orders fetch failed, using loaded orders', e); }
    window._lcOrders = lcOrders;
  } else {
    lcOrders = window._lcOrders || [];
  }
  // Fallback to in-memory orders if the endpoint returned nothing
  const sourceOrders = lcOrders.length ? lcOrders : ALL_DATA;

  // Filter data
  let filtered = sourceOrders.filter(o => {
    const d = extractDate(o.createdAt || '');
    const matchDate  = (!sDate || !eDate) || (d && d >= sDate && d <= eDate);
    const matchAgent = agentFlt === 'All' || o.agent === agentFlt;
    return matchDate && matchAgent;
  });

  LIFECYCLE_DATA = filtered;
  if (badge) badge.textContent = filtered.length + ' orders' + ((sDate&&eDate) ? ' (' + sDate + ' → ' + eDate + ')' : ' in range');

  // Build Clickpost order_id → status lookup map (normalised, no #)
  const cpMap = {};
  (OPS_CP_DATA || []).forEach(function(r) {
    const oid = String(r['Order ID']||'').trim().replace(/#/g,'').toUpperCase();
    if (oid) cpMap[oid] = r;
    // Also index by waybill as fallback
    const wb = String(r['Waybill']||'').trim().toUpperCase();
    if (wb) cpMap[wb] = r;
  });
  window._cpMapLC = cpMap; // store for CSV export

  // Build Return Scanned set from SCAN_HISTORY_DATA (by orderId and AWB)
  // Also build a scan-AWB map so couriers like DTDC (whose AWB is in scanning, not clickpost) get an AWB.
  const returnScannedSet = new Set();
  const returnAwbSet = new Set();
  const scanAwbByOrder = {}; // normalised orderId -> awb from Dispatch & Scan
  (SCAN_HISTORY_DATA || []).forEach(function(s) {
    const rid = String(s.orderId||'').replace(/#/g,'').trim().toUpperCase();
    const rawb = String(s.awb||'').trim().toUpperCase();
    if (rid && rawb && !scanAwbByOrder[rid]) scanAwbByOrder[rid] = rawb;
    if ((s.dispatchStatus||'').toLowerCase()==='returned') {
      if (rid) returnScannedSet.add(rid);
      if (rawb) returnAwbSet.add(rawb);
    }
  });

  // Build Payment lookup map from LC_PAYMENT_DATA
  const payMap = {}; // keyed by normalised orderId AND awb
  (window.LC_PAYMENT_DATA || []).forEach(function(r) {
    ['orderId','awb'].forEach(function(k) {
      const key = String(r[k]||'').replace(/#/g,'').trim().toUpperCase();
      if (key) payMap[key] = r;
    });
  });
  window._lcPayMap = payMap;

  // Calculate durations per order
  const rows = filtered.map(o => {
    // Stage 1: Order Received → Assigned (createdAt → assignDate)
    const stage1 = diffHours(o.createdAt, o.assignDate);
    // Stage 2: Assigned → Agent Called/Updated (assignDate → lastUpdated)
    const stage2 = (o.status !== 'Pending' && o.lastUpdated && o.assignDate)
      ? diffHours(o.assignDate, o.lastUpdated) : null;
    // Stage 3: Called → Dispatched (lastUpdated → scanTimestamp)
    const stage3 = (o.dispatchStatus === 'Dispatched' && o.scanTimestamp && o.lastUpdated)
      ? diffHours(o.lastUpdated, o.scanTimestamp) : null;

    // Match to Clickpost by Order ID first, then AWB fallback
    const normOid = String(o.orderId||'').replace(/#/g,'').trim().toUpperCase();
    const awb = String(o.awb||'').trim().toUpperCase();
    const cpRow = (normOid && cpMap[normOid]) ? cpMap[normOid] : (awb && cpMap[awb] ? cpMap[awb] : null);
    const cpStatus = cpRow ? String(cpRow['Status']||'').trim() : '';
    // AWB & Courier: order's own value first, else clickpost_webhook, else Dispatch & Scan (DTDC etc.)
    const awbFinal = (awb || String(cpRow?.['Waybill']||'').trim().toUpperCase() || scanAwbByOrder[normOid] || '');
    const courierFinal = o.courierName || o.courier || String(cpRow?.['Courier']||'').trim();

    // Determine Final Status — based on whether payment was received (matched in uploaded payment files)
    const isDelivered = cpStatus.toLowerCase().includes('deliver') && !cpStatus.toLowerCase().includes('rto');
    const isRTO = cpStatus.toLowerCase().includes('rto');
    const isInTransit = cpStatus.toLowerCase().includes('transit');
    const payGateway = String(o.paymentGateway||o.financialStatus||'').toLowerCase();
    const courierN = String(cpRow?.['Courier']||o.courierName||o.courier||'').toLowerCase();

    // Payment match — look up this order/AWB in the payment files map
    const _normRowId = String(o.orderId||'').replace(/#/g,'').trim().toUpperCase();
    const _rowAwb = awbFinal;
    const _payRec = (payMap[_normRowId] || (_rowAwb ? payMap[_rowAwb] : null)) || null;

    let finalStatus = '';
    if (_payRec) {
      finalStatus = 'Payment Received';
    } else {
      finalStatus = 'Payment Not Received';
    }

    // Return Status — from Dispatch & Scan (scanning) data.
    // Scan team scans the AWB (sometimes the order number) when a parcel comes back to HO.
    // The lifecycle_orders endpoint sets o.scannedReturned when ANY scan row for this order is 'Returned'
    // (including AWB-only returns matched via Clickpost). We also check the in-memory scan sets as a backup.
    const normRowId = String(o.orderId||'').replace(/#/g,'').trim().toUpperCase();
    const rowAwb = awbFinal; // order's AWB, else Clickpost waybill, else scan AWB
    const wasScannedBack = o.scannedReturned === true
                     || returnScannedSet.has(normRowId) || returnAwbSet.has(normRowId)
                     || (rowAwb && (returnScannedSet.has(rowAwb) || returnAwbSet.has(rowAwb)));
    let returnStatus = '';
    if (wasScannedBack) {
      returnStatus = 'Returned to HO';        // physically scanned back into the warehouse
    } else if (cpStatus.toLowerCase().includes('rto')) {
      returnStatus = 'Not Received Yet';       // courier marked RTO but not scanned back yet
    }

    // Payment lookup from payment_files (by Order ID or AWB)
    const payRec = (payMap[normRowId] || (rowAwb ? payMap[rowAwb] : null)) || null;

    // Payment Gateway — from payment_files first, else Shopify order data
    const paymentGateway = (payRec && (payRec.gateway || payRec.paymentMethod)) || o.paymentMethod || o.paymentGateway || '';

    // Payment Received from payment_files
    const paymentReceived = payRec ? ('₹' + (payRec.amount||'')) : '';

    return { ...o, awb: awbFinal, courierName: courierFinal, stage1, stage2, stage3, cpStatus, finalStatus, returnStatus, paymentGateway, paymentReceived };
  });

  // Expose return sets for CSV export
  window._lcReturnScannedSet = returnScannedSet;
  window._lcReturnAwbSet = returnAwbSet;

  // Averages (only non-null)
  const avg = (arr, key) => {
    const vals = arr.map(r=>r[key]).filter(v=>v!==null&&!isNaN(v));
    return vals.length > 0 ? vals.reduce((a,b)=>a+b,0)/vals.length : null;
  };
  const avgS1 = avg(rows, 'stage1');
  const avgS2 = avg(rows, 'stage2');
  const avgS3 = avg(rows, 'stage3');
  const unassigned = rows.filter(r=>!r.agent).length;
  const dispatched = rows.filter(r=>r.dispatchStatus==='Dispatched').length;
  const called     = rows.filter(r=>r.status!=='Pending'&&r.agent).length;

  // ── Delivery Performance (like the Delivery Report) — computed from Clickpost status per order ──
  (function renderLcDelPerf(){
    const box = document.getElementById('lc-delperf');
    if (!box) return;
    const isPaidRow = r => {
      const fin = String(r.financialStatus||'').toLowerCase();
      const tg = String(r.tags||'').toLowerCase(), pm = String(r.paymentMethod||'').toLowerCase();
      const ppcod = tg.includes('ppcod')||tg.includes('gokwik_ppcod')||pm.includes('ppcod')||pm.includes('gokwik_ppcod');
      return fin==='paid' && !ppcod;            // Prepaid only if paid and not PPCOD
    };
    let total=0, cod=0, pp=0;
    let del=0,delCod=0,delPp=0, rto=0,rtoCod=0,rtoPp=0, transit=0, ofd=0, failed=0;
    rows.forEach(r=>{
      total++;
      const paid = isPaidRow(r);
      if (paid) pp++; else cod++;
      const st = String(r.cpStatus||'').toLowerCase();
      if (st.includes('rto')) { rto++; paid?rtoPp++:rtoCod++; }
      else if (st.includes('deliver')) { del++; paid?delPp++:delCod++; }
      else if (st.includes('out for delivery')||st==='ofd') { ofd++; }
      else if (st.includes('transit')) { transit++; }
      else if (st.includes('fail')||st.includes('undeliver')||st.includes('exception')) { failed++; }
    });
    const pc = (n,d)=> d>0 ? (n/d*100).toFixed(1) : '0.0';
    const card = (label,val,sub,color,dot,extra)=>`
      <div style="background:#fff;border:1px solid #eef0f3;border-radius:12px;padding:14px 16px;position:relative">
        <div style="position:absolute;top:14px;right:14px;width:8px;height:8px;border-radius:50%;background:${dot}"></div>
        <div style="font-size:10px;font-weight:700;letter-spacing:.06em;color:#94a3b8;text-transform:uppercase">${label}</div>
        <div style="font-size:26px;font-weight:900;color:${color};line-height:1.1;margin-top:6px">${val}</div>
        ${sub?`<div style="font-size:11px;color:#94a3b8;margin-top:2px">${sub}</div>`:''}
        ${extra||''}
      </div>`;
    const split = (codTxt,ppTxt)=>`
      <div style="display:flex;gap:18px;margin-top:10px;padding-top:10px;border-top:1px solid #f1f5f9">
        <div><div style="font-size:9px;color:#94a3b8;font-weight:700">COD</div><div style="font-size:13px;font-weight:800;color:#ea6a1e">${codTxt}</div></div>
        <div><div style="font-size:9px;color:#94a3b8;font-weight:700">PREPAID</div><div style="font-size:13px;font-weight:800;color:#6366f1">${ppTxt}</div></div>
      </div>`;
    box.innerHTML = `
      <div style="font-size:12px;font-weight:700;color:#374151;margin-bottom:12px;text-transform:uppercase;letter-spacing:0.06em">Delivery Performance</div>
      <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px">
        ${card('Total Orders', total.toLocaleString(), (sDate&&eDate)?(sDate+' → '+eDate):'', '#1e293b', '#3b82f6', split(cod.toLocaleString()+' · '+pc(cod,total)+'%', pp.toLocaleString()+' · '+pc(pp,total)+'%'))}
        ${card('Del %', pc(del,total)+' %', del+' delivered', '#15803d', '#22c55e', split(pc(delCod,cod)+'% · '+delCod, pc(delPp,pp)+'% · '+delPp))}
        ${card('RTO %', pc(rto,total)+' %', rto+' returned', '#b91c1c', '#ef4444', split(pc(rtoCod,cod)+'% · '+rtoCod, pc(rtoPp,pp)+'% · '+rtoPp))}
        ${card('In Transit', transit.toLocaleString(), pc(transit,total)+'% of total', '#a16207', '#f59e0b')}
        ${card('OFD', ofd.toLocaleString(), 'Out for delivery', '#15803d', '#22c55e')}
        ${card('Failed Orders', failed.toLocaleString(), pc(failed,total)+'% of total', '#ea6a1e', '#f97316')}
      </div>`;
  })();

  // ── KPI Cards ──
  const kpi = (label, val, sub, color, icon) => `
    <div style="padding:16px 20px;border-right:1px solid #f1f5f9;display:flex;align-items:center;gap:12px">
      <div style="width:40px;height:40px;border-radius:10px;background:${color}15;color:${color};display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0">
        <i class="fas fa-${icon}"></i>
      </div>
      <div>
        <div style="font-size:22px;font-weight:900;color:${color};line-height:1">${val}</div>
        <div style="font-size:11px;font-weight:700;color:#374151;margin-top:2px">${label}</div>
        <div style="font-size:10px;color:#94a3b8;margin-top:1px">${sub}</div>
      </div>
    </div>`;

  if (kpisDiv) kpisDiv.innerHTML =
    kpi('Avg: Received → Assigned', formatDuration(avgS1), `${unassigned} still unassigned`, '#3b82f6', 'user-plus') +
    kpi('Avg: Assigned → Called',   formatDuration(avgS2), `${called} of ${rows.filter(r=>r.agent).length} called`, '#8b5cf6', 'phone') +
    kpi('Avg: Called → Dispatched', formatDuration(avgS3), `${dispatched} dispatched`, '#10b981', 'truck') +
    kpi('Total Orders in Range',    filtered.length, `${dispatched} dispatched (${filtered.length>0?Math.round(dispatched/filtered.length*100):0}%)`, '#f59e0b', 'box');

  // ── Timeline Visual ──
  const totalAvg = (avgS1||0) + (avgS2||0) + (avgS3||0);
  const pct = (v) => totalAvg > 0 ? Math.round((v||0)/totalAvg*100) : 33;
  const p1=pct(avgS1), p2=pct(avgS2), p3=100-p1-p2;

  const stage = (label, val, color, pct, icon) => `
    <div style="flex:${pct};min-width:80px;padding:14px 16px;background:${color}10;border-right:1px solid ${color}30;position:relative">
      <div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:${color};margin-bottom:4px"><i class="fas fa-${icon}" style="margin-right:4px"></i>${label}</div>
      <div style="font-size:20px;font-weight:900;color:#1e293b">${val}</div>
      <div style="position:absolute;bottom:0;left:0;height:3px;width:100%;background:${color};border-radius:0 0 0 0"></div>
    </div>`;
  const arrow = (color) => `<div style="width:32px;flex-shrink:0;display:flex;align-items:center;justify-content:center;color:${color};font-size:14px"><i class="fas fa-arrow-right"></i></div>`;

  if (tlDiv) tlDiv.innerHTML =
    `<div style="padding:14px 16px;background:#f8fafc;min-width:80px;display:flex;flex-direction:column;justify-content:center">
      <div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#94a3b8;margin-bottom:4px"><i class="fas fa-shopping-cart" style="margin-right:4px"></i>ORDER IN</div>
      <div style="font-size:12px;font-weight:700;color:#64748b">Shopify</div>
    </div>` +
    arrow('#3b82f6') +
    stage('Received → Assigned', formatDuration(avgS1), '#3b82f6', p1, 'user-plus') +
    arrow('#8b5cf6') +
    stage('Assigned → Called', formatDuration(avgS2), '#8b5cf6', p2, 'phone') +
    arrow('#10b981') +
    stage('Called → Dispatched', formatDuration(avgS3), '#10b981', p3, 'truck') +
    `<div style="padding:14px 16px;background:#f0fdf4;min-width:80px;display:flex;flex-direction:column;justify-content:center">
      <div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#16a34a;margin-bottom:4px"><i class="fas fa-check-circle" style="margin-right:4px"></i>DONE</div>
      <div style="font-size:12px;font-weight:700;color:#15803d">Dispatched</div>
    </div>`;

  // ── Table rows ──
  const badge_st = (status,dispatchStatus) => {
    if (dispatchStatus==='Dispatched') return '<span style="background:#dcfce7;color:#15803d;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700;border:1px solid #bbf7d0">Dispatched</span>';
    const sc = {Done:'#10b981',Cancel:'#ef4444',Pending:'#f59e0b',Busy:'#3b82f6',NP:'#f97316'};
    const c = sc[status]||'#94a3b8';
    return `<span style="background:${c}15;color:${c};padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700;border:1px solid ${c}30">${status||'Pending'}</span>`;
  };

  const cell = (hours, isLast=false) => {
    if (hours===null) return `<td style="padding:10px 14px;text-align:center;background:#f8fafc;color:#94a3b8;font-size:12px${isLast?';background:#f0fdf4':''}">—</td>`;
    const c = durationColor(hours);
    const bgc = hours<=4?'#f0fdf4':hours<=24?'#fffbeb':hours<=72?'#fff7ed':'#fef2f2';
    return `<td style="padding:10px 14px;text-align:center;background:${bgc}${isLast?';background:#f0fdf4':''}">
      <span style="font-weight:700;color:${c};font-size:13px">${formatDuration(hours)}</span>
    </td>`;
  };

  // Sort by stage1 descending (slowest to assign first)
  rows.sort((a,b) => String(b.createdAt||'').localeCompare(String(a.createdAt||'')));

  // Clickpost status badge
  const cpBadge = (st) => {
    if (!st) return '<span style="color:#94a3b8;font-size:11px">—</span>';
    const stl = st.toLowerCase();
    const cfg = stl.includes('deliver')&&!stl.includes('rto') ? ['#15803d','#f0fdf4','#bbf7d0','✅'] :
                stl.includes('rto') ? ['#b91c1c','#fef2f2','#fecaca','↩'] :
                stl.includes('transit') ? ['#1d4ed8','#eff6ff','#bfdbfe','🚚'] :
                stl.includes('order') ? ['#6b7280','#f9fafb','#e5e7eb','📋'] :
                ['#92400e','#fffbeb','#fde68a','📦'];
    return `<span style="background:${cfg[1]};color:${cfg[0]};border:1px solid ${cfg[2]};padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700">${cfg[3]} ${st}</span>`;
  };

  // Final status badge
  const fsBadge = (fs) => {
    if (!fs) return '<span style="color:#94a3b8;font-size:11px">—</span>';
    const fsl = fs.toLowerCase();
    const cfg = fsl.includes('not received') ? ['#b91c1c','#fef2f2','#fecaca'] :
                fsl.includes('paid')||fsl.includes('payment received') ? ['#15803d','#f0fdf4','#bbf7d0'] :
                fsl.includes('return') ? ['#b91c1c','#fef2f2','#fecaca'] :
                fsl.includes('transit') ? ['#1d4ed8','#eff6ff','#bfdbfe'] :
                ['#92400e','#fffbeb','#fde68a'];
    return `<span style="background:${cfg[1]};color:${cfg[0]};border:1px solid ${cfg[2]};padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700;white-space:nowrap">${fs}</span>`;
  };

  // Render first 500 rows for performance; user can load more
  const RENDER_LIMIT = isLoadMore ? Infinity : 500;
  window._lcAllRows = rows; // store for load-more
  const renderRows = rows.slice(0, RENDER_LIMIT);
  tbody.innerHTML = renderRows.map(r =>
    `<tr style="border-bottom:1px solid #f8fafc" onmouseover="this.style.background='#f8fafc'" onmouseout="this.style.background=''">
      <td style="position:sticky;left:0;z-index:2;background:#fff;min-width:120px;max-width:120px;overflow:hidden;text-overflow:ellipsis;border-right:1px solid #f1f5f9;padding:10px 14px;font-weight:700;color:#1e293b;font-size:13px;font-family:monospace" title="#${r.orderId}">#${r.orderId}</td>
      <td style="position:sticky;left:120px;z-index:2;background:#fff;border-right:2px solid #e2e8f0;padding:10px 14px;font-size:12px;color:#64748b;white-space:nowrap">${r.createdAt?extractDate(r.createdAt):'—'}</td>
      ${r.agent ? cell(r.stage1) : `<td style="padding:10px 14px;text-align:center;background:#fff7ed"><span style="background:#ffedd5;color:#c2410c;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700">⏳ Unassigned</span></td>`}
      ${r.agent && r.status!=='Pending' ? cell(r.stage2) : `<td style="padding:10px 14px;text-align:center;background:#f5f3ff"><span style="background:#ede9fe;color:#6d28d9;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700">${r.agent?'📞 Pending Call':'—'}</span></td>`}
      ${r.dispatchStatus==='Dispatched' ? cell(r.stage3,true) : `<td style="padding:10px 14px;text-align:center;background:#f0fdf4"><span style="background:#dcfce7;color:#15803d;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700">🚚 Not Yet</span></td>`}
      <td style="padding:10px 14px;text-align:center;font-size:12px;color:#374151;font-weight:600">${r.agent||'<span style="color:#94a3b8">Unassigned</span>'}</td>
      <td style="padding:10px 14px;text-align:center;font-size:11px;color:#92400e;background:#fffbeb;white-space:nowrap">${r.assignDate ? extractDate(r.assignDate) : '<span style="color:#cbd5e1">—</span>'}</td>
      <td style="padding:10px 14px;text-align:center;background:#fffbeb">${(()=>{const sc={Done:'#10b981',Cancel:'#ef4444',Pending:'#f59e0b',Busy:'#3b82f6',NP:'#f97316'};const c=sc[r.status]||'#94a3b8';return `<span style="background:${c}15;color:${c};padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700;border:1px solid ${c}30">${r.status||'Pending'}</span>`;})()}</td>
      <td style="padding:10px 14px;font-size:11px;color:#92400e;background:#fffbeb;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="${(r.agentRemark||'').replace(/"/g,'&quot;')}">${r.agentRemark||'<span style="color:#cbd5e1">—</span>'}</td>
      <td style="padding:10px 14px;text-align:center">${badge_st(r.status,r.dispatchStatus)}</td>
      <td style="padding:10px 14px;font-size:11px;color:#6d28d9;background:#faf5ff;white-space:nowrap;font-family:monospace">${r.sku ? r.sku : '<span style="color:#cbd5e1">—</span>'}</td>
      <td style="padding:10px 14px;text-align:center;font-size:12px;color:#374151;background:#faf5ff;font-weight:700">${r.itemQty || 1}</td>
      <td style="padding:10px 14px;font-size:11px;color:#0f766e;background:#f0fdfa;white-space:nowrap;font-family:monospace">${r.awb ? r.awb : '<span style="color:#cbd5e1">—</span>'}</td>
      <td style="padding:10px 14px;font-size:11px;color:#0f766e;background:#f0fdfa;white-space:nowrap">${(r.courierName||r.courier) ? (r.courierName||r.courier) : '<span style="color:#cbd5e1">—</span>'}</td>
      <td style="padding:10px 14px;text-align:center;font-size:11px;color:#0f766e;background:#f0fdfa;white-space:nowrap">${(r.dispatchStatus==='Dispatched'&&r.scanTimestamp) ? extractDate(r.scanTimestamp) : '<span style="color:#cbd5e1">—</span>'}</td>
      <td style="padding:10px 14px;text-align:center;background:#f0f7ff">${cpBadge(r.cpStatus)}</td>
      <td style="padding:10px 14px;text-align:center;background:#fef2f2">
        ${r.returnStatus==='Returned to HO'
          ? '<span style="background:#dcfce7;color:#15803d;border:1px solid #bbf7d0;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700">✅ Returned to HO</span>'
          : r.returnStatus==='Not Received Yet'
          ? '<span style="background:#fee2e2;color:#b91c1c;border:1px solid #fecaca;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700">⚠ Not Received Yet</span>'
          : '<span style="color:#94a3b8;font-size:11px">—</span>'}
      </td>
      <td style="padding:10px 14px;text-align:center;background:#f5f3ff">
        ${r.paymentGateway
          ? '<span style="background:#ede9fe;color:#6d28d9;border:1px solid #ddd6fe;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600">'+r.paymentGateway+'</span>'
          : '<span style="color:#94a3b8;font-size:11px">—</span>'}
      </td>
      <td style="padding:10px 14px;text-align:center;background:#ecfdf5">
        ${r.paymentReceived
          ? '<span style="background:#d1fae5;color:#047857;border:1px solid #a7f3d0;padding:2px 8px;border-radius:99px;font-size:11px;font-weight:700">'+r.paymentReceived+'</span>'
          : '<span style="color:#94a3b8;font-size:11px">—</span>'}
      </td>
      <td style="padding:10px 14px;text-align:center;background:#f0fdf4">${fsBadge(r.finalStatus)}</td>
    </tr>`
  ).join('') + (rows.length > RENDER_LIMIT
    ? `<tr id="lc-load-more-row"><td colspan="20" style="text-align:center;padding:14px">
        <button onclick="lcLoadMoreRows()" style="background:#6366f1;color:#fff;border:none;border-radius:8px;padding:8px 20px;font-size:12px;font-weight:700;cursor:pointer">
          Load more (showing ${RENDER_LIMIT} of ${rows.length}) →
        </button>
       </td></tr>`
    : '');
  // Add header funnel filters & re-apply any active column filters after render
  lcInjectColumnFilters();
  lcFilterTable();
}

function exportLifecycleCSV() {
  if (!LIFECYCLE_DATA.length) { showToast('Run the report first','error'); return; }
  // Respect on-screen filters: only export orders whose table row is currently visible
  const visibleOrderIds = new Set();
  document.querySelectorAll('#lc-table-body tr').forEach(tr => {
    if (tr.style.display === 'none') return;
    const firstCell = tr.querySelector('td');
    if (firstCell) visibleOrderIds.add(firstCell.textContent.replace(/#/g,'').trim().toUpperCase());
  });
  const sourceData = visibleOrderIds.size > 0
    ? LIFECYCLE_DATA.filter(o => visibleOrderIds.has(String(o.orderId||'').replace(/#/g,'').trim().toUpperCase()))
    : LIFECYCLE_DATA;
  const headers = ['Order ID','Order Date','Agent','Assigned Date','Agent Status','Agent Remark','Dispatch Status','SKU','Qty','AWB No.','Courier','Dispatch Date','Received to Assigned (hrs)','Assigned to Called (hrs)','Called to Dispatched (hrs)','Clickpost Status','Return Status','Payment Gateway','Payment Received','Final Status'];
  const rows = sourceData.map(o => {
    const s1 = diffHours(o.createdAt, o.assignDate);
    const s2 = (o.status!=='Pending'&&o.lastUpdated&&o.assignDate) ? diffHours(o.assignDate,o.lastUpdated) : null;
    const s3 = (o.dispatchStatus==='Dispatched'&&o.scanTimestamp&&o.lastUpdated) ? diffHours(o.lastUpdated,o.scanTimestamp) : null;
    // Use the values already computed on the row (Final Status = Payment Received / Not Received)
    const cpStatusCSV = o.cpStatus || '';
    const fsCSV = o.finalStatus || '';
    const retStatusCSV = o.returnStatus || '';
    const awbCsv2 = String(o.awb||'').trim().toUpperCase();
    const courierCsv2 = o.courierName || o.courier || '';
    const pgCSV = o.paymentGateway || '';
    const payReceivedCSV = o.paymentReceived || '';
    return [o.orderId, o.createdAt?extractDate(o.createdAt):'', o.agent||'Unassigned', o.assignDate?extractDate(o.assignDate):'', o.status||'Pending', o.agentRemark||'', o.dispatchStatus||'Pending',
      o.sku||'', o.itemQty||1, awbCsv2||'', courierCsv2||'', (o.dispatchStatus==='Dispatched'&&o.scanTimestamp)?extractDate(o.scanTimestamp):'',
      s1!==null?s1.toFixed(1):'', s2!==null?s2.toFixed(1):'', s3!==null?s3.toFixed(1):'', cpStatusCSV, retStatusCSV, pgCSV, payReceivedCSV, fsCSV];
  });
  const csv = [headers, ...rows].map(r=>r.map(c=>'"'+String(c||'').replace(/"/g,'""')+'"').join(',')).join('\n');
  const blob = new Blob([csv],{type:'text/csv;charset=utf-8;'});
  const link = document.createElement('a'); link.href=URL.createObjectURL(blob);
  link.download = 'order_lifecycle_'+new Date().toISOString().slice(0,10)+'.csv';
  document.body.appendChild(link); link.click(); document.body.removeChild(link);
  showToast('Lifecycle report exported!','success');
}


// ============================================================
// UPLOAD FILES SYSTEM
// ============================================================
window.UPLOAD_DATA = {}; // {slotKey: [{orderId,awb,amount,gateway,...}]}

const UPLOAD_SLOT_PARSERS = {
  // ── COD PAYMENT FILES ─────────────────────────────────
  dtdc_cod: function(rows) {
    // DTDC: ORDER ID = '#3434336821_SP/...' -> before '_', AMT = amount
    return rows.map(function(r) {
      const rawOid = String(r['ORDER ID']||r['Order ID']||'').trim();
      const oid = rawOid.split('_')[0].replace(/#/g,'').trim();
      const awb = String(r['Consignment Numbar']||r['Consignment Number']||r['AWB']||'').trim();
      const amt = String(r['AMT']||r['Amount']||'').trim();
      if (!oid&&!awb) return null;
      return {orderId:oid, awb:awb, amount:amt, gateway:'COD', paymentMethod:'COD', utr:String(r['UTR ']||r['UTR']||'')};
    }).filter(Boolean);
  },
  shiprocket_cod: function(rows) {
    // Shiprocket: Order Id, total_adjusted_amt, AWB
    return rows.map(function(r) {
      const oid = String(r['Order Id']||r['ORDER ID']||'').replace(/#/g,'').trim();
      const awb = String(r['AWB']||r['Waybill']||'').trim();
      const amt = String(r['total_adjusted_amt']||r['Order Value']||'').trim();
      if (!oid&&!awb) return null;
      return {orderId:oid, awb:awb, amount:amt, gateway:'COD', paymentMethod:'COD', utr:String(r['UTR']||r['Settlement UTR']||'')};
    }).filter(Boolean);
  },
  bluedart_cod: function(rows) {
    return rows.map(function(r) {
      const oid = String(r['Order Id']||r['ORDER ID']||r['Reference No']||'').replace(/#/g,'').trim();
      const awb = String(r['AWB']||r['Consignment No']||r['Waybill']||'').trim();
      const amt = String(r['Amount']||r['COD Amount']||r['Credit']||'').trim();
      if (!oid&&!awb) return null;
      return {orderId:oid, awb:awb, amount:amt, gateway:'COD', paymentMethod:'COD', utr:String(r['UTR']||r['Settlement UTR']||'')};
    }).filter(Boolean);
  },
  delhivery_cod: function(rows) {
    return rows.map(function(r) {
      const oid = String(r['Order Id']||r['ORDER ID']||r['Reference No']||'').replace(/#/g,'').trim();
      const awb = String(r['AWB']||r['Waybill No']||r['Waybill']||'').trim();
      const amt = String(r['Amount']||r['COD Amount']||r['Credit']||'').trim();
      if (!oid&&!awb) return null;
      return {orderId:oid, awb:awb, amount:amt, gateway:'COD', paymentMethod:'COD', utr:String(r['UTR']||r['Settlement UTR']||'')};
    }).filter(Boolean);
  },
  // ── GOKWIK PREPAID ────────────────────────────────────
  gokwik_com: function(rows) {
    // Platform Order Id = #3434..., Credit = amount, Payment Method = upi/cc
    const out = [];
    rows.forEach(function(r) {
      const pid = String(r['Platform Order Id']||r['Platform Order ID']||'').replace(/#/g,'').trim();
      const mid = String(r['Merchant Order Id']||r['Merchant Order ID']||'').replace(/#/g,'').trim();
      const amt = String(r['Credit']||r['Amount']||'').trim();
      const pm = String(r['Payment Method']||'').trim();
      if (pid) out.push({orderId:pid, awb:'', amount:amt, gateway:pm, paymentMethod:pm, utr:String(r['Settlement UTR']||'')});
      if (mid && mid!==pid) out.push({orderId:mid, awb:'', amount:amt, gateway:pm, paymentMethod:pm, utr:String(r['Settlement UTR']||'')});
    });
    return out;
  },
  gokwik_in: function(rows) {
    // Merchant Order Id = Shopify full #, Credit = amount, Payment Method = upi/cc
    const out = [];
    rows.forEach(function(r) {
      const pid = String(r['Platform Order Id']||r['Platform Order ID']||'').replace(/#/g,'').trim();
      const mid = String(r['Merchant Order Id']||r['Merchant Order ID']||'').replace(/#/g,'').trim();
      const amt = String(r['Credit']||r['Amount']||'').trim();
      const pm = String(r['Payment Method']||'').trim();
      if (mid) out.push({orderId:mid, awb:'', amount:amt, gateway:pm, paymentMethod:pm, utr:String(r['Settlement UTR']||'')});
      if (pid && pid!==mid) out.push({orderId:pid, awb:'', amount:amt, gateway:pm, paymentMethod:pm, utr:String(r['Settlement UTR']||'')});
    });
    return out;
  },
  // ── GENERIC (charges, orders, etc.) ──────────────────
  // ── NDR FEEDS ─────────────────────────────────────────
  ndr_raw2: function(rows) {
    return rows.map(function(r) {
      const awb = String(r['Awb']||r['AWB']||r['awb']||'').trim();
      if (!awb) return null;
      return {
        courier_partner: String(r['Courier Partner']||r['Courier']||'').trim(),
        ndr_timestamp:   String(r['Ndr Timestamp']||r['NDR Timestamp']||'').trim(),
        awb:             awb,
        ndr_reason:      String(r['Ndr Reason']||r['NDR Reason']||'').trim(),
        ndr_remark:      String(r['Ndr Remark']||r['NDR Remark']||'').trim(),
        current_status:  String(r['Current Status']||'').trim(),
        order_id:        String(r['Order Id']||r['Order ID']||'').trim(),
        ofd_count:       String(r['OFD Count']||r['Ofd Count']||'').trim(),
        order_type:      String(r['Order Type']||'').trim()
      };
    }).filter(Boolean);
  },
  _generic: function(rows, slotKey) {
    return rows.map(function(r) {
      const pid = String(r['Platform Order Id']||r['Platform Order ID']||'').replace(/#/g,'').trim();
      const mid = String(r['Merchant Order Id']||r['Merchant Order ID']||'').replace(/#/g,'').trim();
      const oid = pid || mid || String(r['Order Id']||r['ORDER ID']||r['order_id']||'').replace(/#/g,'').trim();
      const awb = String(r['AWB']||r['Waybill']||r['Consignment Numbar']||r['AWB No']||'').trim();
      const amt = String(r['Credit']||r['Amount']||r['total_adjusted_amt']||r['AMT']||r['COD Amount']||'').trim();
      const pm = String(r['Payment Method']||r['Payment Mode']||'').trim();
      if (!oid&&!awb) return null;
      return {orderId:oid, awb:awb, amount:amt, gateway:pm, paymentMethod:pm, utr:String(r['UTR']||r['Settlement UTR']||'')};
    }).filter(Boolean);
  }
};

async function handleSlotUpload(input, slotKey) {
  const file = input.files[0];
  if (!file) return;
  const statusEl = document.getElementById('status-' + slotKey);
  const card = document.getElementById('slot-' + slotKey);
  if (statusEl) statusEl.textContent = '⏳ Parsing…';
  if (statusEl) statusEl.className = 'upload-slot-status';

  const reader = new FileReader();
  reader.onload = function(e) {
    try {
      const wb = XLSX.read(e.target.result, {type:'array', cellDates:false});
      const ws = wb.Sheets[wb.SheetNames[0]];
      const rows = XLSX.utils.sheet_to_json(ws, {defval:''});

      const parser = UPLOAD_SLOT_PARSERS[slotKey] || function(r){ return UPLOAD_SLOT_PARSERS._generic(r, slotKey); };
      const parsed = parser(rows);

      window.UPLOAD_DATA[slotKey] = parsed;

      // Refresh global LC_PAYMENT_DATA from all uploaded slots
      rebuildPaymentData();

      if (statusEl) { statusEl.textContent = '✅ ' + parsed.length + ' records loaded — ' + file.name; statusEl.className = 'upload-slot-status loaded'; }
      if (card) card.classList.add('uploaded');
      showToast(slotKey + ': ' + parsed.length + ' records loaded', 'success');
      input.value = '';
    } catch(err) {
      if (statusEl) { statusEl.textContent = '❌ Parse error: ' + err.message; statusEl.className = 'upload-slot-status error'; }
      console.error('Upload parse error', slotKey, err);
    }
  };
  reader.readAsArrayBuffer(file);
}

function rebuildPaymentData() {
  // Merge all payment slots into LC_PAYMENT_DATA for lifecycle matching
  const paymentSlots = ['dtdc_cod','shiprocket_cod','bluedart_cod','delhivery_cod','gokwik_com','gokwik_in'];
  let allRows = [];
  paymentSlots.forEach(function(key) {
    if (window.UPLOAD_DATA[key]) allRows = allRows.concat(window.UPLOAD_DATA[key]);
  });
  window.LC_PAYMENT_DATA = allRows;
  const lc_status = document.getElementById('lc-pay-status');
  if (lc_status && allRows.length) lc_status.textContent = '✅ ' + allRows.length + ' payment records loaded';
}

async function saveAllPaymentsToDB() {
  // ALL upload slots — charges + orders + COD + prepaid (previously only COD/prepaid were saved, so charges files showed 0)
  const allSlots = ['shiprocket_orders','bluedart_charges','delhivery_charges','dtdc_charges','dtdc_cod','shiprocket_cod','bluedart_cod','delhivery_cod','gokwik_com','gokwik_in'];
  const statusEl = document.getElementById('upload-batch-status');
  let saved = 0;
  const errors = [];
  if (statusEl) statusEl.textContent = '⏳ Saving…';

  for (const slotKey of allSlots) {
    const records = window.UPLOAD_DATA[slotKey];
    if (!records || !records.length) continue;
    try {
      const r = await apiCall('save_payment_batch', {file_type: slotKey, records: records, batch_id: new Date().toISOString().split('T')[0]});
      if (r && r.status === 'success') saved += r.count || 0;
      else errors.push(slotKey + ': ' + ((r && r.msg) || 'unknown error'));
    } catch(e) { errors.push(slotKey + ': ' + e.message); console.warn('Save failed for', slotKey, e); }
  }

  // NDR feeds save to their own tables (separate from payment_files)
  for (const ndrSlot of [['ndr_raw2','save_ndr_raw2']]) {
    const recs = window.UPLOAD_DATA[ndrSlot[0]];
    if (!recs || !recs.length) continue;
    try {
      const r = await apiCall(ndrSlot[1], {records: recs});
      if (r && r.status === 'success') saved += r.count || 0;
      else errors.push(ndrSlot[0] + ': ' + ((r && r.msg) || 'unknown error'));
    } catch(e) { errors.push(ndrSlot[0] + ': ' + e.message); }
  }

  if (errors.length) {
    if (statusEl) statusEl.textContent = '⚠️ Saved ' + saved + ' — errors: ' + errors.join(' | ');
    showToast('Save errors: ' + errors.join(' | '), 'error');
  } else {
    if (statusEl) statusEl.textContent = '✅ Saved ' + saved + ' records to DB';
    showToast('Saved ' + saved + ' records to database', 'success');
  }
  await loadUploadSummary();
}

async function loadUploadSummary() {
  const tableEl = document.getElementById('upload-summary-table');
  if (!tableEl) return;
  tableEl.innerHTML = '<div style="color:#94a3b8;font-size:12px;text-align:center;padding:16px"><i class="fas fa-spinner fa-spin"></i> Loading...</div>';
  try {
    const r = await apiCall('get_payment_summary');
    if (!r.data || !r.data.length) { tableEl.innerHTML = '<div style="color:#94a3b8;font-size:12px;text-align:center;padding:16px">No records saved to DB yet. Upload files and click "Save All to DB".</div>'; return; }
    const labels = {'shiprocket_orders':'Shiprocket Orders','bluedart_charges':'Bluedart Charges','delhivery_charges':'Delhivery Charges','dtdc_charges':'DTDC Charges','dtdc_cod':'DTDC COD Payment','shiprocket_cod':'Shiprocket COD Payment','bluedart_cod':'Bluedart COD Payment','delhivery_cod':'Delhivery COD Payment','gokwik_com':'Gokwik .com (Prepaid)','gokwik_in':'Gokwik .in (Prepaid)'};
    tableEl.innerHTML = '<table style="width:100%;border-collapse:collapse;font-size:12px"><thead><tr style="background:#f8fafc"><th style="padding:9px 12px;text-align:left;font-weight:700;color:#64748b;border-bottom:1px solid #e2e8f0">File Type</th><th style="padding:9px 12px;text-align:right;font-weight:700;color:#64748b;border-bottom:1px solid #e2e8f0">Records</th><th style="padding:9px 12px;text-align:left;font-weight:700;color:#64748b;border-bottom:1px solid #e2e8f0">Last Uploaded</th></tr></thead><tbody>' +
      r.data.map(function(row) {
        return '<tr style="border-bottom:1px solid #f1f5f9"><td style="padding:9px 12px;color:#374151;font-weight:600">' + (labels[row.file_type]||row.file_type) + '</td><td style="padding:9px 12px;text-align:right;color:#6366f1;font-weight:700">' + row.cnt + '</td><td style="padding:9px 12px;color:#64748b">' + (row.last_upload||'').split('T')[0] + '</td></tr>';
      }).join('') + '</tbody></table>';

    // Also update slot cards
    r.data.forEach(function(row) {
      const st = document.getElementById('status-' + row.file_type);
      if (st) { st.textContent = '✅ ' + row.cnt + ' records in DB (last: ' + (row.last_upload||'').split('T')[0] + ')'; st.className = 'upload-slot-status loaded'; }
      const cd = document.getElementById('slot-' + row.file_type);
      if (cd) cd.classList.add('uploaded');
    });
  } catch(e) {
    tableEl.innerHTML = '<div style="color:#dc2626;font-size:12px;padding:12px">Error loading summary: ' + e.message + '</div>';
  }
}

async function loadPaymentDataFromDB() {
  // Load payment data from DB into LC_PAYMENT_DATA for lifecycle matching
  try {
    const r = await apiCall('get_payment_data');
    if (r.status==='success' && r.data && r.data.length) {
      window.LC_PAYMENT_DATA = r.data.map(function(row) {
        return {orderId:row.order_id||'', awb:row.awb||'', amount:String(row.amount||''), gateway:row.gateway||row.payment_method||'', paymentMethod:row.payment_method||''};
      });
      showToast('Payment data loaded from DB: ' + window.LC_PAYMENT_DATA.length + ' records', 'success');
      const lc_status = document.getElementById('lc-pay-status');
      if (lc_status) lc_status.textContent = '✅ ' + window.LC_PAYMENT_DATA.length + ' records from DB';
    }
  } catch(e) { console.warn('loadPaymentDataFromDB error', e); }
}

function renderUploadsView() {
  // Slot definitions — Shopify (.com/.in) and Clickpost removed (webhook handles those)
  const UPLOAD_SLOTS = [
    { key:'shiprocket_orders', color:'#8b5cf6', icon:'fas fa-rocket',         label:'Shiprocket Orders Dump',  desc:'Order / AWB dump from Shiprocket dashboard' },
    { key:'bluedart_charges',  color:'#f59e0b', icon:'fas fa-file-invoice',   label:'Bluedart Charges',        desc:'Bluedart shipping charges / invoice' },
    { key:'delhivery_charges', color:'#f59e0b', icon:'fas fa-file-invoice',   label:'Delhivery Charges',       desc:'Delhivery shipping charges / invoice' },
    { key:'dtdc_charges',      color:'#f59e0b', icon:'fas fa-file-invoice',   label:'DTDC Charges',            desc:'DTDC shipping charges / invoice' },
    { key:'bluedart_cod',      color:'#10b981', icon:'fas fa-money-bill-wave',label:'Bluedart COD Payment',    desc:'COD remittance from Bluedart' },
    { key:'delhivery_cod',     color:'#10b981', icon:'fas fa-money-bill-wave',label:'Delhivery COD Payment',   desc:'COD remittance from Delhivery' },
    { key:'dtdc_cod',          color:'#10b981', icon:'fas fa-money-bill-wave',label:'DTDC COD Payment',        desc:'COD remittance from DTDC' },
    { key:'shiprocket_cod',    color:'#10b981', icon:'fas fa-money-bill-wave',label:'Shiprocket COD Payment',  desc:'COD remittance from Shiprocket' },
    { key:'gokwik_com',        color:'#dc2626', icon:'fas fa-credit-card',    label:'Gokwik .com (Prepaid)',   desc:'Gokwik prepaid settlement — filohevis.com (Platform Order Id = #3434...)' },
    { key:'gokwik_in',         color:'#dc2626', icon:'fas fa-credit-card',    label:'Gokwik .in (Prepaid)',    desc:'Gokwik prepaid settlement — filohevis.in (Merchant Order Id = Shopify #)' },
    { key:'ndr_raw2',          color:'#0891b2', icon:'fas fa-truck-loading',  label:'Clickpost NDR (Raw2)',    desc:'NDR feed — for NDR section. Headers: Courier Partner, Ndr Timestamp, Awb, Ndr Reason, Ndr Remark, Current Status, Order Id, OFD Count, Order Type. (Delivered status is auto-detected from the live Clickpost webhook — no separate status upload needed.)' },
  ];

  const grid = document.getElementById('upload-slots-grid');
  if (grid && !grid.dataset.rendered) {
    grid.innerHTML = UPLOAD_SLOTS.map(function(s) {
      return '<div class="upload-slot-card" id="slot-' + s.key + '">' +
        '<div class="upload-slot-header" style="background:' + s.color + '"><i class="' + s.icon + '"></i>&nbsp;' + s.label + '</div>' +
        '<div class="upload-slot-body">' +
          '<div class="upload-slot-desc">' + s.desc + '</div>' +
          '<div class="upload-slot-status" id="status-' + s.key + '">No file uploaded</div>' +
          '<div style="display:flex;gap:8px;flex-wrap:wrap">' +
            '<label class="upload-slot-btn"><i class="fas fa-upload"></i>&nbsp;Upload ' +
              '<input type="file" accept=".xlsx,.csv,.xls" onchange="handleSlotUpload(this,\'' + s.key + '\')" style="display:none">' +
            '</label>' +
            '<button type="button" onclick="downloadSlotTemplate(\'' + s.key + '\')" style="display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border:1px dashed ' + s.color + ';color:' + s.color + ';background:#fff;border-radius:8px;font-size:12px;font-weight:600;cursor:pointer" title="Download a sample Excel template with the expected columns"><i class="fas fa-file-excel"></i>&nbsp;Template</button>' +
          '</div>' +
        '</div>' +
      '</div>';
    }).join('');
    grid.dataset.rendered = '1';
  }

  loadUploadSummary();
}

// ── UPLOAD TEMPLATES (Excel) ─────────────────────────────
// Column headers match exactly what UPLOAD_SLOT_PARSERS reads for each slot
const SLOT_TEMPLATES = {
  ndr_raw2: {
    headers: ['Courier Partner','Ndr Timestamp','Awb','Ndr Reason','Ndr Remark','Current Status','Order Id','OFD Count','Order Type'],
    example: ['Delhivery','2026-06-18 10:00','39701911206251','Customer unavailable','Call later','FailedDelivery','#3434361318','2','COD']
  },
  shiprocket_orders: {
    headers: ['Order Id','AWB','Amount','Payment Method','UTR'],
    example: ['3434336821','78901234567','999','COD','UTR123456789']
  },
  bluedart_charges: {
    headers: ['Order Id','AWB','Amount','UTR'],
    example: ['3434336821','78901234567','85.50','UTR123456789']
  },
  delhivery_charges: {
    headers: ['Order Id','AWB','Amount','UTR'],
    example: ['3434336821','78901234567','85.50','UTR123456789']
  },
  dtdc_charges: {
    headers: ['Order Id','AWB','Amount','UTR'],
    example: ['3434336821','78901234567','85.50','UTR123456789']
  },
  bluedart_cod: {
    headers: ['Order Id','AWB','Amount','UTR'],
    example: ['3434336821','78901234567','999','UTR123456789']
  },
  delhivery_cod: {
    headers: ['Order Id','AWB','Amount','UTR'],
    example: ['3434336821','78901234567','999','UTR123456789']
  },
  dtdc_cod: {
    headers: ['ORDER ID','Consignment Number','AMT','UTR'],
    example: ['#3434336821_SP12345','78901234567','999','UTR123456789']
  },
  shiprocket_cod: {
    headers: ['Order Id','AWB','total_adjusted_amt','UTR'],
    example: ['3434336821','78901234567','999','UTR123456789']
  },
  gokwik_com: {
    headers: ['Platform Order Id','Merchant Order Id','Credit','Payment Method','Settlement UTR'],
    example: ['#3434336821','FH1001','999','upi','UTR123456789']
  },
  gokwik_in: {
    headers: ['Platform Order Id','Merchant Order Id','Credit','Payment Method','Settlement UTR'],
    example: ['GK99887','#3434336821','999','upi','UTR123456789']
  }
};

function downloadSlotTemplate(slotKey) {
  const tpl = SLOT_TEMPLATES[slotKey];
  if (!tpl) { showToast('No template defined for ' + slotKey, 'error'); return; }
  try {
    const ws = XLSX.utils.aoa_to_sheet([tpl.headers, tpl.example]);
    // Set reasonable column widths
    ws['!cols'] = tpl.headers.map(function(h){ return {wch: Math.max(h.length + 4, 16)}; });
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, 'Template');
    XLSX.writeFile(wb, slotKey + '_template.xlsx');
    showToast('Template downloaded: ' + slotKey + '_template.xlsx', 'success');
  } catch(e) {
    showToast('Template download failed: ' + e.message, 'error');
    console.error('downloadSlotTemplate error', e);
  }
}


// ── AI Analysis (Lifecycle) ──────────────────────────────
function lcToggleAI(){
  const panel=document.getElementById('lc-ai-panel');
  const chev=document.getElementById('lc-ai-chevron');
  if(!panel)return;
  const open=panel.style.display==='none';
  panel.style.display=open?'block':'none';
  if(chev)chev.style.transform=open?'rotate(180deg)':'rotate(0deg)';
  if(open){const p=document.getElementById('lc-ai-prompt');if(p)setTimeout(()=>p.focus(),50);}
}

async function runLcAI(){
  const prompt=(document.getElementById('lc-ai-prompt')?.value||'').trim();
  if(!prompt){showToast('Please enter a prompt','error');return;}
  const data=window._lcAllRows||[];
  if(!data.length){showToast('Run the report first','error');return;}
  const NL=String.fromCharCode(10);
  const totalOrders=data.length;
  const dispatched=data.filter(r=>r.dispatchStatus==='Dispatched').length;
  const rto=data.filter(r=>(r.cpStatus||'').toLowerCase().includes('rto')).length;
  const delivered=data.filter(r=>(r.cpStatus||'').toLowerCase().includes('deliver')&&!(r.cpStatus||'').toLowerCase().includes('rto')).length;
  const agentMap={};
  data.forEach(r=>{const a=r.agent||'Unassigned';if(!agentMap[a])agentMap[a]={t:0,d:0,p:0};agentMap[a].t++;if(r.dispatchStatus==='Dispatched')agentMap[a].d++;else agentMap[a].p++;});
  const agentLines=Object.entries(agentMap).map(([a,v])=>a+': '+v.t+' orders, '+v.d+' dispatched, '+v.p+' pending').join(NL);
  const s1=data.filter(r=>r.stage1!==null&&r.stage1!==undefined).map(r=>r.stage1);
  const s2=data.filter(r=>r.stage2!==null&&r.stage2!==undefined).map(r=>r.stage2);
  const s3=data.filter(r=>r.stage3!==null&&r.stage3!==undefined).map(r=>r.stage3);
  const avg=arr=>arr.length?(arr.reduce((a,b)=>a+b,0)/arr.length).toFixed(1):'N/A';
  const sample=data.slice(0,20).map(r=>'#'+r.orderId+'|'+(r.agent||'Unassigned')+'|'+r.status+'|'+(r.cpStatus||'-')+'|'+(r.finalStatus||'-')+'|Pay:'+(r.paymentReceived||'-')+'|GW:'+(r.paymentGateway||'-')).join(NL);
  const ctx='You are analysing an Order Lifecycle Report for a D2C apparel brand.'+NL+NL+
    'SUMMARY ('+totalOrders+' orders): Dispatched:'+dispatched+' RTO:'+rto+' Delivered:'+delivered+NL+
    'Avg R->A:'+avg(s1)+'h A->C:'+avg(s2)+'h C->D:'+avg(s3)+'h'+NL+NL+
    'AGENTS:'+NL+agentLines+NL+NL+
    'SAMPLE (first 20):'+NL+sample+NL+NL+
    'QUESTION: '+prompt+NL+NL+'Answer directly, concisely, with bullet points.';
  const btn=document.getElementById('lc-ai-btn');
  const loading=document.getElementById('lc-ai-loading');
  const output=document.getElementById('lc-ai-output');
  const error=document.getElementById('lc-ai-error');
  const empty=document.getElementById('lc-ai-empty');
  if(btn){btn.disabled=true;btn.innerHTML='<i class="fas fa-spinner fa-spin"></i>';}
  if(loading)loading.style.display='block';
  if(output)output.style.display='none';
  if(error)error.style.display='none';
  if(empty)empty.style.display='none';
  try{
    const resp=await fetch('https://api.anthropic.com/v1/messages',{method:'POST',headers:{'Content-Type':'application/json','x-api-key':'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','anthropic-version':'2023-06-01','anthropic-dangerous-direct-browser-access':'true'},body:JSON.stringify({model:'claude-sonnet-4-6',max_tokens:1500,messages:[{role:'user',content:ctx}]})});
    const result=await resp.json();
    if(loading)loading.style.display='none';
    if(result.error)throw new Error(result.error.message||'API error');
    const text=(result.content&&result.content[0])?result.content[0].text:'';
    if(output){output.style.display='block';output.innerHTML=text.replace(/\*\*(.+?)\*\*/g,'<strong>$1</strong>').replace(/^[-•]\s(.+)$/gm,'<div style="display:flex;gap:8px;margin:3px 0"><span style="color:#7c3aed">›</span><span>$1</span></div>').replace(/\n/g,'<br>');}
  }catch(e){if(loading)loading.style.display='none';if(error){error.textContent='❌ '+e.message;error.style.display='block';}}
  finally{if(btn){btn.disabled=false;btn.innerHTML='<i class="fas fa-paper-plane" style="margin-right:5px"></i>Ask AI';}}
}


// ════════════════════════════════════════════════════════════
//  NDR AUTOMATION — frontend (additive)
// ════════════════════════════════════════════════════════════
window.NDR_DATA = { ndr: [], rto: [] };
window.NDR_ACTIVE_TABLE = 'ndr';

const NDR_COLUMNS = [
  {key:'ofd_count',      label:'OFD Count'},
  {key:'billing_state',  label:'Billing State'},
  {key:'shipping_addr',  label:'Shipping Address'},
  {key:'last_updated',   label:'Last Updated'},
  {key:'ndr_remark',     label:'NDR Remark'},
  {key:'billing_zip',    label:'Billing Zip'},
  {key:'sku',            label:'SKU'},
  {key:'customer_name',  label:'Customer Name'},
  {key:'tags',           label:'Tags'},
  {key:'total',          label:'Total (INR)'},
  {key:'courier_partner',label:'Courier Partner'},
  {key:'order_type',     label:'Order Type'},
  {key:'first_status',   label:'First Status'},
  {key:'first_date',     label:'First Date'},
  {key:'final_status',   label:'Final Status'},
  {key:'final_date',     label:'Final Date'},
  {key:'ndr_reason',     label:'NDR Reason'},
  {key:'ageing',         label:'Ageing (Days)'},
  {key:'order_id',       label:'Order ID'},
  {key:'awb',            label:'AWB'},
  {key:'billing_phone',  label:'Billing Phone'},
  {key:'alternate_phone',label:'Alternate Phone', edit:true},
  {key:'pasted_date',    label:'Pasted date(new)'},
  {key:'new_old',        label:'New/Old'},
  {key:'action',         label:'Action to be Taken', editAction:true},
  {key:'remark1',        label:'Remark1',  edit:true},
  {key:'remark2',        label:'Remark2',  edit:true}
];

async function ndrRunRefresh() {
  const btn = document.getElementById('ndr-refresh-btn');
  if (btn) { btn.disabled = true; btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Refreshing…'; }
  try {
    const r = await apiCall('ndr_run_refresh');
    if (r && r.status === 'success') {
      showToast(`✅ NDR refreshed — ${r.new} new, ${r.updated} updated, ${r.rto} RTO`, 'success');
      await ndrLoadData();
    } else {
      showToast('NDR refresh failed: ' + ((r&&r.msg)||'unknown'), 'error');
    }
  } catch(e) { showToast('NDR refresh error: ' + e.message, 'error'); }
  if (btn) { btn.disabled = false; btn.innerHTML = '<i class="fas fa-sync"></i> Run Full Refresh'; }
}

async function ndrLoadData() {
  try {
    const r = await apiCall('ndr_get_data');
    if (r && r.status === 'success') {
      window.NDR_DATA.ndr = r.ndr || [];
      window.NDR_DATA.rto = r.rto || [];
      document.getElementById('ndr-count').textContent = '(' + window.NDR_DATA.ndr.length + ')';
      document.getElementById('rto-count').textContent = '(' + window.NDR_DATA.rto.length + ')';
      ndrRenderDashboard();
      ndrRenderTable();
    }
  } catch(e) { console.warn('ndrLoadData', e); }
}

function ndrSwitchTable(which) {
  window.NDR_ACTIVE_TABLE = which;
  window.NDR_COL_FILTERS = {};
  const tNdr = document.getElementById('ndr-tab-ndr'), tRto = document.getElementById('ndr-tab-rto');
  if (which === 'ndr') {
    tNdr.style.color='#0891b2'; tNdr.style.fontWeight='700'; tNdr.style.borderBottom='2px solid #0891b2';
    tRto.style.color='#94a3b8'; tRto.style.fontWeight='600'; tRto.style.borderBottom='2px solid transparent';
  } else {
    tRto.style.color='#dc2626'; tRto.style.fontWeight='700'; tRto.style.borderBottom='2px solid #dc2626';
    tNdr.style.color='#94a3b8'; tNdr.style.fontWeight='600'; tNdr.style.borderBottom='2px solid transparent';
  }
  ndrRenderTable();
}

function ndrRenderDashboard() {
  const all = window.NDR_DATA.ndr;
  const rto = window.NDR_DATA.rto;
  const total = all.length + rto.length;
  const delivered = all.filter(r => String(r.final_status).toLowerCase()==='delivered').length;
  const failed = all.filter(r => String(r.final_status).toLowerCase()==='faileddelivery').length;
  const newCount = all.filter(r => String(r.new_old).toUpperCase()==='NEW').length;
  const oldCount = all.filter(r => String(r.new_old).toUpperCase()==='OLD').length;
  const cod = all.filter(r => String(r.order_type).toUpperCase()==='COD').length;
  const ageingVals = all.map(r => Number(r.ageing)).filter(v=>!isNaN(v)&&v>=0);
  const avgAge = ageingVals.length ? (ageingVals.reduce((a,b)=>a+b,0)/ageingVals.length).toFixed(1) : '0';
  const delRate = total ? ((delivered/total)*100).toFixed(1)+'%' : '0%';
  const rtoRate = total ? ((rto.length/total)*100).toFixed(1)+'%' : '0%';
  const cards = [
    ['Total NDR', all.length, '#6366f1'],
    ['Total RTO', rto.length, '#ef4444'],
    ['Delivered', delivered, '#10b981'],
    ['Failed Delivery', failed, '#f59e0b'],
    ['New Today', newCount, '#10b981'],
    ['Old', oldCount, '#eab308'],
    ['COD Orders', cod, '#3b82f6'],
    ['Avg Ageing', avgAge+'d', '#f97316'],
    ['Delivery Rate', delRate, '#10b981'],
    ['RTO Rate', rtoRate, '#ef4444'],
    ['Total Orders', total, '#8b5cf6'],
    ['NDR Reasons', new Set(all.map(r=>r.ndr_reason).filter(Boolean)).size, '#0891b2']
  ];
  const grid = document.getElementById('ndr-dash');
  if (!grid) return;
  grid.innerHTML = cards.map(c =>
    `<div class="card p-3" style="border-left:4px solid ${c[2]};min-width:0;overflow:hidden">
      <div class="text-xs font-bold text-slate-400 uppercase tracking-wide mb-1" style="font-size:10px">${c[0]}</div>
      <div class="text-2xl font-black" style="color:${c[2]}">${c[1]}</div>
    </div>`).join('');
}

function ndrRenderTable() {
  const rows = window.NDR_ACTIVE_TABLE === 'ndr' ? window.NDR_DATA.ndr : window.NDR_DATA.rto;
  const thead = document.getElementById('ndr-thead');
  const tbody = document.getElementById('ndr-tbody');
  if (!thead || !tbody) return;
  thead.innerHTML = '<tr style="background:#f8fafc">' + NDR_COLUMNS.map((c, idx) => {
    const active = window.NDR_COL_FILTERS && window.NDR_COL_FILTERS[idx] && window.NDR_COL_FILTERS[idx].size > 0;
    return `<th style="padding:8px 10px;text-align:left;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;color:#64748b;border-bottom:1px solid #e2e8f0;white-space:nowrap">${c.label}<span class="ndr-col-funnel" style="cursor:pointer;margin-left:6px;font-size:10px" onclick="ndrOpenColumnFilter(${idx},this)"><i class="fas fa-filter" style="color:${active?'#0891b2':'#cbd5e1'}"></i></span></th>`;
  }).join('') + '</tr>';
  ndrFilter();
}

function ndrOpenColumnFilter(colIndex, anchorEl) {
  document.querySelectorAll('.ndr-col-popover').forEach(p => p.remove());
  const rows = window.NDR_ACTIVE_TABLE === 'ndr' ? window.NDR_DATA.ndr : window.NDR_DATA.rto;
  const colKey = NDR_COLUMNS[colIndex].key;
  const counts = {};
  rows.forEach(r => { let v = r[colKey]!=null ? String(r[colKey]).trim() : ''; if(v==='')v='—'; counts[v]=(counts[v]||0)+1; });
  const values = Object.keys(counts).sort((a,b)=>a.localeCompare(b));
  window.NDR_COL_FILTERS = window.NDR_COL_FILTERS || {};
  const sel = window.NDR_COL_FILTERS[colIndex] || new Set();
  const pop = document.createElement('div');
  pop.className = 'ndr-col-popover';
  pop.style.cssText = 'position:fixed;z-index:9999;background:#fff;border:1px solid #e2e8f0;border-radius:10px;box-shadow:0 8px 28px rgba(0,0,0,0.18);width:240px;max-height:340px;display:flex;flex-direction:column;font-size:12px';
  const rect = anchorEl.getBoundingClientRect();
  let left = rect.left; if (left + 240 > window.innerWidth) left = window.innerWidth - 250;
  pop.style.left = left + 'px'; pop.style.top = (rect.bottom + 4) + 'px';
  const optsHtml = values.map(v => {
    const safe = v.replace(/"/g,'&quot;');
    return `<label style="display:flex;align-items:center;gap:8px;padding:5px 10px;cursor:pointer;border-radius:6px" onmouseover="this.style.background='#f1f5f9'" onmouseout="this.style.background=''"><input type="checkbox" class="ndr-colf-cb" value="${safe}" ${sel.has(v)?'checked':''} style="width:14px;height:14px"><span style="flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="${safe}">${v}</span><span style="color:#94a3b8;font-size:10px">${counts[v]}</span></label>`;
  }).join('');
  pop.innerHTML =
    '<div style="padding:8px 10px;border-bottom:1px solid #f1f5f9"><input type="text" placeholder="Search…" class="ndr-colf-search" style="width:100%;border:1px solid #e2e8f0;border-radius:6px;padding:4px 8px;font-size:12px;outline:none"></div>' +
    '<div class="ndr-colf-list" style="overflow-y:auto;padding:4px">' + optsHtml + '</div>' +
    '<div style="padding:8px 10px;border-top:1px solid #f1f5f9;display:flex;gap:8px">' +
      '<button class="ndr-colf-clear" style="flex:1;background:#f1f5f9;color:#475569;border:none;border-radius:6px;padding:6px;font-size:12px;font-weight:600;cursor:pointer">Clear</button>' +
      '<button class="ndr-colf-apply" style="flex:1;background:#0891b2;color:#fff;border:none;border-radius:6px;padding:6px;font-size:12px;font-weight:600;cursor:pointer">Apply</button>' +
    '</div>';
  document.body.appendChild(pop);
  pop.querySelector('.ndr-colf-search').addEventListener('input', function(){
    const q=this.value.toLowerCase();
    pop.querySelectorAll('.ndr-colf-list label').forEach(l=>{ l.style.display = l.textContent.toLowerCase().includes(q)?'':'none'; });
  });
  pop.querySelector('.ndr-colf-apply').onclick = function(){
    const chosen = new Set();
    pop.querySelectorAll('.ndr-colf-cb:checked').forEach(cb => chosen.add(cb.value));
    if (chosen.size === 0) delete window.NDR_COL_FILTERS[colIndex]; else window.NDR_COL_FILTERS[colIndex] = chosen;
    pop.remove(); ndrRenderTable();
  };
  pop.querySelector('.ndr-colf-clear').onclick = function(){
    delete window.NDR_COL_FILTERS[colIndex]; pop.remove(); ndrRenderTable();
  };
  setTimeout(()=>{ const closer=function(ev){ if(!pop.contains(ev.target)){pop.remove();document.removeEventListener('mousedown',closer);} }; document.addEventListener('mousedown',closer); },0);
}

function ndrFilter() {
  const rows = window.NDR_ACTIVE_TABLE === 'ndr' ? window.NDR_DATA.ndr : window.NDR_DATA.rto;
  const q = (document.getElementById('ndr-search')?.value || '').toLowerCase().trim();
  const tbody = document.getElementById('ndr-tbody');
  if (!tbody) return;
  let filtered = !q ? rows : rows.filter(r =>
    String(r.awb||'').toLowerCase().includes(q) ||
    String(r.order_id||'').toLowerCase().includes(q) ||
    String(r.billing_phone||'').toLowerCase().includes(q) ||
    String(r.customer_name||'').toLowerCase().includes(q));
  // Apply per-column header filters
  if (window.NDR_COL_FILTERS) {
    for (const ci in window.NDR_COL_FILTERS) {
      const sel = window.NDR_COL_FILTERS[ci];
      if (!sel || sel.size === 0) continue;
      const key = NDR_COLUMNS[ci].key;
      filtered = filtered.filter(r => {
        let v = r[key]!=null ? String(r[key]).trim() : ''; if (v==='') v='—';
        return sel.has(v);
      });
    }
  }
  if (!filtered.length) {
    tbody.innerHTML = `<tr><td colspan="${NDR_COLUMNS.length}" style="text-align:center;padding:36px;color:#94a3b8;font-size:13px">No matching NDR records. Upload Clickpost NDR (Raw2) in Upload Files, then Run Full Refresh.</td></tr>`;
    return;
  }
  const actionColors = {Reattempt:'#10b981', RTO:'#ef4444', Rescheduled:'#eab308', Other:'#f59e0b'};
  tbody.innerHTML = filtered.map(r => {
    const awb = String(r.awb||'').replace(/"/g,'&quot;');
    return '<tr style="border-bottom:1px solid #f8fafc">' + NDR_COLUMNS.map(c => {
      const v = r[c.key] != null ? String(r[c.key]) : '';
      if (c.editAction) {
        const cur = v || '';
        const opts = ['','Reattempt','RTO','Rescheduled','Other'].map(o =>
          `<option value="${o}" ${o===cur?'selected':''}>${o||'—'}</option>`).join('');
        const col = actionColors[cur] || '#94a3b8';
        return `<td style="padding:6px 8px"><select onchange="ndrSaveRow('${awb}')" data-awb="${awb}" data-field="action" style="font-size:11px;border:1px solid ${col}55;border-radius:6px;padding:3px 6px;color:${col};font-weight:700;background:${col}10">${opts}</select></td>`;
      }
      if (c.edit) {
        return `<td style="padding:6px 8px"><input type="text" value="${v.replace(/"/g,'&quot;')}" onchange="ndrSaveRow('${awb}')" data-awb="${awb}" data-field="${c.key}" style="font-size:11px;border:1px solid #e2e8f0;border-radius:6px;padding:3px 6px;width:110px"></td>`;
      }
      if (c.key==='new_old') {
        const isNew = v.toUpperCase()==='NEW';
        return `<td style="padding:8px 10px"><span style="background:${isNew?'#dcfce7':'#fef9c3'};color:${isNew?'#15803d':'#a16207'};padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700">${v||'—'}</span></td>`;
      }
      if (c.key==='final_status') {
        const lc=v.toLowerCase();
        const bg = lc==='delivered'?'#dcfce7':lc.includes('rto')?'#fee2e2':lc==='faileddelivery'?'#fef9c3':'#f1f5f9';
        const fg = lc==='delivered'?'#15803d':lc.includes('rto')?'#b91c1c':lc==='faileddelivery'?'#a16207':'#475569';
        return `<td style="padding:8px 10px"><span style="background:${bg};color:${fg};padding:2px 8px;border-radius:99px;font-size:10px;font-weight:700;white-space:nowrap">${v||'—'}</span></td>`;
      }
      const truncate = (c.key==='sku'||c.key==='ndr_remark'||c.key==='ndr_reason'||c.key==='shipping_addr'||c.key==='tags');
      const style = truncate ? 'max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap' : 'white-space:nowrap';
      return `<td style="padding:8px 10px;font-size:11px;color:#374151;${style}" title="${v.replace(/"/g,'&quot;')}">${v||'<span style="color:#cbd5e1">—</span>'}</td>`;
    }).join('') + '</tr>';
  }).join('');
}

async function ndrSaveRow(awb) {
  // Gather the row's editable fields from the DOM
  const get = (field) => {
    const el = document.querySelector(`[data-awb="${awb}"][data-field="${field}"]`);
    return el ? el.value : '';
  };
  try {
    const r = await apiCall('ndr_update_row', {
      awb: awb,
      ndr_action: get('action'),
      alternate_phone: get('alternate_phone'),
      remark1: get('remark1'),
      remark2: get('remark2')
    });
    if (r && r.status === 'success') {
      // update in-memory copy
      const arr = window.NDR_ACTIVE_TABLE==='ndr' ? window.NDR_DATA.ndr : window.NDR_DATA.rto;
      const rec = arr.find(x => String(x.awb)===String(awb));
      if (rec) { rec.action=get('action'); rec.alternate_phone=get('alternate_phone'); rec.remark1=get('remark1'); rec.remark2=get('remark2'); }
      showToast('Saved', 'success');
    } else showToast('Save failed: ' + ((r && r.msg) || 'unknown error'), 'error');
  } catch(e) { showToast('Save error: '+e.message, 'error'); }
}

function ndrExportFiltered() {
  // Re-apply the same filters as the on-screen table
  const rowsAll = window.NDR_ACTIVE_TABLE === 'ndr' ? window.NDR_DATA.ndr : window.NDR_DATA.rto;
  const q = (document.getElementById('ndr-search')?.value || '').toLowerCase().trim();
  let filtered = !q ? rowsAll : rowsAll.filter(r =>
    String(r.awb||'').toLowerCase().includes(q) ||
    String(r.order_id||'').toLowerCase().includes(q) ||
    String(r.billing_phone||'').toLowerCase().includes(q) ||
    String(r.customer_name||'').toLowerCase().includes(q));
  if (window.NDR_COL_FILTERS) {
    for (const ci in window.NDR_COL_FILTERS) {
      const sel = window.NDR_COL_FILTERS[ci];
      if (!sel || sel.size === 0) continue;
      const key = NDR_COLUMNS[ci].key;
      filtered = filtered.filter(r => { let v = r[key]!=null?String(r[key]).trim():''; if(v==='')v='—'; return sel.has(v); });
    }
  }
  if (!filtered.length) { showToast('No rows to export', 'error'); return; }
  const header = NDR_COLUMNS.map(c => c.label);
  const data = filtered.map(r => NDR_COLUMNS.map(c => r[c.key] != null ? String(r[c.key]) : ''));
  try {
    const ws = XLSX.utils.aoa_to_sheet([header, ...data]);
    const wb = XLSX.utils.book_new();
    const sheetName = window.NDR_ACTIVE_TABLE === 'ndr' ? 'NDR' : 'RTO';
    XLSX.utils.book_append_sheet(wb, ws, sheetName);
    XLSX.writeFile(wb, sheetName + '_Export_' + new Date().toISOString().slice(0,10) + '.xlsx');
    showToast(`Exported ${filtered.length} ${sheetName} rows`, 'success');
  } catch(e) { showToast('Export failed: ' + e.message, 'error'); }
}

function ndrExportReattempt(courier) {
  const all = window.NDR_DATA.ndr;
  // Today in dd/MM/yyyy to match pasted_date
  const d = new Date();
  const todayStr = String(d.getDate()).padStart(2,'0')+'/'+String(d.getMonth()+1).padStart(2,'0')+'/'+d.getFullYear();
  const rows = all.filter(r =>
    String(r.action||'').trim().toLowerCase()==='reattempt' &&
    String(r.courier_partner||'').trim().toLowerCase()===courier.toLowerCase() &&
    String(r.pasted_date||'').trim()===todayStr);
  if (!rows.length) {
    showToast(`No Reattempt rows for ${courier} dated ${todayStr}`, 'info');
    return;
  }
  const header = ['Date','Currier Partner','Awb','Ndr reason','Contact no','Filohevis Remark'];
  const data = rows.map(r => [r.pasted_date, r.courier_partner, r.awb, r.ndr_reason, r.billing_phone, r.remark1]);
  try {
    const ws = XLSX.utils.aoa_to_sheet([header, ...data]);
    ws['!cols'] = [{wch:12},{wch:16},{wch:18},{wch:30},{wch:16},{wch:24}];
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, 'Reattempt');
    XLSX.writeFile(wb, courier+'_Reattempt_'+todayStr.replace(/\//g,'-')+'.xlsx');
    showToast(`✅ ${rows.length} ${courier} Reattempt rows exported`, 'success');
  } catch(e) { showToast('Export failed: '+e.message, 'error'); }
}

</script>

<!-- ── USER MODAL ── -->
<div id="userModal" class="modal-backdrop hidden" onclick="if(event.target===this)closeUserModal()">
  <div class="bg-white rounded-2xl shadow-2xl w-full max-w-md overflow-hidden">
    <div style="padding:20px 24px;border-bottom:1px solid #f1f5f9;display:flex;justify-content:space-between;align-items:center;background:linear-gradient(135deg,#f0fdf4,#fff)">
      <div>
        <h3 style="font-weight:800;color:#1e293b;font-size:16px" id="user-modal-title">Add New User</h3>
        <p style="font-size:12px;color:#64748b;margin-top:2px" id="user-modal-sub">Create a new agent account</p>
      </div>
      <button onclick="closeUserModal()" style="color:#94a3b8;background:none;border:none;cursor:pointer;font-size:18px;padding:4px"><i class="fas fa-times"></i></button>
    </div>
    <div style="padding:24px;display:flex;flex-direction:column;gap:16px">
      <input type="hidden" id="um-id">

      <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
        <div>
          <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:6px">Full Name *</label>
          <input type="text" id="um-name" placeholder="e.g. Harika" class="form-input w-full" style="width:100%">
        </div>
        <div>
          <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:6px">Username *</label>
          <input type="text" id="um-username" placeholder="e.g. harika" class="form-input w-full" style="width:100%" autocomplete="off">
        </div>
      </div>

      <div>
        <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:6px">Role *</label>
        <select id="um-role" class="form-select w-full" style="width:100%;height:38px">
          <option value="agent">Agent (Caller)</option>
          <option value="team_lead">Team Lead</option>
          <option value="dispatch">Dispatch Team</option>
          <option value="writer">Writer (Training Editor)</option>
          <option value="accounts">Accounts (Returns Ledger only)</option>
          <option value="ndr">NDR (NDR Automation only)</option>
          <option value="manager">Manager (All except User Management)</option>
          <option value="admin">Admin</option>
        </select>
        <p id="um-role-hint" style="font-size:11px;color:#94a3b8;margin-top:4px">Agent: Can view and update assigned orders only</p>
      </div>

      <div>
        <label style="display:flex;align-items:center;gap:8px;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:6px">
          <input type="checkbox" id="um-custom-toggle" onchange="umToggleCustomPerms()" style="width:14px;height:14px"> Custom Menu Access (overrides role)
        </label>
        <div id="um-perms-grid" style="display:none;border:1px solid #e2e8f0;border-radius:8px;padding:10px;background:#f8fafc">
          <p style="font-size:11px;color:#94a3b8;margin-bottom:8px">Tick exactly which menus this user can see. This replaces the role's default menu.</p>
          <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:6px" id="um-perms-checks"></div>
        </div>
      </div>

      <div>
        <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:6px">
          Password <span id="um-pw-hint" style="font-weight:400;color:#94a3b8">(min 6 characters)</span>
        </label>
        <div style="position:relative">
          <input type="password" id="um-password" placeholder="Enter password" class="form-input w-full" style="width:100%;padding-right:40px" autocomplete="new-password" name="um_new_password" data-form-type="other">
          <button onclick="toggleUMPassword()" style="position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;color:#94a3b8">
            <i class="fas fa-eye" id="um-pw-eye"></i>
          </button>
        </div>
      </div>

      <div id="um-active-row" style="display:flex;align-items:center;gap:10px;padding:12px;background:#f8fafc;border-radius:10px;border:1px solid #e2e8f0">
        <input type="checkbox" id="um-active" checked style="width:16px;height:16px;accent-color:#16a34a;cursor:pointer">
        <div>
          <label for="um-active" style="font-size:13px;font-weight:600;color:#374151;cursor:pointer">Active Account</label>
          <p style="font-size:11px;color:#94a3b8;margin-top:1px">Inactive users cannot log in</p>
        </div>
      </div>

      <div id="um-error" style="display:none;padding:10px 14px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px;font-size:12px;color:#b91c1c;display:flex;align-items:center;gap:6px">
        <i class="fas fa-exclamation-circle"></i><span id="um-error-text"></span>
      </div>
    </div>
    <div style="padding:16px 24px;background:#f8fafc;border-top:1px solid #f1f5f9;display:flex;gap:10px">
      <button onclick="closeUserModal()" class="btn btn-ghost flex-1 justify-center">Cancel</button>
      <button onclick="saveUser()" id="um-save-btn" class="btn btn-primary flex-1 justify-center" style="background:#16a34a">
        <i class="fas fa-save"></i> <span id="um-save-text">Create User</span>
      </button>
    </div>
  </div>
</div>

<!-- ── RESET PASSWORD MODAL ── -->
<div id="resetPwModal" class="modal-backdrop hidden" onclick="if(event.target===this)closeResetModal()">
  <div class="bg-white rounded-2xl shadow-2xl w-full max-w-sm overflow-hidden">
    <div style="padding:20px 24px;border-bottom:1px solid #f1f5f9;display:flex;justify-content:space-between;align-items:center">
      <h3 style="font-weight:800;color:#1e293b;font-size:15px"><i class="fas fa-key" style="color:#f59e0b;margin-right:8px"></i>Reset Password</h3>
      <button onclick="closeResetModal()" style="color:#94a3b8;background:none;border:none;cursor:pointer;font-size:18px"><i class="fas fa-times"></i></button>
    </div>
    <div style="padding:24px;display:flex;flex-direction:column;gap:14px">
      <input type="hidden" id="rp-id">
      <p style="font-size:13px;color:#64748b">Setting new password for: <b id="rp-name" style="color:#1e293b"></b></p>
      <div style="position:relative">
        <input type="password" id="rp-password" placeholder="New password (min 6 chars)" class="form-input w-full" style="width:100%;padding-right:40px" autocomplete="new-password" name="rp_new_password" data-form-type="other">
        <button onclick="document.getElementById('rp-password').type==='password'?(document.getElementById('rp-password').type='text'):(document.getElementById('rp-password').type='password')" style="position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;color:#94a3b8"><i class="fas fa-eye"></i></button>
      </div>
    </div>
    <div style="padding:16px 24px;background:#f8fafc;border-top:1px solid #f1f5f9;display:flex;gap:10px">
      <button onclick="closeResetModal()" class="btn btn-ghost flex-1 justify-center">Cancel</button>
      <button onclick="confirmResetPassword()" class="btn flex-1 justify-center" style="background:#f59e0b;color:#fff"><i class="fas fa-key"></i> Reset</button>
    </div>
  </div>
</div>

<!-- ── ORDER LIFECYCLE TRACKER MODAL ── -->
<div id="lifecycleModal" class="modal-backdrop hidden" onclick="if(event.target===this)closeLifecycleModal()" style="align-items:flex-start;padding:20px;overflow-y:auto">
  <div class="bg-white rounded-2xl shadow-2xl w-full overflow-hidden" style="max-width:calc(100vw - 300px);margin:0 auto;min-height:90vh">

    <!-- Header -->
    <div style="background:linear-gradient(135deg,#7c3aed,#6366f1);padding:20px 28px;display:flex;justify-content:space-between;align-items:center">
      <div>
        <h3 style="font-weight:900;color:#fff;font-size:18px;display:flex;align-items:center;gap:10px">
          <i class="fas fa-route"></i> Order Lifecycle Tracker
        </h3>
        <p style="font-size:12px;color:rgba(255,255,255,0.7);margin-top:3px">Track how long each stage takes — from order received to dispatch</p>
      </div>
      <button onclick="closeLifecycleModal()" style="color:rgba(255,255,255,0.7);background:rgba(255,255,255,0.1);border:none;width:32px;height:32px;border-radius:8px;cursor:pointer;font-size:16px;display:flex;align-items:center;justify-content:center">
        <i class="fas fa-times"></i>
      </button>
    </div>

    <!-- Filters -->
    <div style="padding:16px 28px;border-bottom:1px solid #f1f5f9;background:#fafafa;display:flex;flex-wrap:wrap;gap:10px;align-items:center">
      <div style="display:flex;align-items:center;gap:8px">
        <span style="font-size:12px;font-weight:600;color:#64748b">Date Range:</span>
        <input type="date" id="lc-start" class="form-input text-xs" style="height:32px">
        <span style="color:#94a3b8;font-size:12px">→</span>
        <input type="date" id="lc-end" class="form-input text-xs" style="height:32px">
      </div>
      <select id="lc-agent" class="form-select text-xs" style="height:32px;min-width:140px">
        <option value="All">All Agents</option>
      </select>
      <select id="lc-cp-status" class="form-select text-xs" style="height:32px;min-width:160px" onchange="lcFilterTable()">
        <option value="">All Clickpost Status</option>
        <option value="Delivered">✅ Delivered</option>
        <option value="OutForDelivery">🚚 OutForDelivery</option>
        <option value="InTransit">📦 InTransit</option>
        <option value="RTO-InTransit">↩ RTO-InTransit</option>
        <option value="RTO">↩ RTO</option>
        <option value="FailedDelivery">❌ FailedDelivery</option>
        <option value="DestinationHub">🏭 DestinationHub</option>
        <option value="Awb Registered">📋 Awb Registered</option>
        <option value="OrderPlaced">🛒 OrderPlaced</option>
      </select>
      <select id="lc-awb-filter" class="form-select text-xs" style="height:32px;min-width:150px" onchange="lcFilterTable()">
        <option value="">All AWB</option>
        <option value="generated">📦 AWB Generated</option>
        <option value="notgenerated">⏳ AWB Not Generated</option>
        <option value="gen_not_disp">🚚 AWB Generated — Not Dispatched</option>
      </select>
      <button onclick="window._lcRenderAll=false;window._lcAllRows=null;runLifecycleReport()" class="btn btn-sm" style="background:#6366f1;color:#fff;height:32px">
        <i class="fas fa-play"></i> Run Report
      </button>
      <button onclick="exportLifecycleCSV()" class="btn btn-sm btn-ghost" style="height:32px">
        <i class="fas fa-download"></i> Export CSV
      </button>
      <div style="position:relative;display:flex;align-items:center">
        <i class="fas fa-search" style="position:absolute;left:9px;color:#94a3b8;font-size:11px;pointer-events:none"></i>
        <input type="text" id="lc-search" oninput="lcFilterTable()" placeholder="Search order ID..." autocomplete="off"
          style="height:32px;padding:0 32px 0 28px;border:1.5px solid #e2e8f0;border-radius:10px;font-size:12px;width:180px;outline:none;font-family:inherit"
          onfocus="this.style.borderColor='#6366f1'" onblur="this.style.borderColor='#e2e8f0'">
        <span id="lc-search-count" style="position:absolute;right:8px;font-size:10px;color:#94a3b8;pointer-events:none"></span>
      </div>
      <div style="margin-left:auto;display:flex;align-items:center;gap:8px">
        <button onclick="loadPaymentDataFromDB()" class="btn btn-sm btn-ghost" style="height:32px;border-color:#6366f1;color:#6366f1">
          <i class="fas fa-database"></i> Load from DB
        </button>
        <div style="position:relative">
          <button onclick="document.getElementById('lc-pay-upload').click()" class="btn btn-sm btn-ghost" style="height:32px;border-color:#10b981;color:#10b981">
            <i class="fas fa-file-upload"></i> Upload Files
          </button>
          <input type="file" id="lc-pay-upload" accept=".xlsx,.csv" multiple style="display:none" onchange="lcHandlePaymentUpload(this)">
        </div>
        <span id="lc-pay-status" style="font-size:11px;color:#64748b"></span>
        <span id="lc-count-badge" style="font-size:11px;color:#94a3b8"></span>
      </div>
    </div>

    <!-- Delivery Performance (computed from Clickpost status) -->
    <div id="lc-delperf" style="padding:18px 28px;border-bottom:1px solid #f1f5f9;background:#fafafa"></div>

    <!-- Claude AI Prompt Bar (collapsible) -->
    <div style="padding:14px 28px 0">
      <div style="border:1px solid #e9d5ff;border-radius:12px;overflow:hidden;background:linear-gradient(135deg,#faf5ff,#fff)">
        <div onclick="lcToggleAI()" style="padding:12px 16px;display:flex;align-items:center;gap:10px;cursor:pointer;user-select:none">
          <div style="width:30px;height:30px;border-radius:8px;background:linear-gradient(135deg,#7c3aed,#6366f1);color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;flex-shrink:0">
            <i class="fas fa-sparkles"></i>
          </div>
          <div style="flex:1">
            <div style="font-size:13px;font-weight:800;color:#6d28d9">Ask Claude about this report</div>
            <div style="font-size:11px;color:#a78bfa">Analyse agent performance, RTO patterns, delays & more</div>
          </div>
          <i class="fas fa-chevron-down" id="lc-ai-chevron" style="color:#a78bfa;transition:transform 0.2s"></i>
        </div>
        <div id="lc-ai-panel" style="display:none;padding:0 16px 16px">
          <div style="display:flex;gap:8px;align-items:flex-start">
            <textarea id="lc-ai-prompt" rows="2" placeholder="e.g. Which agent has the slowest Received→Called time? Summarise RTO orders by courier."
              style="flex:1;border:1.5px solid #e2e8f0;border-radius:10px;padding:9px 12px;font-size:13px;font-family:inherit;resize:vertical;outline:none;line-height:1.5"
              onfocus="this.style.borderColor='#7c3aed'" onblur="this.style.borderColor='#e2e8f0'"
              onkeydown="if(event.key==='Enter'&&(event.ctrlKey||event.metaKey)){event.preventDefault();runLcAI();}"></textarea>
            <button id="lc-ai-btn" onclick="runLcAI()" class="btn btn-sm" style="background:linear-gradient(135deg,#7c3aed,#6366f1);color:#fff;height:38px;white-space:nowrap;flex-shrink:0">
              <i class="fas fa-paper-plane" style="margin-right:5px"></i>Ask AI
            </button>
          </div>
          <div style="font-size:10px;color:#a78bfa;margin-top:4px"><i class="fas fa-keyboard" style="margin-right:4px"></i>Ctrl/Cmd + Enter to send · Run the report first so Claude has data</div>
          <div id="lc-ai-loading" style="display:none;margin-top:12px;padding:12px;text-align:center;color:#7c3aed;font-size:13px">
            <i class="fas fa-spinner fa-spin" style="margin-right:6px"></i>Claude is analysing the report…
          </div>
          <div id="lc-ai-error" style="display:none;margin-top:12px;padding:10px 14px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px;font-size:12px;color:#b91c1c"></div>
          <div id="lc-ai-output" style="display:none;margin-top:12px;padding:14px 16px;background:#fff;border:1px solid #e9d5ff;border-radius:10px;font-size:13px;color:#374151;line-height:1.6;max-height:320px;overflow-y:auto"></div>
        </div>
      </div>
    </div>

    <!-- Table -->
    <div style="padding:0 28px 20px">
      <div style="padding:14px 0 10px;font-size:12px;font-weight:700;color:#374151;text-transform:uppercase;letter-spacing:0.06em">Order-wise Breakdown</div>
      <div style="overflow-x:auto;max-height:calc(100vh - 420px);overflow-y:auto;border-radius:12px;border:1px solid #f1f5f9">
        <table style="width:100%;border-collapse:collapse;table-layout:auto">
          <thead style="position:sticky;top:0;z-index:10">
            <tr style="background:#f8fafc">
              <th style="position:sticky;left:0;z-index:11;background:#f8fafc;min-width:120px;max-width:120px;padding:8px 10px;text-align:left;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#64748b;border-bottom:1px solid #e2e8f0;border-right:1px solid #e2e8f0;white-space:nowrap">Order ID</th>
              <th style="position:sticky;left:120px;z-index:11;background:#f8fafc;min-width:100px;padding:8px 10px;text-align:left;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#64748b;border-bottom:1px solid #e2e8f0;border-right:2px solid #e2e8f0;white-space:nowrap">Order Date</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#3b82f6;background:#eff6ff;border-bottom:1px solid #e2e8f0;white-space:nowrap">⏱ Received → Assigned</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#8b5cf6;background:#f5f3ff;border-bottom:1px solid #e2e8f0;white-space:nowrap">📞 Assigned → Called</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#10b981;background:#f0fdf4;border-bottom:1px solid #e2e8f0;white-space:nowrap">🚚 Called → Dispatched</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#64748b;border-bottom:1px solid #e2e8f0;white-space:nowrap">Agent</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#b45309;background:#fffbeb;border-bottom:1px solid #e2e8f0;white-space:nowrap">📅 Assigned Date</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#b45309;background:#fffbeb;border-bottom:1px solid #e2e8f0;white-space:nowrap">👤 Agent Status</th>
              <th style="padding:10px 14px;text-align:left;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#b45309;background:#fffbeb;border-bottom:1px solid #e2e8f0;white-space:nowrap">💬 Agent Remark</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#64748b;border-bottom:1px solid #e2e8f0;white-space:nowrap">Status</th>
              <th style="padding:10px 14px;text-align:left;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#7c3aed;background:#faf5ff;border-bottom:1px solid #e2e8f0;white-space:nowrap">🏷 SKU</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#7c3aed;background:#faf5ff;border-bottom:1px solid #e2e8f0;white-space:nowrap">Qty</th>
              <th style="padding:10px 14px;text-align:left;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#0f766e;background:#f0fdfa;border-bottom:1px solid #e2e8f0;white-space:nowrap">📦 AWB No.</th>
              <th style="padding:10px 14px;text-align:left;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#0f766e;background:#f0fdfa;border-bottom:1px solid #e2e8f0;white-space:nowrap">🚚 Courier</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#0f766e;background:#f0fdfa;border-bottom:1px solid #e2e8f0;white-space:nowrap">📅 Dispatch Date</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#1d4ed8;background:#eff6ff;border-bottom:1px solid #e2e8f0;white-space:nowrap">📡 Clickpost Status</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#b91c1c;background:#fef2f2;border-bottom:1px solid #e2e8f0;white-space:nowrap">↩ Return Status</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#6d28d9;background:#f5f3ff;border-bottom:1px solid #e2e8f0;white-space:nowrap">💳 Payment Gateway</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#047857;background:#ecfdf5;border-bottom:1px solid #e2e8f0;white-space:nowrap">💰 Payment Received</th>
              <th style="padding:10px 14px;text-align:center;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:#15803d;background:#f0fdf4;border-bottom:1px solid #e2e8f0;white-space:nowrap">✅ Final Status</th>
            </tr>
          </thead>
          <tbody id="lc-table-body">
            <tr><td colspan="20" style="text-align:center;padding:40px;color:#94a3b8;font-size:13px">
              <i class="fas fa-route" style="font-size:28px;color:#e2e8f0;display:block;margin-bottom:8px"></i>
              Select a date range and click "Run Report"
            </td></tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</div>


<!-- ════════════════════════════════════════════
     UPLOAD FILES VIEW
════════════════════════════════════════════ -->


<!-- ── TRAINING EDITOR MODAL ── -->
<div id="trainingEditorModal" class="modal-backdrop hidden" onclick="if(event.target===this)closeTrainingEditor()">
  <div class="bg-white rounded-2xl shadow-2xl w-full overflow-hidden" style="max-width:600px">
    <div style="padding:18px 24px;border-bottom:1px solid #f1f5f9;display:flex;justify-content:space-between;align-items:center;background:linear-gradient(135deg,#f0fdf4,#fff)">
      <h3 style="font-weight:800;color:#1e293b;font-size:15px;display:flex;align-items:center;gap:8px"><i class="fas fa-graduation-cap" style="color:#16a34a"></i> <span id="te-title">Add Training Material</span></h3>
      <button onclick="closeTrainingEditor()" style="color:#94a3b8;background:none;border:none;cursor:pointer;font-size:18px"><i class="fas fa-times"></i></button>
    </div>
    <div style="padding:20px 24px;display:flex;flex-direction:column;gap:14px">
      <input type="hidden" id="te-id">
      <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
        <div>
          <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:5px">Header / Category *</label>
          <input type="text" id="te-header" placeholder="e.g. Agent Guide" class="form-input w-full" style="width:100%">
        </div>
        <div>
          <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:5px">Subheading / Topic</label>
          <input type="text" id="te-sub" placeholder="e.g. How to update status" class="form-input w-full" style="width:100%">
        </div>
      </div>
      <div>
        <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:5px">Body Text / Content</label>
        <textarea id="te-body" rows="6" placeholder="Write the training content here..." class="form-input w-full" style="width:100%;height:auto;padding:10px;resize:vertical;line-height:1.6"></textarea>
      </div>
      <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
        <div>
          <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:5px">Image URL (Google Drive)</label>
          <input type="text" id="te-image" placeholder="https://drive.google.com/..." class="form-input w-full" style="width:100%">
        </div>
        <div>
          <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:5px">Video URL (YouTube)</label>
          <input type="text" id="te-video" placeholder="https://youtube.com/..." class="form-input w-full" style="width:100%">
        </div>
      </div>
      <div id="te-error" style="display:none;padding:10px 14px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px;font-size:12px;color:#b91c1c"><i class="fas fa-exclamation-circle" style="margin-right:6px"></i><span id="te-error-text"></span></div>
    </div>
    <div style="padding:14px 24px;background:#f8fafc;border-top:1px solid #f1f5f9;display:flex;gap:10px">
      <button onclick="closeTrainingEditor()" class="btn btn-ghost flex-1 justify-center">Cancel</button>
      <button onclick="saveTrainingMaterial()" id="te-save-btn" class="btn flex-1 justify-center" style="background:#16a34a;color:#fff"><i class="fas fa-save"></i> <span id="te-save-text">Save Material</span></button>
    </div>
  </div>
</div>

<!-- ── SCAN BULK IMPORT MODAL (Admin only) ── -->
<div id="scanImportModal" class="modal-backdrop hidden" onclick="if(event.target===this)closeScanImportModal()">
  <div class="bg-white rounded-2xl shadow-2xl w-full overflow-hidden" style="max-width:580px">
    <div style="padding:18px 24px;border-bottom:1px solid #f1f5f9;display:flex;justify-content:space-between;align-items:center;background:linear-gradient(135deg,#f0f4ff,#fff)">
      <div>
        <h3 style="font-weight:800;color:#1e293b;font-size:15px;display:flex;align-items:center;gap:8px"><i class="fas fa-file-upload" style="color:#6366f1"></i> Bulk Import Scan Records</h3>
        <p style="font-size:12px;color:#64748b;margin-top:2px">Upload CSV with missed/backdated dispatch records</p>
      </div>
      <button onclick="closeScanImportModal()" style="color:#94a3b8;background:none;border:none;cursor:pointer;font-size:18px"><i class="fas fa-times"></i></button>
    </div>
    <div style="padding:20px 24px;display:flex;flex-direction:column;gap:14px">
      <!-- Format guide -->
      <div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:12px 16px">
        <div style="font-size:11px;font-weight:700;color:#374151;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:6px">Required CSV Format</div>
        <code style="font-size:11px;color:#6366f1;background:#eef2ff;padding:4px 8px;border-radius:4px;display:block">order_id, courier_name, dispatch_status, scan_date</code>
        <div style="font-size:11px;color:#94a3b8;margin-top:6px">Example: 3434354140, DTDC, Dispatched, 2026-05-21</div>
        <div style="font-size:11px;color:#94a3b8;margin-top:2px">dispatch_status options: Dispatched / Returned / Cancelled</div>
        <button onclick="downloadImportTemplate()" style="margin-top:8px;background:#f0f4ff;color:#6366f1;border:1px solid #c7d2fe;padding:4px 12px;border-radius:6px;font-size:11px;font-weight:700;cursor:pointer">
          <i class="fas fa-download"></i> Download Template
        </button>
      </div>
      <!-- File upload -->
      <div>
        <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:6px">Select CSV File</label>
        <input type="file" id="import-file" accept=".csv,.xlsx,.xls" class="form-input w-full" style="width:100%;height:auto;padding:8px 12px">
      </div>
      <!-- Default values -->
      <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
        <div>
          <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:5px">Default Courier (if not in CSV)</label>
          <select id="import-default-courier" class="form-select w-full" style="width:100%">
            <option value="">-- Select --</option>
            <option>Xpressbees</option><option>Shadowfax</option><option>Ekart</option>
            <option>Bluedart</option><option>Delhivery</option><option>DTDC</option>
            <option>Amazon</option><option>Others</option>
          </select>
        </div>
        <div>
          <label style="display:block;font-size:11px;font-weight:700;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:5px">Default Status (if not in CSV)</label>
          <select id="import-default-status" class="form-select w-full" style="width:100%">
            <option value="Dispatched">Dispatched</option>
            <option value="Returned">Returned</option>
            <option value="Cancelled">Cancelled</option>
          </select>
        </div>
      </div>
      <!-- Preview -->
      <div id="import-preview" style="display:none;max-height:180px;overflow-y:auto;border:1px solid #e2e8f0;border-radius:8px">
        <table style="width:100%;border-collapse:collapse;font-size:12px">
          <thead><tr style="background:#f8fafc;position:sticky;top:0">
            <th style="padding:7px 12px;text-align:left;color:#64748b;font-weight:700">Order ID</th>
            <th style="padding:7px 12px;text-align:left;color:#64748b;font-weight:700">Courier</th>
            <th style="padding:7px 12px;text-align:left;color:#64748b;font-weight:700">Status</th>
            <th style="padding:7px 12px;text-align:left;color:#64748b;font-weight:700">Date</th>
          </tr></thead>
          <tbody id="import-preview-body"></tbody>
        </table>
      </div>
      <div id="import-error" style="display:none;padding:10px 14px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px;font-size:12px;color:#b91c1c"></div>
      <div id="import-progress" style="display:none;padding:10px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;font-size:12px;color:#15803d;font-weight:600"></div>
    </div>
    <div style="padding:14px 24px;background:#f8fafc;border-top:1px solid #f1f5f9;display:flex;gap:10px">
      <button onclick="closeScanImportModal()" class="btn btn-ghost flex-1 justify-center">Cancel</button>
      <button onclick="previewImport()" class="btn btn-ghost flex-1 justify-center" style="border-color:#6366f1;color:#6366f1"><i class="fas fa-eye"></i> Preview</button>
      <button onclick="submitImport()" id="import-submit-btn" class="btn flex-1 justify-center" style="background:#6366f1;color:#fff"><i class="fas fa-upload"></i> Import</button>
    </div>
  </div>
</div>
</body>
</html>