<commit_before>class ExchangeProductsRenderer
  def initialize(order_cycle, user)
    @order_cycle = order_cycle
    @user = user
  end

  def exchange_products(incoming, enterprise)
    if incoming
      products_for_incoming_exchange(enterprise)
    else
      products_for_outgoing_exchange
    end
  end

  private

  def products_for_incoming_exchange(enterprise)
    supplied_products(enterprise)
  end

  def supplied_products(enterprise)
    if @order_cycle.present? &&
       @order_cycle.prefers_product_selection_from_coordinator_inventory_only?
      enterprise.supplied_products.visible_for(@order_cycle.coordinator)
    else
      enterprise.supplied_products
    end
  end

  def products_for_outgoing_exchange
    products = []
    enterprises_for_outgoing_exchange.each do |enterprise|
      products.push( *supplied_products(enterprise).to_a )

      products.each do |product|
        unless product_supplied_to_order_cycle?(product)
          products.delete(product)
        end
      end
    end
    products
  end

  def product_supplied_to_order_cycle?(product)
    (product.variants.map(&:id) & incoming_exchanges_variants).any?
  end

  def incoming_exchanges_variants
    return @incoming_exchanges_variants if @incoming_exchanges_variants.present?

    @incoming_exchanges_variants = []
    visible_incoming_exchanges.each do |exchange|
      @incoming_exchanges_variants.push(
        *exchange.variants.merge(visible_incoming_variants(exchange)).map(&:id).to_a
      )
    end
    @incoming_exchanges_variants
  end

  def visible_incoming_exchanges
    OpenFoodNetwork::OrderCyclePermissions.
      new(@user, @order_cycle).
      visible_exchanges.
      by_enterprise_name.
      incoming
  end

  def visible_incoming_variants(exchange)
    if exchange.order_cycle.prefers_product_selection_from_coordinator_inventory_only?
      permitted_incoming_variants(exchange).visible_for(exchange.order_cycle.coordinator)
    else
      permitted_incoming_variants(exchange)
    end
  end

  def permitted_incoming_variants(exchange)
    OpenFoodNetwork::OrderCyclePermissions.new(@user, exchange.order_cycle).
      visible_variants_for_incoming_exchanges_from(exchange.sender)
  end

  def enterprises_for_outgoing_exchange
    enterprises = OpenFoodNetwork::OrderCyclePermissions.
      new(@user, @order_cycle)<commit_msg>Convert the manipulation of arrays into active record relations: let the DB do the matching job<commit_after>class ExchangeProductsRenderer
  def initialize(order_cycle, user)
    @order_cycle = order_cycle
    @user = user
  end

  def exchange_products(incoming, enterprise)
    if incoming
      products_for_incoming_exchange(enterprise)
    else
      products_for_outgoing_exchange
    end
  end

  private

  def products_for_incoming_exchange(enterprise)
    supplied_products(enterprise.id)
  end

  def supplied_products(enterprises_query_matcher)
    products_relation = Spree::Product.where(supplier_id: enterprises_query_matcher)

    if @order_cycle.present? &&
       @order_cycle.prefers_product_selection_from_coordinator_inventory_only?
      products_relation = products_relation.visible_for(@order_cycle.coordinator)
    end

    products_relation
  end

  def products_for_outgoing_exchange
    supplied_products(enterprises_for_outgoing_exchange.select(:id)).
      includes(:variants).
      where("spree_variants.id": incoming_exchanges_variants)
  end

  def incoming_exchanges_variants
    return @incoming_exchanges_variants if @incoming_exchanges_variants.present?

    @incoming_exchanges_variants = []
    visible_incoming_exchanges.each do |incoming_exchange|
      @incoming_exchanges_variants.push(
        *incoming_exchange.variants.merge(visible_incoming_variants(incoming_exchange.sender)).map(&:id).to_a
      )
    end
    @incoming_exchanges_variants
  end

  def visible_incoming_exchanges
    OpenFoodNetwork::OrderCyclePermissions.
      new(@user, @order_cycle).
      visible_exchanges.
      by_enterprise_name.
      incoming
  end

  def visible_incoming_variants(incoming_exchange_sender)
    variants_relation = permitted_incoming_variants(incoming_exchange_sender)

    if @order_cycle.prefers_product_selection_from_coordinator_inventory_only?
      variants_relation = variants_relation.visible_for(@order_cycle.coordinator)
    end

    variants_relation
  end

  def permitted_incoming_variants(incoming_exchange_sender)
    OpenFoodNetwork::OrderCyclePermissions.
      new(@user, @order_cycle).
      visible_variants_for_incoming_exchanges_from(incoming_exchange_sender)
  end

  def enterprises_for_outgoing_exchange
    enterprises = OpenFoodNetwork::OrderCyclePermissions.
      new(@user, @order_cycle)
{'fraction_non_alphanumeric': 0.06085665818490246, 'fraction_numerical': 0.0, 'mean_word_length': 4.5625, 'pattern_counts': {'":': 1, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '965202', 'n_tokens_mistral': 1474, 'n_tokens_neox': 1420, 'n_words': 211}