import { Param } from 'src/core/modules/domain/entities/base-filter.entity';
import { Brackets, SelectQueryBuilder } from 'typeorm';

export class SpecificSearchFilter<Entity = any> {
  constructor(
    private query: SelectQueryBuilder<Entity>,
    private readonly table: string,
    private readonly params: Param[],
  ) {}

  getFilter() {
    const params = this.params?.filter((item) => {
      return item.data !== undefined;
    });
    return this.bySearch(this.query, params);
  }

  bySearch(query: SelectQueryBuilder<Entity>, params: Param[]) {
    query.andWhere(
      new Brackets((qb) => {
        params.forEach((param) => {
          const { cols, data, additional, leftJoin } = param;
          const columns = cols.split('.');
          let arr = data;

          if (!columns.includes('status::text')) {
            arr = data?.map((el) =>
              el.includes("'")
                ? `'%${el.trim().replace(/'/g, "''").replace(/\s+/g, ' ')}%'`
                : `'%${el.trim().replace(/\s+/g, ' ')}%'`,
            );
          }

          const aliases = !cols.match(/\./g)
            ? this.table.concat(`.${cols}`)
            : cols;

          qb['andWhere'](`${aliases} ILIKE ANY(ARRAY[${arr}])`);

          if (additional?.length > 0) {
            qb['orWhere'](
              new Brackets((subQb) => {
                for (const addition of additional) {
                  subQb['orWhere'](`${addition}`);
                }
              }),
            );
          }

          if (leftJoin?.length) {
            for (const join of leftJoin) {
              qb['leftJoinAndSelect'](`${join.relations}`, `${join.alias}`);
            }
          }
        });
      }),
    );

    return query;
  }
}
