"use client";

import { FormEvent, useCallback, useEffect, useMemo, useState } from "react";
import { AdminGuard } from "@/components/admin/AdminGuard";
import { AdminShell } from "@/components/admin/AdminShell";
import { adminRequest } from "@/lib/admin-api";
import {
  CategoryFormDialog,
  DeleteCategoryDialog,
  EmptyFaqCategoriesState,
  FaqAdminIntro,
  FaqContentPanel,
  FaqErrorMessage,
  FaqFormDialog,
  FaqLoadingState,
} from "./components";
import { emptyFaqForm, type FaqCategory, type FaqFormState, type FaqItem } from "./types";

export default function AdminFaqsPage() {
  const [faqs, setFaqs] = useState<FaqItem[]>([]);
  const [categories, setCategories] = useState<FaqCategory[]>([]);
  const [activeCategory, setActiveCategory] = useState("");
  const [isLoading, setIsLoading] = useState(true);
  const [isSaving, setIsSaving] = useState(false);
  const [isCategorySaving, setIsCategorySaving] = useState(false);
  const [deletingId, setDeletingId] = useState<number | null>(null);
  const [deletingCategoryId, setDeletingCategoryId] = useState<number | null>(null);
  const [draggingId, setDraggingId] = useState<number | null>(null);
  const [draggingCategoryId, setDraggingCategoryId] = useState<number | null>(null);
  const [form, setForm] = useState<FaqFormState>(emptyFaqForm);
  const [formOpen, setFormOpen] = useState(false);
  const [categoryFormOpen, setCategoryFormOpen] = useState(false);
  const [pendingDeleteCategory, setPendingDeleteCategory] = useState<FaqCategory | null>(null);
  const [categoryName, setCategoryName] = useState("");
  const [errorMessage, setErrorMessage] = useState("");

  const loadFaqData = useCallback(async () => {
    setIsLoading(true);
    setErrorMessage("");

    try {
      const [faqData, categoryData] = await Promise.all([
        adminRequest<{ faqs: FaqItem[] }>("/api/admin/faqs"),
        adminRequest<{ categories: FaqCategory[] }>("/api/admin/faq-categories"),
      ]);

      setFaqs(faqData.faqs);
      setCategories(categoryData.categories);
      setActiveCategory((current) =>
        current && categoryData.categories.some((category) => category.name === current)
          ? current
          : (categoryData.categories[0]?.name ?? ""),
      );
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : "Could not load FAQs");
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    loadFaqData();
  }, [loadFaqData]);

  useEffect(() => {
    if (!formOpen && !categoryFormOpen && !pendingDeleteCategory) {
      return;
    }

    const previousOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";

    return () => {
      document.body.style.overflow = previousOverflow;
    };
  }, [categoryFormOpen, formOpen, pendingDeleteCategory]);

  const activeFaqs = useMemo(() => {
    return faqs
      .filter((faq) => faq.category === activeCategory)
      .sort((first, second) => first.displayOrder - second.displayOrder || first.id - second.id);
  }, [activeCategory, faqs]);

  function getCategoryFaqCount(categoryName: string) {
    return faqs.filter((faq) => faq.category === categoryName).length;
  }

  function openCreateForm() {
    setForm({ ...emptyFaqForm, category: activeCategory || categories[0]?.name || "" });
    setErrorMessage("");
    setFormOpen(true);
  }

  function openEditForm(faq: FaqItem) {
    setForm({
      id: faq.id,
      category: faq.category,
      question: faq.question,
      answer: faq.answer,
      isActive: faq.isActive,
    });
    setErrorMessage("");
    setFormOpen(true);
  }

  function openCategoryForm() {
    setCategoryName("");
    setErrorMessage("");
    setCategoryFormOpen(true);
  }

  async function saveCategory(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setIsCategorySaving(true);
    setErrorMessage("");

    const name = categoryName.trim();

    try {
      await adminRequest("/api/admin/faq-categories", {
        method: "POST",
        body: JSON.stringify({ name }),
      });
      setCategoryFormOpen(false);
      setCategoryName("");
      setActiveCategory(name);
      await loadFaqData();
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : "Could not save FAQ category");
    } finally {
      setIsCategorySaving(false);
    }
  }

  async function saveFaq(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setIsSaving(true);
    setErrorMessage("");

    const payload = {
      category: form.category,
      question: form.question.trim(),
      answer: form.answer.trim(),
      isActive: form.isActive,
    };

    try {
      if (form.id) {
        await adminRequest(`/api/admin/faqs/${form.id}`, {
          method: "PUT",
          body: JSON.stringify(payload),
        });
      } else {
        await adminRequest("/api/admin/faqs", {
          method: "POST",
          body: JSON.stringify(payload),
        });
      }

      setFormOpen(false);
      setForm(emptyFaqForm);
      setActiveCategory(payload.category);
      await loadFaqData();
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : "Could not save FAQ");
    } finally {
      setIsSaving(false);
    }
  }

  async function deleteFaq(faq: FaqItem) {
    if (!window.confirm(`Delete this FAQ?\n\n${faq.question}`)) {
      return;
    }

    setDeletingId(faq.id);
    setErrorMessage("");

    try {
      await adminRequest(`/api/admin/faqs/${faq.id}`, {
        method: "DELETE",
      });
      await loadFaqData();
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : "Could not delete FAQ");
    } finally {
      setDeletingId(null);
    }
  }

  async function deleteCategory(category: FaqCategory) {
    setDeletingCategoryId(category.id);
    setErrorMessage("");

    try {
      await adminRequest(`/api/admin/faq-categories/${category.id}`, {
        method: "DELETE",
      });
      setPendingDeleteCategory(null);
      await loadFaqData();
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : "Could not delete FAQ category");
    } finally {
      setDeletingCategoryId(null);
    }
  }

  async function dropFaq(targetId: number) {
    if (!draggingId || draggingId === targetId) {
      setDraggingId(null);
      return;
    }

    const sourceIndex = activeFaqs.findIndex((faq) => faq.id === draggingId);
    const targetIndex = activeFaqs.findIndex((faq) => faq.id === targetId);

    if (sourceIndex === -1 || targetIndex === -1) {
      setDraggingId(null);
      return;
    }

    const reorderedFaqs = [...activeFaqs];
    const [movedFaq] = reorderedFaqs.splice(sourceIndex, 1);
    reorderedFaqs.splice(targetIndex, 0, movedFaq);
    const reorderedIds = reorderedFaqs.map((faq) => faq.id);
    const previousFaqs = faqs;

    setDraggingId(null);
    setFaqs((currentFaqs) => {
      const displayOrderById = new Map(reorderedIds.map((id, index) => [id, index + 1] as const));

      return currentFaqs.map((faq) =>
        faq.category === activeCategory && displayOrderById.has(faq.id)
          ? { ...faq, displayOrder: displayOrderById.get(faq.id) ?? faq.displayOrder }
          : faq,
      );
    });

    try {
      await adminRequest("/api/admin/faqs/reorder", {
        method: "PUT",
        body: JSON.stringify({ ids: reorderedIds }),
      });
      await loadFaqData();
    } catch (error) {
      setFaqs(previousFaqs);
      setErrorMessage(error instanceof Error ? error.message : "Could not reorder FAQs");
    }
  }

  async function dropCategory(targetId: number) {
    if (!draggingCategoryId || draggingCategoryId === targetId) {
      setDraggingCategoryId(null);
      return;
    }

    const sourceIndex = categories.findIndex((category) => category.id === draggingCategoryId);
    const targetIndex = categories.findIndex((category) => category.id === targetId);

    if (sourceIndex === -1 || targetIndex === -1) {
      setDraggingCategoryId(null);
      return;
    }

    const reorderedCategories = [...categories];
    const [movedCategory] = reorderedCategories.splice(sourceIndex, 1);
    reorderedCategories.splice(targetIndex, 0, movedCategory);
    const reorderedIds = reorderedCategories.map((category) => category.id);
    const previousCategories = categories;

    setDraggingCategoryId(null);
    setCategories(
      reorderedCategories.map((category, index) => ({
        ...category,
        displayOrder: index + 1,
      })),
    );

    try {
      await adminRequest("/api/admin/faq-categories/reorder", {
        method: "PUT",
        body: JSON.stringify({ ids: reorderedIds }),
      });
      await loadFaqData();
    } catch (error) {
      setCategories(previousCategories);
      setErrorMessage(error instanceof Error ? error.message : "Could not reorder FAQ categories");
    }
  }

  return (
    <AdminGuard>
      <AdminShell
        title="FAQs"
        lead="Manage FAQ categories and the questions shown inside each category tab."
      >
        <section className="space-y-5">
          <FaqAdminIntro
            hasCategories={categories.length > 0}
            onAddCategory={openCategoryForm}
            onAddFaq={openCreateForm}
          />
          <FaqErrorMessage message={errorMessage} />

          {isLoading ? (
            <FaqLoadingState />
          ) : categories.length === 0 ? (
            <EmptyFaqCategoriesState />
          ) : (
            <FaqContentPanel
              categories={categories}
              activeCategory={activeCategory}
              activeFaqs={activeFaqs}
              deletingCategoryId={deletingCategoryId}
              deletingId={deletingId}
              draggingCategoryId={draggingCategoryId}
              draggingId={draggingId}
              getCategoryFaqCount={getCategoryFaqCount}
              onDeleteFaq={deleteFaq}
              onDropCategory={dropCategory}
              onDropFaq={dropFaq}
              onEditFaq={openEditForm}
              onSelectCategory={setActiveCategory}
              setDraggingCategoryId={setDraggingCategoryId}
              setDraggingId={setDraggingId}
              setPendingDeleteCategory={setPendingDeleteCategory}
            />
          )}
        </section>

        {categoryFormOpen ? (
          <CategoryFormDialog
            categoryName={categoryName}
            isSaving={isCategorySaving}
            onClose={() => setCategoryFormOpen(false)}
            onSave={saveCategory}
            setCategoryName={setCategoryName}
          />
        ) : null}

        {formOpen ? (
          <FaqFormDialog
            categories={categories}
            form={form}
            isSaving={isSaving}
            onClose={() => setFormOpen(false)}
            onSave={saveFaq}
            setForm={setForm}
          />
        ) : null}

        {pendingDeleteCategory ? (
          <DeleteCategoryDialog
            category={pendingDeleteCategory}
            count={getCategoryFaqCount(pendingDeleteCategory.name)}
            deletingCategoryId={deletingCategoryId}
            onCancel={() => setPendingDeleteCategory(null)}
            onConfirm={deleteCategory}
          />
        ) : null}
      </AdminShell>
    </AdminGuard>
  );
}
