import type { Algorithm, RecommendationList, Visualization } from './mod.ts';
import type { FacetRange } from './params.ts';


type ContentAlgorithm = 'NEWEST_CONTENT' | 'TOP_CONTENT';

export interface RecommendationListConfiguration extends Pick<RecommendationList, 'label' | 'showMoreLink'> {
  /**
   * The identifier to use for this list. Typically a short name describing
   * where on the page it's used.
   */
  id: string;
  /**
   * Which algorithm to use for the recommendationList. Some algorithms require
   * additional parameters for some page types.
   *
   * - `CART` - Unless `CartPage` is used, requires `params.cart` to be specified
   * - `UPSELL | ALTERNATIVES` - Unless `ProductPage` is used,
   *   requires `params.productKey` to be specified
   */
  algorithm?: Algorithm;
  /** How many products to fetch in the result */
  limit?: number;
  /** @deprecated Use productRules instead */
  productFilter?: ProductFilter;
  /**
   * Product rules to apply to limit the product selection in accordance with Elevate product rules syntax
   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/common/page-configuration/
   */
  productRules?: string;
  /** RecommendationList specific parameters */
  params?: RecommendationListParams;
  /** How the list should visaully be presented */
  visualization?: Visualization;
}

interface RecommendationListParams {
  /**
   * The base product to use for `ALTERNATIVES`, `STYLE_WITH` and `UPSELL recommendations.
   * Defaults to `productKey` for `ProductPage` requests.
   */
  productKey?: string;
  /** List of product and/or variant keys to be use in combination with the `CART` Algorithm */
  cart?: string[];
}

interface ContentListConfig {
  /**
   * An identifier for the content listing area. The same ID cannot appear twice in
   * the same request.
   *
   * Has a maximum length limit, as well as validation on character types.
   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/common/page-configuration/#content-lists
   */
  id: string;
  /** The number of items to list. Must be a positive number */
  limit?: number;
  /** Configuration to filter available content items */
  contentFilter?: ContentFilter;
  /** Algorithm to apply for this listing. Defaults to 'NEWEST_CONTENT' */
  algorithm?: ContentAlgorithm;
}

/**
 * @deprecated Use the `productRules` property instead
 *
 * `ProductFilter`, used with primary- and recommendation-lists
 *
 * - `{ "attribute": "val1" }`
 * - `{ "attribute": ["val2","val3"] }`
 * - `{ "range_attribute": { "min": 1, "max": 20 } }`
 *
 * Custom attributes can be used as a filter, but the name must be prefixed with `custom.`
 *
 * @example
 * ```json
 * {
 *   "size": "Women;NO_FORMAT;M",
 *   "brand": ["some_brand", "another_brand"],
 *   "custom.season": "fall",
 *   "discount": 50,
 *   "stock_number": [1, 2],
 *   "price": { "max": 200 },
 *   "rating": { "min": 3.5 }
 * }
 * ```
 */
export interface ProductFilter { [key: string]: string | string[] | number | number[] | FacetRange; }

/**
 * Allows filtering of content lists based on built-in or custom properties.
 * For an item to be included, it must match all specified properties. If multiple
 * values for a property is specified (e.g. `"custom.season": ["Winter", "Spring"]`),
 * it's enough if one value matches.
 *
 * @example
 * ```ts
 * const contentFilter = {
 *   type: 'article',
 *   'custom.season': ['Winter', 'Spring']
 * };
 * ```
 */
export interface ContentFilter {
  /** Content item type (as provided in the data-feed) */
  type?: string | string[];
  /** Content item key (as provided in the data-feed) */
  content_key?: string | string[];
  /** Any custom properties added in the data-feed. */
  [customProperty: `custom.${string}`]: string | string[];
}

export interface PrimaryListPageBody {
  /** Settings for the primary list */
  primaryList?: {
    /**
     * Include primary listing in result, defaults to `false` for landing-page,
     * but will always be `true` for search-page
     */
    include: boolean;
    /** @deprecated Use productRules instead */
    productFilter?: ProductFilter;
    /**
     * Product rules to apply to limit the product selection in accordance with the Elevate product rules syntax
     * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/common/page-configuration/
     */
    productRules?: string;
  };
}

export interface NavigationPageBody {
  /** Settings for navigation */
  navigation?: {
    /** Include navigation in result, defaults to `false` */
    include: boolean;
  };
}

export interface RecommendationListPageBody {
  /** Recommendation list settings, specify to include additional recommendations on a page */
  recommendationLists?: RecommendationListConfiguration[];
}

export interface ContentListPageBody {
  /** Content list settings, for retrieving non-products together with the request */
  contentLists?: ContentListConfig[];
}
