/*
 * Copyright (C) 2022 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {SortOptions} from '@elastic/elasticsearch/lib/api/types.js';
import {SCPriceSort, SCSportCoursePriceGroup, SCThingsField} from '@openstapps/core';

/**
 * Converts a price sort to elasticsearch syntax
 * @param sort A sorting definition
 */
export function buildPriceSort(sort: SCPriceSort): SortOptions {
  return {
    _script: {
      order: sort.order,
      script: buildPriceSortScript(sort.arguments.universityRole, sort.arguments.field),
      type: 'number' as const,
    },
  };
}

/**
 * Provides a script for sorting search results by prices
 * @param universityRole User group which consumes university services
 * @param field Field in which wanted offers with prices are located
 */
export function buildPriceSortScript(
  universityRole: keyof SCSportCoursePriceGroup,
  field: SCThingsField,
): string {
  return `
  // initialize the sort value with the maximum
  double price = Double.MAX_VALUE;

  // if we have any offers
  if (params._source.containsKey('${field}')) {
    // iterate through all offers
    for (offer in params._source.${field}) {
      // if this offer contains a role specific price
      if (offer.containsKey('prices') && offer.prices.containsKey('${universityRole}')) {
        // if the role specific price is smaller than the cheapest we found
        if (offer.prices.${universityRole} < price) {
          // set the role specific price as cheapest for now
          price = offer.prices.${universityRole};
        }
      } else { // we have no role specific price for our role in this offer
        // if the default price of this offer is lower than the cheapest we found
        if (offer.price < price) {
          // set this price as the cheapest
          price = offer.price;
        }
      }
    }
  }

  // return cheapest price for our role
  return price;
  `;
}
