export interface DynamicQueryStructure {
  select: string[] | "*";
  table: string;
  where?: Array<ConditionStructure>;
  join?: Array<DynamicQueryStructure & { foreignColumn: string }>;
  orderBy?: Array<OrderByStructure>;
}

export type ConditionStructure = (
  | {
      structureType: "condition";
      column: string;
      operation: WhereOperation;
      value: ConditionValue;
    }
  | {
      structureType: "nested";
      invert?: boolean;
      conditions: Array<ConditionStructure>;
    }
) & {
  concat: WhereType;
  structureType: "condition" | "nested";
};

export type ConditionValue = FieldType | Array<FieldType> | { start: FieldType; end: FieldType };
export type FieldType = number | string | Date | boolean;

export type WhereType = "OR" | "AND" | "_"; // _ represents initial where in (sub-)query

export type WhereOperation =
  | "eq" //	Equal
  | "neq" //	Not equal
  | "lt" //	Less than
  | "lte" //	Less than or equal to
  | "gt" //	Greater than
  | "gte" //	Greater than or equal to
  | "in" //	Included in an array
  | "notIn" //	Not included in an array
  | "contains" //	Contains
  | "notContains" //	Does not contain
  | "null" //	Is null
  | "notNull" //	Is not null
  | "between" //	Is between
  | "startsWith" //	Starts with
  | "endsWith" //	Ends with
  | "timespanEq"; // Date before x years (YYYY-01-01 <bis> YYYY-12-31)
// TODO: age between | age equals | age greater | age smaller

export type OrderByStructure = {
  column: string;
  order: OrderByType;
};

export type OrderByType = "ASC" | "DESC";

export type QueryResult = {
  [key: string]: FieldType | QueryResult | Array<QueryResult>;
};

export const whereOperationArray = [
  "eq",
  "neq",
  "lt",
  "lte",
  "gt",
  "gte",
  // "in",
  // "notIn",
  "contains",
  "notContains",
  "null",
  "notNull",
  "between",
  "startsWith",
  "endsWith",
  "timespanEq",
];

export const joinTableFormatter: { [key: string]: string } = {
  member_awards: "memberAwards",
  membership_status: "membershipStatus",
  member_qualifications: "memberQualifications",
  member_executive_positions: "memberExecutivePositions",
  communication_type: "communicationType",
  executive_position: "executivePosition",
};
