import { Alpine } from "./alpine";
import { apiPost, apiPut } from "./api";
import { showToast } from "./toast";

// Dashboard functionality with unified collections architecture
// Procedural/imperative style (no OOP)

const SCROLL_AMOUNT = 300;

function scrollCarousel(collectionId: string, direction: number): void {
  const track = document.getElementById(
    `carousel-track-${collectionId}`,
  ) as HTMLElement;
  if (!track) return;

  const scrollAmount = direction * SCROLL_AMOUNT;
  track.scrollBy({ left: scrollAmount, behavior: "smooth" });
}

async function openDashboardSettings(): Promise<void> {
  const librarySelect = document.getElementById(
    "library-select",
  ) as HTMLSelectElement;
  const libraryId = librarySelect?.value;
  if (!libraryId) {
    showToast("No library selected", "error");
    return;
  }

  const response = await fetch(
    `/api/dashboard/preferences?library_id=${libraryId}`,
    {
      headers: { Authorization: `Bearer ${localStorage.getItem("token")}` },
    },
  );

  if (response.ok) {
    const prefs = await response.json();
    applyPreferencesToModal(prefs);
  } else {
    showToast("Failed to load library preferences", "error");
    console.error("API Error:", response.status, response.statusText);
    return; // Don't open modal with stale data.
  }

  const modal = document.getElementById(
    "dashboard-settings-modal",
  ) as HTMLElement;
  modal?.classList.remove("hidden");
}

function applyPreferencesToModal(prefs: any): void {
  const collectionList = document.getElementById(
    "collection-list",
  ) as HTMLElement;
  if (!collectionList) return;

  const slider = document.querySelector(
    '#dashboard-settings-modal input[type="range"]',
  ) as HTMLInputElement;
  const display = document.getElementById("items-count-display") as HTMLElement;
  if (slider && display) {
    slider.value = String(prefs.items_per_section);
    display.textContent = String(prefs.items_per_section);
  }

  // Update checkboxes and reorder items
  const items = collectionList.querySelectorAll(
    "[data-collection-id]",
  ) as NodeListOf<HTMLElement>;
  const orderedItems: HTMLElement[] = [];

  items.forEach((item) => {
    const collectionId = item.dataset.collectionId;
    const checkbox = item.querySelector(
      'input[type="checkbox"]',
    ) as HTMLInputElement;

    // Update checkbox state
    const isHidden = prefs.hidden_collections.includes(collectionId);
    if (checkbox) checkbox.checked = !isHidden;

    // Sort according to collection_order
    const orderIndex = prefs.collection_order.indexOf(collectionId);
    if (orderIndex !== -1) {
      orderedItems[orderIndex] = item;
    } else {
      orderedItems.push(item);
    }
  });

  // Reorder in DOM
  orderedItems.forEach((item) => collectionList.appendChild(item));
}

function closeDashboardSettings(): void {
  const modal = document.getElementById(
    "dashboard-settings-modal",
  ) as HTMLElement;
  modal?.classList.add("hidden");
}
async function saveDashboardSettings(): Promise<void> {
  const collectionList = document.getElementById(
    "collection-list",
  ) as HTMLElement;
  if (!collectionList) return;
  const collectionItems = collectionList.querySelectorAll(
    "[data-collection-id]",
  ) as NodeListOf<HTMLElement>;
  const hiddenCollections: string[] = [];
  const collectionOrder: string[] = [];
  collectionItems.forEach((item) => {
    const collectionId = item.dataset.collectionId;
    const checkbox = item.querySelector(
      'input[type="checkbox"]',
    ) as HTMLInputElement;
    if (collectionId) {
      collectionOrder.push(collectionId);
      if (checkbox && !checkbox.checked) {
        hiddenCollections.push(collectionId);
      }
    }
  });
  const itemsPerCollection =
    (document.querySelector("#items-count-display") as HTMLElement)
      ?.textContent || "20";
  try {
    const librarySelect = document.getElementById(
      "library-select",
    ) as HTMLSelectElement;
    const libraryId = librarySelect?.value || "";
    const response = await apiPut("/dashboard/preferences", {
      library_id: libraryId,
      hidden_collections: hiddenCollections,
      collection_order: collectionOrder,
      items_per_section: parseInt(itemsPerCollection),
    });
    if (response.ok) {
      showToast("Dashboard settings saved", "success");
      closeDashboardSettings();
      // Fetch updated sections and re-render (like switchLibrary does)
      if (!libraryId) {
        showToast("Unable to refresh dashboard - no library selected", "error");
        return;
      }
      const sectionResponse = await fetch(
        `/api/dashboard/sections?library_id=${libraryId}`,
        {
          headers: {
            Authorization: `Bearer ${localStorage.getItem("token")}`,
            "Content-Type": "application/json",
          },
        },
      );
      if (sectionResponse.ok) {
        const data = await sectionResponse.json();
        renderDashboardCollections(data.sections);
        localStorage.setItem("selectedLibrary", libraryId);
      } else {
        showToast("Failed to refresh sections", "error");
      }
    }
  } catch (error) {
    showToast("Failed to save settings", "error");
    console.error("Save dashboard settings error:", error);
  }
}
async function restoreSystemCollection(
  collectionName: string,
  collectionTitle: string,
): Promise<void> {
  if (
    !confirm(
      `Are you sure you want to reset "${collectionTitle}" to its default state? Any customizations will be lost.`,
    )
  ) {
    return;
  }

  try {
    const response = await apiPost("/dashboard/restore-system-collection", {
      collection_name: collectionName,
    });

    if (response.ok) {
      showToast(`"${collectionTitle}" restored to defaults`, "success");
      setTimeout(() => window.location.reload(), 1000);
    }
  } catch (error) {
    showToast("Failed to restore system collection", "error");
    console.error("Restore system collection error:", error);
  }
}

async function switchLibrary(libraryId: string): Promise<void> {
  const container = document.getElementById(
    "collections-container",
  ) as HTMLElement;
  const loading = document.getElementById("loading-spinner") as HTMLElement;

  if (!container || !loading) return;

  try {
    // Step 1: Fade out current content (150ms)
    container.classList.add("opacity-0", "transition-opacity", "duration-150");

    // Wait for fade-out to complete
    await new Promise((resolve) => setTimeout(resolve, 150));

    // Step 2: Show loading spinner
    loading.classList.remove("hidden");

    // Step 3: Fetch new data
    const response = await fetch(
      `/api/dashboard/sections?library_id=${libraryId}`,
      {
        headers: {
          Authorization: `Bearer ${localStorage.getItem("token")}`,
          "Content-Type": "application/json",
        },
      },
    );

    if (!response.ok) {
      throw new Error("Failed to load sections");
    }

    const data = await response.json();
    renderDashboardCollections(data.sections);
    localStorage.setItem("selectedLibrary", libraryId);
  } catch (error) {
    showToast("Failed to load library", "error");
    console.error("Switch library error:", error);
  } finally {
    loading.classList.add("hidden");
  }
}

function renderDashboardCollections(sections: SectionData[]): void {
  const container = document.getElementById(
    "collections-container",
  ) as HTMLElement;
  if (!container) return;

  // Preserve wood paneling attribute
  const currentWood = container.getAttribute("data-wood");

  // Replace content while still invisible (opacity-0 from switchLibrary)
  container.innerHTML = sections
    .map(
      (section) => `
        <div class="dashboard-collection mb-8" data-collection-id="${section.id}">
            <div class="flex items-center justify-between mb-4">
                <div class="flex items-center gap-3">
                    <span class="text-2xl">${section.icon}</span>
                    <div>
                        <h2 class="text-xl font-bold" style="color: var(--text-primary)">${section.title}</h2>
                        ${section.description ? `<p class="text-sm" style="color: var(--text-secondary)">${section.description}</p>` : ""}
                    </div>
                </div>
                ${section.view_all_url ? `<a href="${section.view_all_url}" class="text-sm font-medium hover:underline" style="color: var(--accent);">View All →</a>` : ""}
            </div>

            <div class="carousel-container relative group">
                <button class="carousel-nav-left absolute left-0 top-1/2 -translate-y-1/2 z-10
                               w-12 h-full bg-gradient-to-r from-gray-900 to-transparent
                               flex items-center justify-start opacity-0 group-hover:opacity-100
                               transition-opacity duration-200"
                        data-action="scroll-carousel"
                        data-collection-id="${section.id}"
                        data-direction="-1"
                        aria-label="Scroll left">
                    <span class="text-3xl pl-2" style="color: var(--text-primary);">‹</span>
                </button>

                <div id="carousel-track-${section.id}"
                     class="carousel-track flex gap-4 overflow-x-auto
                                 scroll-smooth snap-x snap-mandatory
                                 px-12 pb-4"
                     style="scrollbar-width: none; -ms-overflow-style: none;">
                    ${
                      section.items.length > 0
                        ? section.items
                            .map((item) => renderBookCard(item))
                            .join("")
                        : '<div class="text-center py-8 w-full" style="color: var(--text-secondary);"><p>No items in this collection</p></div>'
                    }
                </div>

                <button class="carousel-nav-right absolute right-0 top-1/2 -translate-y-1/2 z-10
                               w-12 h-full bg-gradient-to-l from-gray-900 to-transparent
                               flex items-center justify-end opacity-0 group-hover:opacity-100
                               transition-opacity duration-200"
                        data-action="scroll-carousel"
                        data-collection-id="${section.id}"
                        data-direction="1"
                        aria-label="Scroll right">
                    <span class="text-3xl pr-2" style="color: var(--text-primary);">›</span>
                </button>
            </div>
        </div>
    `,
    )
    .join("");

  // Step 5: Fade in new content (300ms for smoother entrance)
  container.classList.remove("duration-150");
  container.classList.add("duration-300");

  // Trigger reflow to ensure transition happens
  void container.offsetHeight;

  // Fade to visible
  container.classList.remove("opacity-0");

  // Clean up transition classes after animation completes
  setTimeout(() => {
    container.classList.remove("transition-opacity", "duration-300");
  }, 300);
  if (currentWood) {
    container.setAttribute("data-wood", currentWood);
  }
}

function renderBookCard(book: BookInfo): string {
  const coverUrl = book.cover_image_path || "/static/placeholder-book.svg";

  return `
        <div class="book-card flex-shrink-0 w-36 rounded-lg overflow-hidden snap-start cursor-pointer
                        transition-transform duration-200 hover:scale-105"
             data-action="view-book"
             data-book-id="${book.media_item_id}"
             tabindex="0"
             role="button"
             aria-label="View ${book.title}">
            <div class="aspect-[2/3] overflow-hidden shadow-lg
                            bg-gradient-to-br from-gray-700 to-gray-900">
                <img src="${coverUrl}"
                     alt="${book.title}"
                     class="w-full h-full object-cover"
                     loading="lazy"
                     onerror="this.src='/static/placeholder-book.svg'">
            </div>
            <div class="book-card-text px-2 py-1 bg-[color-mix(in_srgb,var(--wood-border)_40%,transparent)]">
                <h3 class="font-semibold text-base line-clamp-2" style="color: var(--text-primary)">
                    ${book.title}
                </h3>
                ${book.author ? `<p class="text-sm line-clamp-1" style="color: var(--text-secondary)">${book.author}</p>` : ""}
            </div>
        </div>
    `;
}

// function viewBook(bookId: string): void {
//   console.log("View book:", bookId);
// }

async function reloadPage(): Promise<void> {
  //Get current library from dropdown
  const librarySelect = document.getElementById(
    "library-select",
  ) as HTMLSelectElement;
  const currentLibraryId = librarySelect?.value;

  if (!currentLibraryId) {
    showToast("No library selected", "error");
    return;
  }

  // Reuse switchLibrary logic - it handles the fade transition
  await switchLibrary(currentLibraryId);
}

function updateItemsCount(
  input: HTMLInputElement,
  displayTarget: string,
): void {
  const displayElement = document.getElementById(displayTarget) as HTMLElement;
  if (displayElement) {
    displayElement.textContent = input.value;
  }
}

function initDragAndDrop(): void {
  const collectionList = document.getElementById(
    "collection-list",
  ) as HTMLElement;
  if (!collectionList) return;

  let draggedItem: HTMLElement | null = null;

  collectionList.addEventListener("dragstart", (e: Event) => {
    const target = e.target as HTMLElement;
    if (target.classList.contains("collection-item")) {
      draggedItem = target;
      target.style.opacity = "0.5";
    }
  });

  collectionList.addEventListener("dragend", (e: Event) => {
    const target = e.target as HTMLElement;
    if (target.classList.contains("collection-item")) {
      target.style.opacity = "1";
      draggedItem = null;
    }
  });

  collectionList.addEventListener("dragover", (e: Event) => {
    e.preventDefault();
    const target = e.target as HTMLElement;
    if (
      target.classList.contains("collection-item") &&
      target !== draggedItem &&
      draggedItem
    ) {
      const rect = target.getBoundingClientRect();
      const midY = rect.top + rect.height / 2;
      if ((e as DragEvent).clientY < midY) {
        target.parentNode?.insertBefore(draggedItem, target);
      } else {
        if (target.parentNode) {
          target.parentNode.insertBefore(draggedItem, target.nextSibling);
        }
      }
    }
  });
}

function initDashboard() {
  initDragAndDrop();

  document.addEventListener("click", (e: Event) => {
    const target = e.target as HTMLElement;
    const actionElem = target.closest("[data-action]") as HTMLElement;
    const action = actionElem?.getAttribute("data-action");

    switch (action) {
      case "scroll-carousel": {
        const collectionId =
          target.dataset.collectionId || actionElem?.dataset.collectionId;
        const direction = parseInt(
          target.dataset.direction || actionElem?.dataset.direction || "0",
        );
        if (collectionId) scrollCarousel(collectionId, direction);
        break;
      }

      case "open-dashboard-settings":
        openDashboardSettings();
        break;

      case "close-dashboard-settings":
        closeDashboardSettings();
        break;

      case "save-dashboard-settings":
        saveDashboardSettings();
        break;

      case "restore-system-collection": {
        const colName =
          actionElem?.dataset.collectionName || target.dataset.collectionName;
        const colTitle =
          actionElem?.dataset.collectionTitle ||
          target.dataset.collectionTitle ||
          "System Collection";
        if (colName) restoreSystemCollection(colName, colTitle);
        break;
      }

      // case "view-book": {
      //   const bookId = target.dataset.bookId || actionElem?.dataset.bookId;
      //   if (bookId) viewBook(bookId);
      //   break;
      // }

      case "reload-page":
        reloadPage();
        break;

      case "switch-library": {
        const select = target as HTMLSelectElement;
        if (select.value) switchLibrary(select.value);
        break;
      }
    }

    document.addEventListener("input", (e: Event) => {
      const target = e.target as HTMLElement;
      const actionElem = target.closest("[data-input-action]") as HTMLElement;
      const action = actionElem?.getAttribute("data-input-action");

      switch (action) {
        case "update-items-count": {
          const input = target as HTMLInputElement;
          const displayTarget = input.getAttribute("target");
          if (displayTarget) updateItemsCount(input, displayTarget);
          break;
        }
      }
    });
    // Load saved library on page load
    const librarySelect = document.getElementById(
      "library-select",
    ) as HTMLSelectElement;
    if (librarySelect) {
      librarySelect.addEventListener("change", (e) => {
        const target = e.target as HTMLSelectElement;
        if (target.value) {
          switchLibrary(target.value);
        }
      });
    }
  });
}

export { initDashboard };

Alpine.data("dashboard", () => ({
  initDashboard,
}));
