import { Result } from "../Result";
import { ValueObject } from "../ValueObject";
import { FilterCriteria } from "./Filters";
import { OrderCriteria } from "./Order";
import { OffsetPaging } from "./Pagination";
import { QuickSearchCriteria } from "./QuickSearch";

export interface IQueryCriteriaProps {
  pagination: OffsetPaging;
  order: OrderCriteria;
  //fields: FieldCriteria; // fields=first_name,last_name,tin
  filters: FilterCriteria;
  quickSearch: QuickSearchCriteria;
}

export interface IQueryCriteria {
  pagination: OffsetPaging;
  order: OrderCriteria;
  //fields: string;
  filters: FilterCriteria;
  quickSearch: QuickSearchCriteria;

  toJSON(): string;
  toObject(): Record<string, any>;
}

export class QueryCriteria
  extends ValueObject<IQueryCriteriaProps>
  implements IQueryCriteria
{
  public static create(props: IQueryCriteriaProps): Result<QueryCriteria> {
    return Result.ok<QueryCriteria>(
      new QueryCriteria({
        pagination: props.pagination,
        //fields: props.fields,
        order: props.order,
        filters: props.filters,
        quickSearch: props.quickSearch,
      })
    );
  }

  public get pagination(): OffsetPaging {
    return this.props.pagination;
  }

  public get order(): OrderCriteria {
    return this.props.order;
  }

  public get filters(): FilterCriteria {
    return this.props.filters;
  }

  public get quickSearch(): QuickSearchCriteria {
    return this.props.quickSearch;
  }

  public toObject(): Record<string, any> {
    return {
      pagination: this.pagination?.toObject(),
      order: this.order?.toObject(),
      filters: this.filters?.toObject(),
      quickSearch: this.quickSearch?.toString(),
    };
  }

  public toJSON(): string {
    return JSON.stringify(this.toObject());
  }

  public toPrimitive(): string {
    throw new Error("NOT IMPLEMENT QueryCriteria.toPrimitive()");
  }
}
