import { Alpine } from "./alpine";
import { apiPost, apiPut } from "./api";
import { showToast } from "./toast";
import { initLibrarySwitcher, switchWithTransition } from "./library-switcher";

const SCROLL_AMOUNT = 300;
let scanListenerRegistered = false;

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("Select a specific library to customize preferences", "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;
  }

  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);
  }

  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;

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

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

  orderedItems.forEach((item) => collectionList.appendChild(item));
}

function closeDashboardSettings(): void {
  const modal = document.getElementById(
    "dashboard-settings-modal",
  ) as HTMLElement;
  modal?.classList.add("hidden");
}

async function fetchAndRenderSections(libraryId: string): Promise<void> {
  const param = libraryId ? `library_id=${libraryId}` : "";
  const response = await fetch(
    `/api/dashboard/sections?${param}`,
    {
      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);
}

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();
      if (!libraryId) {
        showToast("Select a specific library to customize preferences", "error");
        return;
      }
      await fetchAndRenderSections(libraryId);
    }
  } 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);
  }
}

function renderSectionHTML(section: SectionData): string {
  return `
        <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 pointer-events-none
                               group-hover:pointer-events-auto 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 pointer-events-none
                               group-hover:pointer-events-auto 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>
    `;
}

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

  const currentWood = container.getAttribute("data-wood");

  container.innerHTML = sections.map((section) => renderSectionHTML(section)).join("");

  container.classList.remove("duration-150");
  container.classList.add("duration-300");

  void container.offsetHeight;

  container.classList.remove("opacity-0");

  setTimeout(() => {
    container.classList.remove("transition-opacity", "duration-300");
  }, 300);
  if (currentWood) {
    container.setAttribute("data-wood", currentWood);
  }
}

const BOOK_OPEN_ICON =
  '<svg class="reader-icon h-5 w-5" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
  '<path d="M12 7v14"></path>' +
  '<path d="M3 4h6a3 3 0 0 1 3 3v14a2 2 0 0 0-2-2H3z"></path>' +
  '<path d="M21 4h-6a3 3 0 0 0-3 3v14a2 2 0 0 1 2-2h7z"></path>' +
  "</svg>";

function renderBookCard(book: BookInfo): string {
  const coverUrl = book.cover_image_path || "/static/placeholder-book.svg";
  const actionHref = book.has_conflict
    ? `/media/${book.media_item_id}`
    : `/readers/${book.media_item_id}`;
  const actionLabel = book.has_conflict
    ? `Resolve progress conflict for ${book.title}`
    : `Read ${book.title}`;
  const actionTitle = book.has_conflict
    ? "Resolve progress conflict"
    : "Read";

  return `
        <div class="flex-shrink-0 w-36 sm:w-40 snap-start" data-media-item-id="${book.media_item_id}">
            <div class="book-card relative w-full h-full rounded-xl overflow-hidden cursor-pointer">
                <a href="/media/${book.media_item_id}" class="block h-full">
                    <div class="book-card-cover aspect-[2/3] overflow-hidden" style="background-color: color-mix(in srgb, var(--text-primary) 8%, transparent);">
                        <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-meta">
                        <h3 class="font-semibold text-sm leading-snug line-clamp-2" style="color: var(--text-primary)" title="${book.title}">
                            ${book.title}
                        </h3>
                        ${book.author ? `<p class="text-xs mt-0.5 line-clamp-1" style="color: var(--text-secondary)" title="${book.author}">${book.author}</p>` : ""}
                    </div>
                </a>
                <div class="book-card-action">
                    <a href="${actionHref}"
                       class="book-card-action-btn"
                       aria-label="${actionLabel}"
                       title="${actionTitle}">${BOOK_OPEN_ICON}</a>
                </div>
            </div>
        </div>
    `;
}

async function reloadPage(): Promise<void> {
  const librarySelect = document.getElementById(
    "library-select",
  ) as HTMLSelectElement;
  const libraryId = librarySelect?.value || "";

  await switchWithTransition("collections-container", () =>
    fetchAndRenderSections(libraryId),
  );
}

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();

  initLibrarySwitcher({
    onSwitch: (libraryId) =>
      switchWithTransition("collections-container", () =>
        fetchAndRenderSections(libraryId),
      ),
  });

  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 "reload-page":
        reloadPage();
        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;
      }
    }
  });

  if (!scanListenerRegistered) {
    scanListenerRegistered = true;
    window.addEventListener("bookhoard:scan-complete", async () => {
      const librarySelect = document.getElementById(
        "library-select",
      ) as HTMLSelectElement;
      const libraryId = librarySelect?.value || "";

      try {
        const param = libraryId ? `library_id=${libraryId}` : "";
        const response = await fetch(
          `/api/dashboard/sections?${param}`,
          {
            headers: {
              Authorization: `Bearer ${localStorage.getItem("token")}`,
              "Content-Type": "application/json",
            },
          },
        );
        if (!response.ok) return;
        const data = await response.json();

        const container = document.getElementById(
          "collections-container",
        ) as HTMLElement;
        if (!container) return;

        const freshSectionIds = new Set(
          (data.sections as SectionData[]).map((s) => s.id),
        );

        for (const section of data.sections as SectionData[]) {
          const track = document.getElementById(
            `carousel-track-${section.id}`,
          );

          if (!track) {
            container.insertAdjacentHTML(
              "beforeend",
              renderSectionHTML(section),
            );
            continue;
          }

          track.innerHTML = 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>';
        }

        const existingSections = container.querySelectorAll<HTMLElement>(
          ".dashboard-collection",
        );
        existingSections.forEach((sec) => {
          const secId = sec.getAttribute("data-collection-id");
          if (secId && !freshSectionIds.has(secId)) {
            sec.remove();
          }
        });
      } catch (err) {
        console.error("[dashboard] scan-complete handler error:", err);
      }
    });
  }
}

export { initDashboard };

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