import React, { forwardRef, useMemo, useCallback, useState, useEffect } from 'react';
import { clsx } from 'clsx';
import { Button, Input, Select } from '../../ui';
import { LoadingSpinner } from '../LoadingSpinner';
import { EmptyState } from '../EmptyState';
import type { SelectOption } from '../../ui';

export interface DataTableColumn<T = any> {
  /** ID único de la columna */
  id: string;
  /** Clave del campo en los datos */
  key: keyof T;
  /** Texto del header */
  header: string;
  /** Habilitar ordenamiento */
  sortable?: boolean;
  /** Habilitar filtrado */
  filterable?: boolean;
  /** Ancho de la columna */
  width?: string | number;
  /** Alineación del contenido */
  align?: 'left' | 'center' | 'right';
  /** Renderizado personalizado de celda */
  cell?: (value: any, row: T, index: number) => React.ReactNode;
  /** Renderizado personalizado de header */
  headerCell?: () => React.ReactNode;
  /** Función de formateo */
  format?: (value: any) => string;
  /** Tipo de columna para filtros */
  type?: 'text' | 'number' | 'date' | 'boolean' | 'select';
  /** Opciones para columnas de tipo select */
  selectOptions?: SelectOption[];
  /** Mínimo ancho de la columna */
  minWidth?: string | number;
  /** Máximo ancho de la columna */
  maxWidth?: string | number;
  /** Columna fija (sticky) */
  sticky?: 'left' | 'right';
  /** Ocultar columna en móviles */
  hideOnMobile?: boolean;
}

export interface DataTableFilter {
  column: string;
  value: any;
  operator?: 'equals' | 'contains' | 'startsWith' | 'endsWith' | 'gt' | 'gte' | 'lt' | 'lte';
}

export interface DataTableSort {
  column: string;
  direction: 'asc' | 'desc';
}

export interface DataTablePagination {
  page: number;
  pageSize: number;
  total: number;
}

export interface DataTableSelection<T = any> {
  mode: 'none' | 'single' | 'multiple';
  selectedRows: T[];
  onSelectionChange: (selectedRows: T[]) => void;
  getRowId?: (row: T) => string | number;
}

export interface DataTableProps<T = any> {
  /** Datos de la tabla */
  data: T[];
  /** Definición de columnas */
  columns: DataTableColumn<T>[];
  /** Estado de carga */
  isLoading?: boolean;
  /** Error */
  error?: string | null;
  /** Configuración de paginación */
  pagination?: DataTablePagination;
  /** Callback para cambio de página */
  onPageChange?: (page: number, pageSize: number) => void;
  /** Configuración de ordenamiento */
  sorting?: DataTableSort;
  /** Callback para cambio de ordenamiento */
  onSortChange?: (sort: DataTableSort) => void;
  /** Filtros aplicados */
  filters?: DataTableFilter[];
  /** Callback para cambio de filtros */
  onFiltersChange?: (filters: DataTableFilter[]) => void;
  /** Configuración de selección */
  selection?: DataTableSelection<T>;
  /** Filas expandibles */
  expandable?: {
    renderExpandedRow: (row: T, index: number) => React.ReactNode;
    isExpanded?: (row: T) => boolean;
    onToggleExpanded?: (row: T) => void;
  };
  /** Habilitar exportación */
  enableExport?: boolean;
  /** Callback para exportación */
  onExport?: (format: 'csv' | 'xlsx') => void;
  /** Texto de búsqueda global */
  searchQuery?: string;
  /** Callback para búsqueda */
  onSearchChange?: (query: string) => void;
  /** Placeholder de búsqueda */
  searchPlaceholder?: string;
  /** Mensaje de estado vacío personalizado */
  emptyStateMessage?: string;
  /** Acción de estado vacío */
  emptyStateAction?: {
    label: string;
    onClick: () => void;
  };
  /** Altura fija de la tabla */
  height?: string | number;
  /** Habilitar scroll horizontal */
  horizontalScroll?: boolean;
  /** Densidad de filas */
  density?: 'compact' | 'normal' | 'comfortable';
  /** Clase CSS adicional */
  className?: string;
  /** Callback para click en fila */
  onRowClick?: (row: T, index: number) => void;
  /** Callback para doble click en fila */
  onRowDoubleClick?: (row: T, index: number) => void;
  /** Función para obtener clases CSS de fila */
  getRowClassName?: (row: T, index: number) => string;
  /** Mostrar números de fila */
  showRowNumbers?: boolean;
  /** Nombre de la tabla para accesibilidad */
  'aria-label'?: string;
}

const DataTable = forwardRef<HTMLDivElement, DataTableProps>(({
  data,
  columns,
  isLoading = false,
  error = null,
  pagination,
  onPageChange,
  sorting,
  onSortChange,
  filters = [],
  onFiltersChange,
  selection,
  expandable,
  enableExport = false,
  onExport,
  searchQuery = '',
  onSearchChange,
  searchPlaceholder = 'Buscar...',
  emptyStateMessage,
  emptyStateAction,
  height,
  horizontalScroll = true,
  density = 'normal',
  className,
  onRowClick,
  onRowDoubleClick,
  getRowClassName,
  showRowNumbers = false,
  'aria-label': ariaLabel = 'Tabla de datos',
  ...props
}, ref) => {
  const [localFilters, setLocalFilters] = useState<Record<string, any>>({});
  const [expandedRows, setExpandedRows] = useState<Set<string | number>>(new Set());

  // Densidad de filas
  const densityClasses = {
    compact: 'py-1 px-2 text-sm',
    normal: 'py-2 px-3 text-sm',
    comfortable: 'py-3 px-4 text-base'
  };

  // Manejo de selección
  const handleSelectAll = useCallback(() => {
    if (!selection || selection.mode !== 'multiple') return;
    
    const allSelected = data.every(row => 
      selection.selectedRows.some(selectedRow => {
        const getId = selection.getRowId || ((r: any) => r.id);
        return getId(row) === getId(selectedRow);
      })
    );

    if (allSelected) {
      selection.onSelectionChange([]);
    } else {
      selection.onSelectionChange([...data]);
    }
  }, [data, selection]);

  const handleRowSelection = useCallback((row: any, checked: boolean) => {
    if (!selection) return;
    
    const getId = selection.getRowId || ((r: any) => r.id);
    const rowId = getId(row);
    
    if (selection.mode === 'single') {
      selection.onSelectionChange(checked ? [row] : []);
    } else if (selection.mode === 'multiple') {
      const newSelection = checked 
        ? [...selection.selectedRows, row]
        : selection.selectedRows.filter(selectedRow => getId(selectedRow) !== rowId);
      selection.onSelectionChange(newSelection);
    }
  }, [selection]);

  const isRowSelected = useCallback((row: any) => {
    if (!selection) return false;
    const getId = selection.getRowId || ((r: any) => r.id);
    return selection.selectedRows.some(selectedRow => getId(selectedRow) === getId(row));
  }, [selection]);

  // Manejo de expansión
  const handleRowExpansion = useCallback((row: any) => {
    if (!expandable) return;
    
    const getId = selection?.getRowId || ((r: any) => r.id);
    const rowId = getId(row);
    
    if (expandable.onToggleExpanded) {
      expandable.onToggleExpanded(row);
    } else {
      setExpandedRows(prev => {
        const newExpanded = new Set(prev);
        if (newExpanded.has(rowId)) {
          newExpanded.delete(rowId);
        } else {
          newExpanded.add(rowId);
        }
        return newExpanded;
      });
    }
  }, [expandable, selection?.getRowId]);

  const isRowExpanded = useCallback((row: any) => {
    if (!expandable) return false;
    
    if (expandable.isExpanded) {
      return expandable.isExpanded(row);
    }
    
    const getId = selection?.getRowId || ((r: any) => r.id);
    return expandedRows.has(getId(row));
  }, [expandable, expandedRows, selection?.getRowId]);

  // Manejo de ordenamiento
  const handleSort = useCallback((columnId: string) => {
    if (!onSortChange) return;
    
    const newDirection = sorting?.column === columnId && sorting.direction === 'asc' ? 'desc' : 'asc';
    onSortChange({ column: columnId, direction: newDirection });
  }, [sorting, onSortChange]);

  // Renderizado de iconos de ordenamiento
  const renderSortIcon = (column: DataTableColumn) => {
    if (!column.sortable) return null;
    
    const isActive = sorting?.column === column.id;
    const direction = sorting?.direction;
    
    return (
      <span className="ml-1 inline-flex flex-col">
        <svg 
          className={clsx('w-3 h-3', {
            'text-color-primary': isActive && direction === 'asc',
            'text-text-tertiary': !isActive || direction !== 'asc'
          })} 
          fill="currentColor" 
          viewBox="0 0 12 12"
        >
          <path d="M6 0L9 4H3L6 0Z"/>
        </svg>
        <svg 
          className={clsx('w-3 h-3 -mt-1', {
            'text-color-primary': isActive && direction === 'desc',
            'text-text-tertiary': !isActive || direction !== 'desc'
          })} 
          fill="currentColor" 
          viewBox="0 0 12 12"
        >
          <path d="M6 12L3 8H9L6 12Z"/>
        </svg>
      </span>
    );
  };

  // Estado de selección para checkbox "seleccionar todo"
  const allSelectedState = useMemo(() => {
    if (!selection || selection.mode !== 'multiple' || data.length === 0) {
      return { checked: false, indeterminate: false };
    }
    
    const selectedCount = data.filter(row => isRowSelected(row)).length;
    
    return {
      checked: selectedCount === data.length,
      indeterminate: selectedCount > 0 && selectedCount < data.length
    };
  }, [data, isRowSelected, selection]);

  // Renderizado de celda
  const renderCell = (column: DataTableColumn, row: any, rowIndex: number) => {
    const value = row[column.key];
    
    if (column.cell) {
      return column.cell(value, row, rowIndex);
    }
    
    if (column.format) {
      return column.format(value);
    }
    
    if (value == null) return '-';
    
    return String(value);
  };

  // Manejo de exportación
  const handleExport = (format: 'csv' | 'xlsx') => {
    if (onExport) {
      onExport(format);
    }
  };

  if (error) {
    return (
      <EmptyState
        variant="error"
        title="Error al cargar datos"
        description={error}
        primaryAction={{
          label: 'Reintentar',
          onClick: () => window.location.reload()
        }}
      />
    );
  }

  return (
    <div ref={ref} className={clsx('flex flex-col', className)} {...props}>
      {/* Header con controles */}
      <div className="flex flex-col sm:flex-row gap-4 mb-4">
        {/* Búsqueda */}
        {onSearchChange && (
          <div className="flex-1">
            <Input
              type="text"
              placeholder={searchPlaceholder}
              value={searchQuery}
              onChange={(e) => onSearchChange(e.target.value)}
              leftIcon={
                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
                </svg>
              }
            />
          </div>
        )}

        {/* Controles de exportación */}
        {enableExport && onExport && (
          <div className="flex gap-2">
            <Button
              variant="outline"
              size="sm"
              onClick={() => handleExport('csv')}
              leftIcon={
                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 10v6m0 0l-3-3m3 3l3-3M3 17V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
                </svg>
              }
            >
              Exportar CSV
            </Button>
            <Button
              variant="outline"
              size="sm"
              onClick={() => handleExport('xlsx')}
              leftIcon={
                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 10v6m0 0l-3-3m3 3l3-3M3 17V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
                </svg>
              }
            >
              Exportar Excel
            </Button>
          </div>
        )}
      </div>

      {/* Información de selección */}
      {selection && selection.selectedRows.length > 0 && (
        <div className="bg-color-primary/10 border border-color-primary/20 rounded-lg p-3 mb-4">
          <span className="text-color-primary text-sm font-medium">
            {selection.selectedRows.length} {selection.selectedRows.length === 1 ? 'fila seleccionada' : 'filas seleccionadas'}
          </span>
        </div>
      )}

      {/* Contenedor de tabla */}
      <div 
        className={clsx(
          'relative border border-border-primary rounded-lg overflow-hidden',
          {
            'overflow-x-auto': horizontalScroll
          }
        )}
        style={{ height }}
      >
        {/* Loading overlay */}
        {isLoading && (
          <div className="absolute inset-0 bg-bg-primary/80 backdrop-blur-sm z-10 flex items-center justify-center">
            <LoadingSpinner size="lg" text="Cargando datos..." />
          </div>
        )}

        {/* Tabla */}
        <table 
          className="w-full border-collapse bg-bg-primary"
          role="table"
          aria-label={ariaLabel}
        >
          {/* Header */}
          <thead className="bg-bg-secondary sticky top-0 z-20">
            <tr>
              {/* Checkbox de selección múltiple */}
              {selection && selection.mode === 'multiple' && (
                <th className={clsx('border-b border-border-primary', densityClasses[density])}>
                  <input
                    type="checkbox"
                    checked={allSelectedState.checked}
                    ref={(input) => {
                      if (input) input.indeterminate = allSelectedState.indeterminate;
                    }}
                    onChange={handleSelectAll}
                    className="rounded border-border-secondary focus:ring-color-primary"
                    aria-label="Seleccionar todas las filas"
                  />
                </th>
              )}

              {/* Números de fila */}
              {showRowNumbers && (
                <th className={clsx('border-b border-border-primary text-left font-medium text-text-secondary', densityClasses[density])}>
                  #
                </th>
              )}

              {/* Columnas de expansión */}
              {expandable && (
                <th className={clsx('border-b border-border-primary', densityClasses[density])}>
                  <span className="sr-only">Expandir</span>
                </th>
              )}

              {/* Columnas de datos */}
              {columns.map((column) => {
                const alignClass = column.align === 'center' ? 'text-center' : column.align === 'right' ? 'text-right' : 'text-left';
                
                return (
                  <th
                    key={column.id}
                    className={clsx(
                      'border-b border-border-primary font-medium text-text-secondary',
                      densityClasses[density],
                      alignClass,
                      {
                        'cursor-pointer hover:bg-bg-tertiary': column.sortable,
                        'hidden sm:table-cell': column.hideOnMobile,
                        'sticky bg-bg-secondary': column.sticky,
                        'left-0': column.sticky === 'left',
                        'right-0': column.sticky === 'right'
                      }
                    )}
                    style={{
                      width: column.width,
                      minWidth: column.minWidth,
                      maxWidth: column.maxWidth
                    }}
                    onClick={() => column.sortable && handleSort(column.id)}
                    role={column.sortable ? 'button' : undefined}
                    aria-sort={
                      sorting?.column === column.id
                        ? sorting.direction === 'asc'
                          ? 'ascending'
                          : 'descending'
                        : undefined
                    }
                  >
                    {column.headerCell ? column.headerCell() : (
                      <div className="flex items-center">
                        {column.header}
                        {renderSortIcon(column)}
                      </div>
                    )}
                  </th>
                );
              })}
            </tr>
          </thead>

          {/* Body */}
          <tbody className="bg-bg-primary">
            {data.length === 0 && !isLoading ? (
              <tr>
                <td colSpan={columns.length + (selection ? 1 : 0) + (showRowNumbers ? 1 : 0) + (expandable ? 1 : 0)} className="p-8 bg-bg-primary">
                  <EmptyState
                    variant="no-data"
                    size="sm"
                    title={emptyStateMessage || 'No hay datos'}
                    description="No se encontraron registros para mostrar"
                    primaryAction={emptyStateAction}
                  />
                </td>
              </tr>
            ) : (
              data.map((row, rowIndex) => {
                const getId = selection?.getRowId || ((r: any) => r.id || rowIndex);
                const rowId = getId(row);
                const isSelected = isRowSelected(row);
                const isExpanded = isRowExpanded(row);
                
                return (
                  <React.Fragment key={rowId}>
                    <tr
                      className={clsx(
                        'border-b border-border-primary hover:bg-bg-secondary transition-colors bg-bg-primary',
                        {
                          'bg-color-primary/5': isSelected,
                          'cursor-pointer': onRowClick
                        },
                        getRowClassName?.(row, rowIndex)
                      )}
                      onClick={() => onRowClick?.(row, rowIndex)}
                      onDoubleClick={() => onRowDoubleClick?.(row, rowIndex)}
                    >
                      {/* Checkbox de selección */}
                      {selection && (
                        <td className={clsx('border-r border-border-primary bg-bg-primary', densityClasses[density])}>
                          <input
                            type={selection.mode === 'single' ? 'radio' : 'checkbox'}
                            checked={isSelected}
                            onChange={(e) => handleRowSelection(row, e.target.checked)}
                            onClick={(e) => e.stopPropagation()}
                            className="rounded border-border-secondary focus:ring-color-primary"
                            aria-label={`Seleccionar fila ${rowIndex + 1}`}
                          />
                        </td>
                      )}

                      {/* Número de fila */}
                      {showRowNumbers && (
                        <td className={clsx('border-r border-border-primary text-text-tertiary font-mono bg-bg-primary', densityClasses[density])}>
                          {rowIndex + 1}
                        </td>
                      )}

                      {/* Botón de expansión */}
                      {expandable && (
                        <td className={clsx('border-r border-border-primary bg-bg-primary', densityClasses[density])}>
                          <Button
                            variant="ghost"
                            size="xs"
                            onClick={(e) => {
                              e.stopPropagation();
                              handleRowExpansion(row);
                            }}
                            aria-label={`${isExpanded ? 'Contraer' : 'Expandir'} fila`}
                          >
                            <svg 
                              className={clsx('w-4 h-4 transition-transform', {
                                'rotate-90': isExpanded
                              })}
                              fill="none" 
                              stroke="currentColor" 
                              viewBox="0 0 24 24"
                            >
                              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
                            </svg>
                          </Button>
                        </td>
                      )}

                      {/* Celdas de datos */}
                      {columns.map((column) => {
                        const alignClass = column.align === 'center' ? 'text-center' : column.align === 'right' ? 'text-right' : 'text-left';
                        
                        return (
                          <td
                            key={column.id}
                            className={clsx(
                              densityClasses[density],
                              alignClass,
                              'bg-bg-primary',
                              {
                                'hidden sm:table-cell': column.hideOnMobile,
                                'sticky bg-bg-primary': column.sticky,
                                'left-0': column.sticky === 'left',
                                'right-0': column.sticky === 'right'
                              }
                            )}
                            style={{
                              width: column.width,
                              minWidth: column.minWidth,
                              maxWidth: column.maxWidth
                            }}
                          >
                            {renderCell(column, row, rowIndex)}
                          </td>
                        );
                      })}
                    </tr>

                    {/* Fila expandida */}
                    {expandable && isExpanded && (
                      <tr>
                        <td 
                          colSpan={columns.length + (selection ? 1 : 0) + (showRowNumbers ? 1 : 0) + 1}
                          className="p-0 border-b border-border-primary bg-bg-primary"
                        >
                          <div className="bg-bg-secondary p-4">
                            {expandable.renderExpandedRow(row, rowIndex)}
                          </div>
                        </td>
                      </tr>
                    )}
                  </React.Fragment>
                );
              })
            )}
          </tbody>
        </table>
      </div>

      {/* Paginación */}
      {pagination && pagination.total > 0 && onPageChange && (
        <div className="flex items-center justify-between mt-4 pt-4 border-t border-border-primary">
          <div className="text-sm text-text-secondary">
            Mostrando {((pagination.page - 1) * pagination.pageSize) + 1} a {Math.min(pagination.page * pagination.pageSize, pagination.total)} de {pagination.total} resultados
          </div>
          
          <div className="flex items-center gap-2">
            <Button
              variant="outline"
              size="sm"
              onClick={() => onPageChange(pagination.page - 1, pagination.pageSize)}
              disabled={pagination.page <= 1}
              leftIcon={
                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
                </svg>
              }
            >
              Anterior
            </Button>
            
            <span className="px-3 py-1 text-sm">
              Página {pagination.page} de {Math.ceil(pagination.total / pagination.pageSize)}
            </span>
            
            <Button
              variant="outline"
              size="sm"
              onClick={() => onPageChange(pagination.page + 1, pagination.pageSize)}
              disabled={pagination.page >= Math.ceil(pagination.total / pagination.pageSize)}
              rightIcon={
                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
                </svg>
              }
            >
              Siguiente
            </Button>
          </div>
        </div>
      )}
    </div>
  );
});

DataTable.displayName = 'DataTable';

export default DataTable;