'use client'

import { useMemo, useState, type ReactNode } from 'react'

export type SortableColumn<T> = {
  key: string
  header: ReactNode
  /** Value used for sorting. Numbers sort numerically, strings alphabetically. */
  accessor: (row: T) => string | number | null | undefined
  /** Custom cell renderer. Defaults to accessor(row). */
  render?: (row: T) => ReactNode
  /** Right-align (also implies numeric formatting). */
  numeric?: boolean
  /** This column is not sortable. */
  noSort?: boolean
  /** Optional explicit width style. */
  width?: string
}

type Props<T> = {
  columns: SortableColumn<T>[]
  rows: T[]
  defaultSortKey?: string
  defaultDir?: 'asc' | 'desc'
  rowKey: (row: T) => string
  rowClassName?: (row: T) => string | undefined
  /** Rendered after each row's tr — useful for full-width sub-rows. */
  caption?: ReactNode
  /** Optional footer row. */
  footer?: ReactNode
  empty?: ReactNode
}

function compareValues(
  a: string | number | null | undefined,
  b: string | number | null | undefined,
): number {
  if (a == null && b == null) return 0
  if (a == null) return 1
  if (b == null) return -1
  if (typeof a === 'number' && typeof b === 'number') return a - b
  return String(a).localeCompare(String(b))
}

export function SortableTable<T>({
  columns,
  rows,
  defaultSortKey,
  defaultDir = 'desc',
  rowKey,
  rowClassName,
  footer,
  empty,
}: Props<T>) {
  const [sortKey, setSortKey] = useState<string | null>(defaultSortKey ?? null)
  const [sortDir, setSortDir] = useState<'asc' | 'desc'>(defaultDir)

  const sorted = useMemo(() => {
    if (!sortKey) return rows
    const col = columns.find((c) => c.key === sortKey)
    if (!col) return rows
    const copy = [...rows]
    copy.sort((a, b) => {
      const cmp = compareValues(col.accessor(a), col.accessor(b))
      return sortDir === 'asc' ? cmp : -cmp
    })
    return copy
  }, [rows, columns, sortKey, sortDir])

  function toggleSort(key: string) {
    if (sortKey === key) {
      setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))
    } else {
      setSortKey(key)
      setSortDir('desc')
    }
  }

  if (rows.length === 0 && empty) {
    return <div>{empty}</div>
  }

  return (
    <div className="table-wrap">
      <table className="data">
        <thead>
          <tr>
            {columns.map((c) => {
              const active = sortKey === c.key
              const indicator = active ? (sortDir === 'asc' ? ' ▲' : ' ▼') : ''
              return (
                <th
                  key={c.key}
                  className={c.numeric ? 'num' : undefined}
                  style={c.width ? { width: c.width } : undefined}
                >
                  {c.noSort ? (
                    c.header
                  ) : (
                    <button
                      type="button"
                      onClick={() => toggleSort(c.key)}
                      style={{
                        background: 'transparent',
                        color: active ? '#1a1a1a' : '#555',
                        border: 'none',
                        padding: 0,
                        font: 'inherit',
                        cursor: 'pointer',
                        textTransform: 'inherit',
                        letterSpacing: 'inherit',
                        textAlign: c.numeric ? 'right' : 'left',
                        width: '100%',
                        fontWeight: 'inherit',
                      }}
                    >
                      {c.header}
                      <span style={{ opacity: 0.6 }}>{indicator}</span>
                    </button>
                  )}
                </th>
              )
            })}
          </tr>
        </thead>
        <tbody>
          {sorted.map((row) => (
            <tr key={rowKey(row)} className={rowClassName?.(row)}>
              {columns.map((c) => (
                <td key={c.key} className={c.numeric ? 'num' : undefined}>
                  {c.render ? c.render(row) : (c.accessor(row) ?? '—')}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
        {footer}
      </table>
    </div>
  )
}
