import * as React from "react";
import { SortAsc, SortDesc } from "lucide-react";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { cn } from "@/lib/utils";
import {
  DndContext,
  DragEndEvent,
  PointerSensor,
  TouchSensor,
  useSensor,
  useSensors,
  closestCenter,
} from "@dnd-kit/core";
import {
  SortableContext,
  arrayMove,
  horizontalListSortingStrategy,
  useSortable,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { ProductMetric, ProductMetricColumnKey } from "@/types/products";
import { Skeleton } from "@/components/ui/skeleton";
import { StatusBadge } from "@/components/products/StatusBadge";
import { ColumnDef } from "@/components/products/columnDefinitions";

interface ProductTableProps {
  products: ProductMetric[];
  onViewProduct: (id: number) => void;
  isLoading?: boolean;
  onColumnOrderChange?: (newOrder: ProductMetricColumnKey[]) => void;
  visibleColumns?: Set<ProductMetricColumnKey>;
  columnOrder?: ProductMetricColumnKey[];
  onSort: (column: ProductMetricColumnKey) => void;
  sortColumn: ProductMetricColumnKey;
  sortDirection: 'asc' | 'desc';
  columnDefs: ColumnDef[];
}

interface SortableHeaderProps {
  column: ProductMetricColumnKey;
  columnDef?: ColumnDef;
  onSort: (column: ProductMetricColumnKey) => void;
  sortColumn: ProductMetricColumnKey;
  sortDirection: 'asc' | 'desc';
}

function SortableHeader({ column, columnDef, onSort, sortColumn, sortDirection }: SortableHeaderProps) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: column });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
    zIndex: isDragging ? 10 : 1,
    position: 'relative' as const,
    touchAction: 'none' as const,
    width: columnDef?.width ? undefined : 'auto',
    minWidth: columnDef?.key === 'imageUrl' ? '60px' : '100px',
  };

  // Skip rendering content for 'noLabel' columns (like image)
  if (columnDef?.noLabel) {
    return (
      <TableHead
        ref={setNodeRef}
        style={style}
        className={cn(columnDef?.width, "select-none", "whitespace-nowrap")}
        {...attributes}
        {...listeners}
      />
    );
  }

  return (
    <TableHead
      ref={setNodeRef}
      style={style}
      className={cn(
        "cursor-pointer select-none group whitespace-nowrap",
        columnDef?.width,
        sortColumn === column && "bg-accent/50"
      )}
      {...attributes}
      {...listeners}
      onClick={() => onSort(column)}
    >
      <div className="flex items-center gap-1">
        {columnDef?.label ?? column}
        {sortColumn === column && (
          sortDirection === 'desc'
            ? <SortDesc className="h-4 w-4 min-w-4" />
            : <SortAsc className="h-4 w-4 min-w-4" />
        )}
      </div>
    </TableHead>
  );
}

export function ProductTable({
  products = [],
  onViewProduct,
  isLoading = false,
  onColumnOrderChange,
  visibleColumns = new Set<ProductMetricColumnKey>(),
  columnOrder = [],
  onSort,
  sortColumn,
  sortDirection,
  columnDefs,
}: ProductTableProps) {
  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: { distance: 5 },
    }),
    useSensor(TouchSensor, {
      activationConstraint: { delay: 250, tolerance: 5 },
    })
  );

  // Filter columnOrder to only include visible columns for SortableContext
  const orderedVisibleColumns = React.useMemo(() => {
    return columnOrder.filter(col => visibleColumns.has(col));
  }, [columnOrder, visibleColumns]);

  const handleDragEnd = (event: DragEndEvent) => {
    const { active, over } = event;

    if (over && active.id !== over.id && onColumnOrderChange) {
      const oldIndex = orderedVisibleColumns.indexOf(active.id as ProductMetricColumnKey);
      const newIndex = orderedVisibleColumns.indexOf(over.id as ProductMetricColumnKey);

      if (oldIndex !== -1 && newIndex !== -1) {
        const newVisibleOrder = arrayMove(orderedVisibleColumns, oldIndex, newIndex);
        onColumnOrderChange(newVisibleOrder);
      }
    }
  };

  // Pre-compute a Map for O(1) column def lookups instead of O(n) find() per cell
  const columnDefMap = React.useMemo(() => {
    return new Map(columnDefs.map(col => [col.key, col]));
  }, [columnDefs]);

  const formatColumnValue = (product: ProductMetric, columnKey: ProductMetricColumnKey): React.ReactNode => {
    const value = product[columnKey as keyof ProductMetric];
    const columnDef = columnDefMap.get(columnKey);

    // Use the format function from column definition if available
    if (columnDef?.format) {
      return columnDef.format(value, product);
    }

    // Special handling for status - proper React component instead of dangerouslySetInnerHTML
    if (columnKey === 'status') {
      return <StatusBadge status={value as string} />;
    }
    
    // Special handling for boolean values
    if (typeof value === 'boolean') {
      return value ? 'Yes' : 'No';
    }
    
    // Handle date strings consistently
    if (value && typeof value === 'string' && 
        (columnKey.toLowerCase().includes('date') || columnKey === 'replenishDate')) {
      try {
        return new Date(value).toLocaleDateString();
      } catch (e) {
        return String(value);
      }
    }
    
    if (value === null || value === undefined || value === '') {
      return '-';
    }

    // Fallback to string conversion
    return String(value);
  };

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <div className="border rounded-md relative">
        {isLoading && (
          <div className="absolute inset-0 bg-background/70 flex items-center justify-center z-20">
            <Skeleton className="h-8 w-32" />
          </div>
        )}
        <div className="overflow-x-auto">
          <Table className={cn(isLoading ? 'opacity-50' : '', "w-max min-w-full")}>
            <TableHeader className="sticky top-0 bg-background z-10">
              <TableRow>
                <SortableContext
                  items={orderedVisibleColumns}
                  strategy={horizontalListSortingStrategy}
                >
                  {orderedVisibleColumns.map((columnKey) => (
                    <SortableHeader
                      key={columnKey}
                      column={columnKey}
                      columnDef={columnDefMap.get(columnKey)}
                      onSort={onSort}
                      sortColumn={sortColumn}
                      sortDirection={sortDirection}
                    />
                  ))}
                </SortableContext>
              </TableRow>
            </TableHeader>
            <TableBody>
              {products.length === 0 && !isLoading ? (
                <TableRow>
                  <TableCell
                    colSpan={orderedVisibleColumns.length}
                    className="text-center py-8 text-muted-foreground"
                  >
                    No products found matching your criteria.
                  </TableCell>
                </TableRow>
              ) : (
                products.map((product) => (
                  <TableRow
                    key={product.pid}
                    onClick={() => onViewProduct(product.pid)}
                    className="cursor-pointer hover:bg-muted/50"
                    data-state={isLoading ? 'loading' : undefined}
                  >
                    {orderedVisibleColumns.map((columnKey) => {
                      const colDef = columnDefMap.get(columnKey);
                      return (
                        <TableCell 
                          key={`${product.pid}-${columnKey}`} 
                          className={cn(
                            colDef?.width,
                            "whitespace-nowrap",
                            columnKey === 'title' && "max-w-[300px] truncate"
                          )}
                        >
                          {columnKey === 'imageUrl' ? (
                            <div className="flex items-center justify-center h-12 w-[60px]">
                              {product.imageUrl ? (
                                <img
                                  src={product.imageUrl}
                                  alt={product.title || 'Product image'}
                                  className="max-h-full max-w-full object-contain bg-white p-0.5 border rounded"
                                  loading="lazy"
                                />
                              ) : (
                                <div className="h-10 w-10 bg-muted rounded flex items-center justify-center text-muted-foreground text-xs">No Image</div>
                              )}
                            </div>
                          ) : (
                            formatColumnValue(product, columnKey)
                          )}
                        </TableCell>
                      );
                    })}
                  </TableRow>
                ))
              )}
              {isLoading && products.length === 0 && Array.from({length: 10}).map((_, i) => (
                <TableRow key={`skel-${i}`}>
                  {orderedVisibleColumns.map(key => {
                    const colDef = columnDefMap.get(key);
                    return (
                      <TableCell 
                        key={`skel-${i}-${key}`} 
                        className={cn(colDef?.width, "whitespace-nowrap")}
                      >
                        <Skeleton className={`h-5 ${key==='imageUrl' ? 'w-10 h-10' : 'w-full'}`} />
                      </TableCell>
                    );
                  })}
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </div>
      </div>
    </DndContext>
  );
} 
