import { Alpine } from "./alpine";
import { showToast } from "./toast";
import { createWebSocket } from "./websocket";
import {
  getCurrentLibraryId,
  initLibrarySwitcher,
  switchWithTransition,
} from "./library-switcher";

let collectionId: string | null = null;

function initializeCollectionWebSocket(): void {
  const dataEl = document.getElementById("collection-data");
  if (!dataEl) return;

  collectionId = dataEl.dataset.id || null;

  if (!collectionId) return;

  createWebSocket({
    onMessage: (message) => {
      if (
        message.type === "collection_updated" &&
        message.data.collection_id === collectionId
      ) {
        const actionText =
          message.data.action === "books_added"
            ? `Added ${message.data.count || 0} book(s)`
            : message.data.action === "book_removed"
              ? "Removed a book"
              : message.data.action === "books_bulk_removed"
                ? `Removed ${message.data.count || 0} book(s)`
                : "Collection updated";

        showToast(actionText, "info");

        const activeElement = document.activeElement;
        const isUserActive =
          activeElement &&
          (activeElement.tagName === "INPUT" ||
            activeElement.tagName === "TEXTAREA" ||
            activeElement.tagName === "SELECT" ||
            activeElement.getAttribute("contenteditable") === "true");

        if (!isUserActive) {
          setTimeout(() => {
            location.reload();
          }, 1000);
        }
      }
    },
    enableReconnect: true,
    reconnectDelay: 5000,
  });
}

async function loadCollections(): Promise<void> {
  const token = localStorage.getItem("token");
  if (!token) return;

  try {
    const response = await fetch("/api/collections", {
      headers: { Authorization: `Bearer ${token}` },
    });

    if (response.ok) {
      const data = await response.json();
      renderCollectionsGrid(data.collections || []);
    }
  } catch (error) {
    console.error("Failed to load collections:", error);
  }
}

function renderCollectionsGrid(collections: CollectionData[]): void {
  const container = document.getElementById("collections-list");
  if (!container) return;

  if (collections.length === 0) {
    container.innerHTML = `
      <div class="text-center py-16 col-span-full" style="color: var(--text-secondary)">
        <div class="text-6xl mb-4">📚</div>
        <h3 class="text-xl font-semibold mb-2" style="color: var(--text-primary)">No Collections Yet</h3>
        <p class="mb-4">Create collections to organize your books</p>
        <button hx-get="/collections/create-modal" hx-target="#modal-container" hx-swap="innerHTML"
                class="btn-primary px-4 py-2 rounded-lg">Create Your First Collection</button>
      </div>`;
    return;
  }

  const libraryId = getCurrentLibraryId();
  const libraryParam = libraryId ? `?library_id=${libraryId}` : "";

  container.innerHTML = collections
    .map(
      (col) => `
        <div @click="navigateToCollection($el)" data-href="/collections/${col.id}${libraryParam}" class="block">
          <div class="card p-6 rounded-lg border-l-4 cursor-pointer hover:shadow-lg transition-shadow"
               style="background-color: var(--bg-secondary);"
               data-color="${col.color}">
            <div class="flex justify-between items-start mb-4">
              <div class="text-3xl">${col.icon}</div>
              <div class="flex space-x-2">
                <button hx-get="/collections/${col.id}/edit-modal" hx-target="#modal-container"
                        hx-swap="innerHTML" class="p-2 hover:opacity-80 rounded"
                        style="color: var(--text-secondary); background-color: var(--bg-primary);">✏️</button>
                <button hx-delete="/api/collections/${col.id}" hx-redirect="/collections"
                        hx-confirm="Are you sure you want to delete this collection?"
                        class="p-2 hover:opacity-80 rounded"
                        style="color: var(--text-secondary); background-color: var(--bg-primary);">🗑️</button>
              </div>
            </div>
            <h3 class="text-lg font-semibold mb-2" style="color: var(--text-primary)">${col.name}</h3>
            <p class="text-sm mb-4" style="color: var(--text-secondary)">${col.description}</p>
            ${col.book_count > 0 ? `<p class="text-xs" style="color: var(--text-secondary)">${col.book_count} books</p>` : ""}
          </div>
        </div>
    `,
    )
    .join("");

  initColorSelection();
  Alpine.initTree(container);
}

function renderCollectionBooks(books: BookInfo[]): void {
  const container = document.getElementById("books-container");
  if (!container) return;

  const dataEl = document.getElementById("collection-data");
  const isSystem = dataEl?.dataset.isSystem === "true";

  if (books.length === 0) {
    container.innerHTML = `<div id="empty-state" class="col-span-full text-center py-16" style="color: var(--text-secondary)">No books in this collection yet.</div>`;
    return;
  }

  container.innerHTML = books
    .map(
      (book) => `
      <div class="card p-4 rounded-2xl collection-book-card" data-title="${book.title}" data-author="${book.author || ""}" data-media-id="${book.media_item_id}">
        <div class="flex gap-4">
          ${isSystem ? "" : `
          <div class="flex-shrink-0 pt-1">
            <label class="flex items-center cursor-pointer p-2 -m-2">
              <input type="checkbox" class="w-5 h-5"
                     :checked="selectedBooks.includes('${book.media_item_id}')"
                     @change="toggleSelection('${book.media_item_id}')"/>
            </label>
          </div>`}
          <div class="flex-1 min-w-0">
            <a href="/media/${book.media_item_id}">
              <h3 class="font-semibold text-lg mb-1 line-clamp-2 hover:underline" style="color: var(--text-primary)">${book.title}</h3>
            </a>
            ${book.author ? `<p class="text-sm line-clamp-1" style="color: var(--text-secondary)">by ${book.author}</p>` : ""}
          </div>
          <div class="flex-shrink-0 w-16 sm:w-20">
            <a href="/media/${book.media_item_id}">
              <img src="${book.cover_image_path || "/static/placeholder-book.svg"}" alt="Cover"
                   class="w-full aspect-[3/4] object-cover rounded shadow-md"
                   onerror="this.src='/static/placeholder-book.svg'"/>
            </a>
          </div>
        </div>
        ${isSystem ? "" : `
        <div class="mt-3 pt-3 border-t" style="border-color: var(--border);">
          <button @click="requestRemoveBook('${book.media_item_id}')" class="btn btn-secondary w-full">
            🗑️ Remove from Collection
          </button>
        </div>`}
      </div>
    `,
    )
    .join("");

  Alpine.initTree(container);
}

async function loadCollectionRules(collectionId: string): Promise<void> {
  const token = localStorage.getItem("token");
  if (!token) return;

  try {
    const response = await fetch(`/api/collections/${collectionId}/rules`, {
      headers: { Authorization: `Bearer ${token}` },
    });

    if (response.ok) {
      const rules: CollectionRule[] = await response.json();
      renderRules(rules);
    }
  } catch (error) {
    console.error("Failed to load rules:", error);
  }
}

function renderRules(rules: CollectionRule[]): void {
  const container = document.getElementById("rules-list");
  if (!container) return;

  if (rules.length === 0) {
    container.innerHTML =
      '<p class="text-center p-4" style="color: var(--text-secondary)">No rules defined</p>';
    return;
  }

  container.innerHTML = rules
    .map(
      (rule) => `
        <div class="p-3 rounded-lg border mb-2 flex justify-between items-center"
             style="background-color: var(--bg-secondary); border-color: var(--border)">
            <div>
                <p class="font-medium" style="color: var(--text-primary)">${rule.field} ${rule.operator} "${rule.value}"</p>
                <p class="text-sm" style="color: var(--text-secondary)">Priority: ${rule.priority} | ${rule.enabled ? "Enabled" : "Disabled"}</p>
            </div>
            <div class="flex space-x-2">
                <button onclick="window.editRule('${rule.id}')" class="btn-secondary px-2 py-1 rounded text-sm">Edit</button>
                <button onclick="window.deleteRule('${rule.id}')" class="btn-secondary px-2 py-1 rounded text-sm">Delete</button>
            </div>
        </div>
    `,
    )
    .join("");
}

async function createRule(
  collectionId: string,
  rule: Partial<CollectionRule>,
): Promise<void> {
  const token = localStorage.getItem("token");
  if (!token) return;

  try {
    const response = await fetch(`/api/collections/${collectionId}/rules`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(rule),
    });

    if (response.ok) {
      showToast("Rule created", "success");
      loadCollectionRules(collectionId);
    } else {
      const error = await response.json();
      showToast(error.error || "Failed to create rule", "error");
    }
  } catch (error) {
    console.error("Failed to create rule:", error);
    showToast("Failed to create rule", "error");
  }
}

async function deleteRule(collectionId: string, ruleId: string): Promise<void> {
  const token = localStorage.getItem("token");
  if (!token) return;

  if (!confirm("Are you sure you want to delete this rule?")) return;

  try {
    const response = await fetch(
      `/api/collections/${collectionId}/rules/${ruleId}`,
      {
        method: "DELETE",
        headers: { Authorization: `Bearer ${token}` },
      },
    );

    if (response.ok) {
      showToast("Rule deleted", "success");
      loadCollectionRules(collectionId);
    }
  } catch (error) {
    console.error("Failed to delete rule:", error);
    showToast("Failed to delete rule", "error");
  }
}

async function testRule(
  collectionId: string,
  rule: Partial<CollectionRule>,
): Promise<void> {
  const token = localStorage.getItem("token");
  if (!token) return;

  try {
    const response = await fetch(
      `/api/collections/${collectionId}/rules/test`,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(rule),
      },
    );

    if (response.ok) {
      const results = await response.json();
      renderTestResults(results);
    }
  } catch (error) {
    console.error("Failed to test rule:", error);
    showToast("Failed to test rule", "error");
  }
}

function renderTestResults(results: unknown[]): void {
  const container = document.getElementById("test-results");
  if (!container) return;

  if (!results || (Array.isArray(results) && results.length === 0)) {
    container.innerHTML =
      '<p class="p-2 text-sm" style="color: var(--text-secondary)">No matching books found</p>';
    return;
  }

  container.innerHTML = `<p class="p-2 text-sm" style="color: var(--text-secondary)">${Array.isArray(results) ? results.length : 0} matching books</p>`;
}

function setupHTMXAuth(): void {
  document.body.addEventListener("htmx:configRequest", function (evt: Event) {
    const token = localStorage.getItem("token");
    (evt as any).detail.headers["Authorization"] = `Bearer ${token}`;
  });
}

function navigateToCollection(element: HTMLElement): void {
  const event = window.event as Event;
  if (event && event.target instanceof HTMLElement) {
    const target = event.target as HTMLElement;
    if (target.tagName === "BUTTON" || target.closest("button") !== null) {
      return;
    }
  }

  const href = element.getAttribute("data-href");
  if (href) {
    window.location.href = href;
  }
}

const borderClasses: Record<string, string> = {
  blue: "border-blue-500",
  red: "border-red-500",
  yellow: "border-yellow-500",
  green: "border-green-500",
  purple: "border-purple-500",
};

function selectColor(color: string): void {
  const colorInput = document.getElementById(
    "collection-color",
  ) as HTMLInputElement;
  if (colorInput) {
    colorInput.value = color;
  }
  document.querySelectorAll(".color-option").forEach((btn) => {
    (btn as HTMLElement).style.outline = "none";
    (btn as HTMLElement).style.outlineOffset = "0";
  });
  const selectedBtn = document.querySelector(
    `.color-option[data-color="${color}"]`,
  ) as HTMLElement;
  if (selectedBtn) {
    selectedBtn.style.outline = "3px solid var(--text-primary)";
    selectedBtn.style.outlineOffset = "3px";
  }
}

function closeCollectionModal(): void {
  const modal = document.querySelector(".fixed.inset-0");
  if (modal) {
    modal.remove();
  }
}

function initColorSelection(): void {
  const colorInput = document.getElementById(
    "collection-color",
  ) as HTMLInputElement;
  if (colorInput && colorInput.value) {
    selectColor(colorInput.value);
  }

  document.querySelectorAll("[data-color]").forEach((card) => {
    const color = (card as HTMLElement).getAttribute("data-color");
    if (color && borderClasses[color]) {
      Object.values(borderClasses).forEach((cls) => {
        (card as HTMLElement).classList.remove(cls);
      });
      (card as HTMLElement).classList.add(borderClasses[color]);
    }
  });
}

function setupHTMXModalInit(): void {
  document.body.addEventListener("htmx:afterSwap", function (evt: CustomEvent) {
    const target = evt.detail.target;
    if (target && target.id === "modal-container") {
      populateIconGrid();
      initColorSelection();
      Alpine.initTree(target);
    }
    if (target && target.id === "book-picker-grid") {
      Alpine.initTree(target);
    }
  });
}

function showAllIcons(): void {
  populateIconGrid();

  const searchInput = document.getElementById(
    "icon-search",
  ) as HTMLInputElement;
  if (searchInput) {
    searchInput.value = "";
  }

  const iconGrid = document.getElementById("icon-grid");
  if (!iconGrid) return;

  const buttons = iconGrid.querySelectorAll(".icon-btn");
  buttons.forEach((btn) => {
    (btn as HTMLElement).style.display = "";
  });
}

const iconData: Record<string, string[]> = {
  "📚": ["book", "books", "library", "read", "reading"],
  "📖": ["book", "open", "read", "reading"],
  "📝": ["memo", "note", "write", "writing", "edit"],
  "📰": ["news", "newspaper", "press", "article"],
  "🗂️": ["card", "index", "organize", "file"],
  "📁": ["file", "folder", "directory"],
  "📂": ["folder", "open", "directory"],
  "📓": ["notebook", "book", "write"],
  "📔": ["notebook", "book"],
  "📕": ["book", "read", "red"],
  "📗": ["book", "read", "green"],
  "📘": ["book", "read", "blue"],
  "📙": ["book", "read", "orange"],
  "⭐": ["star", "favorite", "like", "rating"],
  "❤️": ["heart", "love", "favorite", "like"],
  "🔥": ["fire", "hot", "popular", "trending", "flame"],
  "💡": ["idea", "bulb", "light", "think", "smart"],
  "🎯": ["target", "goal", "aim", "focus"],
  "🏆": ["trophy", "winner", "award", "achievement"],
  "🎨": ["art", "paint", "color", "creative"],
  "✅": ["check", "done", "complete", "success"],
  "❌": ["cross", "x", "wrong", "error", "fail"],
  "⚡️": ["bolt", "fast", "quick", "energy"],
  "🚀": ["rocket", "fast", "launch", "space"],
  "💎": ["gem", "diamond", "stone", "rich"],
  "👍": ["thumb", "up", "good", "yes", "like"],
  "👎": ["thumb", "down", "bad", "no", "dislike"],
  "🏠": ["house", "home", "building"],
  "🏢": ["building", "office", "work", "company"],
  "🚗": ["car", "auto", "vehicle", "drive"],
  "✈️": ["plane", "airplane", "fly", "travel"],
  "🎮": ["game", "play", "video", "gaming"],
};

function populateIconGrid(): void {
  const iconGrid = document.getElementById("icon-grid");
  if (!iconGrid) return;
  iconGrid.innerHTML = "";
  Object.entries(iconData).forEach(([emoji, keywords]) => {
    const button = document.createElement("button");
    button.type = "button";
    button.className = "icon-btn text-2xl p-1 hover:bg-opacity-80 rounded";
    button.textContent = emoji;
    button.setAttribute("data-emoji", emoji);
    button.setAttribute("data-keywords", keywords.join(","));
    button.addEventListener("click", () => selectIcon(emoji));
    iconGrid.appendChild(button);
  });
}

function selectIcon(icon: string): void {
  const iconInput = document.getElementById(
    "collection-icon",
  ) as HTMLInputElement;
  const searchInput = document.getElementById(
    "icon-search",
  ) as HTMLInputElement;

  if (iconInput) iconInput.value = icon;
  if (searchInput) searchInput.value = icon;

  document.querySelectorAll(".icon-btn").forEach((btn) => {
    (btn as HTMLElement).style.outline = "none";
    (btn as HTMLElement).style.backgroundColor = "";
  });

  const selectedBtn = document.querySelector(
    `.icon-btn[data-emoji="${icon}"]`,
  ) as HTMLElement;
  if (selectedBtn) {
    selectedBtn.style.outline = "2px solid var(--text-primary)";
    selectedBtn.style.backgroundColor = "var(--bg-secondary)";
  }
}

function filterIcons(searchTerm: string): void {
  const iconGrid = document.getElementById("icon-grid");
  const iconInput = document.getElementById(
    "collection-icon",
  ) as HTMLInputElement;
  if (iconInput) iconInput.value = searchTerm;
  if (!iconGrid) return;
  const buttons = iconGrid.querySelectorAll(".icon-btn");
  const lowerSearchTerm = searchTerm.toLowerCase();

  buttons.forEach((btn) => {
    const emoji = (btn as HTMLElement).textContent || "";
    const keywords = iconData[emoji] || [];

    const matches =
      searchTerm === "" ||
      emoji.includes(searchTerm) ||
      keywords.some((keyword) =>
        keyword.toLowerCase().includes(lowerSearchTerm),
      );

    (btn as HTMLElement).style.display = matches ? "" : "none";
  });
}

function isDetailPage(): boolean {
  const dataEl = document.getElementById("collection-data");
  return !!dataEl?.dataset.id;
}

function initCollectionsPage(): void {
  if (isDetailPage()) {
    const dataEl = document.getElementById("collection-data");
    const collId = dataEl?.dataset.id || "";

    initLibrarySwitcher({
      onSwitch: async (libraryId) => {
        const dataEl = document.getElementById("collection-data");
        if (dataEl) dataEl.dataset.libraryId = libraryId;

        await switchWithTransition("books-container", async () => {
          const param = libraryId ? `?library_id=${libraryId}` : "";
          const response = await fetch(
            `/api/collections/${collId}${param}`,
            {
              headers: {
                Authorization: `Bearer ${localStorage.getItem("token")}`,
                "Content-Type": "application/json",
              },
            },
          );
          if (!response.ok) throw new Error("Failed to load collection");
          const data = await response.json();
          renderCollectionBooks(data.books || []);
        });
      },
    });
  }

  initializeCollectionWebSocket();
  setupHTMXModalInit();
}

function getCollectionId(): string {
  const dataEl = document.getElementById("collection-data");
  return dataEl?.dataset.id || "";
}

function toggleSelection(this: any, id: string): void {
  const idx = this.selectedBooks.indexOf(id);
  if (idx >= 0) {
    this.selectedBooks.splice(idx, 1);
  } else {
    this.selectedBooks.push(id);
  }
}

async function doRemoveBook(id: string): Promise<void> {
  const token = localStorage.getItem("token");
  if (!token) return;
  try {
    const response = await fetch(
      `/api/collections/${getCollectionId()}/books/${id}`,
      {
        method: "DELETE",
        headers: { Authorization: `Bearer ${token}` },
      },
    );
    if (response.ok) {
      showToast("Removed from collection", "success");
      setTimeout(() => location.reload(), 500);
    } else {
      showToast("Failed to remove book", "error");
    }
  } catch {
    showToast("Error removing book", "error");
  }
}

async function doBulkRemove(ids: string[]): Promise<void> {
  const token = localStorage.getItem("token");
  if (!token) return;
  try {
    const response = await fetch(
      `/api/collections/${getCollectionId()}/books/bulk-remove`,
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({ book_ids: ids }),
      },
    );
    if (response.ok) {
      showToast(`Removed ${ids.length} book(s)`, "success");
      setTimeout(() => location.reload(), 500);
    } else {
      showToast("Failed to remove books", "error");
    }
  } catch {
    showToast("Error removing books", "error");
  }
}

function filterCollectionBooks(): void {
  const input = document.getElementById(
    "collection-search",
  ) as HTMLInputElement;
  if (!input) return;
  const query = input.value.toLowerCase();
  const cards = document.querySelectorAll<HTMLElement>(
    ".collection-book-card",
  );
  cards.forEach((card) => {
    const title = (card.dataset.title || "").toLowerCase();
    const author = (card.dataset.author || "").toLowerCase();
    card.style.display =
      title.includes(query) || author.includes(query) ? "" : "none";
  });
}

export {
  closeCollectionModal,
  createRule,
  deleteRule,
  filterCollectionBooks,
  filterIcons,
  initColorSelection,
  initializeCollectionWebSocket,
  initCollectionsPage,
  loadCollectionRules,
  loadCollections,
  navigateToCollection,
  populateIconGrid,
  selectColor,
  selectIcon,
  setupHTMXAuth,
  setupHTMXModalInit,
  showAllIcons,
  testRule,
  toggleSelection,
};

Alpine.data("collections", () => ({
  closeCollectionModal,
  createRule,
  deleteRule,
  filterCollectionBooks,
  filterIcons,
  initColorSelection,
  initializeCollectionWebSocket,
  initCollectionsPage,
  loadCollectionRules,
  loadCollections,
  navigateToCollection,
  populateIconGrid,
  selectColor,
  selectIcon,
  selectedBooks: [] as string[],
  setupHTMXModalInit,
  showAllIcons,
  testRule,
  toggleSelection,

  showConfirm: false,
  confirmMessage: "",
  confirmLabel: "Remove",
  pendingAction: null as null | (() => void),

  requestRemoveBook(this: any, id: string) {
    this.confirmMessage = "Remove this book from the collection?";
    this.pendingAction = () => doRemoveBook(id);
    this.showConfirm = true;
  },

  requestBulkRemove(this: any) {
    if (this.selectedBooks.length === 0) return;
    this.confirmMessage = `Remove ${this.selectedBooks.length} book(s) from this collection?`;
    const ids = [...this.selectedBooks];
    this.pendingAction = () => doBulkRemove(ids);
    this.showConfirm = true;
  },

  executeConfirmed(this: any) {
    this.showConfirm = false;
    const action = this.pendingAction;
    this.pendingAction = null;
    if (action) action();
  },

  closeConfirm(this: any) {
    this.showConfirm = false;
    this.pendingAction = null;
  },
}));
