import {
  FilterCriteria,
  IQueryCriteria,
  OffsetPaging,
  OrderCriteria,
  QueryCriteria,
  QuickSearchCriteria,
} from "@shared/contexts";
import { ApplicationService } from "./ApplicationService";

export interface IQueryCriteriaServiceProps {
  page: string;
  limit: string;

  sort_by: string;
  fields: string;
  filters: string;
  q: string; // <- si viene separado por comas, es un array
}

export class QueryCriteriaService extends ApplicationService {
  public static parse(params: Partial<IQueryCriteriaServiceProps>): IQueryCriteria {
    const {
      page = undefined,
      limit = undefined,
      sort_by = undefined,
      q = undefined,

      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      fields = null, // fields / select
      //scopes:
    } = params || {};

    const filters = params["$filters"];

    // Pagination
    const _pagination = QueryCriteriaService.parsePagination(page, limit);

    const _filters: FilterCriteria = QueryCriteriaService.parseFilter(filters);

    const _order: OrderCriteria = QueryCriteriaService.parseOrder(sort_by);

    const _quickSearch: QuickSearchCriteria = QueryCriteriaService.parseQuickSearch(q);

    return QueryCriteria.create({
      pagination: _pagination,
      quickSearch: _quickSearch,
      filters: _filters,
      order: _order,
    }).object;
  }

  protected static parsePagination(page?: string, limit?: string) {
    if (!page && !limit) {
      return OffsetPaging.createWithDefaultValues().object;
    }

    const paginationOrError = OffsetPaging.create({
      offset: page,
      limit,
    });

    if (paginationOrError.isFailure) {
      throw paginationOrError.error;
    }

    return paginationOrError.object;
  }

  protected static parseFilter(filter?: string): FilterCriteria {
    const filterOrError = FilterCriteria.create(filter);
    if (filterOrError.isFailure) {
      throw filterOrError.error;
    }

    return filterOrError.object;
  }

  protected static parseOrder(sort_by?: string): OrderCriteria {
    const orderOrError = OrderCriteria.create(sort_by);
    if (orderOrError.isFailure) {
      throw orderOrError.error;
    }

    return orderOrError.object;
  }

  protected static parseQuickSearch(quickSearch?: string): QuickSearchCriteria {
    const quickSearchOrError = QuickSearchCriteria.create(quickSearch?.split(","));
    if (quickSearchOrError.isFailure) {
      throw quickSearchOrError.error;
    }

    return quickSearchOrError.object;
  }
}
