import type { DataTableColumnDef } from '../types';
import { getRelationIncludes } from './get-relation-includes';

describe('getRelationIncludes', () => {
  it('returns an empty array when no column declares a relation', () => {
    const columns: DataTableColumnDef<unknown>[] = [{ id: 'rowId' }, { id: 'name' }];
    expect(getRelationIncludes(columns)).toEqual([]);
  });

  it('does NOT infer relations from dotted ids alone', () => {
    const columns: DataTableColumnDef<unknown>[] = [{ id: 'boundedContext.name' }];
    expect(getRelationIncludes(columns)).toEqual([]);
  });

  it('extracts the association from a column with explicit relation', () => {
    const columns: DataTableColumnDef<unknown>[] = [
      { id: 'name' },
      { id: 'boundedContext.name', relation: { association: 'boundedContext' } },
    ];
    expect(getRelationIncludes(columns)).toEqual([{ association: 'boundedContext' }]);
  });

  it('deduplicates repeated associations across multiple columns', () => {
    const columns: DataTableColumnDef<unknown>[] = [
      { id: 'boundedContext.name', relation: { association: 'boundedContext' } },
      { id: 'boundedContext.code', relation: { association: 'boundedContext' } },
    ];
    expect(getRelationIncludes(columns)).toEqual([{ association: 'boundedContext' }]);
  });

  it('returns one entry per distinct association', () => {
    const columns: DataTableColumnDef<unknown>[] = [
      { id: 'name' },
      { id: 'boundedContext.name', relation: { association: 'boundedContext' } },
      { id: 'tenant.code', relation: { association: 'tenant' } },
    ];
    expect(getRelationIncludes(columns)).toEqual([
      { association: 'boundedContext' },
      { association: 'tenant' },
    ]);
  });

  it('preserves a nested include chain (deep relation)', () => {
    const columns: DataTableColumnDef<unknown>[] = [
      {
        id: 'account.user.name',
        relation: { association: 'account', include: [{ association: 'user' }] },
      },
    ];
    expect(getRelationIncludes(columns)).toEqual([
      { association: 'account', include: [{ association: 'user' }] },
    ]);
  });

  it('merges sibling sub-relations under the same root', () => {
    const columns: DataTableColumnDef<unknown>[] = [
      {
        id: 'account.user.name',
        relation: { association: 'account', include: [{ association: 'user' }] },
      },
      {
        id: 'account.tenant.code',
        relation: { association: 'account', include: [{ association: 'tenant' }] },
      },
    ];
    expect(getRelationIncludes(columns)).toEqual([
      {
        association: 'account',
        include: [{ association: 'user' }, { association: 'tenant' }],
      },
    ]);
  });

  it('does not duplicate a sub-relation already present', () => {
    const columns: DataTableColumnDef<unknown>[] = [
      {
        id: 'account.user.name',
        relation: { association: 'account', include: [{ association: 'user' }] },
      },
      {
        id: 'account.user.email',
        relation: { association: 'account', include: [{ association: 'user' }] },
      },
    ];
    expect(getRelationIncludes(columns)).toEqual([
      { association: 'account', include: [{ association: 'user' }] },
    ]);
  });

  it('merges chains of three or more levels', () => {
    const columns: DataTableColumnDef<unknown>[] = [
      {
        id: 'account.user.profile.avatar',
        relation: {
          association: 'account',
          include: [{ association: 'user', include: [{ association: 'profile' }] }],
        },
      },
      {
        id: 'account.user.role.name',
        relation: {
          association: 'account',
          include: [{ association: 'user', include: [{ association: 'role' }] }],
        },
      },
    ];
    expect(getRelationIncludes(columns)).toEqual([
      {
        association: 'account',
        include: [
          {
            association: 'user',
            include: [{ association: 'profile' }, { association: 'role' }],
          },
        ],
      },
    ]);
  });

  it('does not mutate the source column relation', () => {
    const sourceRelation = {
      association: 'account',
      include: [{ association: 'user' }],
    };
    const columns: DataTableColumnDef<unknown>[] = [
      { id: 'account.user.name', relation: sourceRelation },
      {
        id: 'account.tenant.code',
        relation: { association: 'account', include: [{ association: 'tenant' }] },
      },
    ];

    getRelationIncludes(columns);

    // Source object remains untouched after merging.
    expect(sourceRelation).toEqual({
      association: 'account',
      include: [{ association: 'user' }],
    });
  });
});
