import type { ColumnRelation, DataTableColumnDef } from '../types';

/**
 * Builds a deduplicated, deep-merged `include` tree from columns that declare
 * a `relation`. The result is shaped like Sequelize's `include` and can be
 * passed straight to a paginate query — required for `where` predicates of
 * the form `'$a.b.c$'` and `order` entries of the form `[a, b, c, dir]` to
 * resolve at the database level.
 *
 * Two columns referencing the same association are collapsed into a single
 * entry. When their nested chains differ, the chains are merged: e.g.
 *
 *   col A → { association: 'account', include: [{ association: 'user' }] }
 *   col B → { association: 'account', include: [{ association: 'tenant' }] }
 *
 *   getRelationIncludes([A, B])
 *   // → [{ association: 'account',
 *   //      include: [{ association: 'user' }, { association: 'tenant' }] }]
 *
 * Source columns are never mutated; the returned tree is a fresh object
 * structure safe for the consumer to extend.
 *
 * The function reads the explicit `relation` field — it does NOT scan column
 * ids — so the dependency on a relation is visible at the column definition
 * site.
 */
export function getRelationIncludes<T>(columns: DataTableColumnDef<T>[]): ColumnRelation[] {
  const tree: ColumnRelation[] = [];
  for (const col of columns) {
    if (col.relation) mergeInto(tree, col.relation);
  }
  return tree;
}

function mergeInto(target: ColumnRelation[], rel: ColumnRelation): void {
  let existing = target.find((r) => r.association === rel.association);
  if (!existing) {
    existing = { association: rel.association };
    target.push(existing);
  }
  if (rel.include) {
    existing.include ??= [];
    for (const child of rel.include) {
      mergeInto(existing.include, child);
    }
  }
}
