// Library management functionality for admin/library page
// Procedural/imperative style t
// nt
// OOP)

import { Alpine } from "./alpine";
import {
  apiPut,
  apiPost,
  apiGet,
  handleResponse,
  handleError,
  handleVoidResponse,
  apiDelete,
} from "./api";
import { showToast } from "./toast";

interface Library {
  id: string;
  name: string;
  description: string | null;
  library_type_id: string;
  type_name: string;
  created_at: string;
  updated_at: string;
}

interface LibraryFolder {
  id: string;
  library_id: string;
  folder_path: string;
  created_at: string;
}

interface LibrariesResponse {
  data: Library[];
}

// State (already SSR'd, used for updates)
let libraries: Library[] = [];

// Reload libraries from API (called after create/delete/update)
async function reloadLibraries(): Promise<void> {
  try {
    const response = await apiGet("/libraries");
    const result = (await handleResponse(
      response,
    )) as unknown as LibrariesResponse;
    libraries = result.data;
    renderLibraries();
  } catch (error) {
    handleError(error, "Failed to load libraries");
  }
}

// Render libraries list (replaces SSR content after updates)
function renderLibraries(): void {
  const container = document.getElementById("libraries-list");
  if (!container) return;
  if (libraries.length === 0) {
    container.innerHTML =
      '<p style="color: var(--text-secondary)" class="text-center py-8">No libraries yet. Create your first library to get started.</p>';
    return;
  }

  container.innerHTML = libraries
    .map(
      (library) =>
        '<div class="p-4 border rounded-lg" style="background-color: var(--bg-primary); border-color: var(--border)">' +
        '<div class="flex justify-between items-start mb-2">' +
        "<div>" +
        `<h4 class="font-semibold" style="color: var(--text-primary)">${escapeHtmlLocal(library.name)}</h4>` +
        (library.description
          ? `<p class="text-sm" style="color: var(--text-secondary)">${escapeHtmlLocal(library.description)}</p>`
          : "") +
        `<span class="inline-block px-2 py-1 text-xs rounded" style="background-color: var(--accent); color: var(--bg-primary)">${escapeHtmlLocal(library.type_name)}</span>` +
        "</div>" +
        '<div class="flex space-x-2">' +
        `<button data-library-id="${library.id}" data-action="show-folders" class="text-xs px-2 py-1 rounded" style="background-color: var(--bg-secondary); color: var(--text-primary)">Folders</button>` +
        `<button data-library-id="${library.id}" data-action="edit" class="text-xs px-2 py-1 rounded" style="background-color: var(--accent); color: var(--bg-primary)">Edit</button>` +
        `<button data-library-id="${library.id}" data-action="delete" class="text-xs px-2 py-1 rounded text-red-500">Delete</button>` +
        "</div>" +
        "</div>" +
        `<div id="library-folders-${library.id}" class="hidden mt-3 space-y-2"></div>` +
        "</div>",
    )
    .join("");
}

// Load user's visible libraries for visibility management
async function loadUserVisibility(): Promise<void> {
  const select = document.getElementById("user-select") as HTMLSelectElement;
  const userId = select?.value;
  if (!userId) {
    const container = document.getElementById("user-libraries");
    if (container) {
      container.innerHTML =
        '<p style="color: var(--text-secondary)">Please select a user</p>';
    }
    return;
  }

  try {
    const response = await apiGet("/libraries/visible");
    const visibleLibraries = (await handleResponse(
      response,
    )) as unknown as Library[];
    const container = document.getElementById("user-libraries");
    if (!container) return;

    const visibleIds = new Set(visibleLibraries.map((lib: Library) => lib.id));

    container.innerHTML = libraries
      .map((library) => {
        const isVisible = visibleIds.has(library.id);
        return (
          '<label class="flex items-center space-x-3 p-2 rounded" style="background-color: var(--bg-primary);">' +
          `<input type="checkbox" ${isVisible ? "checked" : ""} ` +
          `data-user-id="${userId}" data-library-id="${library.id}" ` +
          `onchange="setLibraryVisibility('${userId}', '${library.id}', this.checked)" ` +
          'class="w-4 h-4">' +
          `<span style="color: var(--text-primary)">${escapeHtmlLocal(library.name)} (${escapeHtmlLocal(library.type_name)})</span>` +
          "</label>"
        );
      })
      .join("");
  } catch (error) {
    handleError(error, "Failed to load user libraries");
  }
}

// Set library visibility for a user
async function setLibraryVisibility(
  userId: string,
  libraryId: string,
  isVisible: boolean,
): Promise<void> {
  // userId is used in the HTML onchange handler but the API gets user from JWT context
  console.debug(
    "Setting visibility for user:",
    userId,
    "library:",
    libraryId,
    "visible:",
    isVisible,
  );

  try {
    const response = await apiPost("/libraries/visibility", {
      library_id: libraryId,
      is_visible: isVisible,
    });
    await handleVoidResponse(response);

    showToast("Library visibility updated", "success");

    // Refresh visibility controls
    void loadUserVisibility();
  } catch (error) {
    handleError(error, "Failed to update library visibility");
  }
}

// Create library form handler
async function handleCreateLibrarySubmit(event: Event): Promise<void> {
  event.preventDefault();

  const form = event.target as HTMLFormElement;
  const formData = new FormData(form);

  const libraryId = (document.getElementById("library-id") as HTMLInputElement)
    ?.value;
  const isEdit = !!libraryId;

  const libraryData = {
    name: formData.get("name") as string,
    description: formData.get("description") as string,
    type: formData.get("type") as string,
  };

  try {
    const url = isEdit ? `/libraries/${libraryId}` : "/libraries";
    const response = isEdit
      ? await apiPut(url, libraryData)
      : await apiPost(url, libraryData);

    if (isEdit) {
      await handleVoidResponse(response);
    } else {
      (await handleResponse(response)) as unknown as { data: Library };
    }

    showToast(
      isEdit ? "Library updated successfully" : "Library created successfully",
      "success",
    );

    hideCreateLibraryModal();
    form.reset();

    const libraryIdInput = document.getElementById(
      "library-id",
    ) as HTMLInputElement;
    if (libraryIdInput) {
      libraryIdInput.value = "";
    }

    void reloadLibraries();
  } catch (error) {
    handleError(
      error,
      isEdit ? "Failed to update library" : "Failed to create library",
    );
  }
}

// Delete library
async function deleteLibrary(libraryId: string): Promise<void> {
  const library = libraries.find((l) => l.id === libraryId);
  if (!library) return;

  showDeleteModal(library);
}

// Show library folders
async function showLibraryFolders(libraryId: string): Promise<void> {
  const container = document.getElementById(`library-folders-${libraryId}`);
  if (!container) return;

  try {
    const response = await apiGet(`/libraries/${libraryId}/folders`);
    const folders = (await handleResponse(
      response,
    )) as unknown as LibraryFolder[];

    container.innerHTML = folders
      .map(
        (folder: LibraryFolder) =>
          '<div class="flex justify-between items-center p-2 rounded" style="background-color: var(--bg-secondary); border-color: var(--border)">' +
          `<span class="text-sm" style="color: var(--text-primary)">${escapeHtmlLocal(folder.folder_path)}</span>` +
          `<button data-library-id="${libraryId}" data-folder-path="${escapeHtmlLocal(folder.folder_path)}" data-action="remove-folder" ` +
          'class="text-xs text-red-500">Remove</button>' +
          "</div>",
      )
      .join("");

    container.innerHTML +=
      '<div class="mt-2 flex space-x-2">' +
      `<input type="text" id="folder-path-${libraryId}" placeholder="Add folder path" ` +
      'class="flex-1 px-2 py-1 text-sm border rounded" style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border)">' +
      `<button data-action="browse-folder" data-input-id="folder-path-${libraryId}" ` +
      'class="btn-secondary px-2 py-1 text-xs rounded">Browse</button>' +
      `<button data-library-id="${libraryId}" data-action="add-folder" ` +
      'class="btn-primary px-2 py-1 text-xs rounded">Add</button>' +
      "</div>";

    container.classList.remove("hidden");
  } catch (error) {
    handleError(error, "Failed to load folders");
  }
}

// Add library folder
async function addLibraryFolder(libraryId: string): Promise<void> {
  const input = document.getElementById(
    `folder-path-${libraryId}`,
  ) as HTMLInputElement;
  const folderPath = input?.value.trim();

  if (!folderPath) {
    return;
  }

  try {
    const response = await apiPost(`/libraries/${libraryId}/folders`, {
      folder_path: folderPath,
    });
    await handleVoidResponse(response);

    showToast("Folder added successfully", "success");

    if (input) {
      input.value = "";
    }
    void showLibraryFolders(libraryId); // Refresh
  } catch (error) {
    handleError(error, "Failed to add folder");
  }
}

// Remove library folder
async function removeLibraryFolder(
  libraryId: string,
  folderPath: string,
): Promise<void> {
  if (!confirm(`Remove folder "${folderPath}" from the library?`)) {
    return;
  }

  try {
    const response = await apiDelete(`/libraries/${libraryId}/folders`, {
      folder_path: folderPath,
    });
    await handleVoidResponse(response);

    showToast("Folder removed successfully", "success");

    void showLibraryFolders(libraryId); // Refresh
  } catch (error) {
    handleError(error, "Failed to remove folder");
  }
}

// Edit library (placeholder - opens modal or navigates to edit page)
function editLibrary(libraryId: string): void {
  const library = libraries.find((l) => l.id === libraryId);
  if (!library) {
    showToast("Library not found", "error");
    return;
  }

  const form = document.getElementById(
    "create-library-form",
  ) as HTMLFormElement;
  if (form) {
    const nameInput = form.querySelector('[name="name"]') as HTMLInputElement;
    const descInput = form.querySelector(
      '[name="description"]',
    ) as HTMLTextAreaElement;
    const typeInput = form.querySelector('[name="type"]') as HTMLSelectElement;

    if (nameInput) nameInput.value = library.name;
    if (descInput) descInput.value = library.description || "";
    if (typeInput) typeInput.value = library.type_name;
  }

  const modalTitle = document.querySelector("#create-library-modal h2");
  if (modalTitle) {
    modalTitle.textContent = "Edit Library";
  }

  const libraryIdInput = document.getElementById(
    "library-id",
  ) as HTMLInputElement;
  if (libraryIdInput) {
    libraryIdInput.value = libraryId;
  }

  showCreateLibraryModal();
}

// Modal controls
function showCreateLibraryModal(): void {
  const modal = document.getElementById("create-library-modal") as HTMLElement;
  if (modal) {
    modal.classList.remove("hidden");

    const modalTitle = document.querySelector("#create-library-modal h2");
    if (modalTitle) {
      modalTitle.textContent = "Create Library";
    }
  }
}

function hideCreateLibraryModal(): void {
  const modal = document.getElementById("create-library-modal") as HTMLElement;
  if (modal) {
    modal.classList.add("hidden");
  }
}

// Delete modal state
let libraryToDelete: Library | null = null;

function showDeleteModal(library: Library): void {
  libraryToDelete = library;

  const modal = document.getElementById("delete-library-modal") as HTMLElement;
  const content = document.getElementById(
    "delete-modal-content",
  ) as HTMLElement;

  if (modal && content) {
    const message = `Are you sure you want to delete "<strong>${escapeHtmlLocal(library.name)}</strong>"?

This will remove:
• Library metadata from the database
• All folder references
• All book records from the database

⚠️ Book files on disk will NOT be deleted.

This action cannot be undone.`;

    content.innerHTML = message.replace(/\n/g, "<br>");
    modal.classList.remove("hidden");
  }
}

function hideDeleteModal(): void {
  const modal = document.getElementById("delete-library-modal") as HTMLElement;
  if (modal) {
    modal.classList.add("hidden");
  }
  libraryToDelete = null;
}

async function confirmDeleteLibrary(): Promise<void> {
  if (!libraryToDelete) return;

  const libraryId = libraryToDelete.id;
  hideDeleteModal();

  try {
    const response = await apiDelete(`/libraries/${libraryId}`);
    await handleVoidResponse(response);

    showToast("Library deleted successfully", "success");

    await reloadLibraries();

    const libraryIdInput = document.getElementById(
      "library-id",
    ) as HTMLInputElement | null;
    if (libraryIdInput) {
      libraryIdInput.value = "";
    }
  } catch (error) {
    handleError(error, "Failed to delete library");
  }
}

// Local escape HTML helper
function escapeHtmlLocal(text: string): string {
  const div = document.createElement("div");
  div.textContent = text;
  return div.innerHTML;
}

// Event delegation for handling dynamic button clicks
function handleLibraryListClick(event: Event): void {
  const target = event.target as HTMLElement;
  const button = target.closest("button") as HTMLElement;
  if (!button) return;

  const action = button.dataset.action;
  const libraryId = button.dataset.libraryId;

  switch (action) {
    case "show-folders":
      if (libraryId) showLibraryFolders(libraryId);
      break;
    case "delete":
      if (libraryId) deleteLibrary(libraryId);
      break;
    case "edit":
      if (libraryId) editLibrary(libraryId);
      break;
    case "add-folder":
      if (libraryId) addLibraryFolder(libraryId);
      break;
    case "remove-folder":
      if (libraryId && button.dataset.folderPath) {
        removeLibraryFolder(libraryId, button.dataset.folderPath);
      }
      break;
    case "browse-folder":
      if (button.dataset.inputId) showFolderBrowser(button.dataset.inputId);
      break;
  }
}

function handleFolderBrowserClick(event: Event): void {
  const target = event.target as HTMLElement;
  const button = target.closest("button") as HTMLElement;
  const div = target.closest("div[data-action]") as HTMLElement;

  if (button) {
    const action = button.dataset.action;
    const path = button.dataset.path;

    switch (action) {
      case "browse-parent":
        if (path) navigateFolderBrowser(path);
        break;
      case "browse-cancel":
        hideFolderBrowser();
        break;
      case "browse-select":
        if (path) selectBrowseFolder(path);
        break;
    }
  }

  if (div && div.dataset.action === "browse-navigate") {
    const path = div.dataset.path;
    if (path) navigateFolderBrowser(path);
  }
}

function handleGlobalClick(event: Event): void {
  const target = event.target as HTMLElement;
  const button = target.closest("button") as HTMLElement;
  if (!button) return;

  const action = button.dataset.action;

  switch (action) {
    case "show-create-modal":
      showCreateLibraryModal();
      break;
    case "hide-create-modal":
      hideCreateLibraryModal();
      break;
    case "hide-delete-modal":
      hideDeleteModal();
      break;
    case "confirm-delete":
      void confirmDeleteLibrary();
      break;
  }
}

// Folder browser state
let currentBrowsePath = "";
let currentBrowseInputId = "";

// Show folder browser modal
function showFolderBrowser(inputId: string): void {
  currentBrowseInputId = inputId;
  currentBrowsePath = "/";

  const modal = document.getElementById("folder-browser-modal") as HTMLElement;
  if (modal) {
    modal.classList.remove("hidden");
    void loadBrowseDirectories(currentBrowsePath);
  }
}

// Load directories for browsing
async function loadBrowseDirectories(path: string): Promise<void> {
  try {
    const response = await apiGet(
      `/libraries/browse?path=${encodeURIComponent(path)}`,
    );
    const data = (await handleResponse(response)) as unknown as {
      current_path: string;
      parent_path: string;
      directories: string[];
    };

    currentBrowsePath = data.current_path;
    renderBrowseDirectories(data);
  } catch (error) {
    handleError(error, "Failed to load directories");
  }
}

// Render browse directories (uses event delegation via data-action attributes)
function renderBrowseDirectories(data: {
  current_path: string;
  parent_path: string;
  directories: string[];
}): void {
  const container = document.getElementById("folder-browser-content");
  if (!container) return;

  let html = `
        <div class="flex items-center gap-2 mb-4">
            ${
              data.parent_path
                ? `<button type="button" data-action="browse-parent" data-path="${escapeHtmlLocal(data.parent_path)}" class="btn-secondary px-3 py-1 rounded">↑ Parent</button>`
                : ""
            }
            <span class="text-sm" style="color: var(--text-secondary)">${escapeHtmlLocal(data.current_path)}</span>
        </div>
        <div class="max-h-64 overflow-y-auto space-y-1">
    `;

  if (data.directories.length === 0) {
    html +=
      '<p style="color: var(--text-secondary)" class="text-center py-4">No subdirectories</p>';
  } else {
    data.directories.forEach((dir) => {
      const fullPath =
        data.current_path === "/" ? `/${dir}` : `${data.current_path}/${dir}`;
      html += `
                <div class="p-2 rounded cursor-pointer hover:opacity-80"
                     style="background-color: var(--bg-secondary); color: var(--text-primary)"
                     data-action="browse-navigate"
                     data-path="${escapeHtmlLocal(fullPath)}">
                    📁 ${escapeHtmlLocal(dir)}
                </div>
            `;
    });
  }

  html += `
        </div>
        <div class="mt-4 flex justify-end gap-2">
            <button type="button" data-action="browse-cancel" class="btn-secondary px-4 py-2 rounded">Cancel</button>
            <button type="button" data-action="browse-select" data-path="${escapeHtmlLocal(data.current_path)}" class="btn-primary px-4 py-2 rounded">Select This Folder</button>
        </div>
    `;

  container.innerHTML = html;
}

// Navigate to subdirectory
function navigateFolderBrowser(path: string): void {
  void loadBrowseDirectories(path);
}

// Select folder and close browser
function selectBrowseFolder(path: string): void {
  const input = document.getElementById(
    currentBrowseInputId,
  ) as HTMLInputElement;
  if (input) {
    input.value = path;
  }
  hideFolderBrowser();
}

// Hide folder browser modal
function hideFolderBrowser(): void {
  const modal = document.getElementById("folder-browser-modal") as HTMLElement;
  if (modal) {
    modal.classList.add("hidden");
  }
}

// Initialize page
function initializeLibraryAdmin(): void {
  // Setup event listeners
  const librariesList = document.getElementById("libraries-list");
  if (librariesList) {
    librariesList.addEventListener("click", handleLibraryListClick);
  }

  const folderBrowserModal = document.getElementById("folder-browser-modal");
  if (folderBrowserModal) {
    folderBrowserModal.addEventListener("click", handleFolderBrowserClick);
  }

  document.addEventListener("click", handleGlobalClick);

  // Setup form submission
  const createLibraryForm = document.getElementById("create-library-form");
  if (createLibraryForm) {
    createLibraryForm.addEventListener("submit", handleCreateLibrarySubmit);
  }

  // SSR provides initial library list - no need to fetch on page load
  // reloadLibraries() is called after create/delete/update operations
}

// Export functions for global access
export {
  addLibraryFolder,
  confirmDeleteLibrary,
  deleteLibrary,
  editLibrary,
  handleCreateLibrarySubmit,
  hideDeleteModal,
  hideFolderBrowser,
  initializeLibraryAdmin,
  loadUserVisibility,
  navigateFolderBrowser,
  removeLibraryFolder,
  selectBrowseFolder,
  setLibraryVisibility,
  showDeleteModal,
  showFolderBrowser,
  showLibraryFolders,
};

Alpine.data("library", () => ({
  addLibraryFolder,
  confirmDeleteLibrary,
  deleteLibrary,
  editLibrary,
  handleCreateLibrarySubmit,
  hideDeleteModal,
  hideFolderBrowser,
  initializeLibraryAdmin,
  loadUserVisibility,
  navigateFolderBrowser,
  removeLibraryFolder,
  selectBrowseFolder,
  setLibraryVisibility,
  showDeleteModal,
  showFolderBrowser,
  showLibraryFolders,
}));
