import { useState } from 'react'
import { ArrowDown, ArrowUp, ChevronsUpDown } from 'lucide-react'
import { cn } from '@/shared/lib/cn'

type SortState = { key: string; desc: boolean }

/**
 * Состояние сортировки таблицы. Клик по новому столбцу — по возрастанию; повторный клик по тому же —
 * переключает направление. Для серверных списков `sort`/`desc` передаются в API (и в queryKey), для
 * клиентских — в {@link sortRows}.
 */
export function useTableSort(defaultKey: string, defaultDesc = false) {
  const [sort, setSort] = useState<SortState>({ key: defaultKey, desc: defaultDesc })
  const toggle = (key: string) =>
    setSort((s) => (s.key === key ? { key, desc: !s.desc } : { key, desc: false }))
  return { sort, toggle }
}

/** Заголовок-кнопка столбца со стрелкой сортировки. */
export function SortHeader({
  label,
  sortKey,
  sort,
  onToggle,
  className,
}: {
  label: string
  sortKey: string
  sort: SortState
  onToggle: (key: string) => void
  className?: string
}) {
  const active = sort.key === sortKey
  const Icon = !active ? ChevronsUpDown : sort.desc ? ArrowDown : ArrowUp
  return (
    // aria-sort — атрибут заголовка столбца, а не кнопки внутри него: у роли button его нет,
    // и скринридер там его просто не прочтёт.
    <th
      className={cn('px-4 py-2 font-medium', className)}
      aria-sort={active ? (sort.desc ? 'descending' : 'ascending') : 'none'}
    >
      <button
        type="button"
        onClick={() => onToggle(sortKey)}
        className={cn(
          'inline-flex items-center gap-1 hover:text-foreground',
          active && 'text-foreground',
        )}
      >
        {label}
        <Icon className={cn('h-3.5 w-3.5', !active && 'opacity-40')} />
      </button>
    </th>
  )
}

type Comparable = string | number | boolean | null | undefined

/** Клиентская сортировка строк по выбранному ключу (для непагинированных списков). nulls — в конец. */
export function sortRows<T>(
  rows: T[],
  sort: SortState,
  accessors: Record<string, (row: T) => Comparable>,
): T[] {
  const accessor = accessors[sort.key]
  if (!accessor) return rows
  const dir = sort.desc ? -1 : 1
  return [...rows].sort((a, b) => {
    const av = accessor(a)
    const bv = accessor(b)
    if (av == null && bv == null) return 0
    if (av == null) return 1
    if (bv == null) return -1
    if (typeof av === 'string' && typeof bv === 'string') return av.localeCompare(bv) * dir
    return (av < bv ? -1 : av > bv ? 1 : 0) * dir
  })
}
