import type { ReactNode } from "react";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import TableSortLabel from "@mui/material/TableSortLabel";

export interface DataColumn<T> {
  key: string;
  header: string;
  align?: "left" | "right";
  /** Render the cell with the DM Mono numeric face. */
  mono?: boolean;
  /** Emphasize the cell (font-weight 500). */
  bold?: boolean;
  /** If set, the header becomes a clickable sort control (requires onSort). */
  sortKey?: string;
  /**
   * Fixed column width (number = px, string = any CSS width incl. "%"). When
   * ANY column sets a width the table switches to `table-layout: fixed`, so
   * columns keep a stable size regardless of cell content (e.g. while
   * filtering). Overflowing text is clipped with an ellipsis.
   */
  width?: number | string;
  render: (row: T) => ReactNode;
}

export interface DataTableProps<T> {
  columns: DataColumn<T>[];
  rows: T[];
  rowKey: (row: T) => string | number;
  rowInactive?: (row: T) => boolean;
  /** When set, each row is clickable and shows a pointer cursor. */
  onRowClick?: (row: T) => void;
  /** When it returns true, the row is tinted with the error palette (danger highlight). */
  rowDanger?: (row: T) => boolean;
  empty?: ReactNode;
  /** Server-sort wiring: active key (matches a column's sortKey), direction, handler. */
  sortBy?: string;
  sortDir?: "asc" | "desc";
  onSort?: (key: string) => void;
}

/** Dense, Soft-SaaS-styled data table. Styling only — never re-formats values. */
export default function DataTable<T>({
  columns,
  rows,
  rowKey,
  rowInactive,
  onRowClick,
  rowDanger,
  empty,
  sortBy,
  sortDir,
  onSort,
}: DataTableProps<T>) {
  if (import.meta.env.DEV && columns.some((c) => c.sortKey) && !onSort) {
    console.warn("DataTable: columns with sortKey require an onSort prop.");
  }
  if (rows.length === 0 && empty) return <>{empty}</>;
  // When any column declares a width, lock the table to fixed layout so column
  // widths come from the colgroup (stable) instead of from cell content (which
  // jumps as rows are filtered). Tables that set no widths keep auto layout.
  const hasWidths = columns.some((c) => c.width != null);
  const colWidth = (w: number | string | undefined) =>
    w == null ? undefined : typeof w === "number" ? `${w}px` : w;
  return (
    <TableContainer sx={{ borderRadius: 2, overflowX: "auto" }}>
      <Table
        size="small"
        sx={{
          ...(hasWidths ? { tableLayout: "fixed", minWidth: 720 } : {}),
          "& td, & th": { borderColor: "divider" },
        }}
      >
        {hasWidths && (
          <colgroup>
            {columns.map((c) => (
              <col key={c.key} style={{ width: colWidth(c.width) }} />
            ))}
          </colgroup>
        )}
        <TableHead>
          <TableRow>
            {columns.map((c) => (
              <TableCell
                key={c.key}
                align={c.align}
                sortDirection={
                  c.sortKey && sortBy === c.sortKey ? (sortDir ?? "asc") : false
                }
                sx={{
                  textTransform: "uppercase",
                  letterSpacing: ".05em",
                  fontSize: ".64rem",
                  fontWeight: 700,
                  color: "text.secondary",
                }}
              >
                {c.sortKey && onSort ? (
                  <TableSortLabel
                    active={sortBy === c.sortKey}
                    direction={
                      sortBy === c.sortKey ? (sortDir ?? "asc") : "asc"
                    }
                    onClick={() => onSort(c.sortKey!)}
                  >
                    {c.header}
                  </TableSortLabel>
                ) : (
                  c.header
                )}
              </TableCell>
            ))}
          </TableRow>
        </TableHead>
        <TableBody>
          {rows.map((row) => (
            <TableRow
              key={rowKey(row)}
              hover
              onClick={onRowClick ? () => onRowClick(row) : undefined}
              sx={[
                onRowClick ? { cursor: "pointer" } : {},
                rowDanger?.(row)
                  ? {
                      bgcolor: "error.light",
                      opacity: 0.88,
                      "&:hover": {
                        bgcolor: "error.light",
                        filter: "brightness(0.97)",
                      },
                    }
                  : {},
                rowInactive?.(row) ? { opacity: 0.55 } : {},
              ]}
            >
              {columns.map((c) => (
                <TableCell
                  key={c.key}
                  align={c.align}
                  sx={{
                    fontSize: ".8rem",
                    ...(c.bold ? { fontWeight: 500 } : {}),
                    ...(c.mono
                      ? { fontFamily: "'DM Mono', Menlo, monospace" }
                      : {}),
                    ...(hasWidths
                      ? {
                          whiteSpace: "nowrap",
                          overflow: "hidden",
                          textOverflow: "ellipsis",
                        }
                      : {}),
                  }}
                >
                  {c.render(row)}
                </TableCell>
              ))}
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}
