import { Operator } from '@aurorajs.dev/core-common';
import type { ColumnFilter } from '../types';
import { toSequelizeWhereKey } from './nested-column';

const OPERATOR_MAP: Record<string, string> = {
  contains: Operator.iLike,
  equals: Operator.eq,
  startsWith: Operator.iLike,
  endsWith: Operator.iLike,
  greaterThan: Operator.gt,
  lessThan: Operator.lt,
};

function wrapValue(operator: string, value: string): string {
  switch (operator) {
    case 'contains':
      return `%${value}%`;
    case 'startsWith':
      return `${value}%`;
    case 'endsWith':
      return `%${value}`;
    default:
      return value;
  }
}

/**
 * Converts ColumnFilter[] from the TableFilters into a
 * Sequelize-compatible `where` clause using Aurora operators.
 *
 * Multiple filters on different columns are combined with AND.
 * Multiple filters on the same column are combined with OR.
 *
 * Filter columns using dot notation (e.g. `'boundedContext.name'`) are
 * translated to Sequelize's `$assoc.col$` syntax automatically. The list
 * query must `include` the corresponding association — derive it via
 * `getRelationIncludes(columns)`.
 *
 * @returns A where object for QueryStatement, or undefined if no filters
 */
export function buildFilterWhere(filters: ColumnFilter[]): Record<string, unknown> | undefined {
  if (!filters.length) return undefined;

  const conditions = filters.map((f) => ({
    [toSequelizeWhereKey(f.column)]: {
      [OPERATOR_MAP[f.operator] ?? Operator.iLike]: wrapValue(f.operator, f.value),
    },
  }));

  if (conditions.length === 1) return conditions[0];

  return { [Operator.and]: conditions };
}
