import type { CSSProperties, ReactNode } from "react";

export type ConnectionTreeColumn<T> = {
  id: string;
  header: ReactNode;
  width?: string;
  align?: "left" | "center" | "right";
  render: (row: T, depth: number) => ReactNode;
};

export type ConnectionTreeProps<T> = {
  rows: T[];
  columns: ConnectionTreeColumn<T>[];
  getRowKey: (row: T) => string;
  getChildren?: (row: T) => T[];
  renderActions?: (row: T, depth: number) => ReactNode;
  emptyText?: ReactNode;
  className?: string;
  rowClassName?: (row: T, depth: number) => string;
};

type FlatRow<T> = {
  row: T;
  depth: number;
};

export default function ConnectionTree<T>({
  rows,
  columns,
  getRowKey,
  getChildren,
  renderActions,
  emptyText = "i18n:govoplan-core.no_entries_configured.48e7b97c",
  className = "",
  rowClassName
}: ConnectionTreeProps<T>) {
  const flatRows = flattenRows(rows, getChildren);
  const gridTemplateColumns = `${columns.map((column) => column.width || "minmax(0, 1fr)").join(" ")} ${renderActions ? "var(--connection-tree-actions-column, 196px)" : ""}`.trim();

  return (
    <div className={`connection-tree ${className}`.trim()}>
      <div className="connection-tree-header" style={{ gridTemplateColumns }}>
        {columns.map((column) =>
        <div className={`connection-tree-cell ${column.align ? `align-${column.align}` : ""}`.trim()} key={column.id}>
            {column.header}
          </div>
        )}
        {renderActions && <div className="connection-tree-cell align-right">i18n:govoplan-core.actions.c3cd636a</div>}
      </div>
      {flatRows.length === 0 && <div className="connection-tree-empty">{emptyText}</div>}
      {flatRows.map(({ row, depth }) => {
        const className = ["connection-tree-row", depth > 0 ? "is-child" : "is-parent", rowClassName?.(row, depth) || ""].filter(Boolean).join(" ");
        return (
          <div className={className} style={{ gridTemplateColumns }} key={getRowKey(row)}>
            {columns.map((column, index) =>
            <div
              className={`connection-tree-cell ${column.align ? `align-${column.align}` : ""} ${index === 0 ? "connection-tree-primary-cell" : ""}`.trim()}
              key={column.id}>
                {index === 0 ?
                  <div className="connection-tree-primary-content" style={{ "--connection-tree-depth": String(depth) } as CSSProperties}>
                    {column.render(row, depth)}
                  </div> :
                  column.render(row, depth)
                }
              </div>
            )}
            {renderActions && <div className="connection-tree-cell align-right connection-tree-actions">{renderActions(row, depth)}</div>}
          </div>);

      })}
    </div>);

}

function flattenRows<T>(rows: T[], getChildren?: (row: T) => T[]): FlatRow<T>[] {
  const result: FlatRow<T>[] = [];
  for (const row of rows) {
    result.push({ row, depth: 0 });
    for (const child of getChildren?.(row) ?? []) {
      result.push({ row: child, depth: 1 });
    }
  }
  return result;
}
