import { Alpine } from "./alpine";
import { showToast } from "./toast";
import { getToken } from "./storage";

let selectedMediaItem: string | null = null;

function searchMatches(
  progressId: string,
  sha256: string,
  title: string,
): void {
  const container = document.getElementById(`matches-${progressId}`);
  const matchesList = document.getElementById(`matches-list-${progressId}`);

  if (!container || !matchesList) return;

  container.classList.remove("hidden");
  matchesList.innerHTML =
    '<p class="text-sm" style="color: var(--text-secondary)">Searching...</p>';

  const token = getToken();
  const url = sha256
    ? `/api/books/match?sha256=${sha256}`
    : `/api/books/match?title=${encodeURIComponent(title)}`;

  fetch(url, {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  })
    .then((response) => response.json())
    .then((result) => {
      if (result.matches && result.matches.length > 0) {
        matchesList.innerHTML = result.matches
          .map(
            (match: any) => `
            <div class="card p-4 rounded-lg border cursor-pointer hover:shadow-lg transition-shadow"
                 style="background-color: var(--bg-primary); border-color: var(--border);"
                 data-action="auto-link" data-progress-id="${progressId}" data-media-item-id="${match.media_item_id}" data-confidence="${match.confidence}">
                <div class="flex gap-4">
                    <img src="${match.cover_image_path || "/static/placeholder-book.svg"}"
                         alt="Cover" class="w-16 h-24 object-cover rounded">
                    <div>
                        <h5 class="font-semibold" style="color: var(--text-primary)">${match.title}</h5>
                        <p class="text-sm" style="color: var(--text-secondary)">by ${match.author || "Unknown"}</p>
                        <div class="mt-2 flex items-center gap-2">
                            <span class="text-xs px-2 py-1 rounded" style="background-color: var(--accent); color: var(--bg-primary);">
                                ${Math.round(match.confidence * 100)}% confidence
                            </span>
                            <span class="text-xs" style="color: var(--text-secondary)">${match.match_method}</span>
                        </div>
                    </div>
                </div>
            </div>
        `,
          )
          .join("");
      } else {
        matchesList.innerHTML =
          '<p class="text-sm" style="color: var(--text-secondary)">No matches found. Try manual linking.</p>';
      }
    })
    .catch((error) => {
      console.error("Failed to search", error);
      matchesList.innerHTML =
        '<p class="text-sm" style="color: var(--error)">Failed to search</p>';
    });
}

function autoLinkBook(
  progressId: string,
  mediaItemId: string,
  confidence: number,
): void {
  if (
    !confirm(
      "Link this book? The confidence score is " +
        Math.round(confidence * 100) +
        "%",
    )
  ) {
    return;
  }

  const progressElement = document.getElementById(`matches-${progressId}`);
  const codeElement = progressElement?.querySelector("code");
  const sha256Element = progressElement?.querySelector('[title="SHA-256"]');

  const data = {
    device_file: {
      file_path: codeElement?.textContent || "",
      sha256: sha256Element?.textContent || "",
    },
    media_item_id: mediaItemId,
    confidence_score: confidence,
  };

  const token = getToken();
  fetch(`/api/devices/sync/link-book`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify(data),
  })
    .then((response) => response.json())
    .then(() => {
      showToast("Book linked successfully", "success");
      window.location.reload();
    })
    .catch((error) => {
      console.error("Failed to link book", error);
      showToast("Failed to link book", "error");
    });
}

function showManualLinkModal(progressId: string, bookTitle: string): void {
  const modal = document.getElementById("manual-link-modal");
  const progressIdInput = document.getElementById(
    "link-progress-id",
  ) as HTMLInputElement;
  const bookTitleInput = document.getElementById(
    "link-book-title",
  ) as HTMLInputElement;
  const searchResults = document.getElementById("link-search-results");

  if (modal) modal.classList.remove("hidden");
  if (progressIdInput) progressIdInput.value = progressId;
  if (bookTitleInput) bookTitleInput.value = bookTitle;
  if (searchResults)
    searchResults.innerHTML =
      '<p style="color: var(--text-secondary)">Search for books to link</p>';
  selectedMediaItem = null;
}

function hideManualLinkModal(): void {
  const modal = document.getElementById("manual-link-modal");
  const searchInput = document.getElementById(
    "link-search-input",
  ) as HTMLInputElement;

  if (modal) modal.classList.add("hidden");
  if (searchInput) searchInput.value = "";
  selectedMediaItem = null;
}

function searchBooksForLink(): void {
  const searchInput = document.getElementById(
    "link-search-input",
  ) as HTMLInputElement;
  const resultsContainer = document.getElementById("link-search-results");

  if (!searchInput || !resultsContainer) return;

  const searchTerm = searchInput.value;

  if (searchTerm.length < 2) {
    resultsContainer.innerHTML =
      '<p class="text-sm" style="color: var(--text-secondary)">Enter at least 2 characters</p>';
    return;
  }

  resultsContainer.innerHTML =
    '<p class="text-sm" style="color: var(--text-secondary)">Searching...</p>';

  const token = getToken();
  fetch(`/api/books/match?title=${encodeURIComponent(searchTerm)}`, {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  })
    .then((response) => response.json())
    .then((result) => {
      if (result.matches && result.matches.length > 0) {
        resultsContainer.innerHTML = result.matches
          .map(
            (match: any) => `
            <div class="card p-3 rounded-lg border cursor-pointer ${selectedMediaItem === match.media_item_id ? "border-2 border-blue-500" : ""}"
                 style="background-color: var(--bg-primary); border-color: var(--border);"
                 data-action="select-book" data-media-item-id="${match.media_item_id}" data-title="${match.title}" data-cover="${match.cover_image_path || ""}">
                <div class="flex gap-3">
                    <img src="${match.cover_image_path || "/static/placeholder-book.svg"}"
                         alt="Cover" class="w-12 h-16 object-cover rounded">
                    <div>
                        <h5 class="font-semibold text-sm" style="color: var(--text-primary)">${match.title}</h5>
                        <p class="text-xs" style="color: var(--text-secondary)">by ${match.author || "Unknown"}</p>
                        <p class="text-xs" style="color: var(--accent)">${Math.round(match.confidence * 100)}% confidence</p>
                    </div>
                </div>
            </div>
        `,
          )
          .join("");
      } else {
        resultsContainer.innerHTML =
          '<p class="text-sm" style="color: var(--text-secondary)">No matches found</p>';
      }
    })
    .catch((error) => {
      console.error("Failed to search", error);
      resultsContainer.innerHTML =
        '<p class="text-sm" style="color: var(--error)">Failed to search</p>';
    });
}

function selectBookForLink(mediaItemId: string, _coverPath: string): void {
  selectedMediaItem = mediaItemId;
  const resultsContainer = document.getElementById("link-search-results");
  if (!resultsContainer) return;

  const cards = resultsContainer.querySelectorAll(".card");
  cards.forEach((card) => {
    card.classList.remove("border-2", "border-blue-500");
    if ((card as HTMLElement).dataset.mediaItemId === mediaItemId) {
      card.classList.add("border-2", "border-blue-500");
    }
  });
}

function confirmManualLink(): void {
  if (!selectedMediaItem) {
    showToast("Please select a book to link", "error");
    return;
  }

  const progressIdInput = document.getElementById(
    "link-progress-id",
  ) as HTMLInputElement;
  const confidenceInput = document.getElementById(
    "link-confidence",
  ) as HTMLInputElement;
  const bookTitleInput = document.getElementById(
    "link-book-title",
  ) as HTMLInputElement;
  const sha256Input = document.getElementById(
    "link-book-sha256",
  ) as HTMLInputElement;

  if (!progressIdInput) return;

  const confidence = parseFloat(confidenceInput?.value || "0");
  const bookTitle = bookTitleInput?.value || "";
  const sha256 = sha256Input?.value || "";

  const data = {
    device_file: {
      file_path: bookTitle,
      sha256: sha256,
    },
    media_item_id: selectedMediaItem,
    confidence_score: confidence,
  };

  const token = getToken();
  fetch(`/api/devices/sync/link-book`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify(data),
  })
    .then((response) => response.json())
    .then(() => {
      showToast("Book linked successfully", "success");
      hideManualLinkModal();
      window.location.reload();
    })
    .catch((error) => {
      console.error("Failed to link book", error);
      showToast("Failed to link book", "error");
    });
}

function toggleAllUnlinked(): void {
  const selectAll = document.getElementById(
    "select-all-unlinked",
  ) as HTMLInputElement;
  if (!selectAll) return;

  document.querySelectorAll(".unlinked-checkbox").forEach((cb) => {
    (cb as HTMLInputElement).checked = selectAll.checked;
  });
  updateSelectedCount();
}

function getSelectedUnlinked(): { progressId: string; title: string }[] {
  return Array.from(
    document.querySelectorAll(".unlinked-checkbox:checked"),
  ).map((cb) => ({
    progressId: cb.getAttribute("data-progress-id") || "",
    title: cb.getAttribute("data-title") || "",
  }));
}

function updateSelectedCount(): void {
  const count = document.querySelectorAll(".unlinked-checkbox:checked").length;
  const countElement = document.getElementById("selected-count");
  if (countElement) {
    countElement.textContent = `${count} selected`;
  }
}

async function bulkAutoLink(): Promise<void> {
  const selected = getSelectedUnlinked();
  if (selected.length === 0) {
    showToast("Please select at least one book", "error");
    return;
  }

  if (
    !confirm(
      `Auto-link ${selected.length} books with high confidence matches (≥80%)?`,
    )
  ) {
    return;
  }

  const token = getToken();
  try {
    const response = await fetch("/sync/auto-link-books", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${token}`,
      },
      body: JSON.stringify({
        confidence_threshold: 0.8,
        limit: selected.length,
      }),
    });

    const result = await response.json();
    showToast(
      `Auto-linked ${result.auto_linked} books successfully`,
      "success",
    );
    setTimeout(() => window.location.reload(), 1500);
  } catch (error) {
    console.error("Auto-link failed", error);
    showToast(`Auto-link failed: ${(error as Error).message}`, "error");
  }
}

async function bulkGetSuggestions(): Promise<void> {
  const selected = getSelectedUnlinked();
  if (selected.length === 0) {
    showToast("Please select at least one book", "error");
    return;
  }

  const token = getToken();
  for (const book of selected) {
    try {
      const response = await fetch(
        `/sync/unlinked-books/${book.progressId}/suggestions`,
        {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        },
      );

      const result = await response.json();
      displaySuggestions(book.progressId, result.suggestions, result.action);
    } catch (error) {
      console.error("Failed to get suggestions:", error);
    }
  }
}

function displaySuggestions(
  progressId: string,
  suggestions: any[],
  _action: string,
): void {
  const container = document.getElementById(`matches-${progressId}`);
  if (!container) return;

  container.classList.remove("hidden");
  const listContainer = container.querySelector(".matches-list");
  if (!listContainer) return;

  listContainer.innerHTML = "";

  if (suggestions.length === 0) {
    listContainer.innerHTML =
      '<p style="color: var(--text-secondary)">No matches found</p>';
    return;
  }

  suggestions.forEach((match) => {
    const div = document.createElement("div");
    div.className =
      "p-3 border rounded cursor-pointer hover:bg-opacity-80 transition-colors";
    div.style.cssText = `background-color: var(--bg-primary); border-color: var(--border);`;
    div.innerHTML = `
      <div class="flex justify-between items-center">
        <div>
          <h4 class="font-semibold" style="color: var(--text-primary)">${match.title}</h4>
          <p class="text-sm" style="color: var(--text-secondary)">Author: ${match.author || "Unknown"}</p>
        </div>
        <div class="text-right">
          <div class="text-sm font-semibold" style="color: var(--text-primary)">
            ${(match.confidence * 100).toFixed(0)}% confidence
          </div>
          <div class="text-xs" style="color: var(--text-secondary)">${match.match_method}</div>
        </div>
      </div>
    `;
    (div as HTMLElement).dataset.action = "select-match";
    (div as HTMLElement).dataset.progressId = progressId;
    (div as HTMLElement).dataset.mediaItemId = match.media_item_id;
    (div as HTMLElement).dataset.confidence = String(match.confidence);
    listContainer.appendChild(div);
  });
}

function showBulkManualLink(): void {
  const selected = getSelectedUnlinked();
  if (selected.length === 0) {
    showToast("Please select at least one book", "error");
    return;
  }

  showToast(
    `Bulk manual link for ${selected.length} books - select target book in library`,
    "info",
  );
  window.location.href =
    "/library?mode=link&unlinked=" +
    selected.map((s) => s.progressId).join(",");
}

function setupEventDelegation(): void {
  document.addEventListener("click", (e) => {
    const target = e.target as HTMLElement;
    const card = target.closest("[data-action]") as HTMLElement;

    if (!card) return;

    const action = card.dataset.action;

    if (action === "auto-link") {
      autoLinkBook(
        card.dataset.progressId || "",
        card.dataset.mediaItemId || "",
        parseFloat(card.dataset.confidence || "0"),
      );
    } else if (action === "select-book") {
      selectBookForLink(
        card.dataset.mediaItemId || "",
        card.dataset.cover || "",
      );
    } else if (action === "select-match") {
      autoLinkBook(
        card.dataset.progressId || "",
        card.dataset.mediaItemId || "",
        parseFloat(card.dataset.confidence || "0"),
      );
    }
  });

  document.addEventListener("change", (e) => {
    const target = e.target as HTMLElement;
    if (target.classList.contains("unlinked-checkbox")) {
      updateSelectedCount();
    }
  });
}

export {
  bulkAutoLink,
  bulkGetSuggestions,
  confirmManualLink,
  displaySuggestions,
  hideManualLinkModal,
  searchBooksForLink,
  searchMatches,
  selectBookForLink,
  setupEventDelegation,
  showBulkManualLink,
  showManualLinkModal,
  toggleAllUnlinked,
};

Alpine.data("unlinkedBooks", () => ({
  bulkAutoLink,
  bulkGetSuggestions,
  confirmManualLink,
  displaySuggestions,
  hideManualLinkModal,
  searchBooksForLink,
  searchMatches,
  selectBookForLink,
  setupEventDelegation,
  showBulkManualLink,
  showManualLinkModal,
  toggleAllUnlinked,
}));
