import { ReactNode, useState, useMemo } from 'react'
import {
  ChevronUpIcon,
  ChevronDownIcon,
  ChevronLeftIcon,
  ChevronRightIcon,
} from '@heroicons/react/20/solid'
import clsx from 'clsx'

// Types
export interface Column<T> {
  key: string
  header: string
  width?: string
  sortable?: boolean
  render?: (item: T, index: number) => ReactNode
  align?: 'left' | 'center' | 'right'
}

export interface TableProps<T> {
  data: T[]
  columns: Column<T>[]
  keyExtractor: (item: T) => string
  onRowClick?: (item: T) => void
  selectedKey?: string
  emptyMessage?: string
  isLoading?: boolean
  loadingRows?: number

  // Sorting
  sortable?: boolean
  defaultSortKey?: string
  defaultSortOrder?: 'asc' | 'desc'
  onSort?: (key: string, order: 'asc' | 'desc') => void

  // Pagination
  pagination?: boolean
  pageSize?: number
  currentPage?: number
  totalItems?: number
  onPageChange?: (page: number) => void

  // Styling
  compact?: boolean
  striped?: boolean
  hoverable?: boolean
  stickyHeader?: boolean
}

export default function Table<T>({
  data,
  columns,
  keyExtractor,
  onRowClick,
  selectedKey,
  emptyMessage = 'No hay datos disponibles',
  isLoading = false,
  loadingRows = 5,
  sortable = true,
  defaultSortKey,
  defaultSortOrder = 'asc',
  onSort,
  pagination = false,
  pageSize = 10,
  currentPage: controlledPage,
  totalItems,
  onPageChange,
  compact = false,
  striped = false,
  hoverable = true,
  stickyHeader = false,
}: TableProps<T>) {
  const [sortKey, setSortKey] = useState(defaultSortKey)
  const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>(defaultSortOrder)
  const [internalPage, setInternalPage] = useState(1)

  const currentPage = controlledPage ?? internalPage
  const setCurrentPage = onPageChange ?? setInternalPage

  // Handle sorting
  const handleSort = (key: string) => {
    const newOrder = sortKey === key && sortOrder === 'asc' ? 'desc' : 'asc'
    setSortKey(key)
    setSortOrder(newOrder)
    onSort?.(key, newOrder)
  }

  // Sort data locally if no external handler
  const sortedData = useMemo(() => {
    if (!sortKey || onSort) return data

    return [...data].sort((a, b) => {
      const aVal = (a as Record<string, unknown>)[sortKey]
      const bVal = (b as Record<string, unknown>)[sortKey]

      if (aVal === bVal) return 0
      if (aVal === null || aVal === undefined) return 1
      if (bVal === null || bVal === undefined) return -1

      const comparison = aVal < bVal ? -1 : 1
      return sortOrder === 'asc' ? comparison : -comparison
    })
  }, [data, sortKey, sortOrder, onSort])

  // Pagination
  const total = totalItems ?? sortedData.length
  const totalPages = Math.ceil(total / pageSize)

  const paginatedData = useMemo(() => {
    if (!pagination || onPageChange) return sortedData
    const start = (currentPage - 1) * pageSize
    return sortedData.slice(start, start + pageSize)
  }, [sortedData, pagination, currentPage, pageSize, onPageChange])

  // Cell padding based on compact mode
  const cellPadding = compact ? 'px-3 py-2' : 'px-4 py-3'

  return (
    <div className="w-full">
      <div className="overflow-x-auto rounded-lg border border-slate-700/50">
        <table className="min-w-full divide-y divide-slate-700/50">
          {/* Header */}
          <thead
            className={clsx(
              'bg-slate-800/50',
              stickyHeader && 'sticky top-0 z-10'
            )}
          >
            <tr>
              {columns.map((column) => (
                <th
                  key={column.key}
                  className={clsx(
                    cellPadding,
                    'text-xs font-semibold text-slate-400 uppercase tracking-wider',
                    'text-left',
                    column.align === 'center' && 'text-center',
                    column.align === 'right' && 'text-right',
                    column.sortable !== false && sortable && 'cursor-pointer hover:text-white',
                    column.width
                  )}
                  style={{ width: column.width }}
                  onClick={() =>
                    column.sortable !== false &&
                    sortable &&
                    handleSort(column.key)
                  }
                >
                  <div className="flex items-center gap-1">
                    <span>{column.header}</span>
                    {column.sortable !== false && sortable && (
                      <span className="flex flex-col">
                        <ChevronUpIcon
                          className={clsx(
                            'w-3 h-3 -mb-1',
                            sortKey === column.key && sortOrder === 'asc'
                              ? 'text-accent-500'
                              : 'text-slate-600'
                          )}
                        />
                        <ChevronDownIcon
                          className={clsx(
                            'w-3 h-3 -mt-1',
                            sortKey === column.key && sortOrder === 'desc'
                              ? 'text-accent-500'
                              : 'text-slate-600'
                          )}
                        />
                      </span>
                    )}
                  </div>
                </th>
              ))}
            </tr>
          </thead>

          {/* Body */}
          <tbody className="divide-y divide-slate-700/30 bg-card">
            {isLoading ? (
              // Loading skeleton
              Array.from({ length: loadingRows }).map((_, i) => (
                <tr key={i}>
                  {columns.map((column) => (
                    <td key={column.key} className={cellPadding}>
                      <div className="h-4 bg-slate-700 rounded animate-shimmer" />
                    </td>
                  ))}
                </tr>
              ))
            ) : paginatedData.length === 0 ? (
              // Empty state
              <tr>
                <td
                  colSpan={columns.length}
                  className="px-4 py-12 text-center text-slate-500"
                >
                  {emptyMessage}
                </td>
              </tr>
            ) : (
              // Data rows
              paginatedData.map((item, index) => {
                const key = keyExtractor(item)
                const isSelected = selectedKey === key

                return (
                  <tr
                    key={key}
                    onClick={() => onRowClick?.(item)}
                    className={clsx(
                      'transition-colors duration-100',
                      striped && index % 2 === 1 && 'bg-slate-800/30',
                      hoverable && 'hover:bg-slate-700/30',
                      onRowClick && 'cursor-pointer',
                      isSelected && 'bg-accent-500/10 hover:bg-accent-500/20'
                    )}
                  >
                    {columns.map((column) => (
                      <td
                        key={column.key}
                        className={clsx(
                          cellPadding,
                          'text-sm text-slate-300',
                          column.align === 'center' && 'text-center',
                          column.align === 'right' && 'text-right'
                        )}
                      >
                        {column.render
                          ? column.render(item, index)
                          : String((item as Record<string, unknown>)[column.key] ?? '-')}
                      </td>
                    ))}
                  </tr>
                )
              })
            )}
          </tbody>
        </table>
      </div>

      {/* Pagination */}
      {pagination && totalPages > 1 && (
        <div className="flex items-center justify-between mt-4 px-2">
          <p className="text-sm text-slate-500">
            Mostrando {(currentPage - 1) * pageSize + 1} -{' '}
            {Math.min(currentPage * pageSize, total)} de {total}
          </p>

          <div className="flex items-center gap-2">
            <button
              type="button"
              onClick={() => setCurrentPage(currentPage - 1)}
              disabled={currentPage === 1}
              className={clsx(
                'p-2 rounded-lg transition-colors',
                'disabled:opacity-50 disabled:cursor-not-allowed',
                'hover:bg-slate-700 text-slate-400 hover:text-white'
              )}
            >
              <ChevronLeftIcon className="w-5 h-5" />
            </button>

            {/* Page numbers */}
            <div className="flex items-center gap-1">
              {Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
                let pageNum: number
                if (totalPages <= 5) {
                  pageNum = i + 1
                } else if (currentPage <= 3) {
                  pageNum = i + 1
                } else if (currentPage >= totalPages - 2) {
                  pageNum = totalPages - 4 + i
                } else {
                  pageNum = currentPage - 2 + i
                }

                return (
                  <button
                    key={pageNum}
                    type="button"
                    onClick={() => setCurrentPage(pageNum)}
                    className={clsx(
                      'w-8 h-8 rounded-lg text-sm font-medium transition-colors',
                      currentPage === pageNum
                        ? 'bg-accent-500 text-white'
                        : 'text-slate-400 hover:bg-slate-700 hover:text-white'
                    )}
                  >
                    {pageNum}
                  </button>
                )
              })}
            </div>

            <button
              type="button"
              onClick={() => setCurrentPage(currentPage + 1)}
              disabled={currentPage === totalPages}
              className={clsx(
                'p-2 rounded-lg transition-colors',
                'disabled:opacity-50 disabled:cursor-not-allowed',
                'hover:bg-slate-700 text-slate-400 hover:text-white'
              )}
            >
              <ChevronRightIcon className="w-5 h-5" />
            </button>
          </div>
        </div>
      )}
    </div>
  )
}
