import { apiPost } from "./api";
import { showToast } from "./toast";

interface FilterField {
  id: string;
  label: string;
  operators: Operator[];
  valueType: "text" | "number" | "date" | "select" | "multiselect";
  options?: string[];
}

interface Operator {
  id: string;
  label: string;
  requiresValue: boolean;
}

interface FilterRule {
  id: string;
  field: string;
  operator: string;
  value: string | string[];
  priority: number;
}

const FILTER_FIELDS: FilterField[] = [
  {
    id: "title",
    label: "Title",
    operators: [
      { id: "contains", label: "Contains", requiresValue: true },
      { id: "equals", label: "Equals", requiresValue: true },
      { id: "starts_with", label: "Starts With", requiresValue: true },
      { id: "ends_with", label: "Ends With", requiresValue: true },
      { id: "regex", label: "Matches Regex", requiresValue: true },
    ],
    valueType: "text",
  },
  {
    id: "author",
    label: "Author",
    operators: [
      { id: "contains", label: "Contains", requiresValue: true },
      { id: "equals", label: "Equals", requiresValue: true },
    ],
    valueType: "text",
  },
  // {
  //   id: "genre",
  //   label: "Genre",
  //   operators: [
  //     { id: "equals", label: "Equals", requiresValue: true },
  //     { id: "not_equals", label: "Not Equals", requiresValue: true },
  //     { id: "in", label: "In", requiresValue: true },
  //     { id: "not_in", label: "Not In", requiresValue: true },
  //   ],
  //   valueType: "select",
  //   options: [
  //     "Fiction",
  //     "Non-Fiction",
  //     "Sci-Fi",
  //     "Fantasy",
  //     "Mystery",
  //     "Romance",
  //     "Thriller",
  //     "Biography",
  //     "History",
  //     "Self-Help",
  //   ],
  // },
  {
    id: "tags",
    label: "Tags",
    operators: [
      { id: "equals", label: "Equals", requiresValue: true },
      { id: "not_equals", label: "Not Equals", requiresValue: true },
      { id: "in", label: "In", requiresValue: true },
      { id: "not_in", label: "Not In", requiresValue: true },
    ],
    valueType: "select",
    options: [
      "Fiction",
      "Non-Fiction",
      "Sci-Fi",
      "Fantasy",
      "Mystery",
      "Romance",
      "Thriller",
      "Biography",
      "History",
      "Self-Help",
    ],
  },
  {
    id: "series",
    label: "Series",
    operators: [
      { id: "is_set", label: "Is Set", requiresValue: false },
      { id: "is_not_set", label: "Is Not Set", requiresValue: false },
      { id: "equals", label: "Equals", requiresValue: true },
      { id: "contains", label: "Contains", requiresValue: true },
    ],
    valueType: "text",
  },
  {
    id: "progress",
    label: "Reading Progress",
    operators: [
      { id: "equals", label: "Equals", requiresValue: true },
      { id: "not_equals", label: "Not Equals", requiresValue: true },
      { id: "greater_than", label: "Greater Than", requiresValue: true },
      { id: "less_than", label: "Less Than", requiresValue: true },
      { id: "between", label: "Between", requiresValue: true },
      { id: "is_set", label: "Is Set", requiresValue: false },
      { id: "is_not_set", label: "Is Not Set", requiresValue: false },
    ],
    valueType: "number",
  },
  {
    id: "rating",
    label: "Rating",
    operators: [
      { id: "equals", label: "Equals", requiresValue: true },
      { id: "not_equals", label: "Not Equals", requiresValue: true },
      { id: "greater_than", label: "Greater Than", requiresValue: true },
      { id: "less_than", label: "Less Than", requiresValue: true },
      { id: "is_set", label: "Is Set", requiresValue: false },
      { id: "is_not_set", label: "Is Not Set", requiresValue: false },
    ],
    valueType: "number",
  },
  {
    id: "date_added",
    label: "Date Added",
    operators: [
      { id: "equals", label: "Equals", requiresValue: true },
      { id: "not_equals", label: "Not Equals", requiresValue: true },
      { id: "before", label: "Before", requiresValue: true },
      { id: "after", label: "After", requiresValue: true },
      { id: "between", label: "Between", requiresValue: true },
      { id: "last_x_days", label: "Last X Days", requiresValue: true },
    ],
    valueType: "date",
  },
  {
    id: "last_read",
    label: "Last Read Date",
    operators: [
      { id: "equals", label: "Equals", requiresValue: true },
      { id: "before", label: "Before", requiresValue: true },
      { id: "after", label: "After", requiresValue: true },
      { id: "between", label: "Between", requiresValue: true },
      { id: "last_x_days", label: "Last X Days", requiresValue: true },
      { id: "is_set", label: "Is Set", requiresValue: false },
      { id: "is_not_set", label: "Is Not Set", requiresValue: false },
    ],
    valueType: "date",
  },
  {
    id: "publisher",
    label: "Publisher",
    operators: [
      { id: "contains", label: "Contains", requiresValue: true },
      { id: "equals", label: "Equals", requiresValue: true },
    ],
    valueType: "text",
  },
  {
    id: "language",
    label: "Language",
    operators: [
      { id: "equals", label: "Equals", requiresValue: true },
      { id: "not_equals", label: "Not Equals", requiresValue: true },
      { id: "in", label: "In", requiresValue: true },
    ],
    valueType: "select",
    options: [
      "English",
      "Spanish",
      "French",
      "German",
      "Japanese",
      "Chinese",
      "Russian",
      "Other",
    ],
  },
  {
    id: "format",
    label: "Format",
    operators: [
      { id: "equals", label: "Equals", requiresValue: true },
      { id: "in", label: "In", requiresValue: true },
    ],
    valueType: "select",
    options: ["Ebook", "Audiobook", "Comic", "Manga", "Magazine"],
  },
  {
    id: "tags",
    label: "Tags",
    operators: [
      { id: "contains", label: "Contains", requiresValue: true },
      { id: "not_contains", label: "Does Not Contain", requiresValue: true },
      { id: "equals", label: "Equals", requiresValue: true },
    ],
    valueType: "text",
  },
  {
    id: "narrators",
    label: "Narrators (Audiobooks)",
    operators: [
      { id: "contains", label: "Contains", requiresValue: true },
      { id: "equals", label: "Equals", requiresValue: true },
      { id: "is_set", label: "Is Set", requiresValue: false },
      { id: "is_not_set", label: "Is Not Set", requiresValue: false },
    ],
    valueType: "text",
  },
];

let ruleCounter = 0;
let selectedBooks: Map<string, BookInfo> = new Map();
let customSectionTimeout: number | null = null;

function initCustomSectionBuilder(): void {
  const addRuleBtn = document.getElementById("add-rule-btn");
  const previewBtn = document.getElementById("preview-btn");
  const searchBtn = document.getElementById("search-books-btn");
  const bookSearchInput = document.getElementById("book-search");
  const cancelBtn = document.getElementById("cancel-btn");
  const form = document.getElementById("custom-section-form");

  if (addRuleBtn) {
    addRuleBtn.addEventListener("click", addFilterRule);
  }

  if (previewBtn) {
    previewBtn.addEventListener("click", loadPreview);
  }

  if (searchBtn) {
    searchBtn.addEventListener("click", searchBooks);
  }

  if (bookSearchInput) {
    bookSearchInput.addEventListener("input", onBookSearchInput);
    bookSearchInput.addEventListener("keypress", (e) => {
      if (e.key === "Enter") {
        e.preventDefault();
        searchBooks();
      }
    });
  }

  if (cancelBtn) {
    cancelBtn.addEventListener("click", () => {
      window.location.href = "/dashboard";
    });
  }

  if (form) {
    form.addEventListener("submit", saveCustomSection);
  }
}

function addFilterRule(): void {
  const container = document.getElementById("rules-container");
  if (!container) return;

  ruleCounter++;
  const ruleId = `rule-${ruleCounter}`;

  const ruleElement = document.createElement("div");
  ruleElement.className = "rule-item p-3 rounded border";
  ruleElement.dataset.ruleId = ruleId;
  ruleElement.style.cssText = `background-color: var(--bg-primary); border-color: var(--border);`;

  ruleElement.innerHTML = `
        <div class="flex items-center gap-2 mb-2">
            <select class="field-select flex-1 px-3 py-1 rounded border"
                    style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border);">
                <option value="">Select field...</option>
                ${FILTER_FIELDS.map((field) => `<option value="${field.id}">${field.label}</option>`).join("")}
            </select>
            <button type="button" class="remove-rule-btn text-red-500 hover:text-red-700 px-2" data-rule-id="${ruleId}">
                Remove
            </button>
        </div>
        <div class="flex items-center gap-2">
            <select class="operator-select flex-1 px-3 py-1 rounded border"
                    style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border);"
                    disabled>
                <option value="">Select field first...</option>
            </select>
            <input type="text" class="value-input flex-1 px-3 py-1 rounded border hidden"
                   style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border);"
                   placeholder="Enter value...">
        </div>
    `;

  container.appendChild(ruleElement);

  const fieldSelect = ruleElement.querySelector(
    ".field-select",
  ) as HTMLSelectElement;
  const removeBtn = ruleElement.querySelector(
    ".remove-rule-btn",
  ) as HTMLButtonElement;

  fieldSelect.addEventListener("change", () => onFieldChange(ruleElement));
  removeBtn.addEventListener("click", () => removeFilterRule(ruleId));
}

function onFieldChange(ruleElement: HTMLElement): void {
  const fieldSelect = ruleElement.querySelector(
    ".field-select",
  ) as HTMLSelectElement;
  const operatorSelect = ruleElement.querySelector(
    ".operator-select",
  ) as HTMLSelectElement;
  const valueInput = ruleElement.querySelector(
    ".value-input",
  ) as HTMLInputElement;

  const fieldId = fieldSelect.value;
  const field = FILTER_FIELDS.find((f) => f.id === fieldId);

  operatorSelect.innerHTML = field
    ? field.operators
        .map((op) => `<option value="${op.id}">${op.label}</option>`)
        .join("")
    : '<option value="">Select field first...</option>';

  operatorSelect.disabled = !field;

  if (
    field &&
    field.operators.some(
      (op) => op.id === operatorSelect.value && op.requiresValue,
    )
  ) {
    valueInput.classList.remove("hidden");

    if (field.valueType === "select" && field.options) {
      valueInput.type = "select";
    } else if (field.valueType === "number") {
      valueInput.type = "number";
      valueInput.step = "0.01";
    } else if (field.valueType === "date") {
      valueInput.type = "date";
    } else {
      valueInput.type = "text";
    }
  } else {
    valueInput.classList.add("hidden");
  }

  operatorSelect.addEventListener("change", () => {
    const selectedOp = field?.operators.find(
      (op) => op.id === operatorSelect.value,
    );
    if (selectedOp?.requiresValue) {
      valueInput.classList.remove("hidden");
    } else {
      valueInput.classList.add("hidden");
    }
  });
}

function removeFilterRule(ruleId: string): void {
  const ruleElement = document.querySelector(`[data-rule-id="${ruleId}"]`);
  if (ruleElement) {
    ruleElement.remove();
  }
}

function onBookSearchInput(): void {
  if (customSectionTimeout) {
    clearTimeout(customSectionTimeout);
  }
  customSectionTimeout = window.setTimeout(() => {
    searchBooks();
  }, 300);
}

async function searchBooks(): Promise<void> {
  const searchInput = document.getElementById(
    "book-search",
  ) as HTMLInputElement;
  const librarySelect = document.getElementById(
    "section-library",
  ) as HTMLSelectElement;
  const resultsContainer = document.getElementById(
    "search-results",
  ) as HTMLElement;

  const query = searchInput?.value.trim();
  const libraryId = librarySelect?.value;

  if (!query || !libraryId) {
    if (resultsContainer) resultsContainer.classList.add("hidden");
    return;
  }

  try {
    const response = await fetch(
      `/api/books/search?q=${encodeURIComponent(query)}&library_id=${libraryId}`,
      {
        headers: {
          Authorization: `Bearer ${localStorage.getItem("token")}`,
          "Content-Type": "application/json",
        },
      },
    );

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

    const data = await response.json();
    displaySearchResults(data.books || []);
  } catch (error) {
    console.error("Search books error:", error);
    showToast("Failed to search books", "error");
  }
}

function displaySearchResults(books: BookInfo[]): void {
  const resultsContainer = document.getElementById(
    "search-results",
  ) as HTMLElement;
  if (!resultsContainer) return;

  if (books.length === 0) {
    resultsContainer.innerHTML =
      '<p class="text-center" style="color: var(--text-secondary);">No books found</p>';
  } else {
    resultsContainer.innerHTML = books
      .map(
        (book) => `
            <div class="flex items-center gap-2 p-2 hover:bg-gray-700 rounded cursor-pointer"
                 data-book-id="${book.media_item_id}"
                 onclick="addBookToSelection('${book.media_item_id}', '${builderEscapeHtml(book.title)}', '${builderEscapeHtml(book.author)}')">
                <img src="${book.cover_image_path || "/static/placeholder-book.svg"}"
                     alt="${builderEscapeHtml(book.title)}"
                     class="w-10 h-15 object-cover rounded">
                <div class="flex-1">
                    <p class="text-sm font-medium" style="color: var(--text-primary);">${builderEscapeHtml(book.title)}</p>
                    <p class="text-xs" style="color: var(--text-secondary);">${builderEscapeHtml(book.author)}</p>
                </div>
                <button type="button" class="text-green-500 hover:text-green-700 text-xl">+</button>
            </div>
        `,
      )
      .join("");
  }

  resultsContainer.classList.remove("hidden");
}

const addBookToSelection = (
  bookId: string,
  title: string,
  author: string,
): void => {
  if (selectedBooks.has(bookId)) {
    showToast("Book already selected", "error");
    return;
  }

  selectedBooks.set(bookId, {
    media_item_id: bookId,
    title: title,
    author: author,
    cover_image_path: "",
  });

  updateSelectedBooksDisplay();
};

const removeBookFromSelection = (bookId: string): void => {
  selectedBooks.delete(bookId);
  updateSelectedBooksDisplay();
};

function updateSelectedBooksDisplay(): void {
  const container = document.getElementById("selected-books") as HTMLElement;
  if (!container) return;

  if (selectedBooks.size === 0) {
    container.innerHTML =
      '<p class="text-sm text-center" style="color: var(--text-secondary);">No books selected</p>';
    return;
  }

  container.innerHTML = Array.from(selectedBooks.values())
    .map(
      (book) => `
        <div class="inline-flex items-center gap-2 px-3 py-1 m-1 rounded-full text-sm"
             style="background-color: var(--accent);">
            <span>${builderEscapeHtml(book.title)}</span>
            <button type="button" onclick="removeBookFromSelection('${book.media_item_id}')"
                    class="hover:opacity-70">×</button>
        </div>
    `,
    )
    .join("");
}

async function loadPreview(): Promise<void> {
  const previewContainer = document.getElementById(
    "preview-container",
  ) as HTMLElement;
  const librarySelect = document.getElementById(
    "section-library",
  ) as HTMLSelectElement;
  const libraryId = librarySelect?.value;

  if (!libraryId) {
    showToast("Please select a library first", "error");
    return;
  }

  const rules = gatherFilterRules();
  const manualBookIds = Array.from(selectedBooks.keys());

  previewContainer.innerHTML =
    '<div class="text-center"><div class="animate-spin inline-block w-8 h-8 border-4 border-current border-t-transparent rounded-full"></div></div>';

  try {
    const response = await apiPost("/collections/preview", {
      library_id: libraryId,
      rules: rules,
      manual_book_ids: manualBookIds,
      limit: 20,
    });

    if (response.ok) {
      const data = await response.json();
      displayPreview(data.items || []);
    } else {
      throw new Error("Failed to load preview");
    }
  } catch (error) {
    console.error("Preview error:", error);
    previewContainer.innerHTML =
      '<p class="text-center text-red-500">Failed to load preview</p>';
  }
}

function gatherFilterRules(): FilterRule[] {
  const container = document.getElementById("rules-container") as HTMLElement;
  if (!container) return [];

  const ruleElements = container.querySelectorAll(".rule-item");
  const rules: FilterRule[] = [];

  ruleElements.forEach((element, index) => {
    const fieldSelect = element.querySelector(
      ".field-select",
    ) as HTMLSelectElement;
    const operatorSelect = element.querySelector(
      ".operator-select",
    ) as HTMLSelectElement;
    const valueInput = element.querySelector(
      ".value-input",
    ) as HTMLInputElement;

    if (fieldSelect.value && operatorSelect.value) {
      rules.push({
        id: `rule-${index}`,
        field: fieldSelect.value,
        operator: operatorSelect.value,
        value: valueInput.value,
        priority: index,
      });
    }
  });

  return rules;
}

function displayPreview(items: BookInfo[]): void {
  const previewContainer = document.getElementById(
    "preview-container",
  ) as HTMLElement;
  if (!previewContainer) return;

  if (items.length === 0) {
    previewContainer.innerHTML =
      '<p class="text-center" style="color: var(--text-secondary);">No items match your criteria</p>';
    return;
  }

  previewContainer.innerHTML = `
        <div class="flex gap-4 overflow-x-auto pb-4">
            ${items
              .map(
                (item) => `
                <div class="flex-shrink-0 w-32">
                    <div class="aspect-[2/3] rounded-lg overflow-hidden shadow-lg mb-2">
                        <img src="${item.cover_image_path || "/static/placeholder-book.svg"}"
                             alt="${builderEscapeHtml(item.title)}"
                             class="w-full h-full object-cover">
                    </div>
                    <h3 class="text-sm font-semibold line-clamp-2" style="color: var(--text-primary);">
                        ${builderEscapeHtml(item.title)}
                    </h3>
                    ${item.author ? `<p class="text-xs line-clamp-1" style="color: var(--text-secondary);">${builderEscapeHtml(item.author)}</p>` : ""}
                </div>
            `,
              )
              .join("")}
        </div>
        <p class="text-sm text-center mt-2" style="color: var(--text-secondary);">
            ${items.length} item${items.length !== 1 ? "s" : ""} will be shown
        </p>
    `;
}

async function saveCustomSection(event: Event): Promise<void> {
  event.preventDefault();

  const formData = new FormData(event.target as HTMLFormElement);
  const libraryId = formData.get("library_id") as string;
  const name = formData.get("name") as string;
  const icon = formData.get("icon") as string;
  const description = formData.get("description") as string;
  const matchType = (document.getElementById("match-type") as HTMLSelectElement)
    .value;

  if (!libraryId || !name) {
    showToast("Please fill in required fields", "error");
    return;
  }

  const rules = gatherFilterRules();
  const manualBookIds = Array.from(selectedBooks.keys());

  if (rules.length === 0 && manualBookIds.length === 0) {
    showToast("Please add filter rules or select books", "error");
    return;
  }

  try {
    const response = await apiPost("/collections", {
      library_id: libraryId,
      name: name,
      icon: icon,
      description: description,
      show_on_dashboard: true,
      auto_assign_rules: JSON.stringify(rules),
      manual_book_ids: manualBookIds,
      match_type: matchType,
    });

    if (response.ok) {
      showToast("Custom section created successfully", "success");
      setTimeout(() => {
        window.location.href = "/dashboard";
      }, 1000);
    } else {
      throw new Error("Failed to save custom section");
    }
  } catch (error) {
    console.error("Save custom section error:", error);
    showToast("Failed to save custom section", "error");
  }
}

function builderEscapeHtml(text: string): string {
  const div = document.createElement("div");
  div.textContent = text;
  return div.innerHTML;
}

initCustomSectionBuilder();

export { addBookToSelection, removeBookFromSelection };
