// Global window.fetch Interceptor for Token Session Authentication
const originalFetch = window.fetch;
window.fetch = async function (url, options = {}) {
  const token = localStorage.getItem('hotel_auth_token');
  if (token && url.startsWith('/api/')) {
    options.headers = options.headers || {};
    options.headers['Authorization'] = `Bearer ${token}`;
  }
  try {
    const response = await originalFetch(url, options);
    if (response.status === 401 && !url.includes('/api/login')) {
      try {
        const clone = response.clone();
        const data = await clone.json();
        if (data && data.error && data.error.includes('Unauthorized')) {
          console.warn('Session expired or unauthorized. Redirecting to login...');
          localStorage.removeItem('hotel_auth_token');
          localStorage.removeItem('user');
          if (typeof state !== 'undefined') {
            state.currentUser = null;
          }
          document.getElementById('app-container').classList.remove('active');
          document.getElementById('login-container').classList.add('active');
        }
      } catch (e) {}
    }
    return response;
  } catch (err) {
    throw err;
  }
};

// Global Application State
const state = {
  currentUser: null,
  activeView: 'dashboard',
  roomsList: [],
  settings: {},
  heartbeatInterval: null,
  selectedRoomIdCtx: null,
  activeCameraStream: null,
  guestPhotoBase64: null,
  loadedGuestId: null,
  calendarStartDate: new Date().toISOString().split('T')[0],
  whatsappLogs: []
};

// ================= INITIALIZATION & AUTHENTICATION ================= //

document.addEventListener('DOMContentLoaded', () => {
  initClock();
  setupEventListeners();
  initWebSocket();
  
  // Start heartbeat immediately on page load to keep the backend server alive
  startHeartbeat();
  
  // Check persistent login credentials
  const savedUser = localStorage.getItem('user');
  const savedToken = localStorage.getItem('hotel_auth_token');
  if (savedUser && savedToken) {
    loginSuccess(JSON.parse(savedUser));
  } else {
    showView('login');
  }
});

function initClock() {
  const clockEl = document.getElementById('live-clock');
  setInterval(() => {
    const now = new Date();
    clockEl.textContent = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
  }, 1000);
}

function setupEventListeners() {
  // Mobile Menu Hamburger Toggle
  document.getElementById('btn-sidebar-toggle').addEventListener('click', () => {
    document.querySelector('.sidebar').classList.toggle('active');
  });

  // Login Form
  document.getElementById('login-form').addEventListener('submit', handleLogin);
  
  // Sidebar Navigation
  document.querySelectorAll('.menu-item').forEach(item => {
    item.addEventListener('click', (e) => {
      e.preventDefault();
      
      // Auto close sidebar on navigation (mobile)
      document.querySelector('.sidebar').classList.remove('active');
      
      const view = item.getAttribute('data-view');
      navigateTo(view);
    });
  });

  // Logout Trigger
  document.getElementById('btn-logout-trigger').addEventListener('click', handleLogout);

  // Tab Buttons
  document.querySelectorAll('.tab-btn').forEach(btn => {
    btn.addEventListener('click', () => {
      const tabName = btn.getAttribute('data-tab');
      // Set active button
      btn.parentElement.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      // Set active content
      const contentId = 'tab-' + tabName;
      const tabContent = document.getElementById(contentId);
      tabContent.parentElement.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
      tabContent.classList.add('active');
      
      if (tabName.startsWith('wa-tpl-')) {
        updateWhatsAppPreview(tabName.replace('wa-tpl-', ''));
      }
    });
  });

  // Modals close buttons
  document.querySelectorAll('.btn-close, .modal-footer .btn-secondary').forEach(btn => {
    btn.addEventListener('click', () => {
      closeAllModals();
    });
  });

  // Context Menu Global Dismissal
  document.addEventListener('click', (e) => {
    if (!e.target.closest('#room-context-menu') && !e.target.closest('.room-card')) {
      document.getElementById('room-context-menu').classList.add('hidden');
    }
  });

  // Context Menu Actions
  document.querySelectorAll('#room-context-menu .context-item').forEach(item => {
    item.addEventListener('click', (e) => {
      e.preventDefault();
      const action = item.getAttribute('data-action');
      handleRoomContextAction(action);
    });
  });

  // New Booking Button & Modal timeline changes
  document.getElementById('btn-quick-booking').addEventListener('click', () => {
    openBookingModal();
  });
  document.getElementById('book-checkin-date').addEventListener('change', calculateBookingPrice);
  document.getElementById('book-checkout-date').addEventListener('change', calculateBookingPrice);
  document.getElementById('book-status-select').addEventListener('change', calculateBookingPrice);
  document.getElementById('btn-booking-next').addEventListener('click', () => gotoBookingStep(2));
  document.getElementById('btn-booking-back').addEventListener('click', () => gotoBookingStep(1));
  document.getElementById('btn-cancel-booking-1').addEventListener('click', closeAllModals);

  // Webcam logic
  document.getElementById('btn-start-camera').addEventListener('click', startWebcam);
  document.getElementById('btn-snap-photo').addEventListener('click', captureWebcamPhoto);

  // Guest Search Autocomplete inside booking
  const searchInput = document.getElementById('book-guest-search-input');
  searchInput.addEventListener('input', handleGuestSearchAutocomplete);
  searchInput.addEventListener('focus', handleGuestSearchAutocomplete);
  document.getElementById('btn-clear-guest-search').addEventListener('click', clearBookingGuestForm);

  // Global click dismissal for autocomplete dropdown
  document.addEventListener('click', (e) => {
    if (!e.target.closest('.guest-search-panel')) {
      const dropdown = document.getElementById('guest-search-dropdown');
      if (dropdown) dropdown.classList.add('hidden');
    }
  });

  // Booking Save Form
  document.getElementById('booking-form').addEventListener('submit', handleBookingSubmit);

  // Guest Search Directory
  document.getElementById('guest-search-btn').addEventListener('click', loadGuestsList);
  document.getElementById('guest-search-input').addEventListener('keypress', (e) => {
    if (e.key === 'Enter') loadGuestsList();
  });
  document.getElementById('btn-add-guest').addEventListener('click', () => {
    openBookingModal(); // Pre-activates Guest Registration tab
  });

  // Billing and Checkout triggers
  document.getElementById('checkout-room-select').addEventListener('change', loadCheckoutRoomDetails);
  document.getElementById('reprint-invoice-select').addEventListener('change', loadReprintInvoiceDetails);
  document.querySelectorAll('input[name="gst-region"]').forEach(radio => {
    radio.addEventListener('change', updateCheckoutSummaryRates);
  });
  document.getElementById('btn-submit-checkout').addEventListener('click', submitCheckoutPayment);
  document.getElementById('btn-print-invoice').addEventListener('click', () => {
    if (activeBillingBooking) {
      const token = localStorage.getItem('hotel_auth_token') || '';
      const printUrl = `/api/invoices/pdf?id=${activeBillingBooking.id}&token=${token}`;
      window.open(printUrl, '_blank');
    } else {
      alert('Please load an active checkout booking first.');
    }
  });
  document.getElementById('btn-email-invoice').addEventListener('click', triggerWhatsAppInvoiceMock);
  document.getElementById('btn-email-invoice-real').addEventListener('click', shareInvoiceViaEmail);
  
  // Guest edit triggers
  document.getElementById('btn-close-edit-guest').addEventListener('click', closeAllModals);
  document.getElementById('btn-cancel-edit-guest').addEventListener('click', closeAllModals);
  document.getElementById('edit-guest-form').addEventListener('submit', handleEditGuestFormSubmit);
  const btnSendWaTest = document.getElementById('btn-send-wa-test');
  if (btnSendWaTest) btnSendWaTest.addEventListener('click', sendWhatsAppTestMessage);

  // WhatsApp Logs console triggers
  document.getElementById('btn-whatsapp-logs-trigger').addEventListener('click', openWhatsAppLogsModal);
  document.getElementById('btn-close-whatsapp').addEventListener('click', closeAllModals);

  // Calendar timeline navigation
  document.getElementById('btn-calendar-prev').addEventListener('click', () => adjustCalendarTimeline(-7));
  document.getElementById('btn-calendar-next').addEventListener('click', () => adjustCalendarTimeline(7));
  document.getElementById('btn-calendar-today').addEventListener('click', () => {
    state.calendarStartDate = new Date().toISOString().split('T')[0];
    document.getElementById('calendar-start-date').value = state.calendarStartDate;
    loadCalendarView();
  });
  document.getElementById('calendar-start-date').addEventListener('change', (e) => {
    state.calendarStartDate = e.target.value;
    loadCalendarView();
  });

  // Housekeeping triggers
  document.getElementById('btn-add-inventory').addEventListener('click', () => openInventoryModal());
  document.getElementById('inventory-form').addEventListener('submit', saveInventoryItem);
  document.getElementById('btn-add-lostfound').addEventListener('click', () => openLostFoundModal());
  document.getElementById('lostfound-form').addEventListener('submit', saveLostFoundItem);
  document.getElementById('claim-lostfound-form').addEventListener('submit', submitLostFoundClaim);

  // Staff triggers
  document.getElementById('btn-log-attendance').addEventListener('click', openAttendanceModal);
  document.getElementById('attendance-form').addEventListener('submit', saveAttendanceLog);
  document.getElementById('btn-pay-salary').addEventListener('click', openSalaryModal);
  document.getElementById('salary-form').addEventListener('submit', saveSalaryRecord);

  // Report triggers
  document.getElementById('btn-generate-report').addEventListener('click', generateReportsData);
  document.getElementById('btn-export-csv').addEventListener('click', exportReportToCSV);

  // Settings triggers
  document.getElementById('settings-hotel-form').addEventListener('submit', saveHotelSettings);
  document.getElementById('settings-utility-form').addEventListener('submit', saveUtilitySettings);
  document.getElementById('settings-whatsapp-form').addEventListener('submit', saveActiveTemplate);
  const apiForm = document.getElementById('settings-whatsapp-api-form-manual');
  if (apiForm) apiForm.addEventListener('submit', saveManualWaCredentials);

  // Live preview bindings for dynamic WhatsApp templates
  ['tpl-image', 'tpl-body', 'tpl-footer', 'tpl-btn-text', 'tpl-url', 'tpl-meta-name', 'tpl-meta-lang'].forEach(id => {
    const el = document.getElementById(id);
    if (el) {
      el.addEventListener('input', updateWhatsAppPreview);
      el.addEventListener('change', updateWhatsAppPreview);
    }
  });
  document.getElementById('btn-admin-add-room').addEventListener('click', () => openAdminRoomModal());
  document.getElementById('btn-close-admin-room').addEventListener('click', closeAllModals);
  document.getElementById('btn-cancel-admin-room').addEventListener('click', closeAllModals);
  document.getElementById('admin-room-form').addEventListener('submit', handleAdminRoomFormSubmit);
  document.getElementById('btn-trigger-backup').addEventListener('click', triggerDatabaseBackup);
  document.getElementById('btn-test-gdrive-upload').addEventListener('click', testGoogleDriveUpload);
  document.getElementById('settings-gdrive-form').addEventListener('submit', saveGoogleDriveSettings);
  document.getElementById('settings-smtp-form').addEventListener('submit', saveSMTPSettings);
  document.getElementById('btn-test-smtp-connection').addEventListener('click', testSMTPConnection);

  // Logo file upload helper
  document.getElementById('set-hotel-logo-file').addEventListener('change', (e) => {
    const file = e.target.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = function(evt) {
      document.getElementById('set-hotel-logo').value = evt.target.result;
    };
    reader.readAsDataURL(file);
  });

  // Floor config triggers
  document.getElementById('add-floor-form').addEventListener('submit', handleAddFloorSubmit);

  // Channel manager triggers
  document.getElementById('btn-sync-ota-channels').addEventListener('click', syncOTAChannels);

  // Reviews triggers
  document.getElementById('review-reply-form').addEventListener('submit', handleReviewReplySubmit);

  // Custom WhatsApp triggers
  document.getElementById('custom-whatsapp-form').addEventListener('submit', handleCustomWASubmit);

  // Integrations form submit
  document.getElementById('settings-integrations-form').addEventListener('submit', saveIntegrationsSettings);

  // Master reset form submit
  document.getElementById('master-reset-form').addEventListener('submit', handleMasterResetSubmit);

  // Factory reset form submit
  document.getElementById('factory-reset-form').addEventListener('submit', handleFactoryResetSubmit);

  // Seed demo data button trigger
  document.getElementById('btn-seed-demo').addEventListener('click', triggerSeedDemoData);

  // Social Marketing Composer & Settings listeners
  document.getElementById('social-composer-form').addEventListener('submit', handleSocialPublish);
  document.getElementById('social-settings-form').addEventListener('submit', saveSocialSettings);
  document.getElementById('social-post-caption').addEventListener('input', updateSocialPreview);
  document.getElementById('social-media-url').addEventListener('input', updateSocialPreview);
  document.getElementById('social-media-type').addEventListener('change', updateSocialPreview);

  // Setup default calendar dates
  document.getElementById('calendar-start-date').value = state.calendarStartDate;
  
  // Setup default report dates
  const today = new Date().toISOString().split('T')[0];
  const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
  document.getElementById('report-start-date').value = thirtyDaysAgo;
  document.getElementById('report-end-date').value = today;
}

// Show/Hide main layouts
function showView(viewName) {
  if (viewName === 'login') {
    document.getElementById('login-container').classList.add('active');
    document.getElementById('app-container').classList.remove('active');
  } else {
    document.getElementById('login-container').classList.remove('active');
    document.getElementById('app-container').classList.add('active');
  }
}

// Navigate View Sections inside main layout
function navigateTo(viewId) {
  state.activeView = viewId;
  
  // Update sidebar active link
  document.querySelectorAll('.menu-item').forEach(item => {
    item.classList.remove('active');
    if (item.getAttribute('data-view') === viewId) {
      item.classList.add('active');
    }
  });

  // Switch display
  document.querySelectorAll('.content-view').forEach(view => {
    view.classList.remove('active');
  });
  const viewEl = document.getElementById('view-' + viewId);
  if (viewEl) {
    viewEl.classList.add('active');
    // Update top header title text
    const titleMap = {
      'dashboard': 'Dashboard Operations',
      'calendar': 'Room Availability Calendar',
      'guests': 'Guest CRM Directory',
      'billing': 'GST Billing & Check-out Desk',
      'housekeeping': 'Housekeeping, Mini Bar & Stock Management',
      'staff': 'Staff Roster & Payroll Registry',
      'reports': 'Management Reports Console',
      'channel-manager': 'OTA Channel Manager Integration',
      'google-seo': 'Google Business Profile & Local SEO',
      'social-hub': 'Meta Social Marketing & Ad Hub',
      'whatsapp-chat': 'WhatsApp Guest Chat Inbox',
      'settings': 'System Settings & Audit Log Console'
    };
    document.getElementById('view-title').textContent = titleMap[viewId] || 'Shaima Hotel Management';
  }

  // Load specific view data
  if (viewId === 'dashboard') loadDashboardView();
  else if (viewId === 'calendar') loadCalendarView();
  else if (viewId === 'guests') loadGuestsList();
  else if (viewId === 'billing') loadBillingView();
  else if (viewId === 'housekeeping') loadHousekeepingView();
  else if (viewId === 'staff') loadStaffView();
  else if (viewId === 'channel-manager') loadOTABookingsTable();
  else if (viewId === 'google-seo') loadGbpView();
  else if (viewId === 'social-hub') loadSocialHubView();
  else if (viewId === 'whatsapp-chat') loadWhatsAppChatView();
  else if (viewId === 'settings') {
    loadSettingsView();
    loadRoomTypesSettingsTable();
  }
}

async function handleLogin(e) {
  e.preventDefault();
  const usernameEl = document.getElementById('username');
  const passwordEl = document.getElementById('password');
  
  const username = usernameEl.value.trim();
  const password = passwordEl.value.trim();
  
  if (!username || !password) {
    document.getElementById('login-error').textContent = 'Username and password cannot be blank. Please try again.';
    document.getElementById('login-error').classList.remove('hidden');
    usernameEl.value = '';
    passwordEl.value = '';
    return;
  }
  
  showLoader(true, 'Verifying Credentials...');
  try {
    const res = await fetch('/api/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password })
    });
    
    showLoader(false);
    if (res.ok) {
      const data = await res.json();
      localStorage.setItem('hotel_auth_token', data.token);
      loginSuccess(data.user);
    } else {
      const err = await res.json();
      document.getElementById('login-error').textContent = err.error || 'Login Failed';
      document.getElementById('login-error').classList.remove('hidden');
      passwordEl.value = '';
    }
  } catch (err) {
    showLoader(false);
    document.getElementById('login-error').textContent = 'Server connection failed';
    document.getElementById('login-error').classList.remove('hidden');
    passwordEl.value = '';
  }
}

function loginSuccess(user) {
  state.currentUser = user;
  localStorage.setItem('user', JSON.stringify(user));
  
  // Update UI user profile elements
  document.getElementById('current-user-name').textContent = user.name;
  document.getElementById('current-user-role').textContent = user.role;
  document.getElementById('current-user-avatar').textContent = user.name.split(' ').map(n=>n[0]).join('').substring(0,2).toUpperCase();

  // Hide login error if displayed
  document.getElementById('login-error').classList.add('hidden');
  document.getElementById('username').value = '';
  document.getElementById('password').value = '';

  // Switch to main wrapper
  showView('app');
  
  // Run heartbeat
  startHeartbeat();
  
  // Load Default view
  navigateTo('dashboard');
  
  // Poll WhatsApp logs count
  pollWhatsAppLogsCount();
}

function handleLogout() {
  if (confirm('Are you sure you want to log out?')) {
    stopHeartbeat();
    localStorage.removeItem('user');
    localStorage.removeItem('hotel_auth_token');
    state.currentUser = null;
    showView('login');
  }
}

function startHeartbeat() {
  stopHeartbeat();
  // Immediate heartbeat hit
  fetch('/api/heartbeat').catch(()=>{});
  
  state.heartbeatInterval = setInterval(() => {
    fetch('/api/heartbeat').catch(err => {
      console.warn('Lost server heartbeat. Network offline or server stopped.');
    });
  }, 2500);
}

function stopHeartbeat() {
  if (state.heartbeatInterval) {
    clearInterval(state.heartbeatInterval);
    state.heartbeatInterval = null;
  }
}

// ================= REAL-TIME WEBSOCKET STREAM CONNECTION ================= //
let wsClient = null;

function initWebSocket() {
  const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
  const wsUrl = `${protocol}//${window.location.host}`;
  wsClient = new WebSocket(wsUrl);

  wsClient.onopen = () => {
    console.log('[WebSocket]: Connected to server stream.');
  };

  wsClient.onmessage = (event) => {
    try {
      const payload = JSON.parse(event.data);
      console.log('[WebSocket Message Received]:', payload);
      
      if (payload.type === 'new_message') {
        showRealTimeNotification(payload.message);
      } else if (payload.type === 'status_update') {
        if (state.activeView === 'whatsapp-chat') {
          loadWhatsAppChatViewQuiet();
        }
      }
    } catch (err) {
      console.error('[WebSocket parse error]:', err.message);
    }
  };

  wsClient.onclose = () => {
    console.warn('[WebSocket]: Connection closed. Reconnecting in 3 seconds...');
    setTimeout(initWebSocket, 3000);
  };
}

function showRealTimeNotification(msg) {
  const toast = document.createElement('div');
  toast.className = 'wa-toast-alert';
  toast.style.cssText = `
    position: fixed;
    bottom: 20px;
    right: 20px;
    background: #00a884;
    color: #fff;
    padding: 12px 18px;
    border-radius: 8px;
    box-shadow: 0 4px 15px rgba(0,0,0,0.3);
    z-index: 99999;
    font-size: 13px;
    display: flex;
    flex-direction: column;
    gap: 4px;
  `;
  
  toast.innerHTML = `
    <strong>New Message from ${msg.guest_name}</strong>
    <span>${msg.body}</span>
  `;
  
  document.body.appendChild(toast);
  
  try {
    const audio = new Audio('data:audio/wav;base64,UklGRigAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQAAAAAAA==');
    audio.play().catch(()=>{});
  } catch (e) {}

  setTimeout(() => {
    toast.remove();
  }, 4000);

  if (state.activeView === 'whatsapp-chat') {
    loadWhatsAppChatViewQuiet();
  }
}

async function loadWhatsAppChatViewQuiet() {
  try {
    const guestsRes = await fetch('/api/guests');
    const guests = await guestsRes.json();
    state.guestsList = guests;
    renderWhatsAppChatRoster();
    if (activeChatGuestId) {
      renderWhatsAppChatBubblesQuiet();
    }
  } catch (err) {}
}

async function renderWhatsAppChatBubblesQuiet() {
  if (!activeChatGuestId) return;
  try {
    const res = await fetch(`/api/whatsapp/chat-history?guestId=${activeChatGuestId}`);
    if (res.ok) {
      const history = await res.json();
      state.whatsappChatHistories[activeChatGuestId] = history;
      renderWhatsAppChatBubbles();
    }
  } catch (err) {}
}

// ================= UI HELPERS & SPINNER ================= //

function showLoader(show, text = 'Processing Request...') {
  const overlay = document.getElementById('loading-overlay');
  overlay.querySelector('.loading-text').textContent = text;
  if (show) overlay.classList.remove('hidden');
  else overlay.classList.add('hidden');
}

function closeAllModals() {
  document.querySelectorAll('.modal-backdrop, .modal').forEach(modal => {
    modal.classList.remove('active');
  });
  stopWebcam();
}

function openModal(id) {
  closeAllModals();
  const modal = document.getElementById(id);
  if (modal) modal.classList.add('active');
}

function closeModal(id) {
  const modal = document.getElementById(id);
  if (modal) modal.classList.remove('active');
}

// ================= VIEW: DASHBOARD CONTROLLER ================= //

async function loadDashboardView() {
  try {
    const res = await fetch('/api/dashboard-stats');
    if (!res.ok) throw new Error('Failed load stats');
    const data = await res.json();
    
    // Renders Stats Cards
    document.getElementById('stat-occupancy').textContent = data.occupancyRate + '%';
    document.getElementById('occupancy-fill').style.width = data.occupancyRate + '%';
    document.getElementById('stat-checked-in').textContent = data.activeBookingsCount;
    document.getElementById('stat-revenue').textContent = '₹' + data.revenueToday.toLocaleString();
    
    const lowStockEl = document.getElementById('stat-low-stock');
    const lowStockCard = document.getElementById('stock-warning-card');
    lowStockEl.textContent = data.lowStockCount;
    if (data.lowStockCount > 0) {
      lowStockCard.classList.add('warning-active');
    } else {
      lowStockCard.classList.remove('warning-active');
    }

    state.roomsList = data.roomList;
    renderRoomMatrix(data.roomList);
    if (typeof updateDashboardWaStats === 'function') {
      updateDashboardWaStats(data);
    }
  } catch (err) {
    console.error('Error loading dashboard stats:', err);
  }
}

function renderRoomMatrix(rooms) {
  const matrixContainer = document.getElementById('room-matrix');
  matrixContainer.innerHTML = '';

  // Group rooms by Floor
  const floors = {};
  rooms.forEach(r => {
    if (!floors[r.floor]) floors[r.floor] = [];
    floors[r.floor].push(r);
  });

  // Render Floors
  for (const floorName in floors) {
    const floorDiv = document.createElement('div');
    floorDiv.className = 'floor-group';

    const floorTitle = document.createElement('div');
    floorTitle.className = 'floor-title';
    floorTitle.textContent = floorName;
    floorDiv.appendChild(floorTitle);

    const roomsRow = document.createElement('div');
    roomsRow.className = 'rooms-row';

    floors[floorName].forEach(room => {
      const roomCard = document.createElement('div');
      roomCard.className = `room-card ${room.status.toLowerCase()}`;
      roomCard.setAttribute('data-id', room.id);
      roomCard.setAttribute('data-number', room.room_number);
      roomCard.setAttribute('data-status', room.status);

      roomCard.innerHTML = `
        <div class="room-card-number">${room.room_number}</div>
        <div class="room-card-type">${room.type}</div>
        <span class="room-card-status">${room.status}</span>
      `;

      // Right Click Context Menu
      roomCard.addEventListener('contextmenu', (e) => {
        e.preventDefault();
        openRoomContextMenu(e, room);
      });

      // Left Click Trigger for Context Menu (easier touch & accessibility support)
      roomCard.addEventListener('click', (e) => {
        openRoomContextMenu(e, room);
      });

      roomsRow.appendChild(roomCard);
    });

    floorDiv.appendChild(roomsRow);
    matrixContainer.appendChild(floorDiv);
  }
}

function openRoomContextMenu(e, room) {
  e.stopPropagation();
  state.selectedRoomIdCtx = room.id;
  
  const menu = document.getElementById('room-context-menu');
  document.getElementById('ctx-room-number').textContent = room.room_number;

  // Toggle Context elements based on state
  const viewBookingLink = document.getElementById('ctx-view-booking-link');
  const transferLink = document.getElementById('ctx-room-transfer-link');
  
  if (room.status === 'Occupied') {
    viewBookingLink.style.display = 'block';
    transferLink.style.display = 'block';
  } else {
    viewBookingLink.style.display = 'none';
    transferLink.style.display = 'none';
  }

  // Position Context menu
  menu.style.left = e.pageX + 'px';
  menu.style.top = e.pageY + 'px';
  menu.classList.remove('hidden');
}

async function handleRoomContextAction(action) {
  const menu = document.getElementById('room-context-menu');
  menu.classList.add('hidden');
  
  const roomId = state.selectedRoomIdCtx;
  const room = state.roomsList.find(r => r.id === roomId);
  if (!room) return;

  if (action.startsWith('make-')) {
    // Change Room Status
    const statusMap = {
      'make-vacant': 'Vacant',
      'make-dirty': 'Dirty',
      'make-cleaning': 'Cleaning',
      'make-maintenance': 'Maintenance'
    };
    const newStatus = statusMap[action];
    
    showLoader(true, `Updating Room ${room.room_number} to ${newStatus}...`);
    try {
      const res = await fetch('/api/rooms/status', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ roomId, status: newStatus, userId: state.currentUser.id })
      });
      showLoader(false);
      if (res.ok) {
        loadDashboardView();
      } else {
        alert('Failed updating room status');
      }
    } catch (e) {
      showLoader(false);
      alert('Connection error');
    }
  } else if (action === 'book-now') {
    openBookingModal(roomId);
  } else if (action === 'view-booking') {
    viewOccupiedBookingDetails(room.id);
  } else if (action === 'transfer-room') {
    triggerRoomTransferPrompt(room.id);
  }
}

// ================= VIEW: AVAILABILITY CALENDAR ================= //

async function loadCalendarView() {
  try {
    const res = await fetch('/api/bookings');
    if (!res.ok) throw new Error('Fail fetch bookings');
    const bookings = await res.json();
    
    // Fetch rooms
    const resRooms = await fetch('/api/rooms');
    const rooms = await resRooms.json();

    renderCalendar(rooms, bookings);
  } catch (err) {
    console.error('Error loading calendar view:', err);
  }
}

function adjustCalendarTimeline(days) {
  const curDate = new Date(state.calendarStartDate);
  curDate.setDate(curDate.getDate() + days);
  state.calendarStartDate = curDate.toISOString().split('T')[0];
  document.getElementById('calendar-start-date').value = state.calendarStartDate;
  loadCalendarView();
}

function renderCalendar(rooms, bookings) {
  const headersRow = document.getElementById('calendar-headers');
  const rowsBody = document.getElementById('calendar-rows');

  headersRow.innerHTML = '<th>Room</th>';
  rowsBody.innerHTML = '';

  // Generate 14-day header range
  const startDate = new Date(state.calendarStartDate);
  const dateRange = [];
  for (let i = 0; i < 14; i++) {
    const nextDate = new Date(startDate);
    nextDate.setDate(startDate.getDate() + i);
    dateRange.push(nextDate);
    
    const dayStr = nextDate.toLocaleDateString([], { weekday: 'short' });
    const dateStr = nextDate.getDate() + '/' + (nextDate.getMonth() + 1);
    
    const th = document.createElement('th');
    th.innerHTML = `<div>${dayStr}</div><div class="calendar-cell-date">${dateStr}</div>`;
    headersRow.appendChild(th);
  }

  // Populate Room Rows
  rooms.forEach(room => {
    const tr = document.createElement('tr');
    tr.innerHTML = `
      <td>
        <span class="calendar-row-room">${room.room_number}</span>
        <span class="calendar-row-type">${room.type}</span>
      </td>
    `;

    // Populate day slots
    dateRange.forEach(date => {
      const td = document.createElement('td');
      td.className = 'calendar-cell-slot';
      td.setAttribute('data-room-id', room.id);
      td.setAttribute('data-date', date.toISOString().split('T')[0]);

      // Handle Quick click to Book Room
      td.addEventListener('click', () => {
        openBookingModal(room.id, date.toISOString().split('T')[0]);
      });

      // Check if room is occupied on this date
      const dateString = date.toISOString().split('T')[0];
      const match = bookings.find(b => {
        // Match active bookings containing this room and containing this date
        const roomsArr = b.room_ids ? b.room_ids.split(',').map(Number) : [];
        if (!roomsArr.includes(room.id)) return false;
        
        // Date must be >= checkin and < checkout (or checkout included if checkout hour is late)
        return dateString >= b.check_in && dateString < b.check_out && b.status !== 'Cancelled';
      });

      if (match) {
        // Draw booking overlay bar
        const bar = document.createElement('div');
        bar.className = `booking-bar ${match.status.toLowerCase()}`;
        bar.textContent = match.guest_name;
        bar.title = `Guest: ${match.guest_name}\nStay: ${match.check_in} to ${match.check_out}\nBooking ID: ${match.booking_uid}`;
        
        bar.addEventListener('click', (e) => {
          e.stopPropagation();
          viewBookingDetailsModal(match);
        });

        td.appendChild(bar);
      }

      tr.appendChild(td);
    });

    rowsBody.appendChild(tr);
  });
}

// ================= NEW BOOKING & WALKIN MODAL ================= //

async function openBookingModal(preselectedRoomId = null, preselectedDate = null) {
  openModal('modal-booking');
  document.getElementById('booking-form').reset();
  state.guestPhotoBase64 = null;
  state.loadedGuestId = null;
  
  // Reset Wizard step indicators and page displays
  gotoBookingStep(1);
  
  // Clear search field
  document.getElementById('book-guest-search-input').value = '';
  document.getElementById('guest-search-dropdown').classList.add('hidden');
  
  // Clear camera state
  document.getElementById('photo-preview').src = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' fill='%23666'><circle cx='60' cy='45' r='25'/><path d='M20 100c0-20 20-30 40-30s40 10 40 30z'/></svg>";
  document.getElementById('guest-lookup-result').textContent = 'No guest loaded. Complete fields below to register new guest.';
  document.getElementById('guest-lookup-result').className = 'guest-lookup-text';
  
  // Set Timeline
  const checkinDateEl = document.getElementById('book-checkin-date');
  const checkoutDateEl = document.getElementById('book-checkout-date');
  
  const today = preselectedDate || new Date().toISOString().split('T')[0];
  const tomorrow = new Date(new Date(today).getTime() + 24 * 60 * 60 * 1000).toISOString().split('T')[0];

  checkinDateEl.value = today;
  checkoutDateEl.value = tomorrow;

  // Load Vacant Rooms selection checkboxes
  try {
    const res = await fetch('/api/rooms');
    const rooms = await res.json();
    
    const roomsSelectionGrid = document.getElementById('booking-rooms-selection');
    roomsSelectionGrid.innerHTML = '';

    rooms.forEach(room => {
      // Show vacant rooms or the preselected room (even if dirty/cleaning)
      if (room.status === 'Vacant' || room.id === preselectedRoomId) {
        const label = document.createElement('label');
        label.className = 'checkbox-tile';
        
        const checkedStr = room.id === preselectedRoomId ? 'checked' : '';
        label.innerHTML = `
          <input type="checkbox" name="booking-rooms" value="${room.id}" data-price="${room.price}" ${checkedStr}>
          <span>Room ${room.room_number}<small style="display:block; font-weight:normal; font-size:10px; color:#888;">${room.type} (₹${room.price})</small></span>
        `;

        label.querySelector('input').addEventListener('change', calculateBookingPrice);
        roomsSelectionGrid.appendChild(label);
      }
    });

    calculateBookingPrice();
  } catch (err) {
    console.error(err);
  }
}

function gotoBookingStep(step) {
  const track = document.getElementById('booking-wizard-track');
  const ind1 = document.getElementById('booking-indicator-1');
  const ind2 = document.getElementById('booking-indicator-2');
  const indLine = document.getElementById('booking-indicator-line');

  if (!track) return;

  if (step === 2) {
    // Validate Step 1 before proceeding
    const name = document.getElementById('book-guest-name').value.trim();
    const mobile = document.getElementById('book-guest-mobile').value.trim();

    if (!name) {
      alert('Guest Full Name is required.');
      document.getElementById('book-guest-name').focus();
      return;
    }
    if (!mobile || mobile.length < 10) {
      alert('A valid Mobile Number (minimum 10 digits) is required.');
      document.getElementById('book-guest-mobile').focus();
      return;
    }

    // Slide track to Step 2
    track.style.transform = 'translateX(-50%)';

    // Switch indicators
    ind1.classList.add('completed');
    ind1.classList.remove('active');
    indLine.classList.add('active');
    ind2.classList.add('active');
  } else {
    // Slide track to Step 1
    track.style.transform = 'translateX(0)';

    // Switch indicators
    ind1.classList.add('active');
    ind1.classList.remove('completed');
    indLine.classList.remove('active');
    ind2.classList.remove('active');
  }
}

async function handleGuestSearchAutocomplete() {
  const query = document.getElementById('book-guest-search-input').value.trim();
  const dropdown = document.getElementById('guest-search-dropdown');
  const resultText = document.getElementById('guest-lookup-result');

  if (query.length < 2) {
    dropdown.innerHTML = '';
    dropdown.classList.add('hidden');
    return;
  }

  try {
    const res = await fetch(`/api/guests?search=${encodeURIComponent(query)}`);
    const list = await res.json();

    dropdown.innerHTML = '';

    if (list.length === 0) {
      const emptyDiv = document.createElement('div');
      emptyDiv.className = 'autocomplete-item';
      emptyDiv.style.cursor = 'default';
      emptyDiv.innerHTML = `<span>No guest found. Start typing below to create a new one.</span>`;
      dropdown.appendChild(emptyDiv);
      dropdown.classList.remove('hidden');

      // Auto-populate mobile number field if search query looks like a phone number
      const isNum = /^\d+$/.test(query);
      if (isNum && query.length >= 10) {
        document.getElementById('book-guest-mobile').value = query;
      }
      return;
    }

    list.slice(0, 5).forEach(guest => {
      const item = document.createElement('div');
      item.className = 'autocomplete-item';
      const vipText = guest.is_vip ? ' <span class="vip-badge" style="font-size: 9px; padding: 2px 4px;">VIP</span>' : '';
      item.innerHTML = `
        <div>
          <strong>${guest.name}</strong>${vipText}<br>
          <small>${guest.mobile} | ${guest.doc_type || 'ID'}: ${guest.doc_number || 'N/A'}</small>
        </div>
        <span>${guest.loyalty_points || 0} pts</span>
      `;

      item.addEventListener('click', () => {
        selectBookingGuest(guest);
        dropdown.classList.add('hidden');
      });

      dropdown.appendChild(item);
    });

    dropdown.classList.remove('hidden');
  } catch (err) {
    console.error('Autocomplete search failed:', err);
  }
}

function selectBookingGuest(guest) {
  state.loadedGuestId = guest.id;
  document.getElementById('book-guest-search-input').value = `${guest.name} (${guest.mobile})`;
  
  document.getElementById('book-guest-name').value = guest.name;
  document.getElementById('book-guest-mobile').value = guest.mobile;
  document.getElementById('book-guest-email').value = guest.email || '';
  document.getElementById('book-guest-doctype').value = guest.doc_type || 'Aadhaar';
  document.getElementById('book-guest-docnum').value = guest.doc_number || '';
  document.getElementById('book-guest-address').value = guest.address || '';
  document.getElementById('book-guest-company').value = guest.company_name || '';
  document.getElementById('book-guest-gst').value = guest.gst_number || '';
  document.getElementById('book-guest-vehicle').value = guest.vehicle_number || '';
  document.getElementById('book-guest-vip').checked = guest.is_vip === 1;

  if (guest.photo) {
    state.guestPhotoBase64 = guest.photo;
    document.getElementById('photo-preview').src = guest.photo;
  }

  const resultText = document.getElementById('guest-lookup-result');
  resultText.textContent = `✅ Guest Loaded: ${guest.name} (${guest.loyalty_points || 0} Loyalty points)`;
  resultText.className = 'guest-lookup-text text-success';
}

function clearBookingGuestForm() {
  state.loadedGuestId = null;
  state.guestPhotoBase64 = null;
  document.getElementById('book-guest-search-input').value = '';
  document.getElementById('book-guest-name').value = '';
  document.getElementById('book-guest-mobile').value = '';
  document.getElementById('book-guest-email').value = '';
  document.getElementById('book-guest-doctype').value = 'Aadhaar';
  document.getElementById('book-guest-docnum').value = '';
  document.getElementById('book-guest-address').value = '';
  document.getElementById('book-guest-company').value = '';
  document.getElementById('book-guest-gst').value = '';
  document.getElementById('book-guest-vehicle').value = '';
  document.getElementById('book-guest-vip').checked = false;
  document.getElementById('photo-preview').src = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' fill='%23666'><circle cx='60' cy='45' r='25'/><path d='M20 100c0-20 20-30 40-30s40 10 40 30z'/></svg>";
  
  const resultText = document.getElementById('guest-lookup-result');
  resultText.textContent = 'No guest loaded. Complete fields below to register new guest.';
  resultText.className = 'guest-lookup-text';
}

// Webcam stream controls
async function startWebcam() {
  const video = document.getElementById('webcam-feed');
  const preview = document.getElementById('photo-preview');
  const btnStart = document.getElementById('btn-start-camera');
  const btnSnap = document.getElementById('btn-snap-photo');

  try {
    const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 320, height: 320 } });
    state.activeCameraStream = stream;
    video.srcObject = stream;
    video.classList.remove('hidden');
    preview.classList.add('hidden');
    btnStart.classList.add('hidden');
    btnSnap.classList.remove('hidden');
  } catch (err) {
    alert('Unable to access webcam. Check permissions.');
    console.error(err);
  }
}

function captureWebcamPhoto() {
  const video = document.getElementById('webcam-feed');
  const canvas = document.getElementById('photo-canvas');
  const preview = document.getElementById('photo-preview');
  const btnStart = document.getElementById('btn-start-camera');
  const btnSnap = document.getElementById('btn-snap-photo');

  const context = canvas.getContext('2d');
  canvas.width = 160;
  canvas.height = 160;
  context.drawImage(video, 0, 0, 160, 160);

  const dataUrl = canvas.toDataURL('image/jpeg');
  state.guestPhotoBase64 = dataUrl;
  
  // Update Preview UI
  preview.src = dataUrl;
  preview.classList.remove('hidden');
  
  // Stop webcam
  stopWebcam();
  
  video.classList.add('hidden');
  btnStart.classList.remove('hidden');
  btnSnap.classList.add('hidden');
}

function stopWebcam() {
  if (state.activeCameraStream) {
    state.activeCameraStream.getTracks().forEach(track => track.stop());
    state.activeCameraStream = null;
  }
}

// Calculate dynamic rates & GST live preview in modal
async function calculateBookingPrice() {
  const checkinVal = document.getElementById('book-checkin-date').value;
  const checkoutVal = document.getElementById('book-checkout-date').value;
  const pricingEl = document.getElementById('dynamic-pricing-info');
  
  if (!pricingEl) return;
  if (!checkinVal || !checkoutVal) return;

  const diffTime = Math.abs(new Date(checkoutVal) - new Date(checkinVal));
  const nights = Math.max(1, Math.ceil(diffTime / (1000 * 60 * 60 * 24)));

  // Collect checked rooms
  const checkedCheckboxes = document.querySelectorAll('input[name="booking-rooms"]:checked');
  if (checkedCheckboxes.length === 0) {
    pricingEl.innerHTML = `
      <div style="text-align: center; color: var(--text-muted); padding: 15px 0;">
        <strong style="display: block; margin-bottom: 6px; color: var(--text-muted);">No Rooms Allocated</strong>
        <span style="font-size: 12px;">Select one or more rooms from the grid to generate a live fare estimation.</span>
      </div>
    `;
    pricingEl.classList.remove('hidden');
    return;
  }

  let totalBase = 0;
  checkedCheckboxes.forEach(cb => {
    const basePrice = parseFloat(cb.getAttribute('data-price'));
    totalBase += basePrice * nights;
  });

  // Fetch settings to get dynamic GST rates
  let gstRate = 5;
  try {
    const setRes = await fetch('/api/settings');
    const settings = await setRes.json();
    gstRate = parseFloat(settings.gst_rate) || 5;
  } catch (e) {}

  const gstAmount = Math.round(totalBase * (gstRate / 100));
  const totalAmount = totalBase + gstAmount;

  pricingEl.innerHTML = `
    <div style="display: flex; flex-direction: column; gap: 8px;">
      <strong style="color: var(--color-primary); font-size: 14px; border-bottom: 1px solid rgba(255,255,255,0.05); padding-bottom: 6px; margin-bottom: 4px; display: block;">
        Fare Summary (${nights} Night${nights > 1 ? 's' : ''})
      </strong>
      <div style="display: flex; justify-content: space-between;">
        <span>Room Charge:</span>
        <strong>₹${totalBase.toLocaleString()}</strong>
      </div>
      <div style="display: flex; justify-content: space-between;">
        <span>GST (${gstRate}%):</span>
        <strong>₹${gstAmount.toLocaleString()}</strong>
      </div>
      <div style="display: flex; justify-content: space-between; font-size: 16px; margin-top: 6px; border-top: 1px dashed rgba(255,255,255,0.1); padding-top: 8px; color: #fff;">
        <span>Grand Total:</span>
        <strong>₹${totalAmount.toLocaleString()}</strong>
      </div>
    </div>
  `;
  pricingEl.classList.remove('hidden');
}

async function handleBookingSubmit(e) {
  e.preventDefault();
  
  const roomCheckboxes = document.querySelectorAll('input[name="booking-rooms"]:checked');
  if (roomCheckboxes.length === 0) {
    return alert('Please allocate at least one room.');
  }

  const roomIds = Array.from(roomCheckboxes).map(cb => parseInt(cb.value, 10));
  const prices = {};
  roomCheckboxes.forEach(cb => {
    prices[cb.value] = parseFloat(cb.getAttribute('data-price'));
  });

  // Construct Guest profile first
  const guestData = {
    id: state.loadedGuestId || undefined,
    name: document.getElementById('book-guest-name').value,
    mobile: document.getElementById('book-guest-mobile').value,
    email: document.getElementById('book-guest-email').value || null,
    doc_type: document.getElementById('book-guest-doctype').value,
    doc_number: document.getElementById('book-guest-docnum').value || null,
    address: document.getElementById('book-guest-address').value || null,
    company_name: document.getElementById('book-guest-company').value || null,
    gst_number: document.getElementById('book-guest-gst').value || null,
    vehicle_number: document.getElementById('book-guest-vehicle').value || null,
    is_vip: document.getElementById('book-guest-vip').checked ? 1 : 0,
    photo: state.guestPhotoBase64,
    userId: state.currentUser.id
  };

  showLoader(true, 'Registering guest & allocating rooms...');
  
  try {
    // 1. Save guest profile
    const guestRes = await fetch('/api/guests', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(guestData)
    });
    
    if (!guestRes.ok) {
      throw new Error('Guest registration failed');
    }
    
    const savedGuest = await guestRes.json();

    // 2. Submit Booking
    const bookingData = {
      guestId: savedGuest.id,
      roomIds,
      checkIn: document.getElementById('book-checkin-date').value,
      checkOut: document.getElementById('book-checkout-date').value,
      status: document.getElementById('book-status-select').value,
      paidAmount: 0,
      prices,
      userId: state.currentUser.id
    };

    const bookingRes = await fetch('/api/bookings/new', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(bookingData)
    });

    showLoader(false);
    if (bookingRes.ok) {
      closeAllModals();
      alert('Booking saved successfully!');
      navigateTo(state.activeView); // Refresh current view
    } else {
      const err = await bookingRes.json();
      alert(`Booking failed: ${err.error}`);
    }
  } catch (err) {
    showLoader(false);
    alert(`Error: ${err.message}`);
  }
}

// ================= GUEST PROFILE & DETAILS POPUP ================= //

async function viewOccupiedBookingDetails(roomId) {
  try {
    const res = await fetch('/api/bookings');
    const bookings = await res.json();
    // Find active checked-in booking for this room
    const booking = bookings.find(b => {
      const rooms = b.room_ids ? b.room_ids.split(',').map(Number) : [];
      return rooms.includes(roomId) && b.status === 'Checked-In';
    });

    if (booking) {
      viewBookingDetailsModal(booking);
    } else {
      alert('No active booking details found for this room.');
    }
  } catch (err) {
    alert('Error loading booking data.');
  }
}

async function viewBookingDetailsModal(booking) {
  // Queries full guest profile
  try {
    const res = await fetch(`/api/guests?search=${booking.guest_mobile}`);
    const guests = await res.json();
    const guest = guests[0];
    
    if (!guest) return alert('Guest profile not found');

    openModal('modal-guest-profile');
    
    // Set Profile UI
    document.getElementById('profile-modal-name').textContent = guest.name;
    document.getElementById('profile-modal-mobile').textContent = guest.mobile;
    document.getElementById('profile-modal-email').textContent = guest.email || 'N/A';
    document.getElementById('profile-modal-doc').textContent = `${guest.doc_type || 'N/A'}: ${guest.doc_number || ''}`;
    document.getElementById('profile-modal-address').textContent = guest.address || 'N/A';
    document.getElementById('profile-modal-company').textContent = `${guest.company_name || 'N/A'} (GSTIN: ${guest.gst_number || 'N/A'})`;
    document.getElementById('profile-modal-vehicle').textContent = guest.vehicle_number || 'N/A';
    document.getElementById('profile-modal-points').textContent = guest.loyalty_points;

    // Badges
    const vip = document.getElementById('profile-modal-vip-badge');
    const bl = document.getElementById('profile-modal-blacklist-badge');
    const blReason = document.getElementById('profile-modal-blacklist-reason');

    if (guest.is_vip) vip.classList.remove('hidden');
    else vip.classList.add('hidden');

    if (guest.is_blacklisted) {
      bl.classList.remove('hidden');
      blReason.textContent = `Reason: ${guest.blacklist_reason}`;
      blReason.classList.remove('hidden');
    } else {
      bl.classList.add('hidden');
      blReason.classList.add('hidden');
    }

    if (guest.photo) {
      document.getElementById('profile-modal-photo').src = guest.photo;
    } else {
      document.getElementById('profile-modal-photo').src = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' fill='%23666'><circle cx='60' cy='45' r='25'/><path d='M20 100c0-20 20-30 40-30s40 10 40 30z'/></svg>";
    }

    // Load Stay history for this guest
    loadGuestStayHistory(guest.id);
  } catch (err) {
    console.error(err);
  }
}

async function loadGuestStayHistory(guestId) {
  const tbody = document.getElementById('guest-history-table-body');
  tbody.innerHTML = '<tr><td colspan="7">Loading history...</td></tr>';
  
  try {
    const res = await fetch('/api/bookings');
    const all = await res.json();
    const guestHistory = all.filter(b => b.guest_id === guestId);

    tbody.innerHTML = '';
    if (guestHistory.length === 0) {
      tbody.innerHTML = '<tr><td colspan="8" style="text-align:center;">No previous stays logged.</td></tr>';
      return;
    }

    guestHistory.forEach(h => {
      const tr = document.createElement('tr');
      
      let cancelBtnHTML = '<span style="color:#64748b; font-size:11px;">-</span>';
      if (h.status === 'Confirmed' || h.status === 'Checked-In') {
        cancelBtnHTML = `<button class="btn btn-danger btn-xs" onclick="cancelGuestBooking(${h.id}, '${h.booking_uid}')" style="padding: 2px 6px; font-size: 10px; border-radius: 4px;">Cancel</button>`;
      }

      tr.innerHTML = `
        <td>${h.booking_uid}</td>
        <td>${h.room_numbers || 'N/A'}</td>
        <td>${h.check_in} to ${h.check_out}</td>
        <td>₹${h.total_amount.toLocaleString()}</td>
        <td>₹${h.paid_amount.toLocaleString()}</td>
        <td><span class="room-card-status" style="padding: 2px 6px; font-size:10px; font-weight:600;">${h.status}</span></td>
        <td>${h.invoice_number || 'N/A'}</td>
        <td style="text-align: right;">${cancelBtnHTML}</td>
      `;
      tbody.appendChild(tr);
    });
    // Trigger timeline loader
    loadGuestTimeline(guestId);
  } catch (e) {
    tbody.innerHTML = '<tr><td colspan="8" style="color:var(--color-maintenance);">Failed loading history.</td></tr>';
  }
}

async function loadGuestTimeline(guestId) {
  const container = document.getElementById('profile-modal-timeline');
  if (!container) return;
  container.innerHTML = '<div style="text-align: center; color: #888;">Loading timeline...</div>';

  try {
    const waRes = await fetch(`/api/whatsapp/chat-history?guestId=${guestId}`);
    const waLogs = waRes.ok ? await waRes.json() : [];

    const emailRes = await fetch(`/api/email/logs?guestId=${guestId}`);
    const emailLogs = emailRes.ok ? await emailRes.json() : [];

    const timeline = [];
    
    waLogs.forEach(m => {
      const isOut = m.direction === 'outgoing';
      timeline.push({
        type: 'whatsapp',
        title: isOut ? `Outgoing WhatsApp (by ${m.sender_type})` : 'Incoming WhatsApp',
        body: m.body,
        time: m.timestamp,
        icon: '💬'
      });
    });

    emailLogs.forEach(e => {
      timeline.push({
        type: 'email',
        title: `Sent Email to ${e.recipient_email}`,
        body: `Subject: ${e.subject}<br>Attachment: ${e.attachment_name || 'None'}`,
        time: e.timestamp,
        icon: '✉️'
      });
    });

    timeline.sort((a, b) => new Date(b.time) - new Date(a.time));

    container.innerHTML = '';
    if (timeline.length === 0) {
      container.innerHTML = '<div style="text-align: center; color: #888; padding: 10px;">No communication timeline logged.</div>';
      return;
    }

    timeline.forEach(item => {
      const div = document.createElement('div');
      div.style.cssText = `
        padding: 8px 12px;
        border-radius: 6px;
        background: rgba(255,255,255,0.03);
        border-left: 3px solid ${item.type === 'whatsapp' ? '#00a884' : '#6366f1'};
      `;
      div.innerHTML = `
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px;">
          <strong style="color: ${item.type === 'whatsapp' ? '#00a884' : '#818cf8'};">${item.icon} ${item.title}</strong>
          <span style="font-size: 9px; color: #888;">${new Date(item.time).toLocaleString([], { dateStyle: 'short', timeStyle: 'short' })}</span>
        </div>
        <div style="opacity: 0.85; white-space: pre-wrap; font-family: sans-serif; font-size: 11.5px;">${item.body}</div>
      `;
      container.appendChild(div);
    });
  } catch (err) {
    container.innerHTML = '<div style="text-align: center; color: var(--color-maintenance);">Failed to load timeline.</div>';
  }
}

async function cancelGuestBooking(bookingId, uid) {
  if (!confirm(`Are you sure you want to cancel booking ${uid}?`)) return;
  showLoader(true, 'Cancelling reservation...');
  try {
    const res = await fetch('/api/bookings/cancel', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ bookingId, userId: state.currentUser ? state.currentUser.id : 1 })
    });
    showLoader(false);
    if (res.ok) {
      alert(`Booking ${uid} successfully cancelled.`);
      closeAllModals();
      loadDashboardGrid();
      loadCalendarView();
    } else {
      const err = await res.json();
      alert(`Cancellation failed: ${err.error || 'Unknown error'}`);
    }
  } catch (e) {
    showLoader(false);
    alert('Connection error');
  }
}

// Room Transfer Action
async function triggerRoomTransferPrompt(oldRoomId) {
  // Let's get list of vacant rooms
  try {
    const res = await fetch('/api/rooms');
    const rooms = await res.json();
    const vacantRooms = rooms.filter(r => r.status === 'Vacant');
    
    if (vacantRooms.length === 0) {
      return alert('No vacant rooms available for transfer.');
    }

    let options = vacantRooms.map(r => `Room ${r.room_number} (${r.type})`).join('\n');
    const selectedRoomNum = prompt(`Enter room number to transfer to:\n\nVacant Rooms:\n${options}`);
    if (!selectedRoomNum) return;

    const targetRoom = vacantRooms.find(r => r.room_number === selectedRoomNum.trim());
    if (!targetRoom) {
      return alert('Invalid room selected or room is not vacant.');
    }

    // Find active booking for oldRoom
    const resBookings = await fetch('/api/bookings');
    const bookings = await resBookings.json();
    const activeBooking = bookings.find(b => {
      const roomIds = b.room_ids ? b.room_ids.split(',').map(Number) : [];
      return roomIds.includes(oldRoomId) && b.status === 'Checked-In';
    });

    if (!activeBooking) return alert('No active occupied booking found for transfer');

    showLoader(true, 'Processing room transfer...');
    const transferRes = await fetch('/api/bookings/transfer', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        bookingId: activeBooking.id,
        oldRoomId,
        newRoomId: targetRoom.id,
        userId: state.currentUser.id
      })
    });
    
    showLoader(false);
    if (transferRes.ok) {
      alert('Room transferred successfully.');
      loadDashboardView();
    } else {
      alert('Transfer failed');
    }
  } catch (e) {
    showLoader(false);
    alert('Network error');
  }
}

// Blacklist logic
function openBlacklistPrompt(guestId, name) {
  openModal('modal-blacklist-guest');
  document.getElementById('blacklist-guest-id').value = guestId;
  document.getElementById('blacklist-guest-name-text').textContent = name;
  document.getElementById('blacklist-reason-input').value = '';
}

document.getElementById('blacklist-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const guestId = parseInt(document.getElementById('blacklist-guest-id').value, 10);
  const reason = document.getElementById('blacklist-reason-input').value;

  showLoader(true, 'Blacklisting guest...');
  try {
    // Fetch guest details
    const resGuest = await fetch('/api/guests');
    const guests = await resGuest.json();
    const guest = guests.find(g => g.id === guestId);

    if (!guest) throw new Error('Guest not found');

    guest.is_blacklisted = 1;
    guest.blacklist_reason = reason;
    guest.userId = state.currentUser.id;

    const saveRes = await fetch('/api/guests', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(guest)
    });

    showLoader(false);
    if (saveRes.ok) {
      closeAllModals();
      loadGuestsList();
      alert('Guest has been blacklisted.');
    } else {
      alert('Blacklist failed');
    }
  } catch (err) {
    showLoader(false);
    alert(err.message);
  }
});

// ================= VIEW: GUEST CRM DIRECTORY ================= //

async function loadGuestsList() {
  const queryVal = document.getElementById('guest-search-input').value.trim();
  const tbody = document.getElementById('guests-table-body');
  tbody.innerHTML = '<tr><td colspan="9">Searching guests catalog...</td></tr>';

  try {
    const res = await fetch(`/api/guests?search=${queryVal}`);
    const list = await res.json();
    state.guestsList = list; // Save to global state
    
    tbody.innerHTML = '';
    if (list.length === 0) {
      tbody.innerHTML = '<tr><td colspan="9" style="text-align:center;">No guest records found.</td></tr>';
      return;
    }

    list.forEach(g => {
      const tr = document.createElement('tr');
      
      const photoSrc = g.photo || "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='44' height='44' fill='%23666'><circle cx='22' cy='16' r='10'/><path d='M8 38c0-10 10-15 14-15s14 5 14 15z'/></svg>";
      
      let badgeHtml = '';
      if (g.is_vip) badgeHtml += '<span class="vip-badge" style="margin-right:4px;">VIP</span>';
      if (g.is_blacklisted) badgeHtml += '<span class="blacklist-badge">Blacklisted</span>';
      if (!badgeHtml) badgeHtml = '<span style="color:#888; font-size:11px;">Standard</span>';

      tr.innerHTML = `
        <td><img src="${photoSrc}" class="guest-thumb"></td>
        <td><strong>${g.name}</strong></td>
        <td>${g.mobile}</td>
        <td><small style="display:block; font-weight:600;">${g.doc_type || 'N/A'}</small><small style="color:#888;">${g.doc_number || ''}</small></td>
        <td><small style="display:block; font-weight:600;">${g.company_name || 'N/A'}</small><small style="color:#888;">${g.gst_number || ''}</small></td>
        <td>${g.vehicle_number || 'N/A'}</td>
        <td><strong>${g.loyalty_points}</strong> pts</td>
        <td>${badgeHtml}</td>
        <td>
          <div style="display: flex; gap: 4px; flex-wrap: wrap;">
            <button class="btn btn-secondary btn-sm" onclick="viewHistory(${g.id})">Profile</button>
            <button class="btn btn-secondary btn-sm" onclick="editGuestDetails(${g.id})">Edit</button>
            <button class="btn btn-primary btn-sm" onclick="openCustomWAModal('${g.name.replace(/'/g, "\\'")}', '${g.mobile}')">WhatsApp</button>
            ${g.is_blacklisted ? '' : `<button class="btn btn-danger btn-sm" onclick="blacklistGuestPrompt(${g.id}, '${g.name.replace(/'/g, "\\'")}')">Blacklist</button>`}
            <button class="btn btn-danger btn-sm" onclick="deleteGuestProfile(${g.id})">Delete</button>
          </div>
        </td>
      `;
      tbody.appendChild(tr);
    });
  } catch (err) {
    tbody.innerHTML = '<tr><td colspan="9" style="color:var(--color-maintenance);">Failed loading guest data.</td></tr>';
  }
}

window.viewHistory = async (guestId) => {
  try {
    const res = await fetch('/api/guests');
    const all = await res.json();
    const guest = all.find(g => g.id === guestId);
    if (!guest) return;
    
    // Simulate booking object
    viewBookingDetailsModal({ guest_mobile: guest.mobile });
  } catch (e) {}
};

window.blacklistGuestPrompt = (guestId, name) => {
  openBlacklistPrompt(guestId, name);
};

function editGuestDetails(guestId) {
  const guest = state.guestsList.find(g => g.id === guestId);
  if (!guest) return;

  openModal('modal-edit-guest');
  
  document.getElementById('edit-guest-id').value = guest.id;
  document.getElementById('edit-guest-name').value = guest.name;
  document.getElementById('edit-guest-mobile').value = guest.mobile;
  document.getElementById('edit-guest-email').value = guest.email || '';
  document.getElementById('edit-guest-doctype').value = guest.doc_type || 'Aadhaar';
  document.getElementById('edit-guest-docnum').value = guest.doc_number || '';
  document.getElementById('edit-guest-address').value = guest.address || '';
  document.getElementById('edit-guest-company').value = guest.company_name || '';
  document.getElementById('edit-guest-gst').value = guest.gst_number || '';
  document.getElementById('edit-guest-vehicle').value = guest.vehicle_number || '';
  document.getElementById('edit-guest-loyalty').value = guest.loyalty_points || 0;
  document.getElementById('edit-guest-vip').checked = guest.is_vip === 1;
}

async function handleEditGuestFormSubmit(e) {
  e.preventDefault();
  
  const id = parseInt(document.getElementById('edit-guest-id').value, 10);
  const name = document.getElementById('edit-guest-name').value.trim();
  const mobile = document.getElementById('edit-guest-mobile').value.trim();
  const email = document.getElementById('edit-guest-email').value.trim();
  const doc_type = document.getElementById('edit-guest-doctype').value;
  const doc_number = document.getElementById('edit-guest-docnum').value.trim();
  const address = document.getElementById('edit-guest-address').value.trim();
  const company_name = document.getElementById('edit-guest-company').value.trim();
  const gst_number = document.getElementById('edit-guest-gst').value.trim();
  const vehicle_number = document.getElementById('edit-guest-vehicle').value.trim();
  const loyalty_points = parseInt(document.getElementById('edit-guest-loyalty').value, 10) || 0;
  const is_vip = document.getElementById('edit-guest-vip').checked;

  showLoader(true, 'Saving guest changes...');
  try {
    const res = await fetch('/api/guests', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        id,
        name,
        mobile,
        email,
        doc_type,
        doc_number,
        address,
        company_name,
        gst_number,
        vehicle_number,
        loyalty_points,
        is_vip,
        userId: state.currentUser.id
      })
    });
    
    showLoader(false);
    if (res.ok) {
      alert('Guest profile updated successfully.');
      closeAllModals();
      loadGuestsList();
    } else {
      const err = await res.json();
      alert(err.error || 'Failed to save guest changes.');
    }
  } catch (err) {
    showLoader(false);
    alert('Connection error.');
  }
}

window.editGuestDetails = editGuestDetails;

async function sendWhatsAppTestMessage() {
  const phone = document.getElementById('wa-test-phone').value.trim();
  if (!phone) {
    return alert('Please enter a recipient phone number with country code (e.g. +919999999999).');
  }

  const metaToken = document.getElementById('set-meta-token').value.trim();
  const metaPhoneId = document.getElementById('set-meta-phone-id').value.trim();

  showLoader(true, 'Sending test WhatsApp message...');
  try {
    const res = await fetch('/api/whatsapp/test', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        provider: 'WhatsAppCloudAPI',
        metaToken,
        metaPhoneId,
        phone,
        message: 'Hello! This is a test message from your hotel management platform to confirm active API connectivity.'
      })
    });

    showLoader(false);
    const result = await res.json();
    if (res.ok) {
      alert(`Success! Test message sent.\nStatus: ${result.statusCode}\nDetails: ${result.message || 'Dispatched via API'}`);
    } else {
      alert(`Connection Failed!\n\nDetails: ${result.error || 'Check credentials'}`);
    }
  } catch (err) {
    showLoader(false);
    alert(`Network Error: ${err.message}`);
  }
}

// ================= VIEW: BILLING & CHECKOUT DESK ================= //

let activeBillingBooking = null;

async function loadBillingView() {
  const select = document.getElementById('checkout-room-select');
  select.innerHTML = '<option value="">Select occupied room...</option>';
  document.getElementById('checkout-details-panel').classList.add('hidden');
  document.getElementById('invoice-preview-area').innerHTML = '<div class="no-invoice-notice">Select an occupied room to generate and preview invoices.</div>';
  document.getElementById('invoice-actions-bar').classList.add('hidden');
  
  // Clear reprint select
  document.getElementById('reprint-invoice-select').value = '';

  try {
    const res = await fetch('/api/rooms');
    const rooms = await res.json();
    
    rooms.forEach(r => {
      if (r.status === 'Occupied') {
        const opt = document.createElement('option');
        opt.value = r.id;
        opt.textContent = `Room ${r.room_number} (${r.type})`;
        select.appendChild(opt);
      }
    });
  } catch (err) {}

  // Fetch completed checkouts list
  loadPreviousCheckoutsList();
}

async function loadPreviousCheckoutsList() {
  const select = document.getElementById('reprint-invoice-select');
  select.innerHTML = '<option value="">Select previous checkout...</option>';
  try {
    const res = await fetch('/api/bookings?status=Checked-Out');
    const bookings = await res.json();
    
    bookings.forEach(b => {
      const opt = document.createElement('option');
      opt.value = b.id;
      opt.textContent = `${b.invoice_number || 'INV'} - Room ${b.room_numbers} (${b.guest_name})`;
      opt.setAttribute('data-booking', JSON.stringify(b));
      select.appendChild(opt);
    });
  } catch (e) {
    console.error('Failed to load completed checkouts:', e);
  }
}

async function loadReprintInvoiceDetails() {
  const select = document.getElementById('reprint-invoice-select');
  const opt = select.options[select.selectedIndex];
  
  if (!select.value) {
    document.getElementById('invoice-preview-area').innerHTML = '<div class="no-invoice-notice">Select an occupied room to generate and preview invoices.</div>';
    document.getElementById('invoice-actions-bar').classList.add('hidden');
    return;
  }

  // Clear active checkout selection to prevent conflicting states
  document.getElementById('checkout-room-select').value = '';
  document.getElementById('checkout-details-panel').classList.add('hidden');

  const booking = JSON.parse(opt.getAttribute('data-booking'));
  activeBillingBooking = booking;

  // Calculate prices based on stored total amount
  const totalAmount = booking.total_amount;
  let gstRate = 5;
  try {
    gstRate = parseFloat(state.settings.gst_rate) || 5;
  } catch (e) {}

  const basePrice = Math.round(totalAmount / (1 + (gstRate / 100)));
  const gstAmount = totalAmount - basePrice;

  // Calculate nights
  const diffTime = Math.abs(new Date(booking.check_out) - new Date(booking.check_in));
  const nights = Math.max(1, Math.ceil(diffTime / (1000 * 60 * 60 * 24)));

  const isLocal = true; // Default to local CGST/SGST splits for printing display

  renderInvoicePreview(booking, basePrice, gstAmount, totalAmount, isLocal, nights);
  document.getElementById('invoice-actions-bar').classList.remove('hidden');
}

async function loadCheckoutRoomDetails() {
  const roomId = parseInt(document.getElementById('checkout-room-select').value, 10);
  if (!roomId) {
    document.getElementById('checkout-details-panel').classList.add('hidden');
    return;
  }

  showLoader(true, 'Calculating billing rates...');
  try {
    // Find active booking for room
    const res = await fetch('/api/bookings');
    const bookings = await res.json();
    const booking = bookings.find(b => {
      const rooms = b.room_ids ? b.room_ids.split(',').map(Number) : [];
      return rooms.includes(roomId) && b.status === 'Checked-In';
    });

    showLoader(false);
    if (!booking) {
      alert('Unable to find active checked-in booking for this room.');
      return;
    }

    activeBillingBooking = booking;

    // Load details
    document.getElementById('bill-guest-name').textContent = booking.guest_name;
    document.getElementById('bill-guest-mobile').textContent = booking.guest_mobile;
    document.getElementById('bill-check-in').textContent = booking.check_in;
    document.getElementById('bill-check-out').textContent = booking.check_out;
    
    // Calculate nights
    const diffTime = Math.abs(new Date(booking.check_out) - new Date(booking.check_in));
    const nights = Math.max(1, Math.ceil(diffTime / (1000 * 60 * 60 * 24)));
    document.getElementById('bill-nights').textContent = nights;

    // Set prices
    document.getElementById('bill-room-rate').textContent = '₹' + (booking.total_amount / nights).toLocaleString() + ' / night (approx)';

    updateCheckoutSummaryRates();
    document.getElementById('checkout-details-panel').classList.remove('hidden');
  } catch (e) {
    showLoader(false);
    alert('Billing calculations failed');
  }
}

function updateCheckoutSummaryRates() {
  if (!activeBillingBooking) return;
  const booking = activeBillingBooking;

  const totalAmount = booking.total_amount;
  // Calculate base from total and GST rate
  let gstRate = 5;
  try {
    gstRate = parseFloat(state.settings.gst_rate) || 5;
  } catch (e) {}

  const basePrice = Math.round(totalAmount / (1 + (gstRate / 100)));
  const gstAmount = totalAmount - basePrice;

  document.getElementById('bill-base-amt').textContent = '₹' + basePrice.toLocaleString();
  
  // Split GST UI
  const isLocal = document.querySelector('input[name="gst-region"]:checked').value === 'local';
  
  const cgstEl = document.getElementById('cgst-row');
  const sgstEl = document.getElementById('sgst-row');
  const igstEl = document.getElementById('igst-row');

  if (isLocal) {
    cgstEl.classList.remove('hidden');
    sgstEl.classList.remove('hidden');
    igstEl.classList.add('hidden');

    document.getElementById('bill-cgst').textContent = '₹' + Math.round(gstAmount / 2).toLocaleString();
    document.getElementById('bill-sgst').textContent = '₹' + Math.round(gstAmount / 2).toLocaleString();
  } else {
    cgstEl.classList.add('hidden');
    sgstEl.classList.add('hidden');
    igstEl.classList.remove('hidden');

    document.getElementById('bill-igst').textContent = '₹' + gstAmount.toLocaleString();
  }

  document.getElementById('bill-total-amt').textContent = '₹' + totalAmount.toLocaleString();
  document.getElementById('bill-paid-amt').value = totalAmount;

  // Calculate nights
  const diffTime = Math.abs(new Date(booking.check_out) - new Date(booking.check_in));
  const nights = Math.max(1, Math.ceil(diffTime / (1000 * 60 * 60 * 24)));
  // Render Invoice Preview
  renderInvoicePreview(booking, basePrice, gstAmount, totalAmount, isLocal, nights);
}

function renderInvoicePreview(booking, basePrice, gstAmount, totalAmount, isLocal, nights) {
  const area = document.getElementById('invoice-preview-area');
  const invoiceNum = 'INV-' + new Date().getFullYear() + '-' + (1000 + booking.id);
  
  const hotelName = state.settings.hotel_name || 'Shaima Hotel Management';
  const address = state.settings.hotel_address || '123 Beach Road, Chennai';
  const gstin = state.settings.hotel_gstin || 'GSTIN123456';
  const upiId = state.settings.upi_id || 'shaimahotel@upi';

  // Construct Invoice details
  let taxDetailsHtml = '';
  if (isLocal) {
    taxDetailsHtml = `
      <tr><td>CGST (2.5%)</td><td style="text-align:right;">₹${Math.round(gstAmount / 2).toLocaleString()}</td></tr>
      <tr><td>SGST (2.5%)</td><td style="text-align:right;">₹${Math.round(gstAmount / 2).toLocaleString()}</td></tr>
    `;
  } else {
    taxDetailsHtml = `
      <tr><td>IGST (5.0%)</td><td style="text-align:right;">₹${gstAmount.toLocaleString()}</td></tr>
    `;
  }

  area.innerHTML = `
    <div style="font-family: monospace; border: 1px solid #ddd; padding: 20px; color:#000; background:#fff;">
      <div style="text-align:center; margin-bottom: 20px;">
        <h2 style="margin: 0; font-size:18px;">${hotelName}</h2>
        <p style="margin: 4px 0; font-size:10px; color:#555;">${address}</p>
        <p style="margin: 2px 0; font-size:10px;">GSTIN: <strong>${gstin}</strong></p>
      </div>

      <div style="display:flex; justify-content:space-between; margin-bottom: 15px; font-size:10px; border-bottom:1px solid #eee; padding-bottom:10px;">
        <div>
          <p><strong>Billed To:</strong></p>
          <p>${booking.guest_name}</p>
          <p>Phone: ${booking.guest_mobile}</p>
          ${booking.company_name ? `<p>Corp: ${booking.company_name} (GSTIN: ${booking.gst_number || ''})</p>` : ''}
        </div>
        <div style="text-align:right;">
          <p><strong>Invoice Details:</strong></p>
          <p>Invoice No: ${invoiceNum}</p>
          <p>Date: ${new Date().toLocaleDateString()}</p>
          <p>Booking ID: ${booking.booking_uid}</p>
        </div>
      </div>

      <table style="width:100%; border-collapse:collapse; margin-bottom: 15px; font-size:10px;">
        <thead>
          <tr style="border-bottom: 1.5px solid #000; font-weight:bold; background:#f5f5f5;">
            <th style="text-align:left; padding: 6px;">Description</th>
            <th style="text-align:right; padding: 6px;">Nights</th>
            <th style="text-align:right; padding: 6px;">Amount</th>
          </tr>
        </thead>
        <tbody>
          <tr style="border-bottom: 1px solid #eee;">
            <td style="padding: 6px;">Accommodation (Room ${booking.room_numbers})</td>
            <td style="text-align:right; padding: 6px;">${nights}</td>
            <td style="text-align:right; padding: 6px;">₹${basePrice.toLocaleString()}</td>
          </tr>
          <tr>
            <td colspan="2" style="padding: 4px 6px; text-align:right; color:#666;">Subtotal:</td>
            <td style="padding: 4px 6px; text-align:right;">₹${basePrice.toLocaleString()}</td>
          </tr>
          ${taxDetailsHtml}
          <tr style="border-top:1.5px solid #000; font-weight:bold; font-size:12px;">
            <td colspan="2" style="padding: 6px; text-align:right;">Grand Total:</td>
            <td style="text-align:right; padding: 6px;">₹${totalAmount.toLocaleString()}</td>
          </tr>
        </tbody>
      </table>

      <div style="display:flex; justify-content:space-between; align-items:center; border-top:1px solid #eee; padding-top:15px; font-size:9px;">
        <div>
          <p><strong>Terms:</strong></p>
          <p>Thank you for staying with us!</p>
          <p>Computer Generated Invoice - No signature required.</p>
        </div>
        <div style="text-align:center;">
          <p style="font-weight:bold; margin-bottom: 4px;">Scan to Pay UPI</p>
          <div id="invoice-upi-qrcode" style="display:inline-block; padding:5px; background:#fff; border:1px solid #ddd;"></div>
          <p style="margin-top:2px; font-size:8px;">${upiId}</p>
        </div>
      </div>
    </div>
  `;

  // Draw UPI QR Code inside container
  const upiLink = `upi://pay?pa=${upiId}&pn=${encodeURIComponent(hotelName)}&am=${totalAmount}&cu=INR&tn=${invoiceNum}`;
  setTimeout(() => {
    const qrDiv = document.getElementById('invoice-upi-qrcode');
    if (qrDiv) {
      qrDiv.innerHTML = '';
      new QRCode(qrDiv, {
        text: upiLink,
        width: 80,
        height: 80,
        correctLevel: QRCode.CorrectLevel.M
      });
    }
  }, 100);

  document.getElementById('invoice-actions-bar').classList.remove('hidden');
}

async function submitCheckoutPayment() {
  if (!activeBillingBooking) return;
  
  const paidAmount = parseFloat(document.getElementById('bill-paid-amt').value);
  if (isNaN(paidAmount)) return alert('Enter a valid amount paid.');

  const isLocal = document.querySelector('input[name="gst-region"]:checked').value === 'local';

  showLoader(true, 'Processing Checkout & Settle Invoices...');
  try {
    const res = await fetch('/api/bookings/checkout', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        bookingId: activeBillingBooking.id,
        paidAmount,
        isLocalGST: isLocal ? 1 : 0,
        userId: state.currentUser.id
      })
    });

    showLoader(false);
    if (res.ok) {
      alert('Checkout completed. Room status updated to Dirty.');
      loadBillingView();
    } else {
      alert('Checkout transaction failed.');
    }
  } catch (e) {
    showLoader(false);
    alert('Server communication error.');
  }
}

async function triggerWhatsAppInvoiceMock() {
  if (!activeBillingBooking) return;
  
  const targetPhone = prompt('Confirm target WhatsApp phone number:', activeBillingBooking.guest_mobile || '+91');
  if (!targetPhone) return;
  
  showLoader(true, 'Generating & Sharing PDF Invoice via WhatsApp...');
  try {
    const res = await fetch('/api/whatsapp/share-invoice', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        bookingId: activeBillingBooking.id,
        phone: targetPhone,
        userId: state.currentUser.id
      })
    });
    showLoader(false);
    if (res.ok) {
      alert('Invoice PDF successfully generated and shared via WhatsApp!');
      pollWhatsAppLogsCount();
    } else {
      const err = await res.json();
      alert(`WhatsApp share failed: ${err.error || 'Unknown error'}`);
    }
  } catch (e) {
    showLoader(false);
    alert('Connection error.');
  }
}

// ================= VIEW: HOUSEKEEPING & STOCK ================= //

async function loadHousekeepingView() {
  // Load tasks
  loadHousekeepingTasks();
  // Load stocks
  loadInventoryStock();
  // Load LostFound
  loadLostFoundLogs();
}

async function loadHousekeepingTasks() {
  const tbody = document.getElementById('hk-tasks-table-body');
  tbody.innerHTML = '<tr><td colspan="7">Loading tasks...</td></tr>';

  try {
    const res = await fetch('/api/housekeeping');
    const tasks = await res.json();
    
    // Fetch housekeepers for assign dropdown
    const resStaff = await fetch('/api/staff');
    const staff = await resStaff.json();
    const housekeepers = staff.filter(s => s.role === 'Housekeeping');

    tbody.innerHTML = '';
    if (tasks.length === 0) {
      tbody.innerHTML = '<tr><td colspan="7" style="text-align:center;">No housekeeping logs logged.</td></tr>';
      return;
    }

    tasks.forEach(t => {
      const tr = document.createElement('tr');
      
      // Assign staff select dropdown
      let staffSelect = '';
      if (t.status === 'Pending') {
        staffSelect = `
          <select class="form-control" style="width:150px; font-size:12px; padding:4px;" onchange="assignHKStaff(${t.id}, this.value)">
            <option value="">Assign staff...</option>
            ${housekeepers.map(h => `<option value="${h.id}">${h.name}</option>`).join('')}
          </select>
        `;
      } else {
        staffSelect = `<strong>${t.staff_name || 'Unassigned'}</strong>`;
      }

      // Actions buttons
      let actionButtons = '';
      if (t.status === 'Pending') {
        actionButtons = '<span style="color:#888; font-size:12px;">Waiting assign</span>';
      } else if (t.status === 'Cleaning') {
        actionButtons = `
          <button class="btn btn-primary btn-sm" onclick="updateHKStatus(${t.id}, 'Cleaned')">Mark Clean</button>
          <button class="btn btn-danger btn-sm" onclick="updateHKStatus(${t.id}, 'Maintenance')">Needs Maint.</button>
        `;
      } else {
        actionButtons = `<span style="color:#888; font-size:12px;">Task ${t.status}</span>`;
      }

      tr.innerHTML = `
        <td>Room ${t.room_number}</td>
        <td>${t.notes || 'N/A'}</td>
        <td><span class="room-card-status" style="font-size:11px; padding:2px 6px;">${t.room_status}</span></td>
        <td>${t.date}</td>
        <td>${staffSelect}</td>
        <td><strong>${t.status}</strong></td>
        <td>${actionButtons}</td>
      `;
      tbody.appendChild(tr);
    });
  } catch (e) {
    tbody.innerHTML = '<tr><td colspan="7" style="color:var(--color-maintenance);">Failed loading tasks.</td></tr>';
  }
}

window.assignHKStaff = async (taskId, staffId) => {
  if (!staffId) return;
  showLoader(true, 'Assigning staff member...');
  try {
    const res = await fetch('/api/housekeeping/assign', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ taskId, staffId: parseInt(staffId, 10), userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      loadHousekeepingTasks();
    }
  } catch (e) {
    showLoader(false);
  }
};

window.updateHKStatus = async (taskId, status) => {
  const notes = prompt(`Enter comments/notes for task (optional):`);
  if (notes === null) return; // cancelled

  showLoader(true, `Updating task to ${status}...`);
  try {
    const res = await fetch('/api/housekeeping/status', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ taskId, status, notes, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      loadHousekeepingView();
    }
  } catch (e) {
    showLoader(false);
  }
};

// Inventory Stock Section
async function loadInventoryStock() {
  const tbody = document.getElementById('hk-inventory-table-body');
  tbody.innerHTML = '<tr><td colspan="6">Loading amenities stocks...</td></tr>';

  try {
    const res = await fetch('/api/inventory');
    const list = await res.json();
    
    tbody.innerHTML = '';
    list.forEach(i => {
      const tr = document.createElement('tr');
      const isLow = i.quantity <= i.min_quantity;
      const statusHtml = isLow 
        ? '<span class="blacklist-badge">Reorder Required</span>' 
        : '<span class="vip-badge">In Stock</span>';

      tr.innerHTML = `
        <td><strong>${i.name}</strong></td>
        <td>${i.category}</td>
        <td><strong class="${isLow ? 'text-danger' : ''}">${i.quantity}</strong> units</td>
        <td>${i.min_quantity} units</td>
        <td>${statusHtml}</td>
        <td>
          <button class="btn btn-secondary btn-sm" onclick="editStockItem(${i.id}, '${i.name}', '${i.category}', ${i.quantity}, ${i.min_quantity})">Add Stock / Edit</button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  } catch (err) {
    tbody.innerHTML = '<tr><td colspan="6" style="color:var(--color-maintenance);">Failed loading inventory stock.</td></tr>';
  }
}

function openInventoryModal() {
  openModal('modal-inventory');
  document.getElementById('inventory-form').reset();
  document.getElementById('inv-item-id').value = '';
  document.getElementById('inventory-modal-title').textContent = 'Add Inventory Stock Item';
}

window.editStockItem = (id, name, category, quantity, min_quantity) => {
  openModal('modal-inventory');
  document.getElementById('inventory-modal-title').textContent = 'Update Stock Item';
  document.getElementById('inv-item-id').value = id;
  document.getElementById('inv-item-name').value = name;
  document.getElementById('inv-item-category').value = category;
  document.getElementById('inv-item-qty').value = quantity;
  document.getElementById('inv-item-min').value = min_quantity;
};

async function saveInventoryItem(e) {
  e.preventDefault();
  const id = document.getElementById('inv-item-id').value;
  const name = document.getElementById('inv-item-name').value;
  const category = document.getElementById('inv-item-category').value;
  const quantity = parseInt(document.getElementById('inv-item-qty').value, 10);
  const min_quantity = parseInt(document.getElementById('inv-item-min').value, 10);

  showLoader(true, 'Saving stock changes...');
  try {
    const res = await fetch('/api/inventory/update', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        id: id ? parseInt(id, 10) : undefined,
        name, category, quantity, min_quantity,
        userId: state.currentUser.id
      })
    });
    showLoader(false);
    if (res.ok) {
      closeAllModals();
      loadInventoryStock();
    }
  } catch (e) {
    showLoader(false);
  }
}

// Lost & Found Section
async function loadLostFoundLogs() {
  const tbody = document.getElementById('hk-lostfound-table-body');
  tbody.innerHTML = '<tr><td colspan="8">Loading registry...</td></tr>';

  try {
    const res = await fetch('/api/lost-found');
    const list = await res.json();

    tbody.innerHTML = '';
    if (list.length === 0) {
      tbody.innerHTML = '<tr><td colspan="8" style="text-align:center;">No lost items logged.</td></tr>';
      return;
    }

    list.forEach(i => {
      const tr = document.createElement('tr');
      
      let actionHtml = '';
      if (i.status === 'Reported') {
        actionHtml = `<button class="btn btn-primary btn-sm" onclick="triggerClaimLostFound(${i.id})">Mark Claimed</button>`;
      } else {
        actionHtml = '<span style="color:#888; font-size:12px;">Sended/Closed</span>';
      }

      tr.innerHTML = `
        <td><strong>${i.item}</strong></td>
        <td>${i.description || 'N/A'}</td>
        <td>${i.date}</td>
        <td>${i.location || 'N/A'}</td>
        <td><strong>${i.status}</strong></td>
        <td>${i.contact_name || '-'}</td>
        <td>${i.contact_phone || '-'}</td>
        <td>${actionHtml}</td>
      `;
      tbody.appendChild(tr);
    });
  } catch (err) {}
}

function openLostFoundModal() {
  openModal('modal-lostfound');
  document.getElementById('lostfound-form').reset();
  document.getElementById('lf-date').value = new Date().toISOString().split('T')[0];
}

async function saveLostFoundItem(e) {
  e.preventDefault();
  const data = {
    item: document.getElementById('lf-item').value,
    description: document.getElementById('lf-desc').value,
    date: document.getElementById('lf-date').value,
    location: document.getElementById('lf-location').value,
    userId: state.currentUser.id
  };

  showLoader(true, 'Recording found item...');
  try {
    const res = await fetch('/api/lost-found/add', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    });
    showLoader(false);
    if (res.ok) {
      closeAllModals();
      loadLostFoundLogs();
    }
  } catch (e) {
    showLoader(false);
  }
}

function triggerClaimLostFound(id) {
  openModal('modal-claim-lostfound');
  document.getElementById('claim-lostfound-form').reset();
  document.getElementById('claim-item-id').value = id;
}

async function submitLostFoundClaim(e) {
  e.preventDefault();
  const id = parseInt(document.getElementById('claim-item-id').value, 10);
  const claimantName = document.getElementById('lf-claimant-name').value;
  const claimantPhone = document.getElementById('lf-claimant-phone').value;

  showLoader(true, 'Settiing claim...');
  try {
    const res = await fetch('/api/lost-found/claim', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id, contact_name: claimantName, contact_phone: claimantPhone, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      closeAllModals();
      loadLostFoundLogs();
    }
  } catch (e) {
    showLoader(false);
  }
}

// ================= VIEW: STAFF ROSTER & ATTENDANCE ================= //

async function loadStaffView() {
  loadStaffAccounts();
  loadStaffAttendance();
  loadStaffSalaries();
}

async function loadStaffAccounts() {
  const tbody = document.getElementById('staff-table-body');
  tbody.innerHTML = '';
  
  try {
    const res = await fetch('/api/staff');
    const staff = await res.json();
    state.staffList = staff; // Store in state
    
    staff.forEach(s => {
      const tr = document.createElement('tr');
      tr.innerHTML = `
        <td><strong>${s.name}</strong></td>
        <td>${s.role}</td>
        <td><code>${s.username}</code></td>
        <td style="text-align: right;">
          <div style="display: flex; gap: 4px; justify-content: flex-end;">
            <button class="btn btn-secondary btn-sm" onclick="editStaffDetails(${s.id})">Edit</button>
            ${s.username === 'admin' ? '' : `<button class="btn btn-danger btn-sm" onclick="deleteStaff(${s.id})">Delete</button>`}
          </div>
        </td>
      `;
      tbody.appendChild(tr);
    });
  } catch (e) {}
}

async function loadStaffAttendance() {
  const tbody = document.getElementById('attendance-table-body');
  tbody.innerHTML = '';

  try {
    const res = await fetch('/api/staff/attendance');
    const logs = await res.json();

    logs.forEach(l => {
      const tr = document.createElement('tr');
      tr.innerHTML = `
        <td>${l.date}</td>
        <td><strong>${l.name}</strong></td>
        <td>${l.role}</td>
        <td><strong>${l.status}</strong></td>
        <td>${l.clock_in || '-'}</td>
        <td>${l.clock_out || '-'}</td>
      `;
      tbody.appendChild(tr);
    });
  } catch (e) {}
}

async function loadStaffSalaries() {
  const tbody = document.getElementById('salaries-table-body');
  tbody.innerHTML = '';

  try {
    const res = await fetch('/api/staff/salaries');
    const logs = await res.json();

    logs.forEach(l => {
      const tr = document.createElement('tr');
      const total = l.base_salary + l.bonus - l.deductions;
      tr.innerHTML = `
        <td>${l.month}</td>
        <td><strong>${l.name}</strong></td>
        <td>${l.role}</td>
        <td>₹${l.base_salary.toLocaleString()}</td>
        <td>₹${l.bonus.toLocaleString()}</td>
        <td>₹${l.deductions.toLocaleString()}</td>
        <td><strong>₹${total.toLocaleString()}</strong></td>
        <td>${l.paid_date}</td>
      `;
      tbody.appendChild(tr);
    });
  } catch (e) {}
}

async function openAttendanceModal() {
  openModal('modal-attendance');
  document.getElementById('attendance-form').reset();
  document.getElementById('att-date').value = new Date().toISOString().split('T')[0];

  const select = document.getElementById('att-staff-select');
  select.innerHTML = '<option value="">Select staff member...</option>';
  
  try {
    const res = await fetch('/api/staff');
    const staff = await res.json();
    staff.forEach(s => {
      const opt = document.createElement('option');
      opt.value = s.id;
      opt.textContent = `${s.name} (${s.role})`;
      select.appendChild(opt);
    });
  } catch (e) {}
}

async function saveAttendanceLog(e) {
  e.preventDefault();
  const data = {
    userId: parseInt(document.getElementById('att-staff-select').value, 10),
    date: document.getElementById('att-date').value,
    status: document.getElementById('att-status').value,
    clockIn: document.getElementById('att-clock-in').value || null,
    clockOut: document.getElementById('att-clock-out').value || null,
    adminUserId: state.currentUser.id
  };

  showLoader(true, 'Saving attendance log...');
  try {
    const res = await fetch('/api/staff/attendance', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    });
    showLoader(false);
    if (res.ok) {
      closeAllModals();
      loadStaffAttendance();
    }
  } catch (e) {
    showLoader(false);
  }
}

async function openSalaryModal() {
  openModal('modal-salary');
  document.getElementById('salary-form').reset();
  document.getElementById('sal-month').value = new Date().toISOString().substring(0, 7);

  const select = document.getElementById('sal-staff-select');
  select.innerHTML = '<option value="">Select staff...</option>';
  
  try {
    const res = await fetch('/api/staff');
    const staff = await res.json();
    staff.forEach(s => {
      const opt = document.createElement('option');
      opt.value = s.id;
      opt.textContent = `${s.name} (${s.role})`;
      select.appendChild(opt);
    });
  } catch (e) {}
}

async function saveSalaryRecord(e) {
  e.preventDefault();
  const data = {
    userId: parseInt(document.getElementById('sal-staff-select').value, 10),
    month: document.getElementById('sal-month').value,
    baseSalary: parseFloat(document.getElementById('sal-base').value),
    bonus: parseFloat(document.getElementById('sal-bonus').value) || 0,
    deductions: parseFloat(document.getElementById('sal-deductions').value) || 0,
    adminUserId: state.currentUser.id
  };

  showLoader(true, 'Recording salary checkout payment...');
  try {
    const res = await fetch('/api/staff/salaries/pay', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    });
    showLoader(false);
    if (res.ok) {
      closeAllModals();
      loadStaffSalaries();
    }
  } catch (e) {
    showLoader(false);
  }
}

// ================= VIEW: REPORTS ENGINE & SVG CHARTS ================= //

let currentReportData = null;
let currentReportType = null;

async function generateReportsData() {
  const type = document.getElementById('report-type-select').value;
  const startDate = document.getElementById('report-start-date').value;
  const endDate = document.getElementById('report-end-date').value;

  if (!startDate || !endDate) return alert('Select date range');

  showLoader(true, `Generating ${type} report...`);
  try {
    const res = await fetch(`/api/reports?type=${type}&startDate=${startDate}&endDate=${endDate}`);
    const data = await res.json();
    
    showLoader(false);
    currentReportData = data;
    currentReportType = type;

    renderReportTable(type, data);
    renderReportChart(type, data);
  } catch (e) {
    showLoader(false);
    alert('Report generation failed');
  }
}

function renderReportTable(type, data) {
  const headers = document.getElementById('report-table-headers');
  const tbody = document.getElementById('report-table-body');

  headers.innerHTML = '';
  tbody.innerHTML = '';

  if (type === 'daily') {
    headers.innerHTML = '<th>Activity KPI Metrics</th><th style="text-align:right;">Value Logged</th>';
    tbody.innerHTML = `
      <tr><td>Bookings Reservations Created</td><td style="text-align:right;">${data.bookingsCreated} bookings</td></tr>
      <tr><td>Estimated Booking Value</td><td style="text-align:right;">₹${data.bookingsValue.toLocaleString()}</td></tr>
      <tr><td>Total Checkouts Finalized</td><td style="text-align:right;">${data.checkoutsCount} checkouts</td></tr>
      <tr style="font-weight:bold; color:var(--color-primary);"><td>Cash Revenue Collected Today</td><td style="text-align:right;">₹${data.revenueCollected.toLocaleString()}</td></tr>
    `;
  } else if (type === 'occupancy') {
    headers.innerHTML = '<th>Room Number</th><th>Total Days Analyzed</th><th>Nights Occupied</th><th style="text-align:right;">Occupancy Rate</th>';
    if (data.length === 0) {
      tbody.innerHTML = '<tr><td colspan="4" style="text-align:center;">No data found</td></tr>';
      return;
    }
    data.forEach(item => {
      tbody.innerHTML += `
        <tr>
          <td>Room ${item.roomNumber}</td>
          <td>${item.totalDays} Days</td>
          <td>${item.occupiedDays} Night(s)</td>
          <td style="text-align:right; font-weight:bold;">${item.rate}%</td>
        </tr>
      `;
    });
  } else if (type === 'revenue') {
    headers.innerHTML = '<th>Checkout Date</th><th style="text-align:right;">Revenue Collected</th>';
    if (data.length === 0) {
      tbody.innerHTML = '<tr><td colspan="2" style="text-align:center;">No billing history in selected period.</td></tr>';
      return;
    }
    data.forEach(item => {
      tbody.innerHTML += `
        <tr>
          <td>${item.date}</td>
          <td style="text-align:right; font-weight:bold; color:var(--color-vacant);">₹${item.amount.toLocaleString()}</td>
        </tr>
      `;
    });
  } else if (type === 'gst') {
    headers.innerHTML = '<th>Invoice Ref</th><th>Tax Date</th><th>Taxable Amount (Base)</th><th>CGST</th><th>SGST</th><th>IGST</th><th style="text-align:right;">Invoice Total</th>';
    
    if (data.details.length === 0) {
      tbody.innerHTML = '<tr><td colspan="7" style="text-align:center;">No tax invoices generated in selected period.</td></tr>';
      return;
    }
    
    data.details.forEach(i => {
      tbody.innerHTML += `
        <tr>
          <td><code>${i.invoice}</code></td>
          <td>${i.date}</td>
          <td>₹${Math.round(i.taxable).toLocaleString()}</td>
          <td>₹${Math.round(i.cgst).toLocaleString()}</td>
          <td>₹${Math.round(i.sgst).toLocaleString()}</td>
          <td>₹${Math.round(i.igst).toLocaleString()}</td>
          <td style="text-align:right; font-weight:bold;">₹${i.gross.toLocaleString()}</td>
        </tr>
      `;
    });

    // Append Summary
    tbody.innerHTML += `
      <tr style="border-top: 2px solid var(--border-color); font-weight:bold; background:rgba(255,255,255,0.02);">
        <td colspan="2">TOTAL REGISTRY SUMMARY:</td>
        <td>₹${Math.round(data.summary.totalTaxable).toLocaleString()}</td>
        <td>₹${Math.round(data.summary.totalGST / 2).toLocaleString()}</td>
        <td>₹${Math.round(data.summary.totalGST / 2).toLocaleString()}</td>
        <td>₹${Math.round(data.summary.totalGST).toLocaleString()}</td>
        <td style="text-align:right; color:var(--color-primary);">₹${data.summary.totalGross.toLocaleString()}</td>
      </tr>
    `;
  } else if (type === 'yearly-tax') {
    headers.innerHTML = '<th>Financial Ledger Account / Line Item</th><th style="text-align:right;">Reported Balance</th>';
    tbody.innerHTML = `
      <tr><td>Gross Bookings Income (incl. GST)</td><td style="text-align:right;">₹${data.grossSales.toLocaleString()}</td></tr>
      <tr><td>GST Liabilities Collected (CGST + SGST)</td><td style="text-align:right;">₹${data.gstCollected.toLocaleString()}</td></tr>
      <tr style="font-weight: bold; background: rgba(255,255,255,0.02);"><td>Net Taxable Sales</td><td style="text-align:right;">₹${data.taxableSales.toLocaleString()}</td></tr>
      <tr><td>Total Roster Salary Expenses</td><td style="text-align:right; color: #ef4444;">- ₹${data.salariesPaid.toLocaleString()}</td></tr>
      <tr><td>Estimated Operational Inventory Expenditures</td><td style="text-align:right; color: #ef4444;">- ₹${data.stockExpenses.toLocaleString()}</td></tr>
      <tr style="font-weight:bold; font-size:14px; border-top: 2px solid var(--border-color); background: rgba(16, 185, 129, 0.05);">
        <td>Reconciled Net Taxable Income (for Tax Filing)</td>
        <td style="text-align:right; color:var(--color-vacant);">₹${data.netProfit.toLocaleString()}</td>
      </tr>
    `;
  } else if (type === 'kpi') {
    headers.innerHTML = '<th>Key Performance Indicator (KPI) Metric</th><th style="text-align:right;">Calculated Value</th>';
    tbody.innerHTML = `
      <tr><td>Total Available Capacity (Rooms)</td><td style="text-align:right;">${data.totalRooms} Rooms</td></tr>
      <tr><td>Period Nights Available</td><td style="text-align:right;">${data.totalNightsAvailable} Nights</td></tr>
      <tr><td>Period Nights Occupied / Sold</td><td style="text-align:right;">${data.totalNightsSold} Nights</td></tr>
      <tr style="font-weight:bold; color:var(--color-primary);"><td>Occupancy Rate</td><td style="text-align:right;">${data.occupancyRate}%</td></tr>
      <tr><td>Net Room Rent Revenue (excl. GST)</td><td style="text-align:right;">₹${data.totalRoomRevenue.toLocaleString()}</td></tr>
      <tr style="font-weight:bold; color:var(--color-vacant);"><td>Average Daily Rate (ADR)</td><td style="text-align:right;">₹${data.adr.toLocaleString()}</td></tr>
      <tr style="font-weight:bold; color:var(--color-vacant);"><td>Revenue Per Available Room (RevPAR)</td><td style="text-align:right;">₹${data.revpar.toLocaleString()}</td></tr>
    `;
  }
}

function renderReportChart(type, data) {
  const svg = document.getElementById('report-svg-chart');
  svg.innerHTML = '';

  const width = svg.clientWidth || 400;
  const height = 240;
  
  if (type === 'daily') {
    // Draw simple Pie-like progress bars
    const total = data.bookingsCreated + data.checkoutsCount;
    if (total === 0) {
      svg.innerHTML = '<text x="50%" y="50%" text-anchor="middle" fill="#888">No data logs to chart.</text>';
      return;
    }
    
    const fill1 = (data.bookingsCreated / total) * 300;
    const fill2 = (data.checkoutsCount / total) * 300;
    
    svg.innerHTML = `
      <!-- Bar Chart -->
      <text x="30" y="40" fill="#fff" font-size="12">Bookings Created: ${data.bookingsCreated}</text>
      <rect x="30" y="50" width="300" height="20" rx="3" fill="#252a3e" />
      <rect x="30" y="50" width="${fill1}" height="20" rx="3" fill="#6366f1" />

      <text x="30" y="110" fill="#fff" font-size="12">Checkouts Settled: ${data.checkoutsCount}</text>
      <rect x="30" y="120" width="300" height="20" rx="3" fill="#252a3e" />
      <rect x="30" y="120" width="${fill2}" height="20" rx="3" fill="#10b981" />
    `;
  } else if (type === 'occupancy') {
    if (data.length === 0) {
      svg.innerHTML = '<text x="50%" y="50%" text-anchor="middle" fill="#888">No occupancy stats found.</text>';
      return;
    }

    // Draw Bar chart for room occupancy rate
    let barsHtml = '';
    const barWidth = Math.max(10, Math.floor((width - 80) / data.length) - 10);
    
    data.forEach((item, idx) => {
      const barHeight = (item.rate / 100) * 150;
      const x = 50 + idx * (barWidth + 10);
      const y = height - 40 - barHeight;
      
      barsHtml += `
        <rect x="${x}" y="${y}" width="${barWidth}" height="${barHeight}" fill="#6366f1" rx="2">
          <title>Room ${item.roomNumber}: ${item.rate}%</title>
        </rect>
        <text x="${x + barWidth/2}" y="${height - 20}" fill="#888" font-size="9" text-anchor="middle">${item.roomNumber}</text>
      `;
    });

    svg.innerHTML = `
      <!-- Y Axis -->
      <line x1="45" y1="30" x2="45" y2="200" stroke="#444" stroke-width="1" />
      <text x="30" y="35" fill="#888" font-size="9">100%</text>
      <text x="35" y="115" fill="#888" font-size="9">50%</text>
      <text x="40" y="200" fill="#888" font-size="9">0%</text>
      ${barsHtml}
    `;
  } else if (type === 'revenue' || type === 'gst') {
    const list = type === 'revenue' ? data : data.details;
    if (list.length === 0) {
      svg.innerHTML = '<text x="50%" y="50%" text-anchor="middle" fill="#888">No transaction data to map.</text>';
      return;
    }

    // Line Graph
    const maxVal = Math.max(...list.map(i => type === 'revenue' ? i.amount : i.gross)) || 1000;
    
    let points = '';
    let axesLabels = '';
    const stepX = (width - 100) / Math.max(1, list.length - 1);
    
    list.forEach((item, idx) => {
      const val = type === 'revenue' ? item.amount : item.gross;
      const x = 70 + idx * stepX;
      const y = height - 40 - (val / maxVal) * 150;
      
      points += `${x},${y} `;
      
      // Draw grid dots
      axesLabels += `
        <circle cx="${x}" cy="${y}" r="4" fill="#10b981" />
        <text x="${x}" y="${height - 20}" fill="#888" font-size="8" text-anchor="middle" transform="rotate(-15 ${x} ${height - 20})">${type === 'revenue' ? item.date.substring(5) : item.date.substring(5)}</text>
      `;
    });

    svg.innerHTML = `
      <!-- Y Axis -->
      <line x1="65" y1="30" x2="65" y2="200" stroke="#444" stroke-width="1" />
      <text x="15" y="35" fill="#888" font-size="9">₹${maxVal.toLocaleString()}</text>
      <text x="30" y="200" fill="#888" font-size="9">₹0</text>
      
      <!-- Trend Line -->
      <polyline fill="none" stroke="#10b981" stroke-width="2.5" points="${points.trim()}" />
      ${axesLabels}
    `;
  } else if (type === 'yearly-tax') {
    const netProfitPercent = (data.netProfit / Math.max(1, data.grossSales)) * 300;
    const salariesPercent = (data.salariesPaid / Math.max(1, data.grossSales)) * 300;
    
    svg.innerHTML = `
      <text x="30" y="40" fill="#fff" font-size="12">Net Taxable Revenue: ₹${data.taxableSales.toLocaleString()}</text>
      <rect x="30" y="50" width="300" height="15" rx="3" fill="#252a3e" />
      <rect x="30" y="50" width="300" height="15" rx="3" fill="#6366f1" />
      
      <text x="30" y="95" fill="#fff" font-size="12">Salaries Paid Ledger: ₹${data.salariesPaid.toLocaleString()}</text>
      <rect x="30" y="105" width="300" height="15" rx="3" fill="#252a3e" />
      <rect x="30" y="105" width="${Math.max(10, Math.min(300, salariesPercent))}" height="15" rx="3" fill="#ef4444" />
      
      <text x="30" y="150" fill="#fff" font-size="12">Net Taxable Profit: ₹${data.netProfit.toLocaleString()}</text>
      <rect x="30" y="160" width="300" height="15" rx="3" fill="#252a3e" />
      <rect x="30" y="160" width="${Math.max(10, Math.min(300, netProfitPercent))}" height="15" rx="3" fill="#10b981" />
    `;
  } else if (type === 'kpi') {
    const occWidth = (data.occupancyRate / 100) * 300;
    const maxVal = Math.max(data.adr, data.revpar, 1000);
    const adrWidth = (data.adr / maxVal) * 300;
    const revparWidth = (data.revpar / maxVal) * 300;

    svg.innerHTML = `
      <text x="30" y="35" fill="#fff" font-size="11" font-weight="600">Occupancy Rate: ${data.occupancyRate}%</text>
      <rect x="30" y="45" width="300" height="15" rx="3" fill="#252a3e" />
      <rect x="30" y="45" width="${occWidth}" height="15" rx="3" fill="#6366f1" />

      <text x="30" y="90" fill="#fff" font-size="11" font-weight="600">Average Daily Rate (ADR): ₹${data.adr.toLocaleString()}</text>
      <rect x="30" y="100" width="300" height="15" rx="3" fill="#252a3e" />
      <rect x="30" y="100" width="${adrWidth}" height="15" rx="3" fill="#10b981" />

      <text x="30" y="145" fill="#fff" font-size="11" font-weight="600">Revenue Per Available Room (RevPAR): ₹${data.revpar.toLocaleString()}</text>
      <rect x="30" y="155" width="300" height="15" rx="3" fill="#252a3e" />
      <rect x="30" y="155" width="${revparWidth}" height="15" rx="3" fill="#f59e0b" />
    `;
  }
}

function exportReportToCSV() {
  if (!currentReportData) return alert('Generate a report first.');
  
  let csvContent = "data:text/csv;charset=utf-8,";
  
  if (currentReportType === 'daily') {
    csvContent += "Metric,Value\n";
    csvContent += `Bookings Created,${currentReportData.bookingsCreated}\n`;
    csvContent += `Booking Value Estimations,${currentReportData.bookingsValue}\n`;
    csvContent += `Checkout operations,${currentReportData.checkoutsCount}\n`;
    csvContent += `Revenue Collected Today,${currentReportData.revenueCollected}\n`;
  } else if (currentReportType === 'occupancy') {
    csvContent += "Room Number,Days Range,Nights Occupied,Occupancy Rate (%)\n";
    currentReportData.forEach(r => {
      csvContent += `${r.roomNumber},${r.totalDays},${r.occupiedDays},${r.rate}\n`;
    });
  } else if (currentReportType === 'revenue') {
    csvContent += "Date,Amount Collected\n";
    currentReportData.forEach(r => {
      csvContent += `${r.date},${r.amount}\n`;
    });
  } else if (currentReportType === 'gst') {
    csvContent += "Invoice Number,Date,Taxable Subtotal,CGST,SGST,IGST,Gross Total\n";
    currentReportData.details.forEach(i => {
      csvContent += `${i.invoice},${i.date},${i.taxable},${i.cgst},${i.sgst},${i.igst},${i.gross}\n`;
    });
  } else if (currentReportType === 'yearly-tax') {
    csvContent += "Financial Account Category,Amount (₹)\n";
    csvContent += `Gross Bookings Income (incl. GST),${currentReportData.grossSales}\n`;
    csvContent += `GST Collected (CGST+SGST),${currentReportData.gstCollected}\n`;
    csvContent += `Net Taxable Sales,${currentReportData.taxableSales}\n`;
    csvContent += `Total Salaries Paid,${currentReportData.salariesPaid}\n`;
    csvContent += `Inventory Stock Expenditures,${currentReportData.stockExpenses}\n`;
    csvContent += `Reconciled Taxable Profit,${currentReportData.netProfit}\n`;
  } else if (currentReportType === 'kpi') {
    csvContent += "KPI Metric,Calculated Value\n";
    csvContent += `Total Available Capacity (Rooms),${currentReportData.totalRooms}\n`;
    csvContent += `Period Nights Available,${currentReportData.totalNightsAvailable}\n`;
    csvContent += `Period Nights Occupied,${currentReportData.totalNightsSold}\n`;
    csvContent += `Occupancy Rate (%),${currentReportData.occupancyRate}\n`;
    csvContent += `Net Room Rent Revenue (₹),${currentReportData.totalRoomRevenue}\n`;
    csvContent += `Average Daily Rate (ADR - ₹),${currentReportData.adr}\n`;
    csvContent += `Revenue Per Available Room (RevPAR - ₹),${currentReportData.revpar}\n`;
  }

  const encodedUri = encodeURI(csvContent);
  const link = document.createElement("a");
  link.setAttribute("href", encodedUri);
  link.setAttribute("download", `Shaima_Hotel_${currentReportType}_report_${new Date().toISOString().split('T')[0]}.csv`);
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

// ================= VIEW: SYSTEM SETTINGS & UTILITIES ================= //

async function loadSettingsView() {
  showLoader(true, 'Fetching settings data...');
  try {
    const res = await fetch('/api/settings');
    const settings = await res.json();
    state.settings = settings;

    // Load into form inputs
    document.getElementById('set-hotel-name').value = settings.hotel_name || '';
    document.getElementById('set-hotel-address').value = settings.hotel_address || '';
    document.getElementById('set-hotel-mobile').value = settings.hotel_mobile || '';
    document.getElementById('set-hotel-gstin').value = settings.hotel_gstin || '';
    document.getElementById('set-hotel-web').value = settings.hotel_web || '';
    document.getElementById('set-hotel-email').value = settings.hotel_email || '';
    document.getElementById('set-hotel-gmaps').value = settings.google_review_link || '';
    document.getElementById('set-hotel-logo').value = settings.hotel_logo || '';

    document.getElementById('set-wifi').value = settings.wifi_password || '';
    document.getElementById('set-phone').value = settings.reception_phone || '';
    document.getElementById('set-gst-rate').value = settings.gst_rate || '5';
    document.getElementById('set-ui-theme').value = localStorage.getItem('theme_vision') || 'dark';

    // WhatsApp API setup inputs
    const providerEl = document.getElementById('set-wa-provider');
    if (providerEl) providerEl.value = settings.whatsapp_provider || 'None';
    
    const setManualToken = document.getElementById('set-manual-token');
    if (setManualToken) setManualToken.value = settings.whatsapp_cloud_token || '';
    const setManualPhoneId = document.getElementById('set-manual-phone-id');
    if (setManualPhoneId) setManualPhoneId.value = settings.whatsapp_cloud_phone_id || '';
    const setManualWabaId = document.getElementById('set-manual-waba-id');
    if (setManualWabaId) setManualWabaId.value = settings.whatsapp_cloud_waba_id || '';
    const setManualAppId = document.getElementById('set-manual-app-id');
    if (setManualAppId) setManualAppId.value = settings.whatsapp_app_id || '';
    const setManualApiVersion = document.getElementById('set-manual-api-version');
    if (setManualApiVersion) setManualApiVersion.value = settings.whatsapp_api_version || 'v20.0';

    const waVerifyTokenTxt = document.getElementById('wa-verify-token-txt');
    if (waVerifyTokenTxt) waVerifyTokenTxt.textContent = settings.whatsapp_webhook_verify_token || 'shaima_hotel_secret';

    const autoSyncCheckbox = document.getElementById('wa-auto-sync-checkbox');
    if (autoSyncCheckbox) autoSyncCheckbox.checked = settings.whatsapp_auto_sync === 'true';

    const waWorkingStart = document.getElementById('wa-working-start');
    if (waWorkingStart) waWorkingStart.value = settings.whatsapp_working_start || '08:00';
    const waWorkingEnd = document.getElementById('wa-working-end');
    if (waWorkingEnd) waWorkingEnd.value = settings.whatsapp_working_end || '22:00';
    const setNotifyWaNew = document.getElementById('set-notify-wa-new');
    if (setNotifyWaNew) setNotifyWaNew.checked = settings.whatsapp_notify_new !== 'false';
    const setNotifyWaFail = document.getElementById('set-notify-wa-fail');
    if (setNotifyWaFail) setNotifyWaFail.checked = settings.whatsapp_notify_fail !== 'false';
    const setNotifyEmailFail = document.getElementById('set-notify-email-fail');
    if (setNotifyEmailFail) setNotifyEmailFail.checked = settings.email_notify_fail !== 'false';
    const setNotifyBrowserPush = document.getElementById('set-notify-browser-push');
    if (setNotifyBrowserPush) setNotifyBrowserPush.checked = settings.notify_browser_push === 'true';

    const callbackDisplay = document.getElementById('wa-webhook-url-txt');
    if (callbackDisplay) {
      callbackDisplay.textContent = window.location.origin + '/api/whatsapp/webhook';
    }

    // Load manual integrations
    document.getElementById('set-ota-booking-url').value = settings.ota_booking_url || '';
    document.getElementById('set-ota-booking-id').value = settings.ota_booking_id || '';
    document.getElementById('set-ota-booking-key').value = settings.ota_booking_key || '';

    document.getElementById('set-ota-mmt-url').value = settings.ota_mmt_url || '';
    document.getElementById('set-ota-mmt-id').value = settings.ota_mmt_id || '';
    document.getElementById('set-ota-mmt-key').value = settings.ota_mmt_key || '';

    document.getElementById('set-ota-agoda-url').value = settings.ota_agoda_url || '';
    document.getElementById('set-ota-agoda-id').value = settings.ota_agoda_id || '';
    document.getElementById('set-ota-agoda-key').value = settings.ota_agoda_key || '';

    document.getElementById('set-google-place-id').value = settings.google_place_id || '';
    document.getElementById('set-google-api-key').value = settings.google_api_key || '';
    document.getElementById('set-reviews-scraping-url').value = settings.reviews_scraping_url || '';
    document.getElementById('set-reviews-sync-freq').value = settings.reviews_sync_freq || 'manual';

    // Google Drive backup inputs
    document.getElementById('set-gdrive-sa-key').value = settings.google_drive_sa_key || '';
    document.getElementById('set-gdrive-folder-id').value = settings.google_drive_folder_id || '';
    document.getElementById('set-backup-interval').value = settings.backup_interval_hours || '24';

    // SMTP Email settings inputs
    document.getElementById('set-smtp-host').value = settings.smtp_host || '';
    document.getElementById('set-smtp-port').value = settings.smtp_port || '';
    document.getElementById('set-smtp-secure').checked = settings.smtp_secure === 'true';
    document.getElementById('set-smtp-user').value = settings.smtp_user || '';
    document.getElementById('set-smtp-pass').value = settings.smtp_pass || '';
    document.getElementById('set-smtp-from').value = settings.smtp_from || '';

    // Parse WhatsApp templates
    await renderWhatsAppTemplatesPanel();

    // Load admin rooms list
    loadAdminRoomsTable();

    // Load floor settings list
    loadFloorSettingsTable();

    // Load audit logs
    loadAuditLogsTable();

    // Load local backups list
    loadLocalBackupsList();
    showLoader(false);
  } catch (e) {
    showLoader(false);
  }
}

async function loadAdminRoomsTable() {
  const tbody = document.getElementById('admin-rooms-table-body');
  tbody.innerHTML = '';
  
  try {
    const res = await fetch('/api/rooms');
    const rooms = await res.json();
    state.adminRoomsList = rooms; // Save to global state
    
    rooms.forEach(room => {
      const tr = document.createElement('tr');
      
      // Select badge class for status
      let badgeClass = 'text-success';
      if (room.status === 'Occupied') badgeClass = 'text-primary';
      else if (room.status === 'Dirty') badgeClass = 'text-warning';
      else if (room.status === 'Cleaning') badgeClass = 'text-warning';
      else if (room.status === 'Maintenance') badgeClass = 'text-danger';

      tr.innerHTML = `
        <td><strong>Room ${room.room_number}</strong></td>
        <td>Floor ${room.floor}</td>
        <td>${room.type}</td>
        <td>₹${room.price}</td>
        <td><span class="${badgeClass}" style="font-weight: 600;">${room.status}</span></td>
        <td style="text-align: right;">
          <button class="btn btn-secondary btn-sm" onclick="editAdminRoom(${room.id})">Edit</button>
          <button class="btn btn-danger btn-sm" onclick="deleteAdminRoom(${room.id})">Delete</button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  } catch (err) {
    console.error('Failed to load admin rooms table:', err);
  }
}

async function openAdminRoomModal(roomToEdit = null) {
  openModal('modal-admin-room');
  document.getElementById('admin-room-form').reset();
  
  const titleEl = document.getElementById('admin-room-modal-title');
  const idEl = document.getElementById('admin-room-id');
  const numEl = document.getElementById('admin-room-number');
  const floorSelect = document.getElementById('admin-room-floor');
  const typeSelect = document.getElementById('admin-room-type');
  const priceInput = document.getElementById('admin-room-price');
  const statusSelect = document.getElementById('admin-room-status');

  showLoader(true, 'Loading catalog definitions...');
  try {
    // Fetch Floors and Room Types dynamically
    const [floorsRes, typesRes] = await Promise.all([
      fetch('/api/floors'),
      fetch('/api/room-types')
    ]);
    const floors = await floorsRes.json();
    const types = await typesRes.json();

    floorSelect.innerHTML = '';
    floors.forEach(f => {
      const opt = document.createElement('option');
      opt.value = f.id;
      opt.textContent = `${f.name}`;
      floorSelect.appendChild(opt);
    });

    typeSelect.innerHTML = '';
    types.forEach(t => {
      const opt = document.createElement('option');
      opt.value = t.id;
      opt.textContent = `${t.name} (Base Price: ₹${t.base_price})`;
      opt.setAttribute('data-base-price', t.base_price);
      typeSelect.appendChild(opt);
    });

    // Auto-fill price input when room type changes
    typeSelect.onchange = () => {
      const selectedOpt = typeSelect.options[typeSelect.selectedIndex];
      if (selectedOpt) {
        priceInput.value = selectedOpt.getAttribute('data-base-price');
      }
    };

    showLoader(false);

    if (roomToEdit) {
      titleEl.textContent = 'Edit Room Details';
      idEl.value = roomToEdit.id;
      numEl.value = roomToEdit.room_number;
      floorSelect.value = roomToEdit.floor_id;
      typeSelect.value = roomToEdit.room_type_id;
      priceInput.value = roomToEdit.custom_price !== null && roomToEdit.custom_price !== undefined ? roomToEdit.custom_price : roomToEdit.price;
      statusSelect.value = roomToEdit.status;
    } else {
      titleEl.textContent = 'Add New Room';
      idEl.value = '';
      statusSelect.value = 'Vacant';
      // Trigger default price fill
      if (types.length > 0) {
        priceInput.value = types[0].base_price;
      }
    }
  } catch (err) {
    showLoader(false);
    alert('Failed to load room catalog settings.');
  }
}

function editAdminRoom(roomId) {
  const room = state.adminRoomsList.find(r => r.id === roomId);
  openAdminRoomModal(room);
}

async function deleteAdminRoom(roomId) {
  if (!confirm('Are you sure you want to delete this room? This cannot be undone.')) return;
  
  showLoader(true, 'Deleting room...');
  try {
    const res = await fetch('/api/rooms/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ roomId, userId: state.currentUser.id })
    });
    showLoader(false);
    
    if (res.ok) {
      alert('Room deleted successfully.');
      loadSettingsView();
      loadDashboardView();
    } else {
      const err = await res.json();
      alert(err.error || 'Failed to delete room.');
    }
  } catch (e) {
    showLoader(false);
    alert('Connection error.');
  }
}

async function handleAdminRoomFormSubmit(e) {
  e.preventDefault();
  
  const id = document.getElementById('admin-room-id').value;
  const roomNumber = document.getElementById('admin-room-number').value.trim();
  const floorId = parseInt(document.getElementById('admin-room-floor').value, 10);
  const roomTypeId = parseInt(document.getElementById('admin-room-type').value, 10);
  const price = parseFloat(document.getElementById('admin-room-price').value);
  const status = document.getElementById('admin-room-status').value;

  showLoader(true, 'Saving room...');
  try {
    const res = await fetch('/api/rooms/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        id: id ? parseInt(id, 10) : null,
        roomNumber,
        floorId,
        roomTypeId,
        price,
        status,
        userId: state.currentUser.id
      })
    });
    showLoader(false);

    if (res.ok) {
      alert('Room details saved successfully.');
      closeAllModals();
      loadSettingsView();
      loadDashboardView();
    } else {
      const err = await res.json();
      alert(err.error || 'Failed to save room.');
    }
  } catch (e) {
    showLoader(false);
    alert('Connection error.');
  }
}

// Bind globals for onclick events
window.editAdminRoom = editAdminRoom;
window.deleteAdminRoom = deleteAdminRoom;

async function saveManualWaCredentials(e) {
  if (e) e.preventDefault();
  const payload = {
    whatsapp_provider: 'WhatsAppCloudAPI',
    whatsapp_cloud_token: document.getElementById('set-manual-token').value.trim(),
    whatsapp_cloud_phone_id: document.getElementById('set-manual-phone-id').value.trim(),
    whatsapp_cloud_waba_id: document.getElementById('set-manual-waba-id').value.trim(),
    whatsapp_app_id: document.getElementById('set-manual-app-id').value.trim(),
    whatsapp_api_version: document.getElementById('set-manual-api-version').value.trim(),
    
    // Auto-sync setting
    whatsapp_auto_sync: document.getElementById('wa-auto-sync-checkbox').checked ? 'true' : 'false',

    // Preferences & bot
    whatsapp_working_start: document.getElementById('wa-working-start').value,
    whatsapp_working_end: document.getElementById('wa-working-end').value,
    whatsapp_notify_new: document.getElementById('set-notify-wa-new').checked ? 'true' : 'false',
    whatsapp_notify_fail: document.getElementById('set-notify-wa-fail').checked ? 'true' : 'false',
    email_notify_fail: document.getElementById('set-notify-email-fail').checked ? 'true' : 'false',
    notify_browser_push: document.getElementById('set-notify-browser-push').checked ? 'true' : 'false'
  };
  await saveSettingsAPI(payload, 'Meta WhatsApp settings and preferences updated successfully!');
}

async function saveHotelSettings(e) {
  e.preventDefault();
  const hotel_name = document.getElementById('set-hotel-name').value;
  const hotel_address = document.getElementById('set-hotel-address').value;
  const hotel_mobile = document.getElementById('set-hotel-mobile').value;
  const hotel_gstin = document.getElementById('set-hotel-gstin').value;
  const hotel_web = document.getElementById('set-hotel-web').value;
  const hotel_email = document.getElementById('set-hotel-email').value;
  const google_review_link = document.getElementById('set-hotel-gmaps').value;
  const hotel_logo = document.getElementById('set-hotel-logo').value;

  const data = {
    hotel_name, hotel_address, hotel_mobile, hotel_gstin, hotel_web, hotel_email, google_review_link, hotel_logo
  };
  saveSettingsAPI(data, 'Hotel information saved.');
}

async function saveUtilitySettings(e) {
  e.preventDefault();
  const wifi_password = document.getElementById('set-wifi').value;
  const reception_phone = document.getElementById('set-phone').value;
  const gst_rate = document.getElementById('set-gst-rate').value;
  const ui_theme = document.getElementById('set-ui-theme').value;

  localStorage.setItem('theme_vision', ui_theme);
  document.body.className = '';
  if (ui_theme === 'light') {
    document.body.classList.add('light-theme');
  } else if (ui_theme === 'emerald') {
    document.body.classList.add('theme-emerald');
  } else if (ui_theme === 'navy') {
    document.body.classList.add('theme-navy');
  }

  const data = {
    wifi_password, reception_phone, gst_rate
  };
  saveSettingsAPI(data, 'Utilities and UI Theme configured successfully.');
}

async function renderWhatsAppTemplatesPanel() {
  try {
    const res = await fetch('/api/whatsapp/templates');
    const templates = await res.json();
    state.whatsappTemplates = templates;

    // Ensure default templates exist
    const defaults = ['booking', 'welcome', 'invoice', 'checkout'];
    defaults.forEach(d => {
      if (!templates[d]) {
        templates[d] = {
          meta_template_name: '',
          meta_language_code: 'en_US',
          image: '',
          body: '',
          footer: '',
          btn_text: '',
          btn_url: ''
        };
      }
    });

    const listContainer = document.getElementById('wa-templates-list');
    if (!listContainer) return;
    listContainer.innerHTML = '';

    // Render list
    Object.keys(templates).forEach(key => {
      const isDefault = defaults.includes(key);
      const activeKey = document.getElementById('set-tpl-key').value;
      const isActive = activeKey === key || (!activeKey && key === 'booking');
      if (isActive && !activeKey) {
        document.getElementById('set-tpl-key').value = key;
      }

      const item = document.createElement('div');
      item.className = `tab-btn ${isActive ? 'active' : ''}`;
      item.style.display = 'flex';
      item.style.justifyContent = 'space-between';
      item.style.alignItems = 'center';
      item.style.padding = '8px 12px';
      item.style.marginBottom = '6px';
      item.style.borderRadius = '6px';
      item.style.cursor = 'pointer';
      
      const label = document.createElement('span');
      label.textContent = key.toUpperCase();
      label.style.fontWeight = '500';
      label.style.flex = '1';
      label.addEventListener('click', () => {
        selectWhatsAppTemplate(key);
      });
      item.appendChild(label);

      if (!isDefault) {
        const delBtn = document.createElement('button');
        delBtn.innerHTML = '🗑️';
        delBtn.type = 'button';
        delBtn.style.background = 'none';
        delBtn.style.border = 'none';
        delBtn.style.cursor = 'pointer';
        delBtn.style.fontSize = '12px';
        delBtn.style.color = '#ef4444';
        delBtn.title = 'Delete Custom Template';
        delBtn.addEventListener('click', (e) => {
          e.stopPropagation();
          deleteWhatsAppTemplate(key);
        });
        item.appendChild(delBtn);
      }

      listContainer.appendChild(item);
    });

    const currentKey = document.getElementById('set-tpl-key').value || 'booking';
    populateTemplateEditor(currentKey);
  } catch (err) {
    console.error('Error loading WhatsApp templates:', err);
  }
}

function selectWhatsAppTemplate(key) {
  document.getElementById('set-tpl-key').value = key;
  
  const items = document.querySelectorAll('#wa-templates-list .tab-btn');
  items.forEach(item => {
    item.classList.remove('active');
    const labelSpan = item.querySelector('span');
    if (labelSpan && labelSpan.textContent.toLowerCase() === key.toLowerCase()) {
      item.classList.add('active');
    }
  });

  populateTemplateEditor(key);
}

function populateTemplateEditor(key) {
  const tpl = (state.whatsappTemplates && state.whatsappTemplates[key]) || {
    meta_template_name: '',
    meta_language_code: 'en_US',
    category: 'UTILITY',
    header_type: 'None',
    header_text: '',
    image: '',
    body: '',
    footer: '',
    btn_type: 'None',
    btn_text: '',
    btn_url: ''
  };

  const nameEl = document.getElementById('tpl-meta-name');
  const langEl = document.getElementById('tpl-meta-lang');
  const catEl = document.getElementById('tpl-category');
  const headerTypeEl = document.getElementById('tpl-header-type');
  const headerTextEl = document.getElementById('tpl-header-text');
  const imgEl = document.getElementById('tpl-image');
  const bodyEl = document.getElementById('tpl-body');
  const footerEl = document.getElementById('tpl-footer');
  const btnTypeEl = document.getElementById('tpl-btn-type');
  const urlEl = document.getElementById('tpl-url');
  const btnTextEl = document.getElementById('tpl-btn-text');

  if (nameEl) nameEl.value = tpl.meta_template_name || '';
  if (langEl) langEl.value = tpl.meta_language_code || 'en_US';
  if (catEl) catEl.value = tpl.category || 'UTILITY';
  if (headerTypeEl) headerTypeEl.value = tpl.header_type || 'None';
  if (headerTextEl) headerTextEl.value = tpl.header_text || '';
  if (imgEl) imgEl.value = tpl.image || '';
  if (bodyEl) bodyEl.value = tpl.body || '';
  if (footerEl) footerEl.value = tpl.footer || '';
  if (btnTypeEl) btnTypeEl.value = tpl.btn_type || 'None';
  if (urlEl) urlEl.value = tpl.btn_url || '';
  if (btnTextEl) btnTextEl.value = tpl.btn_text || '';

  toggleTemplateEditorFields();
  updateWhatsAppPreview();
}

async function saveActiveTemplate(e) {
  if (e) e.preventDefault();
  const key = document.getElementById('set-tpl-key').value;
  if (!key) return alert('No active template selected.');

  const payload = {
    meta_template_name: document.getElementById('tpl-meta-name').value.trim(),
    meta_language_code: document.getElementById('tpl-meta-lang').value.trim(),
    category: document.getElementById('tpl-category').value,
    header_type: document.getElementById('tpl-header-type').value,
    header_text: document.getElementById('tpl-header-text').value.trim(),
    image: document.getElementById('tpl-image').value.trim(),
    body: document.getElementById('tpl-body').value.trim(),
    footer: document.getElementById('tpl-footer').value.trim(),
    btn_type: document.getElementById('tpl-btn-type').value,
    btn_url: document.getElementById('tpl-url').value.trim(),
    btn_text: document.getElementById('tpl-btn-text').value.trim()
  };

  showLoader(true, `Saving template ${key}...`);
  try {
    const res = await fetch('/api/whatsapp/templates/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        key,
        templateData: payload,
        userId: state.currentUser.id
      })
    });
    showLoader(false);
    if (res.ok) {
      const data = await res.json();
      state.whatsappTemplates = data.templates;
      alert('Template saved successfully.');
      renderWhatsAppTemplatesPanel();
    } else {
      const err = await res.json();
      alert(`Failed to save template: ${err.error}`);
    }
  } catch (err) {
    showLoader(false);
    alert(`Connection error: ${err.message}`);
  }
}

async function createNewCustomTemplate() {
  const key = prompt('Enter a unique name key for your custom template (e.g. spring_deal):');
  if (!key) return;
  const cleanKey = key.trim().toLowerCase().replace(/[^a-z0-9_-]/g, '');
  if (!cleanKey) return alert('Invalid key name. Use only alphanumeric characters, dashes, or underscores.');

  const payload = {
    meta_template_name: '',
    meta_language_code: 'en_US',
    image: '',
    body: '',
    footer: '',
    btn_text: '',
    btn_url: ''
  };

  showLoader(true, `Creating custom template "${cleanKey}"...`);
  try {
    const res = await fetch('/api/whatsapp/templates/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ key: cleanKey, templateData: payload, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      document.getElementById('set-tpl-key').value = cleanKey;
      await renderWhatsAppTemplatesPanel();
      selectWhatsAppTemplate(cleanKey);
    } else {
      const err = await res.json();
      alert(`Error creating template: ${err.error || 'Unknown error'}`);
    }
  } catch (err) {
    showLoader(false);
    alert(`Connection error: ${err.message}`);
  }
}

async function deleteWhatsAppTemplate(key) {
  if (!confirm(`Are you sure you want to permanently delete custom template "${key}"?`)) return;

  showLoader(true, `Deleting template "${key}"...`);
  try {
    const res = await fetch('/api/whatsapp/templates/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ key, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      document.getElementById('set-tpl-key').value = 'booking';
      await renderWhatsAppTemplatesPanel();
    } else {
      const err = await res.json();
      alert(`Failed to delete: ${err.error || 'Server error'}`);
    }
  } catch (err) {
    showLoader(false);
    alert(`Connection error: ${err.message}`);
  }
}

async function syncMetaTemplates() {
  showLoader(true, 'Synchronizing approved templates from Meta Graph API...');
  try {
    const res = await fetch('/api/whatsapp/templates/sync', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: state.currentUser.id })
    });
    showLoader(false);
    const data = await res.json();
    if (res.ok) {
      alert(`Sync completed successfully!\nImported/Updated ${data.syncedCount} templates.`);
      await renderWhatsAppTemplatesPanel();
    } else {
      alert(`Sync failed:\n${data.error || 'Please verify WABA credentials.'}`);
    }
  } catch (err) {
    showLoader(false);
    alert(`Network sync error: ${err.message}`);
  }
}

window.syncMetaTemplates = syncMetaTemplates;
window.createNewCustomTemplate = createNewCustomTemplate;
window.saveActiveTemplate = saveActiveTemplate;
window.selectWhatsAppTemplate = selectWhatsAppTemplate;
window.deleteWhatsAppTemplate = deleteWhatsAppTemplate;

// WhatsApp Settings Tabs Switching
function switchWaSetupTab(tabId) {
  const tabs = ['wa-tab-connection', 'wa-tab-multi-number', 'wa-tab-automation', 'wa-tab-settings'];
  tabs.forEach(t => {
    const el = document.getElementById(t);
    const btn = document.getElementById(`btn-${t}`);
    if (el) el.style.display = t === tabId ? 'block' : 'none';
    if (btn) {
      if (t === tabId) btn.classList.add('active');
      else btn.classList.remove('active');
    }
  });
  if (tabId === 'wa-tab-multi-number') {
    loadWaNumbers();
  } else if (tabId === 'wa-tab-automation') {
    loadWaAutomationMap();
  }
}

function toggleWaMode(mode) {
  const embeddedPane = document.getElementById('pane-wa-embedded');
  const manualPane = document.getElementById('pane-wa-manual');
  const btnEmbedded = document.getElementById('btn-mode-embedded');
  const btnManual = document.getElementById('btn-mode-manual');

  if (mode === 'embedded') {
    if (embeddedPane) embeddedPane.style.display = 'block';
    if (manualPane) manualPane.style.display = 'none';
    if (btnEmbedded) btnEmbedded.classList.add('active');
    if (btnManual) btnManual.classList.remove('active');
  } else {
    if (embeddedPane) embeddedPane.style.display = 'none';
    if (manualPane) manualPane.style.display = 'block';
    if (btnEmbedded) btnEmbedded.classList.remove('active');
    if (btnManual) btnManual.classList.add('active');
  }
}

function openAddWaNumberModal() {
  document.getElementById('wa-number-id').value = '';
  document.getElementById('wa-num-name').value = '';
  document.getElementById('wa-num-phone').value = '';
  document.getElementById('wa-num-phone-id').value = '';
  document.getElementById('wa-num-waba-id').value = '';
  document.getElementById('wa-num-token').value = '';
  document.getElementById('wa-num-default').checked = false;
  document.getElementById('wa-num-disabled').checked = false;
  document.getElementById('wa-number-modal-title').textContent = 'Configure Official WhatsApp Number';
  openModal('modal-wa-number');
}

async function saveManualWaCredentials(e) {
  e.preventDefault();
  const payload = {
    whatsapp_cloud_waba_id: document.getElementById('set-manual-waba-id').value.trim(),
    whatsapp_cloud_phone_id: document.getElementById('set-manual-phone-id').value.trim(),
    whatsapp_cloud_token: document.getElementById('set-manual-token').value.trim(),
    whatsapp_app_id: document.getElementById('set-manual-app-id').value.trim(),
    whatsapp_api_version: document.getElementById('set-manual-api-version').value.trim()
  };
  await saveSettingsAPI(payload, 'Manual API Connection credentials saved successfully!');
}

async function saveWaNumberRegistry(e) {
  e.preventDefault();
  const id = document.getElementById('wa-number-id').value;
  const payload = {
    phone_number_id: document.getElementById('wa-num-phone-id').value.trim(),
    display_number: document.getElementById('wa-num-phone').value.trim(),
    display_name: document.getElementById('wa-num-name').value.trim(),
    waba_id: document.getElementById('wa-num-waba-id').value.trim(),
    access_token: document.getElementById('wa-num-token').value.trim(),
    is_default: document.getElementById('wa-num-default').checked ? 1 : 0,
    disabled: document.getElementById('wa-num-disabled').checked ? 1 : 0
  };
  if (id) payload.id = parseInt(id, 10);

  showLoader(true, 'Saving phone number config...');
  try {
    const res = await fetch('/api/whatsapp/numbers/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
    showLoader(false);
    if (res.ok) {
      closeModal('modal-wa-number');
      alert('Number configuration saved successfully!');
      loadWaNumbers();
    } else {
      const data = await res.json();
      alert(`Save failed: ${data.error || 'Unknown error'}`);
    }
  } catch (e) {
    showLoader(false);
    alert(`Connection error: ${e.message}`);
  }
}

async function loadWaNumbers() {
  try {
    const res = await fetch('/api/whatsapp/numbers');
    if (!res.ok) return;
    const numbers = await res.json();
    const tbody = document.getElementById('wa-phone-registry-tbody');
    if (!tbody) return;
    tbody.innerHTML = '';
    
    numbers.forEach(n => {
      const row = document.createElement('tr');
      row.innerHTML = `
        <td><strong>${n.display_name}</strong></td>
        <td>${n.display_number}</td>
        <td><code>${n.phone_number_id}</code></td>
        <td><code>${n.waba_id}</code></td>
        <td>
          <span class="badge badge-${n.disabled ? 'danger' : n.status === 'Connected' ? 'success' : 'warning'}">
            ${n.disabled ? 'Disabled' : n.status}
          </span>
          ${n.is_default ? '<span class="badge badge-primary" style="margin-left:4px;">Default</span>' : ''}
        </td>
        <td>${n.messaging_tier}</td>
        <td><span style="color:#00a884; font-weight:bold;">${n.quality_rating}</span></td>
        <td style="text-align: right; white-space: nowrap;">
          <button type="button" class="btn btn-secondary btn-xs" onclick="editWaNumber(${JSON.stringify(n).replace(/"/g, '&quot;')})" style="padding: 2px 6px;">Edit</button>
          <button type="button" class="btn btn-secondary btn-xs" onclick="testSingleWaNumber(${n.id})" style="padding: 2px 6px;">Test</button>
          ${!n.is_default ? `<button type="button" class="btn btn-secondary btn-xs" onclick="setDefaultWaNumber(${n.id})" style="padding: 2px 6px;">Default</button>` : ''}
          <button type="button" class="btn btn-danger btn-xs" onclick="deleteWaNumber(${n.id})" style="padding: 2px 6px;">Delete</button>
        </td>
      `;
      tbody.appendChild(row);
    });
  } catch (e) {
    console.error('Failed to load WABA numbers:', e);
  }
}

window.editWaNumber = function(n) {
  document.getElementById('wa-number-id').value = n.id;
  document.getElementById('wa-num-name').value = n.display_name;
  document.getElementById('wa-num-phone').value = n.display_number;
  document.getElementById('wa-num-phone-id').value = n.phone_number_id;
  document.getElementById('wa-num-waba-id').value = n.waba_id;
  document.getElementById('wa-num-token').value = '••••••••••••••••';
  document.getElementById('wa-num-default').checked = !!n.is_default;
  document.getElementById('wa-num-disabled').checked = !!n.disabled;
  document.getElementById('wa-number-modal-title').textContent = 'Edit Number Settings';
  openModal('modal-wa-number');
};

async function testSingleWaNumber(id) {
  showLoader(true, 'Executing connection checks on selected number...');
  try {
    const res = await fetch('/api/whatsapp/numbers');
    if (!res.ok) throw new Error('Failed to get numbers list');
    const list = await res.json();
    const item = list.find(n => n.id === id);
    if (!item) throw new Error('Number configuration not found');

    const testRes = await fetch('/api/whatsapp/test-connection', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        token: item.access_token,
        phoneId: item.phone_number_id,
        wabaId: item.waba_id
      })
    });
    showLoader(false);
    const data = await testRes.json();
    alert(`Connection Test Result: ${data.status || 'Verification Failed'}`);
  } catch (e) {
    showLoader(false);
    alert(`Connection check failed: ${e.message}`);
  }
}

async function setDefaultWaNumber(id) {
  showLoader(true, 'Setting active default sender...');
  try {
    const res = await fetch('/api/whatsapp/numbers/set-default', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id })
    });
    showLoader(false);
    if (res.ok) {
      alert('Default sender updated successfully!');
      loadWaNumbers();
    } else {
      alert('Failed to update default sender.');
    }
  } catch (e) {
    showLoader(false);
    alert(`Connection error: ${e.message}`);
  }
}

async function deleteWaNumber(id) {
  if (!confirm('Are you sure you want to delete this number configuration from the registry?')) return;
  showLoader(true, 'Removing number configuration...');
  try {
    const res = await fetch('/api/whatsapp/numbers/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id })
    });
    showLoader(false);
    if (res.ok) {
      alert('Number configuration deleted.');
      loadWaNumbers();
    } else {
      alert('Delete failed.');
    }
  } catch (e) {
    showLoader(false);
    alert(`Connection error: ${e.message}`);
  }
}

async function testActiveWaConnection() {
  const token = document.getElementById('set-manual-token').value.trim() || state.settings.whatsapp_cloud_token;
  const phoneId = document.getElementById('set-manual-phone-id').value.trim() || state.settings.whatsapp_cloud_phone_id;
  const wabaId = document.getElementById('set-manual-waba-id').value.trim() || state.settings.whatsapp_cloud_waba_id;

  if (!token || !phoneId || !wabaId) {
    alert('Please enter Token, Phone Number ID, and WABA ID to test connection.');
    return;
  }

  showLoader(true, 'Testing connection with Meta Developer APIs...');
  try {
    const res = await fetch('/api/whatsapp/test-connection', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ token, phoneId, wabaId })
    });
    showLoader(false);
    const data = await res.json();
    if (res.ok && data.ok) {
      alert(`Test Success!\nStatus: ${data.status}`);
      document.getElementById('wa-embedded-status-badge').className = 'badge badge-success';
      document.getElementById('wa-embedded-status-badge').textContent = 'Connected';
    } else {
      alert(`Test Failed!\nError: ${data.status || 'Verification Failed'}`);
      document.getElementById('wa-embedded-status-badge').className = 'badge badge-danger';
      document.getElementById('wa-embedded-status-badge').textContent = 'Disconnected';
    }
  } catch (e) {
    showLoader(false);
    alert(`Test failed: ${e.message}`);
  }
}

async function syncActiveMetaCredentials() {
  const token = document.getElementById('set-manual-token').value.trim() || state.settings.whatsapp_cloud_token;
  const wabaId = document.getElementById('set-manual-waba-id').value.trim() || state.settings.whatsapp_cloud_waba_id;

  if (!token || !wabaId) {
    alert('Please save/enter WABA ID and Token to execute synchronization.');
    return;
  }

  showLoader(true, 'Synchronizing profile pictures, phone status, and approved templates from Meta Cloud...');
  try {
    const res = await fetch('/api/whatsapp/sync', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ token, wabaId })
    });
    showLoader(false);
    if (res.ok) {
      alert('Synchronization completed successfully!');
      loadWaNumbers();
      renderWhatsAppTemplatesPanel();
    } else {
      const data = await res.json();
      alert(`Sync failed: ${data.error || 'Authentication error'}`);
    }
  } catch (e) {
    showLoader(false);
    alert(`Sync failed: ${e.message}`);
  }
}

async function loadWaAutomationMap() {
  try {
    const mappingsRes = await fetch('/api/whatsapp/automation-map');
    const mappings = await mappingsRes.json();

    const templates = state.settings.whatsapp_templates ? JSON.parse(state.settings.whatsapp_templates) : {};
    const tplOptions = Object.keys(templates).map(k => `<option value="${templates[k].meta_template_name}">${templates[k].meta_template_name}</option>`).join('');

    const grid = document.getElementById('wa-automation-events-grid');
    if (!grid) return;
    grid.innerHTML = '';

    mappings.forEach(map => {
      const card = document.createElement('div');
      card.className = 'card';
      card.style.background = 'rgba(255,255,255,0.01)';
      card.style.padding = '10px 15px';
      card.style.margin = '0';
      card.style.display = 'flex';
      card.style.flexDirection = 'column';
      card.style.gap = '6px';
      
      const label = map.event_key.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');

      card.innerHTML = `
        <div style="display:flex; justify-content:space-between; align-items:center;">
          <strong style="font-size:11px; color:#ddd;">${label}</strong>
          <input type="checkbox" class="wa-auto-enable" data-event="${map.event_key}" ${map.enabled ? 'checked' : ''} style="cursor:pointer;">
        </div>
        <select class="form-control form-control-sm wa-auto-tpl" data-event="${map.event_key}" style="font-size:11px;">
          <option value="">-- No Template Mapped --</option>
          ${tplOptions}
        </select>
      `;

      grid.appendChild(card);
      const select = card.querySelector('.wa-auto-tpl');
      select.value = map.template_name || '';
    });
  } catch (e) {
    console.error('Failed to load automation map:', e);
  }
}

async function saveWaAutomationMappings(e) {
  e.preventDefault();
  const mappings = [];
  const cards = document.querySelectorAll('#wa-automation-events-grid .card');
  cards.forEach(card => {
    const check = card.querySelector('.wa-auto-enable');
    const select = card.querySelector('.wa-auto-tpl');
    mappings.push({
      event_key: check.dataset.event,
      template_name: select.value,
      enabled: check.checked ? 1 : 0
    });
  });

  showLoader(true, 'Updating automation map...');
  try {
    const res = await fetch('/api/whatsapp/automation-map/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ mappings })
    });
    showLoader(false);
    if (res.ok) {
      alert('Reservation automated mappings saved successfully!');
    } else {
      alert('Failed to save mappings.');
    }
  } catch (e) {
    showLoader(false);
    alert(`Connection error: ${e.message}`);
  }
}

function copyText(id) {
  const code = document.getElementById(id);
  if (!code) return;
  navigator.clipboard.writeText(code.textContent);
  alert('Copied to clipboard!');
}

function updateDashboardWaStats(data) {
  if (!data || !data.waStats) return;
  const stats = data.waStats;

  const elActive = document.getElementById('dash-wa-numbers');
  const elStatus = document.getElementById('dash-wa-status-text');
  const elChats = document.getElementById('dash-wa-chats');
  const elUnread = document.getElementById('dash-wa-unread');
  const elSent = document.getElementById('dash-wa-sent');
  const elDelivery = document.getElementById('dash-wa-delivery-stats');
  const elEmails = document.getElementById('dash-email-sent');
  const elPending = document.getElementById('dash-wa-pending-replies');

  if (elActive) elActive.textContent = stats.activeNumbers;
  if (elStatus) elStatus.textContent = stats.defaultStatus;
  if (elChats) elChats.textContent = stats.todayChats;
  if (elUnread) elUnread.textContent = `${stats.unread} unread chats`;
  if (elSent) elSent.textContent = stats.sent;
  if (elDelivery) elDelivery.textContent = `✔ ${stats.delivered + stats.read} | Failed ${stats.failed}`;
  if (elEmails) elEmails.textContent = stats.emails;
  if (elPending) elPending.textContent = stats.pending;
}

window.switchWaSetupTab = switchWaSetupTab;
window.toggleWaMode = toggleWaMode;
window.openAddWaNumberModal = openAddWaNumberModal;
window.saveManualWaCredentials = saveManualWaCredentials;
window.saveWaNumberRegistry = saveWaNumberRegistry;
window.setDefaultWaNumber = setDefaultWaNumber;
window.deleteWaNumber = deleteWaNumber;
window.testSingleWaNumber = testSingleWaNumber;
window.testActiveWaConnection = testActiveWaConnection;
window.syncActiveMetaCredentials = syncActiveMetaCredentials;
window.saveWaAutomationMappings = saveWaAutomationMappings;
window.copyText = copyText;
window.updateDashboardWaStats = updateDashboardWaStats;

async function saveSettingsAPI(payload, successMsg) {
  showLoader(true, 'Updating configurations...');
  try {
    const res = await fetch('/api/settings', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ settings: payload, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      alert(successMsg);
      loadSettingsView();
    } else {
      alert('Fail updating settings');
    }
  } catch (e) {
    showLoader(false);
  }
}

async function loadAuditLogsTable() {
  const tbody = document.getElementById('audit-logs-table-body');
  tbody.innerHTML = '';

  try {
    const res = await fetch('/api/audit-logs');
    const logs = await res.json();
    
    logs.forEach(l => {
      const tr = document.createElement('tr');
      tr.innerHTML = `
        <td><small>${new Date(l.timestamp).toLocaleString()}</small></td>
        <td><strong>${l.user_name || 'System'}</strong></td>
        <td>${l.role || '-'}</td>
        <td><code>${l.action}</code></td>
        <td><small>${l.details || ''}</small></td>
      `;
      tbody.appendChild(tr);
    });
  } catch (e) {}
}

async function triggerDatabaseBackup() {
  showLoader(true, 'Running database backup job...');
  try {
    const res = await fetch('/api/settings/backup', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: state.currentUser.id })
    });
    
    showLoader(false);
    if (res.ok) {
      const data = await res.json();
      alert(`Database successfully backed up!\n\nLocal File:\n${data.file}\n\nGoogle Drive Sync:\n${data.googleDrive}${data.googleDriveError ? '\nError: ' + data.googleDriveError : ''}`);
      loadAuditLogsTable();
      loadLocalBackupsList();
    } else {
      alert('Backup operations failed');
    }
  } catch (e) {
    showLoader(false);
  }
}

async function saveGoogleDriveSettings(e) {
  if (e) e.preventDefault();
  const saKey = document.getElementById('set-gdrive-sa-key').value;
  const folderId = document.getElementById('set-gdrive-folder-id').value;
  const interval = document.getElementById('set-backup-interval').value;

  const payload = {
    google_drive_sa_key: saKey,
    google_drive_folder_id: folderId,
    backup_interval_hours: interval
  };

  showLoader(true, 'Saving Google Drive settings...');
  await saveSettingsAPI(payload, 'Google Drive backup settings saved successfully!');
}

async function testGoogleDriveUpload() {
  const saKey = document.getElementById('set-gdrive-sa-key').value;
  const folderId = document.getElementById('set-gdrive-folder-id').value;

  if (!saKey || !folderId) {
    return alert('Please enter both the Service Account JSON Key and Folder ID before testing.');
  }

  showLoader(true, 'Testing Google Drive connection...');
  try {
    const res = await fetch('/api/settings/google-drive-test', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ saKey, folderId, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      const data = await res.json();
      alert(`Google Drive connection test SUCCESS!\n\nUploaded test file ID:\n${data.fileId}`);
      loadAuditLogsTable();
    } else {
      const err = await res.json();
      alert(`Google Drive connection test FAILED:\n\n${err.error || 'Unknown error'}`);
    }
  } catch (err) {
    showLoader(false);
    alert(`Google Drive test failed to connect: ${err.message}`);
  }
}

async function saveSMTPSettings(e) {
  if (e) e.preventDefault();
  const host = document.getElementById('set-smtp-host').value;
  const port = document.getElementById('set-smtp-port').value;
  const secure = document.getElementById('set-smtp-secure').checked ? 'true' : 'false';
  const user = document.getElementById('set-smtp-user').value;
  const pass = document.getElementById('set-smtp-pass').value;
  const from = document.getElementById('set-smtp-from').value;

  const payload = {
    smtp_host: host,
    smtp_port: port,
    smtp_secure: secure,
    smtp_user: user,
    smtp_pass: pass,
    smtp_from: from
  };

  showLoader(true, 'Saving SMTP Email settings...');
  await saveSettingsAPI(payload, 'SMTP Email settings saved successfully!');
}

async function testSMTPConnection() {
  const host = document.getElementById('set-smtp-host').value;
  const port = document.getElementById('set-smtp-port').value;
  const secure = document.getElementById('set-smtp-secure').checked;
  const user = document.getElementById('set-smtp-user').value;
  const pass = document.getElementById('set-smtp-pass').value;
  const from = document.getElementById('set-smtp-from').value;

  if (!host || !user || !pass) {
    return alert('Please enter SMTP Host, Username, and Password before testing.');
  }

  showLoader(true, 'Verifying SMTP credentials and sending test email...');
  try {
    const res = await fetch('/api/settings/smtp-test', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ host, port, secure, user, pass, from, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      const data = await res.json();
      alert(`SMTP Connection SUCCESS!\n\n${data.message}`);
      loadAuditLogsTable();
    } else {
      const err = await res.json();
      alert(`SMTP Connection FAILED:\n\n${err.error || 'Unknown error'}`);
    }
  } catch (err) {
    showLoader(false);
    alert(`SMTP test failed to connect: ${err.message}`);
  }
}


// ================= WHATSAPP logs console simulator ================= //

async function openWhatsAppLogsModal() {
  openModal('modal-whatsapp-logs');
  renderWhatsAppLogs();
}

function formatWhatsAppSimulatorMessage(message) {
  if (!message.includes('{body}')) {
    return `<div class="whatsapp-item-body">${message.replace(/\n/g, '<br>')}</div>`;
  }

  const extractTag = (msg, tag) => {
    const match = msg.match(new RegExp(`{${tag}}([\\s\\S]*?){/${tag}}`));
    return match ? match[1].trim() : null;
  };

  const imageUrl = extractTag(message, 'image_url');
  const bodyText = (extractTag(message, 'body') || '').replace(/\n/g, '<br>');
  const footerText = extractTag(message, 'footer');
  const buttonRaw = extractTag(message, 'button');

  let html = '<div class="whatsapp-premium-bubble">';
  
  if (imageUrl) {
    html += `
      <div class="whatsapp-bubble-image-wrapper">
        <img src="${imageUrl}" class="whatsapp-bubble-img" onerror="this.parentNode.style.display='none';">
      </div>
    `;
  }

  html += `<div class="whatsapp-bubble-body">${bodyText}</div>`;

  if (footerText) {
    html += `<div class="whatsapp-bubble-footer">${footerText}</div>`;
  }

  if (buttonRaw && buttonRaw.includes('|')) {
    const [btnLabel, btnUrl] = buttonRaw.split('|').map(s => s.trim());
    html += `
      <div class="whatsapp-bubble-actions">
        <a href="${btnUrl}" target="_blank" class="whatsapp-bubble-btn">
          <svg style="width: 13px; height: 13px; fill: currentColor; margin-right: 5px; vertical-align: middle;" viewBox="0 0 24 24">
            <path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/>
          </svg>
          ${btnLabel}
        </a>
      </div>
    `;
  }

  html += '</div>';
  return html;
}

async function renderWhatsAppLogs() {
  const listEl = document.getElementById('whatsapp-queue-list');
  listEl.innerHTML = '<div style="text-align:center; color:#888;">Fetching queue...</div>';
  
  try {
    const res = await fetch('/api/whatsapp-simulator');
    const logs = await res.json();
    state.whatsappLogs = logs;

    listEl.innerHTML = '';
    if (logs.length === 0) {
      listEl.innerHTML = '<div style="text-align:center; color:#888; padding:20px;">No messages sent yet.</div>';
      return;
    }

    logs.forEach(item => {
      const div = document.createElement('div');
      div.className = 'whatsapp-item';
      
      let statusHTML = '';
      if (item.status === 'Read') {
        statusHTML = `<span style="color:#53bdeb; font-weight:600;">✔✔ Read</span>`;
      } else if (item.status === 'Delivered') {
        statusHTML = `<span style="color:#00a884; font-weight:600;">✔✔ Delivered</span>`;
      } else if (item.status === 'Failed') {
        const errorReason = item.error ? `: ${item.error}` : '';
        statusHTML = `<span style="color:#f23f43; font-weight:600;" title="${item.error || 'Undelivered'}">❌ Failed${errorReason}</span>`;
      } else {
        statusHTML = `<span style="color:#8696a0;">✔ Sent</span>`;
      }

      div.innerHTML = `
        <div class="whatsapp-item-meta" style="display:flex; justify-content:space-between; align-items:center; border-bottom: 1px dashed rgba(255,255,255,0.05); padding-bottom:6px; margin-bottom:8px;">
          <span>Recipient: <strong>${item.phone}</strong></span>
          <span style="font-size:11px;">${new Date(item.timestamp).toLocaleTimeString()} - ${statusHTML}</span>
        </div>
        ${formatWhatsAppSimulatorMessage(item.message)}
      `;
      listEl.appendChild(div);
    });

    // Clear badge
    document.getElementById('whatsapp-badge').classList.add('hidden');
  } catch (e) {}
}

async function pollWhatsAppLogsCount() {
  try {
    const res = await fetch('/api/whatsapp-simulator');
    const logs = await res.json();
    
    const badge = document.getElementById('whatsapp-badge');
    const diff = logs.length - state.whatsappLogs.length;
    
    if (diff > 0) {
      badge.textContent = diff;
      badge.classList.remove('hidden');
    } else {
      badge.classList.add('hidden');
    }
  } catch (e) {}
}



// ================= FLOORS SETUP LOGIC =================
async function loadFloorSettingsTable() {
  const tbody = document.getElementById('floor-list-tbody');
  if (!tbody) return;
  tbody.innerHTML = '';
  try {
    const res = await fetch('/api/floors');
    const floors = await res.json();
    floors.forEach(f => {
      const tr = document.createElement('tr');
      tr.innerHTML = `
        <td style="padding: 10px 12px; color:#fff;">Floor ${f.name}</td>
        <td style="text-align: right; padding: 10px 12px;">
          <button class="btn btn-danger btn-sm" onclick="deleteFloor(${f.id})">Delete</button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  } catch (err) {
    console.error('Failed to load floors:', err);
  }
}

async function handleAddFloorSubmit(e) {
  e.preventDefault();
  const nameInput = document.getElementById('add-floor-name');
  const name = nameInput.value.trim();
  if (!name) return;

  showLoader(true, 'Creating floor...');
  try {
    const res = await fetch('/api/floors/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      nameInput.value = '';
      loadFloorSettingsTable();
      loadSettingsView();
    } else {
      const err = await res.json();
      alert(err.error || 'Failed to add floor.');
    }
  } catch (e) {
    showLoader(false);
    alert('Connection error.');
  }
}

async function deleteFloor(floorId) {
  if (!confirm('Are you sure you want to delete this floor?')) return;
  showLoader(true, 'Deleting floor...');
  try {
    const res = await fetch('/api/floors/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ floorId, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      loadFloorSettingsTable();
      loadSettingsView();
    } else {
      const err = await res.json();
      alert(err.error || 'Failed to delete floor.');
    }
  } catch (e) {
    showLoader(false);
    alert('Connection error.');
  }
}

// ================= OTA / CHANNEL MANAGER LOGIC =================
async function loadOTABookingsTable() {
  const tbody = document.getElementById('ota-bookings-tbody');
  if (!tbody) return;
  tbody.innerHTML = '';
  try {
    const [otaRes, roomsRes] = await Promise.all([
      fetch('/api/ota/bookings'),
      fetch('/api/rooms')
    ]);
    const bookings = await otaRes.json();
    const rooms = await roomsRes.json();
    
    state.adminRoomsList = rooms;

    if (bookings.length === 0) {
      tbody.innerHTML = `<tr><td colspan="8" style="text-align: center; color: #888; padding: 20px;">No pending online channel bookings.</td></tr>`;
      return;
    }

    bookings.forEach(b => {
      const tr = document.createElement('tr');
      
      const matchingVacantRooms = rooms.filter(r => r.room_type_id === b.room_type_id && r.status === 'Vacant');
      
      let actionsHTML = '';
      if (b.status === 'Pending') {
        if (matchingVacantRooms.length === 0) {
          actionsHTML = `<span class="text-danger" style="font-size:12px; font-weight:600;">No Vacant ${b.room_type} Room Available</span>`;
        } else {
          let selectOptions = `<option value="">Select Room...</option>`;
          matchingVacantRooms.forEach(vr => {
            selectOptions += `<option value="${vr.id}">Room ${vr.room_number}</option>`;
          });
          
          actionsHTML = `
            <div style="display: flex; gap: 6px;">
              <select id="ota-room-map-${b.id}" class="form-control form-control-sm" style="width: 130px; font-size:12px; padding: 2px 6px; height: auto;">
                ${selectOptions}
              </select>
              <button class="btn btn-primary btn-sm" onclick="mapOTABooking(${b.id}, ${b.room_type_id})">Map & Book</button>
            </div>
          `;
        }
      } else {
        actionsHTML = `<span class="text-success" style="font-weight: 600;">Mapped & Confirmed</span>`;
      }

      let statusBadge = `<span class="text-warning">${b.status}</span>`;
      if (b.status === 'Mapped') {
        statusBadge = `<span class="text-success" style="font-weight:600;">Mapped</span>`;
      }

      tr.innerHTML = `
        <td><strong>${b.channel}</strong></td>
        <td><code>${b.ota_booking_uid}</code></td>
        <td>
          <div style="font-weight:600; font-size:13px; color:#fff;">${b.guest_name}</div>
          <div style="font-size:11px; color:#888;">${b.guest_mobile}</div>
        </td>
        <td style="color:#eee;">
          <div style="font-size:12px;">In: ${b.check_in}</div>
          <div style="font-size:12px;">Out: ${b.check_out}</div>
        </td>
        <td><span class="badge" style="background:rgba(255,255,255,0.08); color:#fff; padding: 4px 8px; border-radius: 4px; font-size:12px;">${b.room_type}</span></td>
        <td style="color:#fff;"><strong>₹${b.amount.toLocaleString()}</strong></td>
        <td>${statusBadge}</td>
        <td style="text-align: right; padding-right: 15px;">${actionsHTML}</td>
      `;
      tbody.appendChild(tr);
    });
  } catch (err) {
    console.error('Failed to load OTA bookings:', err);
  }
}

async function syncOTAChannels() {
  showLoader(true, 'Connecting to channel APIs (Booking.com, MakeMyTrip, Agoda)...');
  try {
    const res = await fetch('/api/ota/bookings/sync', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      alert('Channel Synchronization Complete!\n\nNew incoming bookings fetched and inventory updated successfully.');
      loadOTABookingsTable();
    } else {
      alert('Channel sync failed.');
    }
  } catch (e) {
    showLoader(false);
    alert('Connection error syncing channels.');
  }
}

async function mapOTABooking(otaBookingId, roomTypeId) {
  const roomSelect = document.getElementById(`ota-room-map-${otaBookingId}`);
  if (!roomSelect) return;
  const roomId = parseInt(roomSelect.value, 10);
  if (!roomId) {
    alert('Please select a room to map this OTA booking.');
    return;
  }

  showLoader(true, 'Mapping OTA Booking...');
  try {
    // 1. Fetch the OTA booking details first
    const otaRes = await fetch('/api/ota/bookings');
    const bookings = await otaRes.json();
    const b = bookings.find(item => item.id === otaBookingId);
    if (!b) throw new Error('OTA Booking not found');

    // 2. Submit booking to local database
    const bookingPayload = {
      guestSearchVal: '', // walk-in new guest
      isNewGuest: true,
      // Guest fields
      name: b.guest_name,
      mobile: b.guest_mobile,
      email: '',
      docType: 'Aadhaar',
      docNumber: 'NOT_PROVIDED',
      address: 'Online Sync',
      companyName: '',
      gstNumber: '',
      vehicleNumber: '',
      isVip: false,
      photo: '',
      // Booking details
      checkIn: b.check_in,
      checkOut: b.check_out,
      status: 'Confirmed', // Sync maps as Confirmed Advance Booking
      rooms: [
        { roomId: roomId, price: b.amount }
      ],
      totalAmount: b.amount,
      paidAmount: 0,
      gstAmount: Math.round(b.amount * 0.05),
      userId: state.currentUser.id
    };

    const resMap = await fetch('/api/bookings/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(bookingPayload)
    });

    if (!resMap.ok) {
      const err = await resMap.json();
      throw new Error(err.error || 'Failed to save mapped booking');
    }

    // 3. Mark OTA booking status as Mapped on server
    await fetch('/api/ota/bookings/map', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ otaBookingId, userId: state.currentUser.id })
    });

    showLoader(false);
    alert('OTA Booking mapped successfully and local room reservation confirmed!');
    loadOTABookingsTable();
    loadDashboardView();
  } catch (err) {
    showLoader(false);
    alert('Mapping failed: ' + err.message);
  }
}

// ================= GOOGLE BUSINESS PROFILE & LOCAL SEO LOGIC =================
function switchGmbTab(tabId) {
  const tabs = ['gmb-tab-overview', 'gmb-tab-profile', 'gmb-tab-reviews', 'gmb-tab-posts', 'gmb-tab-seo', 'gmb-tab-competitors', 'gmb-tab-connection'];
  tabs.forEach(t => {
    const el = document.getElementById(t);
    const btn = document.getElementById(`btn-${t}`);
    if (el) el.style.display = t === tabId ? 'block' : 'none';
    if (btn) {
      if (t === tabId) btn.classList.add('active');
      else btn.classList.remove('active');
    }
  });

  if (tabId === 'gmb-tab-overview') {
    loadGbpPerformance();
  } else if (tabId === 'gmb-tab-profile') {
    loadGbpProfile();
    loadGbpPhotos();
  } else if (tabId === 'gmb-tab-reviews') {
    loadGbpReviews();
  } else if (tabId === 'gmb-tab-posts') {
    loadGbpPosts();
  } else if (tabId === 'gmb-tab-seo') {
    loadGbpKeywords();
    loadGbpSeoStatus();
  } else if (tabId === 'gmb-tab-competitors') {
    loadGbpCompetitors();
  }
}

async function loadGbpView() {
  showLoader(true, 'Synchronizing Google Business Profile data...');
  try {
    const statsRes = await fetch('/api/google/dashboard-stats');
    const stats = await statsRes.json();
    showLoader(false);

    const badge = document.getElementById('gbp-connection-badge');
    if (!stats.connected) {
      if (badge) {
        badge.className = 'badge badge-danger';
        badge.textContent = 'Disconnected';
      }
      alert('Google Business Profile is disconnected. Please sign in via the OAuth Credentials tab.');
      switchGmbTab('gmb-tab-connection');
      return;
    }

    if (badge) {
      badge.className = stats.status === 'Connected' ? 'badge badge-success' : 'badge badge-warning';
      badge.textContent = stats.status;
    }

    document.getElementById('gbp-stat-rating').innerHTML = `${stats.rating} <span style="font-size:12px; color:#888;">★</span>`;
    document.getElementById('gbp-stat-reviews-count').textContent = `${stats.totalReviews} total reviews`;
    document.getElementById('gbp-stat-views').textContent = (stats.weeklySearchViews + stats.weeklyMapsViews).toLocaleString();
    document.getElementById('gbp-stat-completion').textContent = `${stats.completionScore}%`;
    document.getElementById('gbp-stat-seo-score').textContent = `${stats.seoHealthScore}%`;

    switchGmbTab('gmb-tab-overview');
  } catch (e) {
    showLoader(false);
    console.error('Failed to load GBP view:', e);
  }
}

let gmbChartInstance = null;
async function loadGbpPerformance() {
  try {
    const res = await fetch('/api/google/performance');
    if (!res.ok) return;
    const data = await res.json();

    const labels = data.map(item => {
      const parts = item.metric_date.split('-');
      return parts[1] + '/' + parts[2];
    });
    const searchViews = data.map(item => item.search_views);
    const mapsViews = data.map(item => item.maps_views);
    const webClicks = data.map(item => item.website_clicks);
    const directionRequests = data.map(item => item.direction_requests);
    const phoneCalls = data.map(item => item.phone_calls);

    const sumWeb = webClicks.reduce((a,b)=>a+b, 0);
    const sumDir = directionRequests.reduce((a,b)=>a+b, 0);
    const sumCalls = phoneCalls.reduce((a,b)=>a+b, 0);
    const sumBookings = data.map(item => item.booking_clicks).reduce((a,b)=>a+b, 0);
    const sumPhotos = data.map(item => item.photo_views).reduce((a,b)=>a+b, 0);

    document.getElementById('gbp-perf-web').textContent = sumWeb;
    document.getElementById('gbp-perf-directions').textContent = sumDir;
    document.getElementById('gbp-perf-calls').textContent = sumCalls;
    document.getElementById('gbp-perf-bookings').textContent = sumBookings;
    document.getElementById('gbp-perf-photos').textContent = sumPhotos;

    const ctx = document.getElementById('gmb-impression-chart');
    if (!ctx) return;

    if (gmbChartInstance) {
      gmbChartInstance.destroy();
    }

    gmbChartInstance = new Chart(ctx, {
      type: 'line',
      data: {
        labels: labels,
        datasets: [
          {
            label: 'Google Search Views',
            data: searchViews,
            borderColor: '#3b82f6',
            backgroundColor: 'rgba(59, 130, 246, 0.1)',
            fill: true,
            tension: 0.3
          },
          {
            label: 'Google Maps Views',
            data: mapsViews,
            borderColor: '#10b981',
            backgroundColor: 'rgba(16, 185, 129, 0.1)',
            fill: true,
            tension: 0.3
          }
        ]
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
          legend: {
            labels: { color: '#ccc', font: { size: 10 } }
          }
        },
        scales: {
          x: { ticks: { color: '#888', font: { size: 9 } }, grid: { display: false } },
          y: { ticks: { color: '#888', font: { size: 9 } }, grid: { color: 'rgba(255,255,255,0.05)' } }
        }
      }
    });
  } catch (e) {
    console.error('Failed to load performance charts:', e);
  }
}

async function loadGbpProfile() {
  try {
    const res = await fetch('/api/google/profile');
    if (!res.ok) return;
    const data = await res.json();

    document.getElementById('gbp-prof-name').value = data.business_name || '';
    document.getElementById('gbp-prof-category').value = data.primary_category || '';
    document.getElementById('gbp-prof-address').value = data.address || '';
    document.getElementById('gbp-prof-phone').value = data.phone || '';
    document.getElementById('gbp-prof-website').value = data.website || '';
    
    document.getElementById('gbp-prof-checkin').value = state.settings.gmb_checkin_time || '12:00';
    document.getElementById('gbp-prof-checkout').value = state.settings.gmb_checkout_time || '11:00';
    document.getElementById('gbp-prof-amenities').value = state.settings.gmb_amenities || 'Free Wi-Fi, Swimming Pool, Private Parking, Room Service';
  } catch (e) {
    console.error('Failed to load GMB profile:', e);
  }
}

async function saveGbpProfile(e) {
  e.preventDefault();
  const payload = {
    business_name: document.getElementById('gbp-prof-name').value,
    primary_category: document.getElementById('gbp-prof-category').value,
    address: document.getElementById('gbp-prof-address').value,
    phone: document.getElementById('gbp-prof-phone').value,
    website: document.getElementById('gbp-prof-website').value,
    checkin_time: document.getElementById('gbp-prof-checkin').value,
    checkout_time: document.getElementById('gbp-prof-checkout').value,
    amenities: document.getElementById('gbp-prof-amenities').value
  };

  showLoader(true, 'Updating listing details on Google Business Profile...');
  try {
    const res = await fetch('/api/google/profile/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
    showLoader(false);
    if (res.ok) {
      alert('Listing profile attributes synchronized successfully!');
      loadSettingsView();
    } else {
      alert('Failed to publish changes.');
    }
  } catch (err) {
    showLoader(false);
    alert('Connection error: ' + err.message);
  }
}

async function loadGbpPhotos() {
  try {
    const res = await fetch('/api/google/photos');
    if (!res.ok) return;
    const photos = await res.json();
    const grid = document.getElementById('gbp-photos-grid');
    if (!grid) return;
    grid.innerHTML = '';

    photos.forEach(p => {
      const card = document.createElement('div');
      card.className = 'card';
      card.style.background = 'rgba(255,255,255,0.02)';
      card.style.padding = '8px';
      card.style.margin = '0';
      card.style.display = 'flex';
      card.style.flexDirection = 'column';
      card.style.gap = '6px';

      card.innerHTML = `
        <div style="position:relative; width:100%; height:80px; overflow:hidden; border-radius:4px; background:#1e293b;">
          <img src="${p.url}" alt="${p.name}" style="width:100%; height:100%; object-fit:cover;">
          <span class="badge badge-primary" style="position:absolute; bottom:4px; left:4px; font-size:8px; text-transform:uppercase; padding:2px 4px;">${p.category}</span>
        </div>
        <div style="display:flex; justify-content:space-between; align-items:center;">
          <span style="font-size:9px; color:#ccc; font-weight:bold; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; width:110px;">${p.name}</span>
          <button type="button" class="btn btn-danger btn-xs" onclick="deleteGbpPhoto(${p.id})" style="padding:1px 4px; font-size:8px;">Delete</button>
        </div>
      `;
      grid.appendChild(card);
    });
  } catch (e) {
    console.error('Failed to load GBP photos:', e);
  }
}

function openAddGbpPhotoModal() {
  document.getElementById('gbp-photo-form').reset();
  openModal('modal-gbp-photo');
}

async function uploadGbpPhoto(e) {
  e.preventDefault();
  const payload = {
    name: document.getElementById('gbp-photo-name').value.trim(),
    category: document.getElementById('gbp-photo-category').value,
    url: document.getElementById('gbp-photo-url').value.trim()
  };

  showLoader(true, 'Publishing photo upload to Google maps listing...');
  try {
    const res = await fetch('/api/google/photos/upload', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
    showLoader(false);
    if (res.ok) {
      closeModal('modal-gbp-photo');
      alert('Photo published successfully!');
      loadGbpPhotos();
    } else {
      alert('Upload failed.');
    }
  } catch (err) {
    showLoader(false);
    alert('Connection error: ' + err.message);
  }
}

async function deleteGbpPhoto(id) {
  if (!confirm('Are you sure you want to remove this photo from the Google Business Profile?')) return;
  showLoader(true, 'Removing photo...');
  try {
    const res = await fetch('/api/google/photos/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id })
    });
    showLoader(false);
    if (res.ok) {
      loadGbpPhotos();
    }
  } catch (err) {
    showLoader(false);
  }
}

async function loadGbpReviews() {
  const container = document.getElementById('gbp-reviews-feed-list');
  if (!container) return;
  container.innerHTML = '';

  const rating = document.getElementById('gbp-review-rating-filter').value;
  const status = document.getElementById('gbp-review-status-filter').value;
  const search = document.getElementById('gbp-review-search-txt').value.trim();

  try {
    const res = await fetch(`/api/google/reviews?rating=${rating}&status=${status}&search=${encodeURIComponent(search)}`);
    if (!res.ok) return;
    const reviews = await res.json();

    if (reviews.length === 0) {
      container.innerHTML = `<div style="text-align:center; padding:30px; color:#888; font-size:11px;">No reviews match active filters.</div>`;
      return;
    }

    const staffRes = await fetch('/api/staff');
    const staffList = staffRes.ok ? await staffRes.json() : [];
    const staffOptions = staffList.map(s => `<option value="${s.id}">${s.name}</option>`).join('');

    reviews.forEach(r => {
      const card = document.createElement('div');
      card.className = 'card';
      card.style.background = 'rgba(255,255,255,0.01)';
      card.style.border = '1px solid rgba(255,255,255,0.04)';
      card.style.padding = '15px';
      card.style.margin = '0';
      card.style.display = 'flex';
      card.style.flexDirection = 'column';
      card.style.gap = '10px';

      const stars = '★'.repeat(r.rating) + '☆'.repeat(5 - r.rating);
      const isReplied = r.status === 'Replied';

      card.innerHTML = `
        <div style="display:flex; justify-content:space-between; align-items:center; font-size:11px;">
          <div style="display:flex; align-items:center; gap:8px;">
            <div style="width:28px; height:28px; border-radius:50%; background:#3b82f6; display:flex; align-items:center; justify-content:center; color:#fff; font-weight:bold; font-size:11px;">
              ${r.reviewer_name.charAt(0)}
            </div>
            <div>
              <strong style="color:#fff; font-size:12px;">${r.reviewer_name}</strong>
              <span style="color:#666; margin-left:6px;">${new Date(r.review_time).toLocaleDateString()}</span>
            </div>
          </div>
          <div style="display:flex; align-items:center; gap:8px;">
            <span style="color:#eab308; font-weight:bold; font-size:12px;">${stars}</span>
            <span class="badge badge-${isReplied ? 'success' : 'warning'}" style="font-size:9px;">${r.status}</span>
          </div>
        </div>

        <p style="margin:0; font-size:11px; color:#ddd; line-height:1.4; font-style:italic;">"${r.comment || '(No comment text)'}"</p>

        <div style="display:flex; flex-direction:column; gap:8px; border-top:1px solid rgba(255,255,255,0.04); padding-top:10px; margin-top:5px;">
          <div style="display:flex; justify-content:space-between; align-items:center; gap:10px; font-size:10px;">
            <div style="display:flex; align-items:center; gap:12px;">
              <label style="display:flex; align-items:center; gap:4px; margin:0; cursor:pointer;">
                <input type="checkbox" onchange="toggleGbpReviewHandled('${r.review_id}', this.checked)" ${r.is_handled ? 'checked' : ''}>
                <span style="color:#aaa;">Mark Handled</span>
              </label>
              <label style="display:flex; align-items:center; gap:4px; margin:0;">
                <span style="color:#aaa;">Assignee:</span>
                <select class="form-control" style="width:110px; font-size:10px; padding:2px; height:22px;" onchange="assignGbpReview('${r.review_id}', this.value)">
                  <option value="">Unassigned</option>
                  ${staffOptions}
                </select>
              </label>
            </div>
            
            <button type="button" class="btn btn-secondary btn-xs" onclick="suggestGbpAiReply('${r.review_id}', ${r.rating}, ${JSON.stringify(r.comment || '').replace(/"/g, '&quot;')})" style="font-size:9px; padding:2px 6px;">✨ Suggest AI Reply</button>
          </div>

          <div id="ai-draft-box-${r.review_id}" style="display:none; background:rgba(139,92,246,0.05); border:1px dashed #8b5cf6; padding:6px; border-radius:4px; font-size:10px; color:#ccc;">
            <strong style="color:#8b5cf6;">AI Suggestion:</strong> <span id="ai-draft-txt-${r.review_id}"></span>
            <div style="text-align:right; margin-top:4px;">
              <button type="button" class="btn btn-secondary btn-xs" style="font-size:8px; padding:1px 4px;" onclick="applyAiDraft('${r.review_id}')">Apply Draft</button>
            </div>
          </div>

          <div style="display:flex; gap:8px;">
            <textarea id="review-reply-txt-${r.review_id}" class="form-control" rows="2" placeholder="Write reply to customer review..." style="font-size:11px; resize:none;">${r.reply_text || ''}</textarea>
            <button type="button" class="btn btn-primary" onclick="submitGbpReviewReply('${r.review_id}')" style="font-size:10px; font-weight:bold; width:90px; padding:4px 8px;">Publish</button>
          </div>
        </div>
      `;
      container.appendChild(card);
      
      const select = card.querySelector('select');
      if (select) select.value = r.assigned_staff_id || '';
    });
  } catch (e) {
    console.error('Failed to load GMB reviews inbox:', e);
  }
}

async function submitGbpReviewReply(reviewId) {
  const replyText = document.getElementById(`review-reply-txt-${reviewId}`).value.trim();
  showLoader(true, 'Publishing reply response to Google reviews platform...');
  try {
    const res = await fetch('/api/google/reviews/reply', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ reviewId, replyText })
    });
    showLoader(false);
    if (res.ok) {
      alert('Review reply published successfully!');
      loadGbpReviews();
    } else {
      alert('Failed to publish reply.');
    }
  } catch (err) {
    showLoader(false);
    alert('Connection error: ' + err.message);
  }
}

async function assignGbpReview(reviewId, staffId) {
  try {
    await fetch('/api/google/reviews/reply', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ reviewId, assignedStaffId: staffId ? parseInt(staffId, 10) : null })
    });
  } catch (e) {}
}

async function toggleGbpReviewHandled(reviewId, checked) {
  try {
    await fetch('/api/google/reviews/reply', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ reviewId, isHandled: checked ? 1 : 0 })
    });
  } catch (e) {}
}

async function suggestGbpAiReply(reviewId, rating, comment) {
  const draftBox = document.getElementById(`ai-draft-box-${reviewId}`);
  const draftTxt = document.getElementById(`ai-draft-txt-${reviewId}`);
  if (!draftBox || !draftTxt) return;

  draftTxt.textContent = 'Generating suggestion...';
  draftBox.style.display = 'block';

  try {
    const res = await fetch('/api/google/reviews/ai-suggest', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ rating, comment })
    });
    if (res.ok) {
      const data = await res.json();
      draftTxt.textContent = data.suggestion;
    } else {
      draftTxt.textContent = 'Failed to fetch AI reply.';
    }
  } catch (e) {
    draftTxt.textContent = 'Connection error.';
  }
}

function applyAiDraft(reviewId) {
  const draftTxt = document.getElementById(`ai-draft-txt-${reviewId}`).textContent;
  const textarea = document.getElementById(`review-reply-txt-${reviewId}`);
  if (textarea) {
    textarea.value = draftTxt;
  }
  const draftBox = document.getElementById(`ai-draft-box-${reviewId}`);
  if (draftBox) draftBox.style.display = 'none';
}

async function loadGbpPosts() {
  try {
    const res = await fetch('/api/google/posts');
    if (!res.ok) return;
    const posts = await res.json();
    const container = document.getElementById('gbp-posts-catalog');
    if (!container) return;
    container.innerHTML = '';

    if (posts.length === 0) {
      container.innerHTML = `<div style="grid-column: 1/-1; text-align:center; padding:30px; color:#888; font-size:11px;">No local posts published yet.</div>`;
      return;
    }

    posts.forEach(p => {
      const card = document.createElement('div');
      card.className = 'card';
      card.style.background = 'rgba(255,255,255,0.01)';
      card.style.border = '1px solid rgba(255,255,255,0.04)';
      card.style.padding = '12px';
      card.style.margin = '0';
      card.style.display = 'flex';
      card.style.flexDirection = 'column';
      card.style.gap = '8px';

      const typeLabel = p.post_type.toUpperCase().replace('_', ' ');

      card.innerHTML = `
        <div style="display:flex; justify-content:space-between; align-items:center;">
          <span class="badge badge-primary" style="font-size:8px;">${typeLabel}</span>
          <span class="badge badge-${p.status === 'published' ? 'success' : p.status === 'scheduled' ? 'warning' : 'secondary'}" style="font-size:8px;">${p.status}</span>
        </div>
        ${p.image_url ? `
        <div style="width:100%; height:120px; overflow:hidden; border-radius:4px; background:#1e293b;">
          <img src="${p.image_url}" alt="Post Banner" style="width:100%; height:100%; object-fit:cover;">
        </div>` : ''}
        <p style="margin:0; font-size:11px; color:#ddd; line-height:1.4; overflow:hidden; display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical;">${p.summary}</p>
        ${p.call_to_action ? `
        <div style="font-size:10px; color:#aaa; font-weight:bold;">
          Button: <span style="color:#a5b4fc;">${p.call_to_action}</span> ➔ <a href="${p.action_url}" target="_blank" style="color:#3b82f6;">Link</a>
        </div>` : ''}
        <div style="display:flex; justify-content:space-between; align-items:center; border-top:1px solid rgba(255,255,255,0.04); padding-top:8px; font-size:9px; color:#666;">
          <span>Created: ${new Date(p.created_at).toLocaleDateString()}</span>
          <div style="display:flex; gap:6px;">
            <button type="button" class="btn btn-secondary btn-xs" onclick="editGbpPost(${JSON.stringify(p).replace(/"/g, '&quot;')})" style="padding:1px 4px; font-size:8px;">Edit</button>
            <button type="button" class="btn btn-danger btn-xs" onclick="deleteGbpPost(${p.id})" style="padding:1px 4px; font-size:8px;">Delete</button>
          </div>
        </div>
      `;
      container.appendChild(card);
    });
  } catch (e) {
    console.error('Failed to load GBP posts:', e);
  }
}

function openAddGbpPostModal() {
  document.getElementById('gbp-post-form').reset();
  document.getElementById('gbp-post-id').value = '';
  document.getElementById('gbp-post-modal-title').textContent = 'Compose Google Business Post';
  toggleGbpPostTypeFields();
  openModal('modal-gbp-post');
}

function toggleGbpPostTypeFields() {
  const type = document.getElementById('gbp-post-type').value;
  
  const titleRow = document.getElementById('gbp-post-title-row');
  const titleLabel = document.getElementById('gbp-post-title-label');
  const titleInput = document.getElementById('gbp-post-title');
  const datesRow = document.getElementById('gbp-post-dates-row');
  const ctaRow = document.getElementById('gbp-post-cta-row');
  const offerDetailsRow = document.getElementById('gbp-post-offer-details-row');
  
  if (type === 'whats_new') {
    if (titleRow) titleRow.style.display = 'none';
    if (titleInput) titleInput.removeAttribute('required');
    if (datesRow) datesRow.style.display = 'none';
    if (ctaRow) ctaRow.style.display = 'grid';
    if (offerDetailsRow) offerDetailsRow.style.display = 'none';
  } else if (type === 'offer') {
    if (titleRow) {
      titleRow.style.display = 'block';
      titleLabel.innerHTML = 'Offer Title <span style="color:var(--color-maintenance);">*</span>';
      titleInput.placeholder = 'E.g., 20% Off Weekend Getaway';
      titleInput.setAttribute('required', 'required');
    }
    if (datesRow) datesRow.style.display = 'grid';
    if (ctaRow) ctaRow.style.display = 'none';
    if (offerDetailsRow) offerDetailsRow.style.display = 'flex';
  } else if (type === 'event') {
    if (titleRow) {
      titleRow.style.display = 'block';
      titleLabel.innerHTML = 'Event Title <span style="color:var(--color-maintenance);">*</span>';
      titleInput.placeholder = 'E.g., Live Music Night & Buffet';
      titleInput.setAttribute('required', 'required');
    }
    if (datesRow) datesRow.style.display = 'grid';
    if (ctaRow) ctaRow.style.display = 'grid';
    if (offerDetailsRow) offerDetailsRow.style.display = 'none';
  }
}

window.editGbpPost = function(p) {
  document.getElementById('gbp-post-id').value = p.id;
  document.getElementById('gbp-post-type').value = p.post_type;
  document.getElementById('gbp-post-title').value = p.title || '';
  document.getElementById('gbp-post-summary').value = p.summary;
  document.getElementById('gbp-post-image-url').value = p.image_url || '';
  document.getElementById('gbp-post-cta').value = p.call_to_action || '';
  document.getElementById('gbp-post-action-url').value = p.action_url || '';
  document.getElementById('gbp-post-offer-url').value = p.action_url || '';
  document.getElementById('gbp-post-start-date').value = p.start_date || '';
  document.getElementById('gbp-post-end-date').value = p.end_date || '';
  document.getElementById('gbp-post-coupon').value = p.coupon_code || '';
  document.getElementById('gbp-post-terms').value = p.terms_conditions || '';
  document.getElementById('gbp-post-schedule').value = p.schedule_time || '';
  document.getElementById('gbp-post-status').value = p.status;
  document.getElementById('gbp-post-modal-title').textContent = 'Edit Google Post';
  
  toggleGbpPostTypeFields();
  openModal('modal-gbp-post');
};

async function saveGbpPost(e) {
  e.preventDefault();
  const id = document.getElementById('gbp-post-id').value;
  const postType = document.getElementById('gbp-post-type').value;
  
  let actionUrl = '';
  if (postType === 'offer') {
    actionUrl = document.getElementById('gbp-post-offer-url').value.trim();
  } else {
    actionUrl = document.getElementById('gbp-post-action-url').value.trim();
  }
  
  const payload = {
    post_type: postType,
    title: document.getElementById('gbp-post-title').value.trim(),
    summary: document.getElementById('gbp-post-summary').value.trim(),
    image_url: document.getElementById('gbp-post-image-url').value.trim(),
    call_to_action: document.getElementById('gbp-post-cta').value,
    action_url: actionUrl,
    start_date: document.getElementById('gbp-post-start-date').value,
    end_date: document.getElementById('gbp-post-end-date').value,
    coupon_code: document.getElementById('gbp-post-coupon').value.trim(),
    terms_conditions: document.getElementById('gbp-post-terms').value.trim(),
    schedule_time: document.getElementById('gbp-post-schedule').value,
    status: document.getElementById('gbp-post-status').value
  };
  if (id) payload.id = parseInt(id, 10);

  showLoader(true, 'Synchronizing post update with Google My Business API...');
  try {
    const res = await fetch('/api/google/posts/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
    showLoader(false);
    if (res.ok) {
      closeModal('modal-gbp-post');
      alert('Post compiled successfully!');
      loadGbpPosts();
    } else {
      alert('Failed to publish post.');
    }
  } catch (err) {
    showLoader(false);
    alert('Connection error: ' + err.message);
  }
}

async function deleteGbpPost(id) {
  if (!confirm('Are you sure you want to delete this post from the Google Business Profile?')) return;
  showLoader(true, 'Removing post...');
  try {
    const res = await fetch('/api/google/posts/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id })
    });
    showLoader(false);
    if (res.ok) {
      loadGbpPosts();
    }
  } catch (err) {
    showLoader(false);
  }
}

async function loadGbpKeywords() {
  try {
    const res = await fetch('/api/google/keywords');
    if (!res.ok) return;
    const list = await res.json();
    const tbody = document.getElementById('gbp-keywords-table-tbody');
    if (!tbody) return;
    tbody.innerHTML = '';

    if (list.length === 0) {
      tbody.innerHTML = `<tr><td colspan="6" style="text-align:center; color:#888;">No tracked keywords index yet.</td></tr>`;
      return;
    }

    list.forEach(k => {
      const tr = document.createElement('tr');
      tr.innerHTML = `
        <td><strong>${k.keyword}</strong></td>
        <td><span class="badge badge-secondary" style="font-size:9px; text-transform:uppercase;">${k.category}</span></td>
        <td>${k.search_volume.toLocaleString()}</td>
        <td><span class="badge badge-${k.competition === 'high' ? 'danger' : k.competition === 'medium' ? 'warning' : 'success'}" style="font-size:9px;">${k.competition}</span></td>
        <td><span style="font-weight:bold; color:#10b981;">#${k.ranking_position}</span></td>
        <td><button type="button" class="btn btn-danger btn-xs" onclick="deleteGbpKeyword(${k.id})" style="padding:1px 4px; font-size:8px;">Remove</button></td>
      `;
      tbody.appendChild(tr);
    });
  } catch (e) {
    console.error('Failed to load keywords registry:', e);
  }
}

function openAddKeywordModal() {
  document.getElementById('gbp-keyword-form').reset();
  openModal('modal-gbp-keyword');
}

async function saveGbpKeyword(e) {
  e.preventDefault();
  const payload = {
    keyword: document.getElementById('gbp-key-term').value.trim(),
    category: document.getElementById('gbp-key-category').value,
    search_volume: parseInt(document.getElementById('gbp-key-volume').value, 10) || 0,
    competition: document.getElementById('gbp-key-competition').value,
    ranking_position: parseInt(document.getElementById('gbp-key-rank').value, 10) || 0,
    click_potential: parseInt(document.getElementById('gbp-key-potential').value, 10) || 80
  };

  showLoader(true, 'Registering keyword term for tracking...');
  try {
    const res = await fetch('/api/google/keywords/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
    showLoader(false);
    if (res.ok) {
      closeModal('modal-gbp-keyword');
      loadGbpKeywords();
    } else {
      alert('Save failed.');
    }
  } catch (err) {
    showLoader(false);
    alert('Connection error: ' + err.message);
  }
}

async function deleteGbpKeyword(id) {
  if (!confirm('Stop tracking this keyword?')) return;
  showLoader(true, 'Deleting keyword...');
  try {
    const res = await fetch('/api/google/keywords/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id })
    });
    showLoader(false);
    if (res.ok) {
      loadGbpKeywords();
    }
  } catch (err) {
    showLoader(false);
  }
}

async function loadGbpSeoStatus() {
  try {
    const res = await fetch('/api/google/seo-status');
    if (!res.ok) return;
    const data = await res.json();
    const container = document.getElementById('gbp-nap-audit-content');
    if (!container) return;
    
    const consistent = data.napConsistent;
    
    container.innerHTML = `
      <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; background:rgba(255,255,255,0.02); padding:8px; border-radius:4px; border:1px solid ${consistent ? 'rgba(16,185,129,0.1)' : 'rgba(239,68,68,0.1)'};">
        <span style="font-weight:bold;">NAP Alignment Status:</span>
        <span class="badge badge-${consistent ? 'success' : 'danger'}" style="font-size:9px;">${consistent ? 'Consistent (Passed)' : 'Mismatch Warning'}</span>
      </div>
      <div style="display:grid; grid-template-columns:1fr 1fr; gap:10px; font-size:10px;">
        <div style="background:rgba(255,255,255,0.01); padding:8px; border-radius:4px; border:1px solid rgba(255,255,255,0.03);">
          <strong style="color:#3b82f6;">PMS Active Settings:</strong>
          <div style="margin-top:4px; color:#aaa;">${data.pmsDetails.name}</div>
          <div style="color:#aaa;">${data.pmsDetails.phone}</div>
        </div>
        <div style="background:rgba(255,255,255,0.01); padding:8px; border-radius:4px; border:1px solid rgba(255,255,255,0.03);">
          <strong style="color:#10b981;">GMB Profile:</strong>
          <div style="margin-top:4px; color:#aaa;">${data.gmbDetails ? data.gmbDetails.name : 'N/A'}</div>
          <div style="color:#aaa;">${data.gmbDetails ? data.gmbDetails.phone : 'N/A'}</div>
        </div>
      </div>
    `;
  } catch (e) {
    console.error('Failed to load SEO status:', e);
  }
}

async function generateSeoCopy(type) {
  const box = document.getElementById('gbp-seo-suggest-box');
  const title = document.getElementById('gbp-seo-suggest-title');
  const txt = document.getElementById('gbp-seo-suggest-txt');
  if (!box || !title || !txt) return;

  txt.textContent = 'Generating optimization recommendations...';
  box.style.display = 'block';

  try {
    const res = await fetch('/api/google/seo-suggest', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ type })
    });
    if (res.ok) {
      const data = await res.json();
      title.textContent = data.suggestion.title;
      txt.textContent = data.suggestion.content;
    } else {
      txt.textContent = 'Generation failed.';
    }
  } catch (e) {
    txt.textContent = 'Connection error.';
  }
}

async function loadGbpCompetitors() {
  try {
    const res = await fetch('/api/google/competitors');
    if (!res.ok) return;
    const list = await res.json();
    const tbody = document.getElementById('gbp-competitors-tbody');
    if (!tbody) return;
    tbody.innerHTML = '';

    if (list.length === 0) {
      tbody.innerHTML = `<tr><td colspan="6" style="text-align:center; color:#888;">No tracked competitor listings defined.</td></tr>`;
      return;
    }

    list.forEach(c => {
      const tr = document.createElement('tr');
      tr.innerHTML = `
        <td><strong>${c.name}</strong></td>
        <td>${c.primary_category}</td>
        <td><strong style="color:#eab308;">${c.rating} ★</strong></td>
        <td>${c.total_reviews.toLocaleString()}</td>
        <td>
          <div style="display:flex; align-items:center; gap:8px;">
            <div style="flex-grow:1; width:50px; height:6px; background:rgba(255,255,255,0.05); border-radius:3px; overflow:hidden;">
              <div style="width:${c.search_visibility}%; height:100%; background:#8b5cf6;"></div>
            </div>
            <span>${c.search_visibility}%</span>
          </div>
        </td>
        <td><button type="button" class="btn btn-danger btn-xs" onclick="deleteGbpCompetitor(${c.id})" style="padding:1px 4px; font-size:8px;">Delete</button></td>
      `;
      tbody.appendChild(tr);
    });
  } catch (e) {
    console.error('Failed to load competitors registry:', e);
  }
}

function openAddCompetitorModal() {
  document.getElementById('gbp-competitor-form').reset();
  openModal('modal-gbp-competitor');
}

async function saveGbpCompetitor(e) {
  e.preventDefault();
  const payload = {
    name: document.getElementById('gbp-comp-name').value.trim(),
    primary_category: document.getElementById('gbp-comp-category').value.trim(),
    rating: parseFloat(document.getElementById('gbp-comp-rating').value) || 0.0,
    total_reviews: parseInt(document.getElementById('gbp-comp-reviews').value, 10) || 0,
    search_visibility: parseInt(document.getElementById('gbp-comp-visibility').value, 10) || 50
  };

  showLoader(true, 'Adding competitor hotel profile...');
  try {
    const res = await fetch('/api/google/competitors/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
    showLoader(false);
    if (res.ok) {
      closeModal('modal-gbp-competitor');
      loadGbpCompetitors();
    } else {
      alert('Save failed.');
    }
  } catch (err) {
    showLoader(false);
    alert('Connection error: ' + err.message);
  }
}

async function deleteGbpCompetitor(id) {
  if (!confirm('Remove competitor hotel profile?')) return;
  showLoader(true, 'Removing competitor...');
  try {
    const res = await fetch('/api/google/competitors/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id })
    });
    showLoader(false);
    if (res.ok) {
      loadGbpCompetitors();
    }
  } catch (err) {
    showLoader(false);
  }
}

function initiateGbpOAuth() {
  showLoader(true, 'Opening Google OAuth Consent screen...');
  fetch('/api/google/auth-url')
    .then(res => res.json())
    .then(data => {
      showLoader(false);
      const w = 600, h = 600;
      const left = (screen.width/2) - (w/2);
      const top = (screen.height/2) - (h/2);
      window.open(data.url, 'Google OAuth Sign-In', `width=${w},height=${h},top=${top},left=${left}`);
    })
    .catch(() => showLoader(false));
}

// ================= CUSTOM WHATSAPP DISPATCH LOGIC =================
// ================= CUSTOM WHATSAPP DISPATCH LOGIC =================
async function getActiveBookingForGuest(phone) {
  try {
    const res = await fetch('/api/bookings');
    const bookings = await res.json();
    const cleanPhone = phone.replace(/[^0-9]/g, '');
    
    // Find active (CheckedIn or Confirmed) booking matching phone
    const active = bookings.find(b => {
      const bPhone = b.guest_mobile ? b.guest_mobile.replace(/[^0-9]/g, '') : '';
      return (bPhone.includes(cleanPhone) || cleanPhone.includes(bPhone)) && (b.status === 'CheckedIn' || b.status === 'Confirmed');
    });
    if (active) return active;

    // Fallback to any booking for this guest
    return bookings.find(b => {
      const bPhone = b.guest_mobile ? b.guest_mobile.replace(/[^0-9]/g, '') : '';
      return bPhone.includes(cleanPhone) || cleanPhone.includes(bPhone);
    });
  } catch (e) {
    return null;
  }
}

async function openCustomWAModal(guestName, guestPhone) {
  openModal('modal-custom-whatsapp');
  document.getElementById('custom-whatsapp-form').reset();
  document.getElementById('wa-custom-phone-raw').value = guestPhone;
  document.getElementById('wa-custom-recipient-name').value = guestName;
  document.getElementById('wa-custom-phone-display').value = guestPhone;

  // Fetch templates if not loaded
  if (!state.whatsappTemplates || Object.keys(state.whatsappTemplates).length === 0) {
    try {
      const res = await fetch('/api/whatsapp/templates');
      state.whatsappTemplates = await res.json();
    } catch (e) {
      state.whatsappTemplates = {};
    }
  }

  // Populate templates select
  const selectEl = document.getElementById('wa-custom-template-select');
  if (selectEl) {
    selectEl.innerHTML = '';
    const keys = Object.keys(state.whatsappTemplates);
    keys.forEach(k => {
      const opt = document.createElement('option');
      opt.value = k;
      opt.textContent = k.toUpperCase();
      selectEl.appendChild(opt);
    });
  }

  // Set mode to custom by default
  document.getElementById('wa-custom-msg-type').value = 'custom';
  toggleWhatsAppModeFields();
}

function toggleWhatsAppModeFields() {
  const mode = document.getElementById('wa-custom-msg-type').value;
  const customGroup = document.getElementById('wa-custom-text-group');
  const templateGroup = document.getElementById('wa-custom-template-group');
  const customMsgTextarea = document.getElementById('wa-custom-message');

  if (mode === 'custom') {
    if (customGroup) customGroup.classList.remove('hidden');
    if (templateGroup) templateGroup.classList.add('hidden');
    if (customMsgTextarea) customMsgTextarea.setAttribute('required', 'true');
  } else {
    if (customGroup) customGroup.classList.add('hidden');
    if (templateGroup) templateGroup.classList.remove('hidden');
    if (customMsgTextarea) customMsgTextarea.removeAttribute('required');
    loadWhatsAppTemplateVariables();
  }
}

async function loadWhatsAppTemplateVariables() {
  const key = document.getElementById('wa-custom-template-select').value;
  const tpl = (state.whatsappTemplates && state.whatsappTemplates[key]) || null;
  const previewDiv = document.getElementById('wa-template-preview-text');
  const variablesContainer = document.getElementById('wa-template-variables-inputs');

  if (!tpl) {
    if (previewDiv) previewDiv.textContent = 'No template body found.';
    if (variablesContainer) variablesContainer.innerHTML = '';
    return;
  }

  if (previewDiv) {
    previewDiv.textContent = `Template Body:\n\n${tpl.body || '(No body text configured)'}`;
  }

  if (!variablesContainer) return;
  variablesContainer.innerHTML = '';

  // Extract variables like {guest_name}, {booking_uid}
  const regex = /\{([a-zA-Z0-9_-]+)\}/g;
  let match;
  const vars = [];
  while ((match = regex.exec(tpl.body || '')) !== null) {
    const v = match[1];
    if (!vars.includes(v)) {
      vars.push(v);
    }
  }

  if (vars.length === 0) {
    const noVarsMsg = document.createElement('div');
    noVarsMsg.textContent = 'This template does not contain any placeholder variables.';
    noVarsMsg.style.fontSize = '11px';
    noVarsMsg.style.opacity = '0.6';
    variablesContainer.appendChild(noVarsMsg);
    return;
  }

  // Pre-fill active booking context lookups
  const phone = document.getElementById('wa-custom-phone-raw').value;
  showLoader(true, 'Fetching booking details to auto-fill placeholders...');
  const booking = await getActiveBookingForGuest(phone);
  showLoader(false);

  const guest_name = document.getElementById('wa-custom-recipient-name').value;
  const wifi_password = (state.settings && state.settings.wifi_password) || '';
  const reception_phone = (state.settings && state.settings.reception_phone) || '';

  const valuesMap = {
    guest_name: guest_name,
    wifi_password: wifi_password,
    reception_phone: reception_phone,
    booking_uid: booking ? booking.uid : '',
    check_in: booking ? booking.check_in : '',
    check_out: booking ? booking.check_out : '',
    room_numbers: booking ? booking.room_numbers || `Room ${booking.room_id}` : '',
    room_type: booking ? booking.room_type || '' : '',
    amount: booking ? `₹${booking.total_price || ''}` : ''
  };

  vars.forEach(v => {
    const group = document.createElement('div');
    group.className = 'form-group';
    
    const label = document.createElement('label');
    label.textContent = `Variable {${v}}`;
    label.style.fontSize = '11px';
    label.style.marginBottom = '2px';
    group.appendChild(label);

    const input = document.createElement('input');
    input.type = 'text';
    input.className = 'form-control form-control-sm wa-tpl-placeholder-input';
    input.setAttribute('data-var-key', v);
    input.value = valuesMap[v] !== undefined ? valuesMap[v] : '';
    input.placeholder = `Enter value for {${v}}`;
    input.required = true;
    
    group.appendChild(input);
    variablesContainer.appendChild(group);
  });
}

async function handleCustomWASubmit(e) {
  e.preventDefault();
  const phone = document.getElementById('wa-custom-phone-raw').value;
  const mode = document.getElementById('wa-custom-msg-type').value;

  if (mode === 'custom') {
    const message = document.getElementById('wa-custom-message').value.trim();
    if (!message) return;

    showLoader(true, 'Sending custom WhatsApp message...');
    try {
      const res = await fetch('/api/whatsapp/custom', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ phone, message, userId: state.currentUser.id })
      });
      showLoader(false);
      if (res.ok) {
        alert('WhatsApp message sent successfully!');
        closeAllModals();
        pollWhatsAppLogsCount();
      } else {
        alert('Failed to send custom message.');
      }
    } catch (err) {
      showLoader(false);
      alert('Connection error.');
    }
  } else {
    // Template mode
    const templateKey = document.getElementById('wa-custom-template-select').value;
    const placeholderInputs = document.querySelectorAll('.wa-tpl-placeholder-input');
    const placeholders = {};
    placeholderInputs.forEach(input => {
      const varKey = input.getAttribute('data-var-key');
      placeholders[varKey] = input.value.trim();
    });

    showLoader(true, `Sending WhatsApp Template "${templateKey}"...`);
    try {
      const res = await fetch('/api/whatsapp/templates/send-manual', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ phone, templateKey, placeholders, userId: state.currentUser.id })
      });
      showLoader(false);
      if (res.ok) {
        alert(`WhatsApp template message "${templateKey}" sent successfully!`);
        closeAllModals();
        pollWhatsAppLogsCount();
      } else {
        const err = await res.json();
        alert(`Failed to send template message: ${err.error || 'Server error'}`);
      }
    } catch (err) {
      showLoader(false);
      alert('Connection error.');
    }
  }
}

window.openCustomWAModal = openCustomWAModal;
window.toggleWhatsAppModeFields = toggleWhatsAppModeFields;
window.loadWhatsAppTemplateVariables = loadWhatsAppTemplateVariables;
window.handleCustomWASubmit = handleCustomWASubmit;

// ================= INTEGRATIONS SAVER LOGIC =================
async function saveIntegrationsSettings(e) {
  e.preventDefault();
  const ota_booking_url = document.getElementById('set-ota-booking-url').value;
  const ota_booking_id = document.getElementById('set-ota-booking-id').value;
  const ota_booking_key = document.getElementById('set-ota-booking-key').value;

  const ota_mmt_url = document.getElementById('set-ota-mmt-url').value;
  const ota_mmt_id = document.getElementById('set-ota-mmt-id').value;
  const ota_mmt_key = document.getElementById('set-ota-mmt-key').value;

  const ota_agoda_url = document.getElementById('set-ota-agoda-url').value;
  const ota_agoda_id = document.getElementById('set-ota-agoda-id').value;
  const ota_agoda_key = document.getElementById('set-ota-agoda-key').value;

  const google_place_id = document.getElementById('set-google-place-id').value;
  const google_api_key = document.getElementById('set-google-api-key').value;
  const reviews_scraping_url = document.getElementById('set-reviews-scraping-url').value;
  const reviews_sync_freq = document.getElementById('set-reviews-sync-freq').value;

  const data = {
    ota_booking_url, ota_booking_id, ota_booking_key,
    ota_mmt_url, ota_mmt_id, ota_mmt_key,
    ota_agoda_url, ota_agoda_id, ota_agoda_key,
    google_place_id, google_api_key, reviews_scraping_url, reviews_sync_freq
  };
  saveSettingsAPI(data, 'Manual integration gateway settings updated.');
}

// Map globals for window event binds
window.deleteFloor = deleteFloor;
window.mapOTABooking = mapOTABooking;
window.openReviewReplyModal = openReviewReplyModal;
window.openCustomWAModal = openCustomWAModal;
window.saveIntegrationsSettings = saveIntegrationsSettings;

async function handleMasterResetSubmit(e) {
  e.preventDefault();
  const password = document.getElementById('reset-security-password').value;
  
  if (!confirm('CRITICAL WARNING:\n\nAre you absolutely sure you want to perform a Master Reset? This will completely purge all databases, guests, bookings, and custom rents. This action CANNOT be undone!')) {
    return;
  }

  showLoader(true, 'Initiating master reset sequence...');
  try {
    const res = await fetch('/api/settings/reset', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ password, userId: state.currentUser.id })
    });
    
    showLoader(false);
    if (res.ok) {
      alert('DATABASE MASTER RESET EXECUTED SUCCESSFULLY!\n\nThe application is rebooting into clean factory default states. You will be logged out now.');
      document.getElementById('master-reset-form').reset();
      
      // Perform log-out operations
      state.currentUser = null;
      localStorage.removeItem('hotel_auth_session');
      window.location.reload();
    } else {
      const err = await res.json();
      alert(err.error || 'Master Reset failed. Incorrect password.');
    }
  } catch (err) {
    showLoader(false);
    alert('Connection lost during restart. The server is re-initializing defaults.');
    
    // Clear session and reload anyway since server is exiting and recreating DB
    state.currentUser = null;
    localStorage.removeItem('hotel_auth_session');
    window.location.reload();
  }
}

window.handleMasterResetSubmit = handleMasterResetSubmit;

async function handleFactoryResetSubmit(e) {
  e.preventDefault();
  const password = document.getElementById('factory-reset-password').value;
  
  if (!confirm('FACTORY RESET WARNING:\n\nAre you sure you want to perform a Database Factory Reset? This will permanently delete all guests, bookings, salaries, inventory logs, attendance logs, and ota mappings. This action cannot be undone!')) {
    return;
  }

  showLoader(true, 'Clearing transaction records...');
  try {
    const res = await fetch('/api/settings/factory-reset', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ password, userId: state.currentUser ? state.currentUser.id : 1 })
    });
    
    showLoader(false);
    if (res.ok) {
      alert('DATABASE FACTORY RESET COMPLETED!\n\nAll transactional history has been successfully cleared. The application is ready for a fresh production setup.');
      document.getElementById('factory-reset-form').reset();
      window.location.reload();
    } else {
      const err = await res.json();
      alert(err.error || 'Factory Reset failed.');
    }
  } catch (err) {
    showLoader(false);
    alert('Connection error');
  }
}

async function triggerSeedDemoData() {
  if (!confirm('LOAD DEMO DATA:\n\nAre you sure you want to load mock demonstration data? This will load demo guest profiles, booking records, ota mappings, and reviews to play with the dashboard.\n\nNote: This can only be loaded into an empty database. Perform a Factory Reset first if you have existing bookings.')) {
    return;
  }

  showLoader(true, 'Loading mock demo datasets...');
  try {
    const res = await fetch('/api/settings/seed-demo', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: state.currentUser ? state.currentUser.id : 1 })
    });
    
    showLoader(false);
    const result = await res.json();
    if (res.ok) {
      alert(result.message || 'Demo data loaded successfully!');
      window.location.reload();
    } else {
      alert(result.error || 'Demo loading failed.');
    }
  } catch (err) {
    showLoader(false);
    alert('Connection error');
  }
}

window.handleFactoryResetSubmit = handleFactoryResetSubmit;
window.triggerSeedDemoData = triggerSeedDemoData;
window.saveGoogleDriveSettings = saveGoogleDriveSettings;
window.testGoogleDriveUpload = testGoogleDriveUpload;

// ================= NEW ENTERPRISE UPGRADE IMPLEMENTATION =================

// 1. Theme Vision Toggler
function initThemeVision() {
  const toggleBtn = document.getElementById('btn-theme-vision-toggle');
  if (toggleBtn) {
    toggleBtn.addEventListener('click', toggleThemeVision);
  }
  const savedTheme = localStorage.getItem('theme_vision') || 'dark';
  document.body.className = '';
  if (savedTheme === 'light') {
    document.body.classList.add('light-theme');
  } else if (savedTheme === 'emerald') {
    document.body.classList.add('theme-emerald');
  } else if (savedTheme === 'navy') {
    document.body.classList.add('theme-navy');
  }
}

function toggleThemeVision() {
  const themes = ['dark', 'emerald', 'navy', 'light'];
  const current = localStorage.getItem('theme_vision') || 'dark';
  const nextIndex = (themes.indexOf(current) + 1) % themes.length;
  const nextTheme = themes[nextIndex];
  
  localStorage.setItem('theme_vision', nextTheme);
  
  document.body.className = '';
  if (nextTheme === 'light') {
    document.body.classList.add('light-theme');
  } else if (nextTheme === 'emerald') {
    document.body.classList.add('theme-emerald');
  } else if (nextTheme === 'navy') {
    document.body.classList.add('theme-navy');
  }
  
  const selectEl = document.getElementById('set-ui-theme');
  if (selectEl) selectEl.value = nextTheme;
}

// 2. Room Types CRUD
async function loadRoomTypesSettingsTable() {
  const tbody = document.getElementById('room-types-list-tbody');
  if (!tbody) return;
  tbody.innerHTML = '<tr><td colspan="3">Loading...</td></tr>';
  try {
    const res = await fetch('/api/room-types');
    const list = await res.json();
    tbody.innerHTML = '';
    
    const roomTypeSelect = document.getElementById('admin-room-type');
    if (roomTypeSelect) {
      roomTypeSelect.innerHTML = list.map(t => `<option value="${t.id}">${t.name} (Base: ₹${t.base_price})</option>`).join('');
    }

    list.forEach(t => {
      const tr = document.createElement('tr');
      tr.innerHTML = `
        <td><strong>${t.name}</strong></td>
        <td>₹${t.base_price}</td>
        <td style="text-align: right;">
          <button class="btn btn-danger btn-sm" onclick="deleteRoomType(${t.id})">Delete</button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  } catch (e) {
    tbody.innerHTML = '<tr><td colspan="3" style="color:var(--color-maintenance);">Failed.</td></tr>';
  }
}

async function handleAddRoomTypeSubmit(e) {
  e.preventDefault();
  const name = document.getElementById('add-room-type-name').value;
  const basePrice = parseFloat(document.getElementById('add-room-type-price').value);
  
  showLoader(true, 'Adding room type...');
  try {
    const res = await fetch('/api/room-types/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name, basePrice, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      document.getElementById('add-room-type-form').reset();
      loadRoomTypesSettingsTable();
    }
  } catch (e) {
    showLoader(false);
  }
}

async function deleteRoomType(roomTypeId) {
  if (!confirm('Are you sure you want to delete this room type?')) return;
  showLoader(true, 'Deleting room type...');
  try {
    const res = await fetch('/api/room-types/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ roomTypeId, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      loadRoomTypesSettingsTable();
    } else {
      const err = await res.json();
      alert(err.error || 'Failed to delete room type.');
    }
  } catch (e) {
    showLoader(false);
  }
}

// 3. Staff CRUD Functions
function openAddStaffModal() {
  document.getElementById('staff-modal-title').textContent = 'Add Staff Member';
  document.getElementById('staff-id').value = '';
  document.getElementById('staff-form').reset();
  openModal('modal-staff');
}

function editStaffDetails(id) {
  const staff = state.staffList.find(s => s.id === id);
  if (!staff) return;
  
  document.getElementById('staff-modal-title').textContent = 'Edit Staff Member';
  document.getElementById('staff-id').value = staff.id;
  document.getElementById('staff-name').value = staff.name;
  document.getElementById('staff-role').value = staff.role;
  document.getElementById('staff-username').value = staff.username;
  document.getElementById('staff-password').value = '';
  
  openModal('modal-staff');
}

async function handleStaffFormSubmit(e) {
  e.preventDefault();
  const id = document.getElementById('staff-id').value;
  const name = document.getElementById('staff-name').value;
  const role = document.getElementById('staff-role').value;
  const username = document.getElementById('staff-username').value;
  const password = document.getElementById('staff-password').value;

  showLoader(true, 'Saving staff account...');
  try {
    const payload = { name, role, username, password, userId: state.currentUser.id };
    if (id) payload.id = parseInt(id, 10);

    const res = await fetch('/api/staff/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
    showLoader(false);
    if (res.ok) {
      closeAllModals();
      loadStaffAccounts();
    } else {
      const err = await res.json();
      alert(err.error || 'Failed to save staff details.');
    }
  } catch (e) {
    showLoader(false);
  }
}

async function deleteStaff(staffId) {
  if (!confirm('Are you sure you want to delete this staff account?')) return;
  showLoader(true, 'Deleting staff...');
  try {
    const res = await fetch('/api/staff/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ staffId, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      loadStaffAccounts();
    } else {
      const err = await res.json();
      alert(err.error || 'Failed to delete staff account.');
    }
  } catch (e) {
    showLoader(false);
  }
}

// 4. Guest Profile Deletion
async function deleteGuestProfile(guestId) {
  if (!confirm('CRITICAL WARNING:\n\nAre you sure you want to permanently delete this guest profile? All loyalties and local history records will be cleared. This action CANNOT be undone!')) {
    return;
  }
  showLoader(true, 'Purging guest profile...');
  try {
    const res = await fetch('/api/guests/delete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ guestId, userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      loadGuestsList();
    } else {
      const err = await res.json();
      alert(err.error || 'Failed to delete guest profile.');
    }
  } catch (e) {
    showLoader(false);
  }
}



// 6. Automated Night Audit Button Trigger
async function runNightAudit() {
  if (!confirm('Reconciliation Audit Confirm:\n\nAre you sure you want to run the end-of-day financial Night Audit now?')) return;
  showLoader(true, 'Running Automated Night Audit...');
  try {
    const res = await fetch('/api/settings/night-audit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: state.currentUser.id })
    });
    showLoader(false);
    if (res.ok) {
      const data = await res.json();
      alert(`Success!\n\n${data.message}\nReconciled Revenues: ₹${data.revenue}`);
      loadSettingsView();
    }
  } catch (e) {
    showLoader(false);
  }
}

// 8. Report Printing & WhatsApp sharing triggers
function printCurrentReport() {
  const type = document.getElementById('report-type-select').value;
  const startDate = document.getElementById('report-start-date').value;
  const endDate = document.getElementById('report-end-date').value;
  
  if (!startDate || !endDate) {
    alert('Please pick a start and end date range first.');
    return;
  }
  
  const token = localStorage.getItem('hotel_auth_token') || '';
  const printUrl = `/api/reports/pdf?type=${type}&startDate=${startDate}&endDate=${endDate}&token=${token}`;
  window.open(printUrl, '_blank');
}

async function shareReportViaWhatsApp() {
  const type = document.getElementById('report-type-select').value;
  const startDate = document.getElementById('report-start-date').value;
  const endDate = document.getElementById('report-end-date').value;
  
  if (!startDate || !endDate) {
    alert('Please pick a start and end date range first.');
    return;
  }

  const target = prompt('Enter recipient mobile number:', '+919999999999');
  if (!target) return;

  showLoader(true, 'Sharing report via WhatsApp...');
  try {
    const res = await fetch('/api/reports/share', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        type,
        startDate,
        endDate,
        channel: 'whatsapp',
        target,
        userId: state.currentUser ? state.currentUser.id : 1
      })
    });
    showLoader(false);
    if (res.ok) {
      alert('Report shared successfully via WhatsApp!');
    } else {
      const err = await res.json();
      alert(`WhatsApp share failed: ${err.error || 'Unknown error'}`);
    }
  } catch (e) {
    showLoader(false);
    alert('Server communication error.');
  }
}

async function shareReportViaEmail() {
  const type = document.getElementById('report-type-select').value;
  const startDate = document.getElementById('report-start-date').value;
  const endDate = document.getElementById('report-end-date').value;
  
  if (!startDate || !endDate) {
    alert('Please pick a start and end date range first.');
    return;
  }

  const target = prompt('Enter recipient email address:', 'manager@hotel.com');
  if (!target) return;

  const cc = prompt('Enter CC email addresses (optional, comma-separated):', '');
  const bcc = prompt('Enter BCC email addresses (optional, comma-separated):', '');

  showLoader(true, 'Generating PDF & sending Email...');
  try {
    const res = await fetch('/api/reports/share', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        type,
        startDate,
        endDate,
        channel: 'email',
        target,
        cc: cc || '',
        bcc: bcc || '',
        userId: state.currentUser ? state.currentUser.id : 1
      })
    });
    showLoader(false);
    if (res.ok) {
      alert('Report shared successfully via Email!');
    } else {
      const err = await res.json();
      alert(`Email share failed: ${err.error || 'Unknown error'}`);
    }
  } catch (e) {
    showLoader(false);
    alert('Server communication error.');
  }
}

// Hook everything in DOM init lifecycle
document.addEventListener('DOMContentLoaded', () => {
  const addRoomTypeForm = document.getElementById('add-room-type-form');
  if (addRoomTypeForm) addRoomTypeForm.addEventListener('submit', handleAddRoomTypeSubmit);

  const staffForm = document.getElementById('staff-form');
  if (staffForm) staffForm.addEventListener('submit', handleStaffFormSubmit);

  const addStaffBtn = document.getElementById('btn-add-staff');
  if (addStaffBtn) addStaffBtn.addEventListener('click', openAddStaffModal);

  const runAuditBtn = document.getElementById('btn-run-night-audit');
  if (runAuditBtn) runAuditBtn.addEventListener('click', runNightAudit);

  const printReportBtn = document.getElementById('btn-print-report');
  if (printReportBtn) printReportBtn.addEventListener('click', printCurrentReport);

  const waReportBtn = document.getElementById('btn-whatsapp-report');
  if (waReportBtn) waReportBtn.addEventListener('click', shareReportViaWhatsApp);

  const emailReportBtn = document.getElementById('btn-email-report');
  if (emailReportBtn) emailReportBtn.addEventListener('click', shareReportViaEmail);

  initThemeVision();
});

// Map globals
window.deleteRoomType = deleteRoomType;
window.editStaffDetails = editStaffDetails;
window.deleteStaff = deleteStaff;
window.deleteGuestProfile = deleteGuestProfile;
window.runNightAudit = runNightAudit;
window.printCurrentReport = printCurrentReport;
window.shareReportViaWhatsApp = shareReportViaWhatsApp;
window.updateWhatsAppPreview = updateWhatsAppPreview;

function updateWhatsAppPreview() {
  const headerTypeEl = document.getElementById('tpl-header-type');
  const headerTextEl = document.getElementById('tpl-header-text');
  const imageEl = document.getElementById('tpl-image');
  const bodyEl = document.getElementById('tpl-body');
  const footerEl = document.getElementById('tpl-footer');
  const btnTypeEl = document.getElementById('tpl-btn-type');
  const btnTextEl = document.getElementById('tpl-btn-text');
  const btnUrlEl = document.getElementById('tpl-url');

  if (!bodyEl) return; // Prevent errors if tab not rendered yet

  const headerType = headerTypeEl ? headerTypeEl.value : 'None';
  const headerTextVal = headerTextEl ? headerTextEl.value.trim() : '';
  const imageVal = imageEl ? imageEl.value.trim() : '';
  let bodyVal = bodyEl ? bodyEl.value : '';
  const footerVal = footerEl ? footerEl.value.trim() : '';
  const btnType = btnTypeEl ? btnTypeEl.value : 'None';
  const btnTextVal = btnTextEl ? btnTextEl.value.trim() : '';
  const btnUrlVal = btnUrlEl ? btnUrlEl.value.trim() : '';

  // Renders Header Text
  const headerTextPreview = document.getElementById('wa-preview-card-header-text');
  if (headerTextPreview) {
    if (headerType === 'Text' && headerTextVal) {
      let hVal = headerTextVal
        .replace(/{guest_name}/g, 'John Doe')
        .replace(/{booking_uid}/g, 'BK-58291');
      headerTextPreview.textContent = hVal;
      headerTextPreview.style.display = 'block';
    } else {
      headerTextPreview.style.display = 'none';
    }
  }

  // Handle placeholders {guest_name} if they wrote classic format
  bodyVal = bodyVal
    .replace(/{guest_name}/g, '<strong>John Doe</strong>')
    .replace(/{booking_uid}/g, '<strong>BK-58291</strong>')
    .replace(/{check_in}/g, '<strong>2026-07-05</strong>')
    .replace(/{check_out}/g, '<strong>2026-07-08</strong>')
    .replace(/{room_type}/g, '<strong>Premium Suite</strong>')
    .replace(/{room_numbers}/g, '<strong>Room 304, 305</strong>')
    .replace(/{wifi_password}/g, '<strong>ShaimaGuest_WiFi (Pass: Shaima@#8870)</strong>')
    .replace(/{reception_phone}/g, '<strong>+91 4567 299 438</strong>')
    .replace(/{amount}/g, '<strong>₹14,500</strong>');

  // Also replace Meta parameters {{1}}, {{2}} with generic preview data
  bodyVal = bodyVal
    .replace(/\{\{1\}\}/g, '<strong>John Doe</strong>')
    .replace(/\{\{2\}\}/g, '<strong>BK-58291</strong>')
    .replace(/\{\{3\}\}/g, '<strong>2026-07-05</strong>')
    .replace(/\{\{4\}\}/g, '<strong>2026-07-08</strong>')
    .replace(/\{\{5\}\}/g, '<strong>Premium Suite</strong>');

  // Renders header image
  const imgWrap = document.getElementById('wa-preview-card-image-wrap');
  const imgEl = document.getElementById('wa-preview-card-img');
  if ((headerType === 'Image' || headerType === 'Document') && imageVal && (imageVal.startsWith('http://') || imageVal.startsWith('https://') || imageVal.startsWith('data:'))) {
    imgEl.src = imageVal;
    if (imgWrap) imgWrap.style.display = 'block';
  } else {
    if (imgWrap) imgWrap.style.display = 'none';
    if (imgEl) imgEl.src = '';
  }

  // Renders body & footer
  const previewBody = document.getElementById('wa-preview-card-body');
  if (previewBody) previewBody.innerHTML = bodyVal || '<i>(Message body text)</i>';

  const previewFooter = document.getElementById('wa-preview-card-footer');
  if (previewFooter) previewFooter.textContent = footerVal || '';

  // Renders CTA / Quick Reply Button
  const btnWrap = document.getElementById('wa-preview-card-btn-wrap');
  const btnEl = document.getElementById('wa-preview-card-btn');
  if (btnType !== 'None' && btnTextVal) {
    if (btnEl) {
      btnEl.innerHTML = btnType.includes('URL') ? `🔗 ${btnTextVal}` : `💬 ${btnTextVal}`;
      let href = btnUrlVal;
      href = href.replace(/\{\{1\}\}/g, 'BK-58291').replace(/\{booking_uid\}/g, 'BK-58291');
      btnEl.href = href || '#';
    }
    if (btnWrap) btnWrap.style.display = 'block';
  } else {
    if (btnWrap) btnWrap.style.display = 'none';
  }
}

async function loadSocialHubView() {
  showLoader(true, 'Loading social marketing console...');
  try {
    const res = await fetch('/api/settings');
    const settings = await res.json();
    
    document.getElementById('set-meta-social-token').value = settings.meta_social_page_token || '';
    document.getElementById('set-meta-social-fb-id').value = settings.meta_social_fb_page_id || '';
    document.getElementById('set-meta-social-ig-id').value = settings.meta_social_ig_account_id || '';
    
    // Set custom preview name if hotel name is configured
    if (settings.hotel_name) {
      document.getElementById('social-preview-name').textContent = settings.hotel_name;
    }
    
    updateSocialPreview();
    showLoader(false);
  } catch (err) {
    showLoader(false);
  }
}

async function saveSocialSettings(e) {
  if (e) e.preventDefault();
  const token = document.getElementById('set-meta-social-token').value;
  const fbId = document.getElementById('set-meta-social-fb-id').value;
  const igId = document.getElementById('set-meta-social-ig-id').value;

  const payload = {
    meta_social_page_token: token,
    meta_social_fb_page_id: fbId,
    meta_social_ig_account_id: igId
  };

  showLoader(true, 'Saving Meta credentials...');
  await saveSettingsAPI(payload, 'Meta Social Marketing configurations saved successfully!');
}

async function handleSocialPublish(e) {
  if (e) e.preventDefault();
  
  const platforms = [];
  if (document.getElementById('pub-platform-fb').checked) platforms.push('facebook');
  if (document.getElementById('pub-platform-ig').checked) platforms.push('instagram');

  if (platforms.length === 0) {
    return alert('Please select at least one publishing platform (Facebook or Instagram) before posting.');
  }

  const message = document.getElementById('social-post-caption').value;
  const mediaUrl = document.getElementById('social-media-url').value;
  const mediaType = document.getElementById('social-media-type').value;

  showLoader(true, 'Publishing marketing post to Meta Network...');
  try {
    const res = await fetch('/api/social/share', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        message,
        platforms,
        mediaUrl,
        mediaType,
        userId: state.currentUser ? state.currentUser.id : 1
      })
    });
    showLoader(false);
    if (res.ok) {
      const data = await res.json();
      let alertMsg = 'Post Published Successfully!\n\n';
      data.results.forEach(r => {
        alertMsg += `• ${r.platform.toUpperCase()}: ${r.status} (ID: ${r.id})\n`;
      });
      alert(alertMsg);
      // Reset composer form
      document.getElementById('social-composer-form').reset();
      updateSocialPreview();
    } else {
      const err = await res.json();
      alert(`Publishing failed:\n\n${err.error || 'Unknown error'}`);
    }
  } catch (err) {
    showLoader(false);
    alert(`Meta Server connection failure: ${err.message}`);
  }
}

function updateSocialPreview() {
  const captionVal = document.getElementById('social-post-caption').value;
  const mediaUrlVal = document.getElementById('social-media-url').value;
  const mediaTypeVal = document.getElementById('social-media-type').value;

  document.getElementById('social-preview-body').textContent = captionVal || 'Compose your caption to see the live feed mockup preview here...';
  
  const previewImg = document.getElementById('social-preview-img');
  const previewPlaceholder = document.getElementById('social-preview-placeholder');
  
  if (mediaUrlVal && (mediaUrlVal.startsWith('http://') || mediaUrlVal.startsWith('https://') || mediaUrlVal.startsWith('data:'))) {
    previewImg.src = mediaUrlVal;
    previewImg.style.display = 'block';
    previewPlaceholder.style.display = 'none';
  } else {
    previewImg.src = '';
    previewImg.style.display = 'none';
    previewPlaceholder.style.display = 'flex';
  }

  const reelsBadge = document.getElementById('social-preview-reels-badge');
  if (mediaTypeVal === 'REEL') {
    reelsBadge.style.display = 'block';
  } else {
    reelsBadge.style.display = 'none';
  }
}

async function shareInvoiceViaEmail() {
  if (!activeBillingBooking) {
    return alert('Please load an active checkout booking first.');
  }

  const guestEmail = activeBillingBooking.guest_email || '';
  const email = prompt('Enter recipient email address:', guestEmail);
  if (!email) return;

  const cc = prompt('Enter CC email addresses (optional, comma-separated):', '');
  const bcc = prompt('Enter BCC email addresses (optional, comma-separated):', '');

  showLoader(true, 'Generating PDF & sending Email...');
  try {
    const res = await fetch('/api/invoices/send-email', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        bookingId: activeBillingBooking.id,
        email: email,
        cc: cc || '',
        bcc: bcc || '',
        userId: state.currentUser.id
      })
    });
    showLoader(false);
    if (res.ok) {
      alert('Invoice PDF successfully generated and emailed!');
    } else {
      const err = await res.json();
      alert(`Failed to share invoice via email: ${err.error || 'Unknown error'}`);
    }
  } catch (err) {
    showLoader(false);
    alert(`Failed to share: ${err.message}`);
  }
}

function toggleTemplateEditorFields() {
  const headerType = document.getElementById('tpl-header-type').value;
  const btnType = document.getElementById('tpl-btn-type').value;

  const grpText = document.getElementById('grp-header-text');
  const grpMedia = document.getElementById('grp-header-media');
  
  if (headerType === 'Text') {
    if (grpText) grpText.style.display = 'block';
    if (grpMedia) grpMedia.style.display = 'none';
  } else if (headerType === 'Image' || headerType === 'Document') {
    if (grpText) grpText.style.display = 'none';
    if (grpMedia) grpMedia.style.display = 'block';
  } else {
    if (grpText) grpText.style.display = 'none';
    if (grpMedia) grpMedia.style.display = 'none';
  }

  const grpBtnText = document.getElementById('grp-btn-text');
  const grpBtnUrl = document.getElementById('grp-btn-url');

  if (btnType === 'None') {
    if (grpBtnText) grpBtnText.style.display = 'none';
    if (grpBtnUrl) grpBtnUrl.style.display = 'none';
  } else if (btnType === 'Quick Reply') {
    if (grpBtnText) grpBtnText.style.display = 'block';
    if (grpBtnUrl) grpBtnUrl.style.display = 'none';
  } else {
    if (grpBtnText) grpBtnText.style.display = 'block';
    if (grpBtnUrl) grpBtnUrl.style.display = 'block';
  }
}

function toggleWhatsAppProviderFields() {
  const providerEl = document.getElementById('set-wa-provider');
  if (!providerEl) return;
  const provider = providerEl.value;
  const grpMeta = document.getElementById('grp-provider-meta');
  const grpWhatsJet = document.getElementById('grp-provider-whatsjet');

  if (provider === 'WhatsAppCloudAPI') {
    if (grpMeta) grpMeta.style.display = 'block';
    if (grpWhatsJet) grpWhatsJet.style.display = 'none';
  } else if (provider === 'WhatsJet') {
    if (grpMeta) grpMeta.style.display = 'none';
    if (grpWhatsJet) grpWhatsJet.style.display = 'block';
  } else {
    if (grpMeta) grpMeta.style.display = 'none';
    if (grpWhatsJet) grpWhatsJet.style.display = 'none';
  }
}

function regenerateAPIToken() {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  let token = 'shaima_apikey_live_';
  for (let i = 0; i < 20; i++) {
    token += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  document.getElementById('set-api-token-val').value = token;
  alert('API Key regenerated successfully! Click "Save Integration Gateways" to save updates.');
}

// ================= WHATSAPP CHAT INBOX CLIENT CLIENT SYSTEM ================= //

let activeChatGuestId = null;
let waChatFilterTab = 'all'; // all, mine, unassigned

// Pre-seeded chat messages store
if (!state.whatsappChatHistories) {
  state.whatsappChatHistories = {};
}

async function loadWhatsAppChatView() {
  showLoader(true, 'Loading WhatsApp Chat Inbox...');
  try {
    // 1. Fetch guests from database
    const guestsRes = await fetch('/api/guests');
    const guests = await guestsRes.json();
    state.guestsList = guests;

    // 2. Fetch staff members for assignment dropdown
    const staffRes = await fetch('/api/staff');
    const staffList = await staffRes.json();
    
    // Populate Assignee Select
    const assigneeSelect = document.getElementById('wa-chat-assignee');
    assigneeSelect.innerHTML = '<option value="">Unassigned</option>';
    staffList.forEach(s => {
      assigneeSelect.innerHTML += `<option value="${s.id}">${s.name} (${s.role})</option>`;
    });

    // 3. Render chat roster list
    renderWhatsAppChatRoster();
    showLoader(false);
  } catch (err) {
    showLoader(false);
    alert(`Failed to load chat client: ${err.message}`);
  }
}

function renderWhatsAppChatRoster() {
  const searchVal = document.getElementById('wa-chat-search-input').value.toLowerCase();
  const rosterContainer = document.getElementById('wa-chat-roster-list');
  if (!rosterContainer) return;
  rosterContainer.innerHTML = '';

  const activeUserId = state.currentUser ? state.currentUser.id : null;

  // Filter guests based on active tab and search query
  const filteredGuests = state.guestsList.filter(g => {
    // Search match
    const matchesSearch = g.name.toLowerCase().includes(searchVal) || g.mobile.includes(searchVal);
    if (!matchesSearch) return false;

    // Tab filter matches
    if (waChatFilterTab === 'starred') {
      return g.is_starred === 1 && g.is_archived === 0;
    } else if (waChatFilterTab === 'archived') {
      return g.is_archived === 1;
    } else if (waChatFilterTab === 'mine') {
      return g.assigned_staff_id === activeUserId && g.is_archived === 0;
    } else if (waChatFilterTab === 'unassigned') {
      return !g.assigned_staff_id && g.is_archived === 0;
    }
    return g.is_archived === 0; // 'all'
  });

  if (filteredGuests.length === 0) {
    rosterContainer.innerHTML = '<div style="padding: 20px; text-align: center; color: #8696a0; font-size: 12px;">No active chat threads</div>';
    return;
  }

  filteredGuests.forEach(g => {
    // Setup initial mock messages if none exist
    if (!state.whatsappChatHistories[g.id]) {
      state.whatsappChatHistories[g.id] = [
        { text: `Hello, this is ${g.name}. Do you have WiFi available?`, sender: 'guest', time: '10:15 AM' },
        { text: 'Hello! Yes, WiFi is available throughout the hotel. The password is Shaima@2026.', sender: 'bot', time: '10:15 AM' },
        { text: 'Thanks! What is the reception extension number?', sender: 'guest', time: '10:18 AM' }
      ];
    }

    const history = state.whatsappChatHistories[g.id];
    const lastMsg = history[history.length - 1];
    const initialChar = g.name.charAt(0).toUpperCase();
    const isActive = activeChatGuestId === g.id;

    const contactItem = document.createElement('div');
    contactItem.className = `wa-chat-contact-item ${isActive ? 'active' : ''}`;
    contactItem.onclick = () => selectWhatsAppChat(g.id);

    contactItem.innerHTML = `
      <div class="wa-chat-avatar">${initialChar}</div>
      <div class="wa-chat-item-info">
        <div class="wa-chat-item-header">
          <span class="wa-chat-contact-name">${g.name}</span>
          <span class="wa-chat-item-time">${lastMsg ? lastMsg.time : ''}</span>
        </div>
        <div class="wa-chat-item-body">
          <span class="wa-chat-last-msg">${lastMsg ? lastMsg.text : 'No messages'}</span>
          ${g.reply_bot_enabled ? '<span style="font-size: 9px; background: rgba(0, 168, 132, 0.15); color: #00a884; padding: 1px 4px; border-radius: 3px; font-weight: bold;">BOT</span>' : ''}
        </div>
      </div>
    `;
    rosterContainer.appendChild(contactItem);
  });

  // Attach keyup listener for live search if not registered
  const searchInput = document.getElementById('wa-chat-search-input');
  if (searchInput && !searchInput.dataset.listening) {
    searchInput.dataset.listening = 'true';
    searchInput.addEventListener('input', renderWhatsAppChatRoster);
  }
}

function filterWhatsAppChats(tab) {
  waChatFilterTab = tab;
  document.querySelectorAll('.wa-chat-tab').forEach(b => b.classList.remove('active'));
  const activeTabEl = document.getElementById(`btn-wa-tab-${tab}`);
  if (activeTabEl) activeTabEl.classList.add('active');
  renderWhatsAppChatRoster();
}

async function selectWhatsAppChat(guestId) {
  activeChatGuestId = guestId;
  const guest = state.guestsList.find(g => g.id === guestId);
  if (!guest) return;

  // Toggle active class on roster
  renderWhatsAppChatRoster();

  // Hide empty state, show panels
  document.getElementById('wa-chat-empty-state').style.display = 'none';
  document.getElementById('wa-chat-active-header').style.display = 'flex';
  document.getElementById('wa-chat-message-window').style.display = 'flex';
  document.getElementById('wa-chat-input-bar').style.display = 'flex';
  document.getElementById('wa-chat-detail-drawer').style.display = 'flex';

  // Populate Header
  document.getElementById('wa-chat-active-name').textContent = guest.name;
  document.getElementById('wa-chat-active-phone').textContent = guest.mobile;
  document.getElementById('wa-chat-active-avatar').textContent = guest.name.charAt(0).toUpperCase();

  // Populate assignee select & bot toggle state
  document.getElementById('wa-chat-assignee').value = guest.assigned_staff_id || '';
  document.getElementById('wa-chat-bot-toggle').checked = guest.reply_bot_enabled === 1;

  // Update Star & Archive button states/colors
  const starBtn = document.getElementById('btn-wa-chat-star');
  const archiveBtn = document.getElementById('btn-wa-chat-archive');
  if (starBtn) {
    starBtn.textContent = guest.is_starred ? '★' : '☆';
    starBtn.style.color = guest.is_starred ? '#eab308' : '#8696a0';
  }
  if (archiveBtn) {
    archiveBtn.style.color = guest.is_archived ? '#00a884' : '#8696a0';
  }

  // Populate right drawer details
  document.getElementById('wa-profile-name').textContent = guest.name;
  document.getElementById('wa-profile-phone').textContent = guest.mobile;
  document.getElementById('wa-profile-email').textContent = guest.email || 'N/A';
  document.getElementById('wa-profile-doc').textContent = guest.doc_number ? `${guest.doc_type || 'ID'}: ${guest.doc_number}` : 'N/A';
  document.getElementById('wa-profile-avatar-char').textContent = guest.name.charAt(0).toUpperCase();

  // Find guest language preference or fallback
  document.getElementById('wa-profile-lang').textContent = guest.email && guest.email.includes('.in') ? 'Hindi (IN)' : 'English (US)';
  
  // Load real history from server
  showLoader(true, 'Fetching chat logs...');
  try {
    const res = await fetch(`/api/whatsapp/chat-history?guestId=${guestId}`);
    if (res.ok) {
      const history = await res.json();
      state.whatsappChatHistories[guestId] = history.map(m => ({
        text: m.body,
        sender: m.sender_type,
        time: new Date(m.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
      }));
    }
  } catch (err) {}
  showLoader(false);

  // Render message history bubbles
  renderWhatsAppChatBubbles();
}

function renderWhatsAppChatBubbles() {
  const msgWindow = document.getElementById('wa-chat-message-window');
  if (!msgWindow) return;
  msgWindow.innerHTML = '';

  const history = state.whatsappChatHistories[activeChatGuestId] || [];
  history.forEach(m => {
    const isOut = m.sender === 'staff' || m.sender === 'bot';
    
    // Detect if content has clickable links
    let bodyHTML = m.text;
    if (m.text.startsWith('http://') || m.text.startsWith('https://')) {
      const filename = m.text.substring(m.text.lastIndexOf('/') + 1);
      bodyHTML = `📄 <a href="${m.text}" target="_blank" style="color: #00a884; font-weight: bold; text-decoration: underline;">${filename || 'Attached File'}</a>`;
    }

    const bubble = document.createElement('div');
    bubble.className = `wa-bubble-wrap ${isOut ? 'wa-bubble-outgoing' : 'wa-bubble-incoming'}`;
    bubble.innerHTML = `
      <div>${bodyHTML}</div>
      <div class="wa-bubble-time" style="display: flex; align-items: center; justify-content: flex-end; gap: 4px;">
        <span>${m.time}</span>
        ${isOut ? '<span style="color: #00a884;">✔✔</span>' : ''}
      </div>
    `;
    msgWindow.appendChild(bubble);
  });

  // Scroll to bottom
  msgWindow.scrollTop = msgWindow.scrollHeight;
}

async function assignWhatsAppChat() {
  if (!activeChatGuestId) return;
  const staffId = document.getElementById('wa-chat-assignee').value;
  
  showLoader(true, 'Assigning chat thread...');
  try {
    const res = await fetch('/api/guests/edit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        id: activeChatGuestId,
        assigned_staff_id: staffId || null
      })
    });
    
    showLoader(false);
    if (res.ok) {
      // Update local state guest list
      const g = state.guestsList.find(x => x.id === activeChatGuestId);
      if (g) g.assigned_staff_id = staffId ? parseInt(staffId, 10) : null;
      renderWhatsAppChatRoster();
    } else {
      alert('Failed to assign team member.');
    }
  } catch (err) {
    showLoader(false);
    alert(err.message);
  }
}

async function toggleWhatsAppChatBot() {
  if (!activeChatGuestId) return;
  const botEnabled = document.getElementById('wa-chat-bot-toggle').checked ? 1 : 0;
  
  showLoader(true, 'Updating Auto-Responder settings...');
  try {
    const res = await fetch('/api/guests/edit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        id: activeChatGuestId,
        reply_bot_enabled: botEnabled
      })
    });
    
    showLoader(false);
    if (res.ok) {
      const g = state.guestsList.find(x => x.id === activeChatGuestId);
      if (g) g.reply_bot_enabled = botEnabled;
      renderWhatsAppChatRoster();
    } else {
      alert('Failed to update bot configurations.');
    }
  } catch (err) {
    showLoader(false);
    alert(err.message);
  }
}

function triggerWhatsAppChatAttachment() {
  const url = prompt('Enter public URL link of invoice receipt / document to attach:');
  if (url) {
    document.getElementById('wa-chat-text-input').value = url;
  }
}

async function sendWhatsAppChatMessage(e) {
  if (e) e.preventDefault();
  if (!activeChatGuestId) return;

  const textInput = document.getElementById('wa-chat-text-input');
  const messageText = textInput.value.trim();
  if (!messageText) return;

  const guest = state.guestsList.find(g => g.id === activeChatGuestId);
  if (!guest) return;

  const timestamp = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });

  // 1. Append message to UI locally
  state.whatsappChatHistories[activeChatGuestId].push({
    text: messageText,
    sender: 'staff',
    time: timestamp
  });

  renderWhatsAppChatBubbles();
  textInput.value = '';

  // 2. Dispatch the real message via backend router using whichever provider is configured
  try {
    await fetch('/api/whatsapp/send', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone: guest.mobile, message: messageText, userId: state.currentUser.id })
    });
  } catch (err) {}

  // 3. AI FAQ bot check
  if (guest.reply_bot_enabled === 1) {
    setTimeout(() => {
      let botResponse = 'Thank you for reaching out! Our reception desk team has been notified of your message. (Concierge AI Bot)';
      const cleanMsg = messageText.toLowerCase();

      if (cleanMsg.includes('wifi') || cleanMsg.includes('internet')) {
        botResponse = 'The Shaima Hotel WiFi SSID is "SHAIMA_GUEST" and the password is: Shaima@2026. (Concierge AI Bot)';
      } else if (cleanMsg.includes('checkout') || cleanMsg.includes('check out') || cleanMsg.includes('settle')) {
        botResponse = 'Standard checkout time is 11:00 AM. If you would like to settle bills early, please click "Billing" in your app to review outstanding room services. (Concierge AI Bot)';
      } else if (cleanMsg.includes('food') || cleanMsg.includes('breakfast') || cleanMsg.includes('menu')) {
        botResponse = 'Breakfast is served daily from 7:30 AM to 10:30 AM at the Sea View Restaurant. Room service menu can be viewed on your desk QR code. (Concierge AI Bot)';
      }

      state.whatsappChatHistories[activeChatGuestId].push({
        text: botResponse,
        sender: 'bot',
        time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
      });

      if (activeChatGuestId === guest.id) {
        renderWhatsAppChatBubbles();
      }
      renderWhatsAppChatRoster();
    }, 1200);
  }
}

function viewWhatsAppChatGuestDetails() {
  if (!activeChatGuestId) return;
  // Switch to Guests CRM view and search for guest
  navigateTo('guests');
  const searchInput = document.getElementById('search-guest');
  if (searchInput) {
    const guest = state.guestsList.find(g => g.id === activeChatGuestId);
    if (guest) {
      searchInput.value = guest.name;
      loadGuestsList();
    }
  }
}

async function toggleWhatsAppChatStar() {
  if (!activeChatGuestId) return;
  const guest = state.guestsList.find(g => g.id === activeChatGuestId);
  if (!guest) return;

  const newStarred = guest.is_starred === 1 ? 0 : 1;
  showLoader(true, 'Updating star tag...');
  try {
    const res = await fetch('/api/guests/edit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        id: activeChatGuestId,
        is_starred: newStarred
      })
    });
    showLoader(false);
    if (res.ok) {
      guest.is_starred = newStarred;
      selectWhatsAppChat(activeChatGuestId);
    } else {
      alert('Failed to update star tag.');
    }
  } catch (err) {
    showLoader(false);
    alert(err.message);
  }
}

async function toggleWhatsAppChatArchive() {
  if (!activeChatGuestId) return;
  const guest = state.guestsList.find(g => g.id === activeChatGuestId);
  if (!guest) return;

  const newArchived = guest.is_archived === 1 ? 0 : 1;
  showLoader(true, 'Updating archive tag...');
  try {
    const res = await fetch('/api/guests/edit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        id: activeChatGuestId,
        is_archived: newArchived
      })
    });
    showLoader(false);
    if (res.ok) {
      guest.is_archived = newArchived;
      if (newArchived === 1) {
        activeChatGuestId = null;
        document.getElementById('wa-chat-empty-state').style.display = 'flex';
        document.getElementById('wa-chat-active-header').style.display = 'none';
        document.getElementById('wa-chat-message-window').style.display = 'none';
        document.getElementById('wa-chat-input-bar').style.display = 'none';
        document.getElementById('wa-chat-detail-drawer').style.display = 'none';
        renderWhatsAppChatRoster();
      } else {
        selectWhatsAppChat(activeChatGuestId);
      }
    } else {
      alert('Failed to update archive tag.');
    }
  } catch (err) {
    showLoader(false);
    alert(err.message);
  }
}

window.toggleWhatsAppProviderFields = toggleWhatsAppProviderFields;
window.toggleTemplateEditorFields = toggleTemplateEditorFields;
window.saveSocialSettings = saveSocialSettings;
window.handleSocialPublish = handleSocialPublish;
window.updateSocialPreview = updateSocialPreview;
window.shareReportViaEmail = shareReportViaEmail;
window.shareInvoiceViaEmail = shareInvoiceViaEmail;
window.saveSMTPSettings = saveSMTPSettings;
window.testSMTPConnection = testSMTPConnection;
window.regenerateAPIToken = regenerateAPIToken;

window.loadWhatsAppChatView = loadWhatsAppChatView;
window.filterWhatsAppChats = filterWhatsAppChats;
window.selectWhatsAppChat = selectWhatsAppChat;
window.assignWhatsAppChat = assignWhatsAppChat;
window.toggleWhatsAppChatBot = toggleWhatsAppChatBot;
window.triggerWhatsAppChatAttachment = triggerWhatsAppChatAttachment;
window.sendWhatsAppChatMessage = sendWhatsAppChatMessage;
window.viewWhatsAppChatGuestDetails = viewWhatsAppChatGuestDetails;
window.toggleWhatsAppChatStar = toggleWhatsAppChatStar;
window.toggleWhatsAppChatArchive = toggleWhatsAppChatArchive;

window.switchGmbTab = switchGmbTab;
window.loadGbpView = loadGbpView;
window.loadGbpPerformance = loadGbpPerformance;
window.loadGbpProfile = loadGbpProfile;
window.saveGbpProfile = saveGbpProfile;
window.loadGbpPhotos = loadGbpPhotos;
window.openAddGbpPhotoModal = openAddGbpPhotoModal;
window.uploadGbpPhoto = uploadGbpPhoto;
window.deleteGbpPhoto = deleteGbpPhoto;
window.loadGbpReviews = loadGbpReviews;
window.submitGbpReviewReply = submitGbpReviewReply;
window.assignGbpReview = assignGbpReview;
window.toggleGbpReviewHandled = toggleGbpReviewHandled;
window.suggestGbpAiReply = suggestGbpAiReply;
window.applyAiDraft = applyAiDraft;
window.loadGbpPosts = loadGbpPosts;
window.openAddGbpPostModal = openAddGbpPostModal;
window.toggleGbpPostTypeFields = toggleGbpPostTypeFields;
window.saveGbpPost = saveGbpPost;
window.deleteGbpPost = deleteGbpPost;
window.loadGbpKeywords = loadGbpKeywords;
window.openAddKeywordModal = openAddKeywordModal;
window.saveGbpKeyword = saveGbpKeyword;
window.deleteGbpKeyword = deleteGbpKeyword;
window.loadGbpSeoStatus = loadGbpSeoStatus;
window.generateSeoCopy = generateSeoCopy;
window.loadGbpCompetitors = loadGbpCompetitors;
window.openAddCompetitorModal = openAddCompetitorModal;
window.saveGbpCompetitor = saveGbpCompetitor;
window.deleteGbpCompetitor = deleteGbpCompetitor;
window.initiateGbpOAuth = initiateGbpOAuth;
window.disconnectGbp = disconnectGbp;
window.saveGbpManualConfig = saveGbpManualConfig;
window.testGbpConnection = testGbpConnection;
window.closeModal = closeModal;

// ================= SQLITE BACKUP & RESTORE CONTROLLERS ================= //
async function loadLocalBackupsList() {
  const tbody = document.getElementById('local-backups-table-tbody');
  if (!tbody) return;
  tbody.innerHTML = '<tr><td colspan="4" style="text-align: center; color: #888;">Scanning backups...</td></tr>';
  
  try {
    const res = await fetch('/api/settings/backups');
    if (!res.ok) return;
    const backups = await res.json();
    tbody.innerHTML = '';
    
    if (backups.length === 0) {
      tbody.innerHTML = '<tr><td colspan="4" style="text-align: center; color: #888;">No local backup files found.</td></tr>';
      return;
    }
    
    backups.forEach(b => {
      const tr = document.createElement('tr');
      const sizeKB = (b.size / 1024).toFixed(1);
      const sizeStr = sizeKB > 1024 ? (sizeKB / 1024).toFixed(2) + ' MB' : sizeKB + ' KB';
      const createdDate = new Date(b.created_at).toLocaleString();
      
      tr.innerHTML = `
        <td><strong>${b.filename}</strong></td>
        <td>${createdDate}</td>
        <td>${sizeStr}</td>
        <td style="text-align: right;">
          <button type="button" class="btn btn-warning btn-xs" onclick="triggerRestoreBackup('${b.filepath.replace(/\\/g, '\\\\')}')" style="padding: 2px 8px; font-size: 10px;">Restore</button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  } catch (e) {
    tbody.innerHTML = '<tr><td colspan="4" style="text-align: center; color: var(--color-maintenance);">Failed to load backups list.</td></tr>';
  }
}

async function triggerRestoreBackup(filepath) {
  const confirmRestore = confirm('WARNING: Are you sure you want to restore this database backup?\\n\\nThis will completely overwrite all current reservations, rooms, billing, and settings. The server will restart automatically.');
  if (!confirmRestore) return;
  
  const password = prompt('Enter Security Master Password to verify restore authorization:');
  if (password !== 'Shaima@#8870') {
    alert('Unauthorized: Invalid security master password.');
    return;
  }
  
  showLoader(true, 'Restoring database & restarting server...');
  try {
    const res = await fetch('/api/settings/restore', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ backupFile: filepath, userId: state.currentUser.id })
    });
    showLoader(false);
    alert('Database restore initialized. The server is restarting to load the backup. Please wait 5 seconds and reload the page.');
    setTimeout(() => {
      window.location.reload();
    }, 5000);
  } catch (err) {
    showLoader(false);
    alert('Database restore initialized. The server is restarting to load the backup. Please wait 5 seconds and reload the page.');
    setTimeout(() => {
      window.location.reload();
    }, 5000);
  }
}

window.loadLocalBackupsList = loadLocalBackupsList;
window.triggerRestoreBackup = triggerRestoreBackup;

