import type { CustomAttributes, Image } from './general.ts';


export type ImageEffect = 'NONE' | 'SWAP' | 'GALLERY';
export type BadgeType = 'NONE' | 'SALE' | 'DISCOUNT' | 'NEW' | 'THEME_1' | 'THEME_2' | 'THEME_3';
export type SwatchType = 'MISSING_COLORS' | 'COLORS' | 'SILVER' | 'GOLD' | 'MULTI';


export interface ProductGroup {
  /** Identifier for this `ProductGroup` */
  key: string;
  /**
   * The number of products within this group not included in the response. E.g. if Elevate has been set to
   * include the first five products in the response and this group has seven, there will be two remaining.
   */
  remaining: number;
  /**
   * Products in the Product group. The first element corresponds to the main product.
   * The remaining elements are the other products in the group, to be shown as thumbnails or color swatches, etc.
   */
  products: Product[];
}

export interface Product {
  /** Product identifier */
  key: string;
  /** Title of the product */
  title: string;
  /** Name of the product */
  name?: string;
  /** Brand of the product */
  brand: string;
  /** Series that this product belongs to. */
  series?: string;
  /** Description of the product, undefined if omitted during import */
  description?: string;
  /** Link to product page */
  link: string;
  /** Use with notifications to identify interaction */
  ticket: string;
  /** Will be undefined when rating is disabled. Otherwise it will be the current rating value*/
  rating?: number;
  /** True if any variant is in stock */
  inStock: boolean;
  /** Min and max list price of variants */
  listPrice: Price;
  /** Min and max selling price of variants */
  sellingPrice: Price;
  /** Main width of product. */
  width?: MeasurementResult;
  /** Main height of product. */
  height?: MeasurementResult;
  /** Main depth of product. */
  depth?: MeasurementResult;
  /** Main length of product. */
  length?: MeasurementResult;
  /** Volume of product. */
  volume?: MeasurementResult;
  /** Weight of product. */
  weight?: MeasurementResult;
  /**
   * Collection of variants
   *
   * Might be empty if all variants are out of stock and the setting
   * `Display out of stock sizes in product card` is disabled
   * */
  variants: Variant[];
  /** Product badges, split per area */
  badges: {
    /** Primary badges */
    primary: Badge[];
    /** Secondary badges */
    secondary: Badge[];
  };
  /** Product images, their presentation and multiple sources */
  imageInfo: {
    /** Effect that should be used for switching images */
    effect: ImageEffect;
    /** Images to be displayed */
    images: Image[];
    /** Thumbnail of the product, will be undefined if no images are defined */
    thumbnail?: string;
  };
  /** Color swatch for product  */
  swatch: {
    /** Type of color swatch */
    type: SwatchType;
    /** Only populated if type === SwatchType.COLORS  */
    colors: string[];
  };
  /**
   * Custom attributes of the product.
   *
   * Attributes included depends on the context. Primary product-group of
   * `/product-page` requests includes all attributes. In listings, attributes
   * included are controlled by:
   * - Parameter `presentCustom`, which includes listed attributes
   * - Parameter `templateId`, which includes all attributes in the target Template
   */
  custom?: CustomAttributes;
  /**
   * Typed custom attributes of the product.
   *
   * Attributes included depends on the context. Primary product-group of
   * `/product-page` requests includes all attributes. In listings, attributes
   * included are controlled by:
   * - Parameter `presentCustom`, which includes listed attributes
   * - Parameter `templateId`, which includes all attributes in the target Template
   */
  typedCustom?: TypedCustomAttributes;
  /** If the product is a sponsored product placement. */
  sponsored?: boolean;
}

export interface Variant {
  /** Variant identifier */
  key: string;
  /** Use with click notification to identify interaction */
  ticket: string;
  /** Size, will be undefined if omitted during import */
  size?: string;
  /** Label, will be undefined if omitted during import */
  label?: string;
  /** Stock number */
  stockNumber: number;
  /** True if variant stock number is greater than 0 */
  inStock: boolean;
  /** Direct link to variant or fallback to product if missing */
  link: string;
  /** List price */
  listPrice: number;
  /** Discounted price, same as listPrice if no discount */
  sellingPrice: number;
  /**
   * Additional prices for presentation. Only available on the /product-page `ProductGroup`
   * and when using the query parameter 'presentPrices'.
   */
  prices: PriceResult[];
  /** Availability of the product in different channels */
  availability: Availability[];
  /** Main width of variant. */
  width?: MeasurementResult;
  /** Main height of variant. */
  height?: MeasurementResult;
  /** Main depth of variant. */
  depth?: MeasurementResult;
  /** Main length of variant. */
  length?: MeasurementResult;
  /** Volume of variant. */
  volume?: MeasurementResult;
  /** Weight of variant. */
  weight?: MeasurementResult;
  /**
   * Custom attributes of the product.
   *
   * Attributes included depends on the context. Primary product-group of
   * `/product-page` requests includes all attributes. In listings, attributes
   * included are controlled by:
   * - Parameter `presentCustom`, which includes listed attributes
   * - Parameter `templateId`, which includes all attributes in the target Template
   */
  custom?: CustomAttributes;
  /**
   * Typed custom attributes of the product.
   *
   * Attributes included depends on the context. Primary product-group of
   * `/product-page` requests includes all attributes. In listings, attributes
   * included are controlled by:
   * - Parameter `presentCustom`, which includes listed attributes
   * - Parameter `templateId`, which includes all attributes in the target Template
   */
  typedCustom?: TypedCustomAttributes;
}

export interface Price {
  /** The lowest variant price */
  min: number;
  /** The highest variant price */
  max: number;
}

export interface MeasurementResult {
  /** The amount of the measurement */
  amount: number;
  /** The unit of the measurement, different measurements have different units */
  unit: string;
}

export interface TypedCustomAttributes {
  /** Custom lengths of the Product/Variant (`custom.length.<attr_name>`) */
  lengths: TypedCustomMeasurementAttribute;
  /** Custom numbers of the Product/Variant (`custom.number.<attr_name>`) */
  numbers: TypedCustomNumberAttribute;
  /** Custom JSON data of the Product/Variant (`custom.json.<attr_name>`) */
  json: TypedCustomJsonAttribute;
}

/**
 * @deprecated Use the `TypedCustomMeasurementAttribute` type instead.
 */
export type TypedCustomAttribute = TypedCustomMeasurementAttribute;

export type TypedCustomMeasurementAttribute = Record<string, MeasurementResult>;
export type TypedCustomNumberAttribute = Record<string, number>;
export type TypedCustomJsonAttribute = Record<string, unknown>;

export interface PriceResult {
  /** The id identifying the custom price. */
  id: string;
  /** The price displayed in the shop as the standard price. */
  listPrice: number;
  /** The price that the customer pays. */
  sellingPrice: number;
}

export interface Badge {
  /** Presentation text of badge */
  label: string;
  /** Identifier for the Badge styling */
  theme: BadgeType;
  /**
   * The related product attribe, will be `undefined` when the `theme`
   * property is `'DISCOUNT'`, `'NEW'` or `'SALE'`
   */
  attribute?: string;
}

export interface Availability {
  /** Channel identifer */
  channel: 'ONLINE' | 'STORE';
  /** Stock number */
  stockNumber: number;
  /** Store identifer */
  key?: string;
}
