import { cn } from '@/lib/utils';
import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/24/outline';
import {
  ColumnDef,
  flexRender,
  getCoreRowModel,
  getExpandedRowModel,
  getSortedRowModel,
  Row,
  SortingState,
  useReactTable,
} from '@tanstack/react-table';
import { useState, useRef } from 'react';
import { TableVirtuoso } from 'react-virtuoso';

// Tooltip wrapper for cells that might overflow
function CellWithTooltip({ children, className }: { children: React.ReactNode; className?: string }) {
  const [showTooltip, setShowTooltip] = useState(false);
  const [tooltipContent, setTooltipContent] = useState('');
  const cellRef = useRef<HTMLDivElement>(null);

  const handleMouseEnter = () => {
    const element = cellRef.current;
    if (element) {
      // Get the text content from the element or its children
      const textContent = element.textContent || '';
      setTooltipContent(textContent);
      
      // Check if content is overflowing by comparing scroll width to client width
      const isOverflowing = element.scrollWidth > element.clientWidth;
      if (isOverflowing && textContent.trim().length > 0) {
        setShowTooltip(true);
      }
    }
  };

  const handleMouseLeave = () => {
    setShowTooltip(false);
  };

  return (
    <div className="relative">
      <div
        ref={cellRef}
        className={className}
        onMouseEnter={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
      >
        {children}
      </div>
      {showTooltip && tooltipContent && (
        <div className="absolute z-50 px-2 py-1 bg-surface-secondary border border-border text-text-primary text-xs rounded shadow-lg whitespace-nowrap -top-8 left-0 pointer-events-none">
          {tooltipContent}
        </div>
      )}
    </div>
  );
}

interface DataTableProps<T> {
  data: T[];
  columns: ColumnDef<T>[];
  loading?: boolean;
  className?: string;
  getRowCanExpand?: (row: Row<T>) => boolean;
  renderSubComponent?: (props: { row: Row<T> }) => React.ReactElement;
  onRowClick?: (row: T) => void;
  height?: number;
}

export function DataTable<T>({
  data,
  columns,
  loading = false,
  className = '',
  getRowCanExpand,
  renderSubComponent,
  onRowClick,
  height,
}: DataTableProps<T>) {
  const [sorting, setSorting] = useState<SortingState>([]);

  const table = useReactTable({
    data,
    columns,
    state: {
      sorting,
    },
    onSortingChange: setSorting,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getExpandedRowModel: getExpandedRowModel(),
    getRowCanExpand,
    enableColumnResizing: true,
    columnResizeMode: 'onChange',
  });

  if (loading) {
    return (
      <div className="flex items-center justify-center h-64 bg-background border border-border rounded-lg">
        <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary-500"></div>
      </div>
    );
  }

  const { rows } = table.getRowModel();

  // For expanded rows, we need to create a flattened list
  const flatRows = rows.reduce<Array<{ type: 'row' | 'expanded'; row: Row<T> }>>((acc, row) => {
    acc.push({ type: 'row', row });
    if (row.getIsExpanded() && renderSubComponent) {
      acc.push({ type: 'expanded', row });
    }
    return acc;
  }, []);

  return (
    <TableVirtuoso
      style={{ height: height ? `${height}px` : '100%' }}
      className={cn('border border-border rounded-lg', className)}
      totalCount={flatRows.length}
      components={{
        Table: ({ style, ...props }) => (
          <table
            {...props}
            style={{
              ...style,
              width: '100%',
              tableLayout: 'fixed',
            }}
            className="bg-background"
          />
        ),
        TableRow: props => {
          const index = props['data-index'] as number;
          const item = flatRows[index];

          if (!item) {
            return null;
          }

          if (item.type === 'expanded') {
            return (
              <tr {...props} className="bg-surface-secondary/50">
                <td colSpan={item.row.getVisibleCells().length} className="p-0">
                  {renderSubComponent?.({ row: item.row })}
                </td>
              </tr>
            );
          }

          return (
            <tr
              {...props}
              className="hover:bg-surface border-b border-border cursor-pointer"
              onClick={() => onRowClick?.(item.row.original)}
            >
              {item.row.getVisibleCells().map(cell => (
                <td
                  key={cell.id}
                  className="px-3 py-2 text-sm text-text-primary"
                  style={{ 
                    width: `${cell.column.getSize()}px`,
                    minWidth: `${cell.column.getSize()}px`,
                    maxWidth: `${cell.column.getSize()}px`,
                  }}
                >
                  {(cell.column.columnDef as { disableTooltip?: boolean }).disableTooltip ? (
                    <div className="truncate overflow-hidden text-ellipsis whitespace-nowrap">
                      {flexRender(cell.column.columnDef.cell, cell.getContext())}
                    </div>
                  ) : (
                    <CellWithTooltip className="truncate overflow-hidden text-ellipsis whitespace-nowrap">
                      {flexRender(cell.column.columnDef.cell, cell.getContext())}
                    </CellWithTooltip>
                  )}
                </td>
              ))}
            </tr>
          );
        },
      }}
      fixedHeaderContent={() =>
        table.getHeaderGroups().map(headerGroup => (
          <tr key={headerGroup.id} className="bg-surface border-b border-border">
            {headerGroup.headers.map(header => (
              <th
                key={header.id}
                colSpan={header.colSpan}
                className={cn(
                  'relative px-3 py-2 text-xs font-medium text-text-secondary uppercase tracking-wider text-left',
                  header.column.getCanSort() && 'cursor-pointer select-none hover:text-text-primary'
                )}
                style={{ 
                  width: `${header.getSize()}px`,
                  minWidth: `${header.getSize()}px`,
                  maxWidth: `${header.getSize()}px`,
                }}
                onClick={header.column.getToggleSortingHandler()}
              >
                {header.isPlaceholder ? null : (
                  <>
                    <div className="flex items-center justify-between">
                      <span className="truncate">
                        {flexRender(header.column.columnDef.header, header.getContext())}
                      </span>
                      {header.column.getCanSort() && (
                        <div className="ml-2 flex-shrink-0">
                          {header.column.getIsSorted() === 'asc' ? (
                            <ChevronUpIcon className="h-4 w-4 text-primary-400" />
                          ) : header.column.getIsSorted() === 'desc' ? (
                            <ChevronDownIcon className="h-4 w-4 text-primary-400" />
                          ) : (
                            <div className="h-4 w-4" />
                          )}
                        </div>
                      )}
                    </div>
                    {/* Column resizer */}
                    {header.column.getCanResize() && (
                      <div
                        onMouseDown={header.getResizeHandler()}
                        onTouchStart={header.getResizeHandler()}
                        className={cn(
                          'absolute right-0 top-0 h-full w-1 cursor-col-resize user-select-none touch-none',
                          'hover:bg-primary-500 hover:opacity-100',
                          header.column.getIsResizing()
                            ? 'bg-primary-500 opacity-100'
                            : 'bg-border opacity-0'
                        )}
                      />
                    )}
                  </>
                )}
              </th>
            ))}
          </tr>
        ))
      }
    />
  );
}
