export interface Column<T> {
  header: string;
  key: keyof T | ((row: T) => string);
  width?: number;
  align?: 'left' | 'right';
}

export function formatTable<T>(rows: T[], columns: Column<T>[]): string {
  if (rows.length === 0) {
    return 'No results found.';
  }

  const getValue = (row: T, col: Column<T>): string => {
    if (typeof col.key === 'function') {
      return col.key(row);
    }
    const val = row[col.key];
    return val == null ? '' : String(val);
  };

  // Calculate column widths
  const widths = columns.map((col) => {
    if (col.width !== undefined) return col.width;
    const headerLen = col.header.length;
    const maxDataLen = rows.reduce((max, row) => {
      const val = getValue(row, col);
      return Math.max(max, val.length);
    }, 0);
    return Math.max(headerLen, maxDataLen);
  });

  const pad = (text: string, width: number, align: 'left' | 'right' = 'left'): string => {
    const truncated = text.length > width ? text.slice(0, width - 1) + '\u2026' : text;
    return align === 'right' ? truncated.padStart(width) : truncated.padEnd(width);
  };

  const headerLine = columns.map((col, i) => pad(col.header, widths[i] ?? 0, col.align ?? 'left')).join('  ');
  const separator = widths.map((w) => '-'.repeat(w)).join('  ');
  const dataLines = rows.map((row) =>
    columns.map((col, i) => pad(getValue(row, col), widths[i] ?? 0, col.align ?? 'left')).join('  '),
  );

  return [headerLine, separator, ...dataLines].join('\n');
}
