"use client"

import { useState, useMemo, useEffect, useCallback } from "react"
import { useRouter } from "next/navigation"
import { toast } from "sonner"
import { LayoutGrid } from "lucide-react"
import { Navbar } from "@/components/dashboard/navbar"
import { CategoryStatsBar } from "@/components/dashboard/categories/CategoryStatsBar"
import { CategoryToolbar } from "@/components/dashboard/categories/CategoryToolbar"
import { CategoryTable, type Category } from "@/components/dashboard/categories/CategoryTable"
import { DashboardTablePagination } from "@/components/dashboard/shared/DashboardTablePagination"
import { DashboardTableViewControls } from "@/components/dashboard/shared/DashboardTableViewControls"
import { useDashboardTableViewControls } from "@/hooks/useDashboardTableViewControls"
import { CategoryFormModal, type CategoryFormData } from "@/components/dashboard/categories/CategoryFormModal"
import { CategoryDeleteModal } from "@/components/dashboard/categories/CategoryDeleteModal"
import { throwIfNotOk } from "@/lib/throw-if-not-ok"
import type { CategoriesListResponse, CategoryMutationResponse, CategoryApiRecord } from "@/types/category-api"

type FilterVisibility = "all" | "visible" | "hidden"

const CATEGORIES_TABLE_ID = "categories-table"

const CATEGORIES_SORT_OPTIONS = [
  { value: "newest", label: "Newest first" },
  { value: "oldest", label: "Oldest first" },
  { value: "updated-newest", label: "Recently updated" },
  { value: "updated-oldest", label: "Least recently updated" },
  { value: "name-asc", label: "Name A → Z" },
  { value: "name-desc", label: "Name Z → A" },
]

const CATEGORIES_SORT_COMPARATORS: Record<string, (a: Category, b: Category) => number> = {
  newest: (a, b) => new Date(b.audit.createdAt).getTime() - new Date(a.audit.createdAt).getTime(),
  oldest: (a, b) => new Date(a.audit.createdAt).getTime() - new Date(b.audit.createdAt).getTime(),
  "updated-newest": (a, b) => new Date(b.audit.updatedAt).getTime() - new Date(a.audit.updatedAt).getTime(),
  "updated-oldest": (a, b) => new Date(a.audit.updatedAt).getTime() - new Date(b.audit.updatedAt).getTime(),
  "name-asc": (a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: "base" }),
  "name-desc": (a, b) => b.name.localeCompare(a.name, undefined, { sensitivity: "base" }),
}

function formatCreatedAt(iso: string): string {
  return new Date(iso).toLocaleDateString("en-US", {
    day: "2-digit",
    month: "short",
    year: "numeric",
  })
}

function mapRecordToRow(c: CategoryApiRecord): Category {
  return {
    id: c.id,
    name: c.name,
    slug: c.slug,
    description: c.description ?? undefined,
    color: c.color,
    iconKey: c.iconKey,
    articleCount: c.articleCount,
    doctorCount: c.doctorCount ?? 0,
    hospitalCount: c.hospitalCount ?? 0,
    procedureCount: c.procedureCount ?? 0,
    isVisible: c.isVisible,
    createdAtIso: c.createdAt,
    createdAt: formatCreatedAt(c.createdAt),
    audit: c.audit ?? {
      createdAt: c.createdAt,
      updatedAt: c.createdAt,
      createdBy: null,
      updatedBy: null,
    },
    translations: c.translations,
  }
}

export default function CategoriesPage() {
  const router = useRouter()
  const [categories, setCategories] = useState<Category[]>([])
  const [listLoading, setListLoading] = useState(true)
  const [listError, setListError] = useState<string | null>(null)

  const [searchQuery, setSearchQuery] = useState("")
  const [filterVisibility, setFilterVisibility] = useState<FilterVisibility>("all")

  const tableView = useDashboardTableViewControls<Category>({
    tableId: CATEGORIES_TABLE_ID,
    defaultSortKey: "newest",
    defaultItemsPerPage: 8,
    sortOptions: CATEGORIES_SORT_OPTIONS,
    comparators: CATEGORIES_SORT_COMPARATORS,
  })

  const [formModalOpen, setFormModalOpen] = useState(false)
  const [editCategory, setEditCategory] = useState<Category | null>(null)
  const [deleteTarget, setDeleteTarget] = useState<Category | null>(null)
  const [isDeleting, setIsDeleting] = useState(false)

  const loadCategories = useCallback(async () => {
    setListError(null)
    setListLoading(true)
    try {
      const res = await fetch("/api/admin/categories", { cache: "no-store" })
      await throwIfNotOk(res)
      const data = (await res.json()) as CategoriesListResponse
      setCategories(data.categories.map(mapRecordToRow))
    } catch (e) {
      const msg = e instanceof Error ? e.message : "Failed to load categories"
      setListError(msg)
      toast.error(msg)
    } finally {
      setListLoading(false)
    }
  }, [])

  useEffect(() => {
    void loadCategories()
  }, [loadCategories])

  const total = categories.length
  const visible = categories.filter((c) => c.isVisible).length
  const hidden = categories.filter((c) => !c.isVisible).length
  const withArticles = categories.filter((c) => c.articleCount > 0).length

  const filtered = useMemo(() => {
    return categories.filter((c) => {
      const matchSearch =
        c.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
        c.slug.toLowerCase().includes(searchQuery.toLowerCase()) ||
        (c.description ?? "").toLowerCase().includes(searchQuery.toLowerCase())
      const matchVisibility =
        filterVisibility === "all"
          ? true
          : filterVisibility === "visible"
            ? c.isVisible
            : !c.isVisible
      return matchSearch && matchVisibility
    })
  }, [categories, searchQuery, filterVisibility])

  const viewResult = useMemo(() => tableView.applyView(filtered), [filtered, tableView.applyView])

  useEffect(() => {
    if (tableView.viewAll) return
    if (tableView.currentPage > viewResult.totalPages) {
      tableView.setCurrentPage(viewResult.totalPages)
    }
  }, [
    tableView.viewAll,
    tableView.currentPage,
    tableView.setCurrentPage,
    viewResult.totalPages,
  ])

  const paginated = viewResult.displayed
  const totalPages = viewResult.totalPages

  function openCreate() {
    setEditCategory(null)
    setFormModalOpen(true)
  }

  function openEdit(category: Category) {
    setEditCategory(category)
    setFormModalOpen(true)
  }

  function openDelete(category: Category) {
    setDeleteTarget(category)
  }

  async function toggleVisibility(category: Category) {
    const next = !category.isVisible
    const snapshot = [...categories]
    setCategories((prev) =>
      prev.map((c) => (c.id === category.id ? { ...c, isVisible: next } : c))
    )
    try {
      const res = await fetch(`/api/admin/categories/${category.id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: category.translations.en.name,
          slug: category.slug,
          description: category.translations.en.description ?? "",
          translations: category.translations,
          color: category.color,
          iconKey: category.iconKey,
          isVisible: next,
        }),
      })
      await throwIfNotOk(res)
      const { category: updated } = (await res.json()) as CategoryMutationResponse
      setCategories((prev) =>
        prev.map((c) => (c.id === category.id ? mapRecordToRow(updated) : c))
      )
      router.refresh()
      toast.success(next ? "Category is now visible" : "Category is now hidden")
    } catch (e) {
      setCategories(snapshot)
      const msg = e instanceof Error ? e.message : "Update failed"
      toast.error(msg)
    }
  }

  async function handleFormSubmit(data: CategoryFormData) {
    if (editCategory) {
      const snapshot = [...categories]
      setCategories((prev) =>
        prev.map((c) =>
          c.id === editCategory.id
            ? {
                ...c,
                name: data.translations.en.name,
                slug: data.slug,
                description: data.translations.en.description || undefined,
                color: data.color,
                iconKey: data.iconKey || null,
                isVisible: data.isVisible,
                translations: data.translations,
              }
            : c
        )
      )
      try {
        const res = await fetch(`/api/admin/categories/${editCategory.id}`, {
          method: "PUT",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            name: data.translations.en.name,
            slug: data.slug,
            description: data.translations.en.description,
            translations: data.translations,
            color: data.color,
          iconKey: data.iconKey || null,
            isVisible: data.isVisible,
          }),
        })
        await throwIfNotOk(res)
        const { category } = (await res.json()) as CategoryMutationResponse
        setCategories((prev) =>
          prev.map((c) => (c.id === editCategory.id ? mapRecordToRow(category) : c))
        )
        toast.success("Category updated")
        router.refresh()
        setFormModalOpen(false)
        setEditCategory(null)
      } catch (e) {
        setCategories(snapshot)
        throw e
      }
    } else {
      const tempId = `temp-${crypto.randomUUID()}`
      const nowIso = new Date().toISOString()
      const optimisticRow: Category = {
        id: tempId,
        name: data.translations.en.name,
        slug: data.slug,
        description: data.translations.en.description || undefined,
        color: data.color,
        iconKey: data.iconKey || null,
        articleCount: 0,
        doctorCount: 0,
        hospitalCount: 0,
        procedureCount: 0,
        isVisible: data.isVisible,
        createdAtIso: nowIso,
        createdAt: formatCreatedAt(nowIso),
        audit: {
          createdAt: nowIso,
          updatedAt: nowIso,
          createdBy: null,
          updatedBy: null,
        },
        translations: data.translations,
      }
      setCategories((prev) => [optimisticRow, ...prev])
      try {
        const res = await fetch("/api/admin/categories", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            name: data.translations.en.name,
            slug: data.slug,
            description: data.translations.en.description,
            translations: data.translations,
            color: data.color,
          iconKey: data.iconKey || null,
            isVisible: data.isVisible,
          }),
        })
        await throwIfNotOk(res)
        const { category } = (await res.json()) as CategoryMutationResponse
        setCategories((prev) =>
          prev.map((c) => (c.id === tempId ? mapRecordToRow(category) : c))
        )
        toast.success("Category created")
        router.refresh()
        setFormModalOpen(false)
      } catch (e) {
        setCategories((prev) => prev.filter((c) => c.id !== tempId))
        throw e
      }
    }
  }

  async function handleDelete() {
    if (!deleteTarget) return
    setIsDeleting(true)
    const snapshot = [...categories]
    const id = deleteTarget.id
    setCategories((prev) => prev.filter((c) => c.id !== id))
    try {
      const res = await fetch(`/api/admin/categories/${id}`, { method: "DELETE" })
      if (res.status === 404) {
        toast.message("Category was already removed")
      } else {
        await throwIfNotOk(res)
        toast.success("Category deleted")
      }
      setDeleteTarget(null)
      router.refresh()
    } catch (e) {
      setCategories(snapshot)
      const msg = e instanceof Error ? e.message : "Delete failed"
      toast.error(msg)
    } finally {
      setIsDeleting(false)
    }
  }

  return (
    <>
      <Navbar
        title="Categories"
        breadcrumbs={[
          { label: "Dashboard", href: "/dashboard" },
          { label: "Categories" },
        ]}
      />

      <div className="p-6 flex flex-col gap-6">
        <div className="flex items-start justify-between gap-4 flex-wrap">
          <div>
            <div className="flex items-center gap-2.5 mb-1">
              <h1 className="text-2xl font-bold text-foreground font-sans">Category Management</h1>
              <span
                className="flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-bold font-sans uppercase tracking-wider"
                style={{
                  background: "rgba(43,182,115,0.10)",
                  color: "var(--brand-green)",
                  border: "1px solid rgba(43,182,115,0.20)",
                }}
              >
                <LayoutGrid className="w-3 h-3" aria-hidden="true" />
                {listLoading ? "…" : total} Categories
              </span>
            </div>
            <p className="text-muted-foreground text-sm font-sans">
              Organize and manage article categories across the platform.
            </p>
          </div>
        </div>

        {listError && (
          <div
            role="alert"
            className="rounded-2xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800 font-sans flex items-center justify-between gap-4 flex-wrap"
          >
            <span>{listError}</span>
            <button
              type="button"
              onClick={() => void loadCategories()}
              className="rounded-xl border border-red-300 bg-white px-3 py-1.5 text-xs font-semibold text-red-900 hover:bg-red-50 cursor-pointer"
            >
              Retry
            </button>
          </div>
        )}

        <CategoryStatsBar
          total={total}
          visible={visible}
          hidden={hidden}
          withArticles={withArticles}
        />

        <div className="bg-card rounded-2xl border border-border overflow-hidden">
          <CategoryToolbar
            searchQuery={searchQuery}
            filterVisibility={filterVisibility}
            onSearchChange={(v) => {
              setSearchQuery(v)
              tableView.resetToFirstPage()
            }}
            onFilterChange={(v) => {
              setFilterVisibility(v)
              tableView.resetToFirstPage()
            }}
            onCreateClick={openCreate}
            viewControls={
              <DashboardTableViewControls
                sortOptions={tableView.sortOptions}
                sortKey={tableView.sortKey}
                onSortChange={tableView.setSortKey}
                pageSizeOptions={tableView.pageSizeOptions}
                itemsPerPage={tableView.itemsPerPage}
                onItemsPerPageChange={tableView.setItemsPerPage}
                viewAll={tableView.viewAll}
                onViewAllToggle={tableView.toggleViewAll}
                displayedCount={viewResult.displayedCount}
                totalCount={viewResult.totalItems}
                itemLabel="categories"
                viewAllCapped={viewResult.viewAllCapped}
                disabled={listLoading || !tableView.hydrated}
              />
            }
          />

          <CategoryTable
            categories={paginated}
            isLoading={listLoading}
            onEdit={openEdit}
            onDelete={openDelete}
            onToggleVisibility={toggleVisibility}
          />

          {!listLoading && !tableView.viewAll && viewResult.totalItems > 0 ? (
            <DashboardTablePagination
              currentPage={tableView.currentPage}
              totalPages={totalPages}
              totalItems={viewResult.totalItems}
              pageSize={tableView.itemsPerPage}
              itemLabel="categories"
              onPageChange={tableView.setCurrentPage}
            />
          ) : null}
        </div>
      </div>

      <CategoryFormModal
        open={formModalOpen}
        editCategory={editCategory}
        onClose={() => {
          setFormModalOpen(false)
          setEditCategory(null)
        }}
        onSubmit={handleFormSubmit}
      />

      <CategoryDeleteModal
        category={deleteTarget}
        isLoading={isDeleting}
        onClose={() => !isDeleting && setDeleteTarget(null)}
        onConfirm={handleDelete}
      />
    </>
  )
}
