"use client"

import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import {
  DEFAULT_PAGE_SIZE_OPTIONS,
  getDashboardTotalPages,
  readPersistedTableView,
  sliceDashboardItems,
  sortDashboardItems,
  writePersistedTableView,
  type DashboardTableSliceResult,
  type DashboardTableViewPersistedState,
} from "@/lib/dashboard-table-view"

export interface DashboardTableSortOption {
  value: string
  label: string
}

export interface UseDashboardTableViewControlsOptions<T> {
  /** Unique id for sessionStorage (e.g. "procedures-table") */
  tableId: string
  defaultSortKey: string
  defaultItemsPerPage?: number
  sortOptions: DashboardTableSortOption[]
  comparators: Record<string, (a: T, b: T) => number>
  pageSizeOptions?: readonly number[]
}

export function useDashboardTableViewControls<T>({
  tableId,
  defaultSortKey,
  defaultItemsPerPage = 6,
  sortOptions,
  comparators,
  pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS,
}: UseDashboardTableViewControlsOptions<T>) {
  // Stable keys so Set/useEffect deps are not invalidated by a new sortOptions array reference each render.
  const sortKeysKey = useMemo(() => sortOptions.map((o) => o.value).join(","), [sortOptions])
  const pageSizesKey = useMemo(() => pageSizeOptions.join(","), [pageSizeOptions])

  const validSortKeys = useMemo(() => new Set(sortKeysKey.split(",").filter(Boolean)), [sortKeysKey])
  const validPageSizes = useMemo(
    () => new Set(pageSizesKey.split(",").map(Number).filter((n) => n > 0)),
    [pageSizesKey],
  )

  const defaults: DashboardTableViewPersistedState = useMemo(
    () => ({
      sortKey: defaultSortKey,
      itemsPerPage: defaultItemsPerPage,
      viewAll: false,
      currentPage: 1,
    }),
    [defaultSortKey, defaultItemsPerPage],
  )

  const [hydrated, setHydrated] = useState(false)
  const [sortKey, setSortKeyState] = useState(defaultSortKey)
  const [itemsPerPage, setItemsPerPageState] = useState(defaultItemsPerPage)
  const [viewAll, setViewAllState] = useState(false)
  const [currentPage, setCurrentPageState] = useState(1)

  const skipPersistRef = useRef(true)
  const hydratedForTableRef = useRef<string | null>(null)

  useEffect(() => {
    if (hydratedForTableRef.current === tableId) return
    hydratedForTableRef.current = tableId
    skipPersistRef.current = true

    const persisted = readPersistedTableView(tableId, defaults)
    setSortKeyState(validSortKeys.has(persisted.sortKey) ? persisted.sortKey : defaults.sortKey)
    setItemsPerPageState(
      validPageSizes.has(persisted.itemsPerPage) ? persisted.itemsPerPage : defaults.itemsPerPage,
    )
    setViewAllState(persisted.viewAll)
    setCurrentPageState(persisted.currentPage)
    setHydrated(true)
    skipPersistRef.current = false
  }, [tableId, defaults, sortKeysKey, pageSizesKey])

  useEffect(() => {
    if (!hydrated || skipPersistRef.current) return
    writePersistedTableView(tableId, {
      sortKey,
      itemsPerPage,
      viewAll,
      currentPage,
    })
  }, [hydrated, tableId, sortKey, itemsPerPage, viewAll, currentPage])

  const setSortKey = useCallback(
    (key: string) => {
      if (!validSortKeys.has(key)) return
      setSortKeyState(key)
      setCurrentPageState(1)
    },
    [validSortKeys],
  )

  const setItemsPerPage = useCallback(
    (size: number) => {
      if (!validPageSizes.has(size)) return
      setItemsPerPageState(size)
      setViewAllState(false)
      setCurrentPageState(1)
    },
    [validPageSizes],
  )

  const setCurrentPage = useCallback((page: number) => {
    setCurrentPageState(Math.max(1, page))
  }, [])

  const toggleViewAll = useCallback(() => {
    setViewAllState((prev) => {
      const next = !prev
      if (next) setCurrentPageState(1)
      return next
    })
  }, [])

  const resetToFirstPage = useCallback(() => {
    setCurrentPageState(1)
  }, [])

  const applyView = useCallback(
    (items: T[]): DashboardTableSliceResult<T> & { sorted: T[]; totalPages: number } => {
      const sorted = sortDashboardItems(items, sortKey, comparators)
      const totalPages = viewAll
        ? 1
        : getDashboardTotalPages(sorted.length, itemsPerPage)

      const safePage = viewAll ? 1 : Math.min(currentPage, totalPages)

      const slice = sliceDashboardItems(sorted, {
        currentPage: safePage,
        itemsPerPage,
        viewAll,
      })

      return {
        ...slice,
        sorted,
        totalPages,
      }
    },
    [sortKey, comparators, itemsPerPage, viewAll, currentPage],
  )

  return {
    hydrated,
    sortKey,
    setSortKey,
    sortOptions,
    itemsPerPage,
    setItemsPerPage,
    pageSizeOptions,
    viewAll,
    toggleViewAll,
    currentPage,
    setCurrentPage,
    resetToFirstPage,
    applyView,
  }
}
