/**
 * Base Module JavaScript
 * Core functionality for the General Bots Suite
 * Handles navigation, theme, settings, accessibility, and HTMX error handling
 */

// DOM Elements
const appsBtn = document.getElementById("apps-btn");
const appsDropdown = document.getElementById("apps-dropdown");
const settingsBtn = document.getElementById("settings-btn");
const settingsPanel = document.getElementById("settings-panel");

// Apps Menu Toggle
if (appsBtn) {
  appsBtn.addEventListener("click", (e) => {
    e.stopPropagation();
    const isOpen = appsDropdown.classList.toggle("show");
    appsBtn.setAttribute("aria-expanded", isOpen);
    settingsPanel.classList.remove("show");
  });
}

// Settings Panel Toggle
if (settingsBtn) {
  settingsBtn.addEventListener("click", (e) => {
    e.stopPropagation();
    const isOpen = settingsPanel.classList.toggle("show");
    settingsBtn.setAttribute("aria-expanded", isOpen);
    appsDropdown.classList.remove("show");
  });
}

// Close dropdowns when clicking outside
document.addEventListener("click", (e) => {
  if (
    appsDropdown &&
    !appsDropdown.contains(e.target) &&
    !appsBtn.contains(e.target)
  ) {
    appsDropdown.classList.remove("show");
    appsBtn.setAttribute("aria-expanded", "false");
  }
  if (
    settingsPanel &&
    !settingsPanel.contains(e.target) &&
    !settingsBtn.contains(e.target)
  ) {
    settingsPanel.classList.remove("show");
    settingsBtn.setAttribute("aria-expanded", "false");
  }
});

// Escape key closes dropdowns
document.addEventListener("keydown", (e) => {
  if (e.key === "Escape") {
    if (appsDropdown) appsDropdown.classList.remove("show");
    if (settingsPanel) settingsPanel.classList.remove("show");
    if (appsBtn) appsBtn.setAttribute("aria-expanded", "false");
    if (settingsBtn) settingsBtn.setAttribute("aria-expanded", "false");
  }
});

// Alt+key shortcuts for navigation
document.addEventListener("keydown", (e) => {
  if (e.altKey && !e.ctrlKey && !e.shiftKey) {
    const shortcuts = {
      1: "chat",
      2: "drive",
      3: "tasks",
      4: "mail",
      5: "calendar",
      6: "meet",
      7: "paper",
      8: "research",
      9: "sources",
      0: "analytics",
      a: "admin",
      m: "monitoring",
    };
    if (shortcuts[e.key]) {
      e.preventDefault();
      const link = document.querySelector(`a[href="#${shortcuts[e.key]}"]`);
      if (link) link.click();
      if (appsDropdown) appsDropdown.classList.remove("show");
    }
    if (e.key === ",") {
      e.preventDefault();
      if (settingsPanel) settingsPanel.classList.toggle("show");
    }
    if (e.key === "s") {
      e.preventDefault();
      const settingsLink = document.querySelector(`a[href="#settings"]`);
      if (settingsLink) settingsLink.click();
    }
  }
});

// Update active app on HTMX swap
document.body.addEventListener("htmx:afterSwap", (e) => {
  if (e.detail.target.id === "main-content") {
    const hash = window.location.hash || "#chat";
    document.querySelectorAll(".app-item").forEach((item) => {
      item.classList.toggle("active", item.getAttribute("href") === hash);
    });
    if (settingsPanel) settingsPanel.classList.remove("show");
  }
});

// Theme handling
// Available themes: dark, light, blue, purple, green, orange, sentient
const themeOptions = document.querySelectorAll(".theme-option");
const savedTheme = localStorage.getItem("gb-theme") || "sentient";
document.body.setAttribute("data-theme", savedTheme);
document
  .querySelector(`.theme-option[data-theme="${savedTheme}"]`)
  ?.classList.add("active");

// Update theme-color meta tag based on theme
function updateThemeColor(theme) {
  const themeColors = {
    // Core Themes
    dark: "#3b82f6",
    light: "#3b82f6",
    blue: "#0ea5e9",
    purple: "#a855f7",
    green: "#22c55e",
    orange: "#f97316",
    sentient: "#d4f505",
    // Retro Themes
    cyberpunk: "#ff00ff",
    retrowave: "#ff6b9d",
    vapordream: "#a29bfe",
    y2kglow: "#00ff00",
    arcadeflash: "#ffff00",
    discofever: "#ff1493",
    grungeera: "#8b4513",
    // Classic Themes
    jazzage: "#d4af37",
    mellowgold: "#daa520",
    midcenturymod: "#e07b39",
    polaroidmemories: "#e6b89c",
    saturdaycartoons: "#ff6347",
    seasidepostcard: "#20b2aa",
    typewriter: "#2f2f2f",
    // Tech Themes
    "3dbevel": "#0000ff",
    xeroxui: "#4a86cf",
    xtreegold: "#ffff00",
  };
  const metaTheme = document.querySelector('meta[name="theme-color"]');
  if (metaTheme) {
    metaTheme.setAttribute("content", themeColors[theme] || "#d4f505");
  }
}
updateThemeColor(savedTheme);

themeOptions.forEach((option) => {
  option.addEventListener("click", () => {
    const theme = option.getAttribute("data-theme");
    document.body.setAttribute("data-theme", theme);
    localStorage.setItem("gb-theme", theme);
    themeOptions.forEach((o) => o.classList.remove("active"));
    option.classList.add("active");
    updateThemeColor(theme);
  });
});

// Global theme setter function (can be called from settings or elsewhere)
window.setTheme = function (theme) {
  document.body.setAttribute("data-theme", theme);
  localStorage.setItem("gb-theme", theme);
  themeOptions.forEach((o) => {
    o.classList.toggle("active", o.getAttribute("data-theme") === theme);
  });
  updateThemeColor(theme);
};

// Quick Settings Toggle
function toggleQuickSetting(el) {
  el.classList.toggle("active");
  const setting = el.id.replace("toggle-", "");
  localStorage.setItem(`gb-${setting}`, el.classList.contains("active"));
}

// Load quick toggle states
["notifications", "sound", "compact"].forEach((setting) => {
  const saved = localStorage.getItem(`gb-${setting}`);
  const toggle = document.getElementById(`toggle-${setting}`);
  if (toggle && saved !== null) {
    toggle.classList.toggle("active", saved === "true");
  }
});

// Show keyboard shortcuts notification
function showKeyboardShortcuts() {
  window.showNotification(
    "Alt+1-9,0 for apps, Alt+A Admin, Alt+M Monitoring, Alt+S Settings, Alt+, quick settings",
    "info",
    8000,
  );
}

// Accessibility: Announce page changes to screen readers
function announceToScreenReader(message) {
  const liveRegion = document.getElementById("aria-live");
  if (liveRegion) {
    liveRegion.textContent = message;
    // Clear after announcement
    setTimeout(() => {
      liveRegion.textContent = "";
    }, 1000);
  }
}

// HTMX accessibility hooks
document.body.addEventListener("htmx:beforeRequest", function (e) {
  const target = e.detail.target;
  if (target && target.id === "main-content") {
    target.setAttribute("aria-busy", "true");
    announceToScreenReader("Loading content...");
  }
});

document.body.addEventListener("htmx:afterSwap", function (e) {
  const target = e.detail.target;
  if (target && target.id === "main-content") {
    target.setAttribute("aria-busy", "false");
    // Focus management: move focus to main content after navigation
    target.focus();
    announceToScreenReader("Content loaded");
  }
});

document.body.addEventListener("htmx:responseError", function (e) {
  const target = e.detail.target;
  if (target) {
    target.setAttribute("aria-busy", "false");
  }
  announceToScreenReader("Error loading content. Please try again.");
});

// Keyboard navigation for apps grid
document.addEventListener("keydown", function (e) {
  const appsGrid = document.querySelector(".apps-grid");
  if (!appsGrid || !appsGrid.closest(".show")) return;

  const items = Array.from(appsGrid.querySelectorAll(".app-item"));
  const currentIndex = items.findIndex(
    (item) => item === document.activeElement,
  );

  if (currentIndex === -1) return;

  let newIndex = currentIndex;
  const columns = 3; // Grid has 3 columns on desktop

  switch (e.key) {
    case "ArrowRight":
      newIndex = Math.min(currentIndex + 1, items.length - 1);
      break;
    case "ArrowLeft":
      newIndex = Math.max(currentIndex - 1, 0);
      break;
    case "ArrowDown":
      newIndex = Math.min(currentIndex + columns, items.length - 1);
      break;
    case "ArrowUp":
      newIndex = Math.max(currentIndex - columns, 0);
      break;
    case "Home":
      newIndex = 0;
      break;
    case "End":
      newIndex = items.length - 1;
      break;
    default:
      return;
  }

  if (newIndex !== currentIndex) {
    e.preventDefault();
    items[newIndex].focus();
  }
});

// Notification System
window.showNotification = function (message, type = "info", duration = 5000) {
  const container = document.getElementById("notifications");
  if (!container) return;

  const notification = document.createElement("div");
  notification.className = `notification ${type}`;
  notification.innerHTML = `
        <div class="notification-content">
            <div class="notification-message">${message}</div>
        </div>
        <button class="notification-close" onclick="this.parentElement.remove()" style="background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:1.25rem;">×</button>
    `;
  container.appendChild(notification);
  if (duration > 0) {
    setTimeout(() => notification.remove(), duration);
  }
};

// Global HTMX error handling with retry mechanism
const htmxRetryConfig = {
  maxRetries: 3,
  retryDelay: 1000,
  retryCount: new Map(),
};

function getRetryKey(elt) {
  return (
    elt.getAttribute("hx-get") ||
    elt.getAttribute("hx-post") ||
    elt.getAttribute("hx-put") ||
    elt.getAttribute("hx-delete") ||
    elt.id ||
    Math.random().toString(36)
  );
}

function showErrorState(target, errorMessage, retryCallback) {
  const errorHtml = `
        <div class="error-state">
            <svg class="error-state-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <circle cx="12" cy="12" r="10"></circle>
                <line x1="12" y1="8" x2="12" y2="12"></line>
                <line x1="12" y1="16" x2="12.01" y2="16"></line>
            </svg>
            <div class="error-state-title">Something went wrong</div>
            <div class="error-state-message">${errorMessage}</div>
            <div class="error-state-actions">
                <button class="btn-retry" onclick="window.retryLastRequest(this)">
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                        <path d="M23 4v6h-6"></path>
                        <path d="M1 20v-6h6"></path>
                        <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10"></path>
                        <path d="M20.49 15a9 9 0 0 1-14.85 3.36L1 14"></path>
                    </svg>
                    Try Again
                </button>
            </div>
        </div>
    `;
  target.innerHTML = errorHtml;
  target.dataset.retryCallback = retryCallback;
}

window.retryLastRequest = function (btn) {
  const target = btn.closest(".error-state").parentElement;
  const retryCallback = target.dataset.retryCallback;

  btn.disabled = true;
  btn.innerHTML = '<span class="spinner"></span> Retrying...';

  if (retryCallback && window[retryCallback]) {
    window[retryCallback]();
  } else {
    // Try to re-trigger HTMX request
    const triggers = target.querySelectorAll("[hx-get], [hx-post]");
    if (triggers.length > 0) {
      htmx.trigger(triggers[0], "htmx:trigger");
    } else {
      // Reload the current app
      const activeApp = document.querySelector(".app-item.active");
      if (activeApp) {
        activeApp.click();
      }
    }
  }
};

// Handle HTMX errors globally
document.body.addEventListener("htmx:responseError", function (e) {
  const target = e.detail.target;
  const xhr = e.detail.xhr;
  const retryKey = getRetryKey(e.detail.elt);

  let currentRetries = htmxRetryConfig.retryCount.get(retryKey) || 0;

  // Auto-retry for network errors (status 0) or server errors (5xx)
  if (
    (xhr.status === 0 || xhr.status >= 500) &&
    currentRetries < htmxRetryConfig.maxRetries
  ) {
    htmxRetryConfig.retryCount.set(retryKey, currentRetries + 1);
    const delay = htmxRetryConfig.retryDelay * Math.pow(2, currentRetries);

    window.showNotification(
      `Request failed. Retrying in ${delay / 1000}s... (${currentRetries + 1}/${htmxRetryConfig.maxRetries})`,
      "warning",
      delay,
    );

    setTimeout(() => {
      htmx.trigger(e.detail.elt, "htmx:trigger");
    }, delay);
  } else {
    // Max retries reached or client error - show error state
    htmxRetryConfig.retryCount.delete(retryKey);

    let errorMessage = "We couldn't load the content.";
    if (xhr.status === 401) {
      errorMessage = "Your session has expired. Please log in again.";
    } else if (xhr.status === 403) {
      errorMessage = "You don't have permission to access this resource.";
    } else if (xhr.status === 404) {
      errorMessage = "The requested content was not found.";
    } else if (xhr.status >= 500) {
      errorMessage =
        "The server is experiencing issues. Please try again later.";
    } else if (xhr.status === 0) {
      errorMessage =
        "Unable to connect. Please check your internet connection.";
    }

    if (target && target.id === "main-content") {
      showErrorState(target, errorMessage);
    } else {
      window.showNotification(errorMessage, "error", 8000);
    }
  }
});

// Clear retry count on successful request
document.body.addEventListener("htmx:afterRequest", function (e) {
  if (e.detail.successful) {
    const retryKey = getRetryKey(e.detail.elt);
    htmxRetryConfig.retryCount.delete(retryKey);
  }
});

// Handle timeout errors
document.body.addEventListener("htmx:timeout", function (e) {
  window.showNotification(
    "Request timed out. Please try again.",
    "warning",
    5000,
  );
});

// Handle send errors (network issues before request sent)
document.body.addEventListener("htmx:sendError", function (e) {
  window.showNotification(
    "Network error. Please check your connection.",
    "error",
    5000,
  );
});
