/**
 * DashboardTable
 *
 * A standardized table component for dashboard use with consistent styling,
 * loading skeletons, and empty states.
 *
 * @example
 * // Basic usage
 * <DashboardTable
 *   columns={[
 *     { key: "name", header: "Name" },
 *     { key: "value", header: "Value", align: "right" },
 *   ]}
 *   data={items}
 * />
 *
 * @example
 * // With custom cell rendering
 * <DashboardTable
 *   columns={[
 *     { key: "name", header: "Name" },
 *     {
 *       key: "status",
 *       header: "Status",
 *       render: (value) => <StatusBadge status={value} />
 *     },
 *     {
 *       key: "amount",
 *       header: "Amount",
 *       align: "right",
 *       render: (value) => formatCurrency(value)
 *     },
 *   ]}
 *   data={orders}
 *   loading={isLoading}
 *   emptyMessage="No orders found"
 * />
 *
 * @example
 * // Scrollable with max height
 * <DashboardTable
 *   columns={columns}
 *   data={largeDataset}
 *   maxHeight="md"
 *   stickyHeader
 * />
 */

import React from "react";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";
import {
  TABLE_STYLES,
  SCROLL_STYLES,
  TYPOGRAPHY,
} from "@/lib/dashboard/designTokens";

// =============================================================================
// TYPES
// =============================================================================

export type CellAlignment = "left" | "center" | "right";

export interface TableColumn<T = Record<string, unknown>> {
  /** Unique key for the column (also used to access data) */
  key: string;
  /** Header text */
  header: string;
  /** Cell alignment */
  align?: CellAlignment;
  /** Width class (e.g., "w-24", "w-[100px]", "min-w-[200px]") */
  width?: string;
  /** Custom render function for cell content */
  render?: (value: unknown, row: T, rowIndex: number) => React.ReactNode;
  /** Whether this column should be hidden on mobile */
  hideOnMobile?: boolean;
  /** Additional className for cells in this column */
  className?: string;
  /** Whether to use tabular-nums for numeric values */
  numeric?: boolean;
  /** Whether this column is sortable */
  sortable?: boolean;
  /** Custom sort key if different from column key */
  sortKey?: string;
}

export type SortDirection = "asc" | "desc";

export interface SortConfig {
  key: string;
  direction: SortDirection;
}

export interface DashboardTableProps<T = Record<string, unknown>> {
  /** Column definitions */
  columns: TableColumn<T>[];
  /** Data rows */
  data: T[];
  /** Loading state - shows skeleton rows */
  loading?: boolean;
  /** Number of skeleton rows to show when loading */
  skeletonRows?: number;
  /** Message when data is empty */
  emptyMessage?: string;
  /** Icon for empty state (from lucide-react) */
  emptyIcon?: React.ReactNode;
  /** Row key accessor (defaults to index) */
  getRowKey?: (row: T, index: number) => string | number;
  /** Row click handler */
  onRowClick?: (row: T, index: number) => void;
  /** Max height with scroll */
  maxHeight?: "sm" | "md" | "lg" | "xl" | "none";
  /** Sticky header when scrolling */
  stickyHeader?: boolean;
  /** Striped rows */
  striped?: boolean;
  /** Compact padding */
  compact?: boolean;
  /** Show borders between cells */
  bordered?: boolean;
  /** Additional className for the table container */
  className?: string;
  /** Additional className for the table element */
  tableClassName?: string;
  /** Current sort configuration (for controlled sorting) */
  sortConfig?: SortConfig;
  /** Callback when a sortable column header is clicked */
  onSort?: (key: string, direction: SortDirection) => void;
}

// =============================================================================
// HELPERS
// =============================================================================

const ALIGNMENT_CLASSES: Record<CellAlignment, string> = {
  left: "text-left",
  center: "text-center",
  right: "text-right",
};

const MAX_HEIGHT_CLASSES = {
  sm: SCROLL_STYLES.sm,
  md: SCROLL_STYLES.md,
  lg: SCROLL_STYLES.lg,
  xl: SCROLL_STYLES.xl,
  none: "",
};

// =============================================================================
// MAIN COMPONENT
// =============================================================================

export function DashboardTable<T extends Record<string, unknown>>({
  columns,
  data,
  loading = false,
  skeletonRows = 5,
  emptyMessage = "No data available",
  emptyIcon,
  getRowKey,
  onRowClick,
  maxHeight = "none",
  stickyHeader = false,
  striped = false,
  compact = false,
  bordered = false,
  className,
  tableClassName,
  sortConfig,
  onSort,
}: DashboardTableProps<T>): React.ReactElement {
  const paddingClass = compact ? "px-3 py-2" : "px-4 py-3";
  const scrollClass = maxHeight !== "none" ? MAX_HEIGHT_CLASSES[maxHeight] : "";

  // Handle sort click - toggles direction or sets new sort key
  const handleSortClick = (col: TableColumn<T>) => {
    if (!onSort || !col.sortable) return;

    const sortKey = col.sortKey || col.key;
    const currentDirection = sortConfig?.key === sortKey ? sortConfig.direction : null;
    const newDirection: SortDirection = currentDirection === "desc" ? "asc" : "desc";

    onSort(sortKey, newDirection);
  };

  // Render header cell content - either plain text or sortable button
  const renderHeaderContent = (col: TableColumn<T>) => {
    if (!col.sortable || !onSort) {
      return col.header;
    }

    const sortKey = col.sortKey || col.key;
    const isActive = sortConfig?.key === sortKey;

    return (
      <Button
        variant={isActive ? "default" : "ghost"}
        size="sm"
        onClick={() => handleSortClick(col)}
        className={cn(
          "h-8 font-medium",
          col.align === "center" && "w-full justify-center",
          col.align === "right" && "w-full justify-end",
          col.align === "left" && "justify-start",
          !col.align && "justify-start"
        )}
      >
        {col.header}
      </Button>
    );
  };

  // Loading skeleton
  if (loading) {
    return (
      <div className={cn(scrollClass, className)}>
        <Table className={tableClassName}>
          <TableHeader>
            <TableRow className={cn(TABLE_STYLES.row, "hover:bg-transparent")}>
              {columns.map((col) => (
                <TableHead
                  key={col.key}
                  className={cn(
                    TABLE_STYLES.headerCell,
                    paddingClass,
                    ALIGNMENT_CLASSES[col.align || "left"],
                    col.width,
                    col.hideOnMobile && "hidden sm:table-cell"
                  )}
                >
                  <Skeleton className="h-4 w-16 bg-muted" />
                </TableHead>
              ))}
            </TableRow>
          </TableHeader>
          <TableBody>
            {Array.from({ length: skeletonRows }).map((_, rowIndex) => (
              <TableRow key={rowIndex} className={TABLE_STYLES.row}>
                {columns.map((col, colIndex) => (
                  <TableCell
                    key={col.key}
                    className={cn(
                      paddingClass,
                      col.hideOnMobile && "hidden sm:table-cell"
                    )}
                  >
                    <Skeleton
                      className={cn(
                        "h-4 bg-muted",
                        colIndex === 0 ? "w-32" : "w-20"
                      )}
                    />
                  </TableCell>
                ))}
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </div>
    );
  }

  // Empty state
  if (!data.length) {
    return (
      <div
        className={cn(
          "flex items-center justify-center py-12 text-muted-foreground",
          className
        )}
      >
        <div className="text-center">
          {emptyIcon && <div className="mb-3">{emptyIcon}</div>}
          <p className={TYPOGRAPHY.cardDescription}>{emptyMessage}</p>
        </div>
      </div>
    );
  }

  // Data table
  return (
    <div className={cn(scrollClass, className)}>
      <Table className={tableClassName}>
        <TableHeader className={stickyHeader ? "sticky top-0 bg-background z-10" : ""}>
          <TableRow className={cn(TABLE_STYLES.row, TABLE_STYLES.header, "hover:bg-transparent")}>
            {columns.map((col) => (
              <TableHead
                key={col.key}
                className={cn(
                  TABLE_STYLES.headerCell,
                  // Reduce padding when sortable since button has its own padding
                  col.sortable && onSort ? "p-1" : paddingClass,
                  ALIGNMENT_CLASSES[col.align || "left"],
                  col.width,
                  col.hideOnMobile && "hidden sm:table-cell"
                )}
              >
                {renderHeaderContent(col)}
              </TableHead>
            ))}
          </TableRow>
        </TableHeader>
        <TableBody>
          {data.map((row, rowIndex) => {
            const rowKey = getRowKey ? getRowKey(row, rowIndex) : rowIndex;

            return (
              <TableRow
                key={rowKey}
                className={cn(
                  TABLE_STYLES.row,
                  TABLE_STYLES.rowHover,
                  onRowClick && "cursor-pointer",
                  striped && rowIndex % 2 === 1 && "bg-muted/30",
                  bordered && "border-b border-border/50"
                )}
                onClick={onRowClick ? () => onRowClick(row, rowIndex) : undefined}
              >
                {columns.map((col) => {
                  const value = row[col.key];
                  const renderedValue = col.render
                    ? col.render(value, row, rowIndex)
                    : (value as React.ReactNode);

                  return (
                    <TableCell
                      key={col.key}
                      className={cn(
                        TABLE_STYLES.cell,
                        paddingClass,
                        ALIGNMENT_CLASSES[col.align || "left"],
                        col.numeric && "tabular-nums",
                        col.className,
                        col.hideOnMobile && "hidden sm:table-cell"
                      )}
                    >
                      {renderedValue}
                    </TableCell>
                  );
                })}
              </TableRow>
            );
          })}
        </TableBody>
      </Table>
    </div>
  );
}

// =============================================================================
// SIMPLE TABLE (for quick key-value displays)
// =============================================================================

export interface SimpleTableRow {
  label: string;
  value: React.ReactNode;
  className?: string;
}

export interface SimpleTableProps {
  rows: SimpleTableRow[];
  loading?: boolean;
  className?: string;
  labelWidth?: string;
}

export const SimpleTable: React.FC<SimpleTableProps> = ({
  rows,
  loading = false,
  className,
  labelWidth = "w-1/3",
}) => {
  if (loading) {
    return (
      <div className={cn("space-y-3", className)}>
        {Array.from({ length: 4 }).map((_, i) => (
          <div key={i} className="flex items-center justify-between py-1">
            <Skeleton className="h-4 w-24 bg-muted" />
            <Skeleton className="h-4 w-32 bg-muted" />
          </div>
        ))}
      </div>
    );
  }

  return (
    <div className={cn("divide-y divide-border/50", className)}>
      {rows.map((row, index) => (
        <div
          key={index}
          className={cn(
            "flex items-center justify-between py-2 first:pt-0 last:pb-0",
            row.className
          )}
        >
          <span className={cn("text-sm text-muted-foreground", labelWidth)}>
            {row.label}
          </span>
          <span className="text-sm font-medium text-foreground">{row.value}</span>
        </div>
      ))}
    </div>
  );
};

export default DashboardTable;
