setup:
  - skip:
      features:
        - close_to

  - requires:
      capabilities:
        - method: POST
          path: /_search
          capabilities: [ transform_rank_rrf_to_retriever ]
      test_runner_features: capabilities
      reason: "Support for transforming deprecated rank_rrf queries to the corresponding rrf retriever is required"

  - do:
      indices.create:
        index: test
        body:
          settings:
            number_of_shards: 5
            number_of_replicas: 0
          mappings:
            properties:
              vector_asc:
                type: dense_vector
                dims: 1
                index: true
                similarity: l2_norm
                index_options:
                  type: hnsw
                  ef_construction: 100
                  m: 16
              vector_desc:
                type: dense_vector
                dims: 1
                index: true
                similarity: l2_norm
                index_options:
                  type: hnsw
                  ef_construction: 100
                  m: 16
              int:
                type: integer
              text:
                type: text

  - do:
      bulk:
        index: test
        refresh: true
        body: |
          { "index": {"_id" : "1"} }
          { "vector_asc": [1.0], "vector_desc": [11.0], "int": 1, "text": "term 1" }
          { "index": {"_id" : "2"} }
          { "vector_asc": [2.0], "vector_desc": [10.0], "int": 2, "text": "term 2" }
          { "index": {"_id" : "3"} }
          { "vector_asc": [3.0], "vector_desc": [9.0], "int": 3, "text": "term 3" }
          { "index": {"_id" : "4"} }
          { "vector_asc": [4.0], "vector_desc": [8.0], "int": 1, "text": "term 4" }
          { "index": {"_id" : "5"} }
          { "vector_asc": [5.0], "vector_desc": [7.0], "int": 2, "text": "term 5" }
          { "index": {"_id" : "6"} }
          { "vector_asc": [6.0], "vector_desc": [6.0], "int": 3, "text": "term 6" }
          { "index": {"_id" : "7"} }
          { "vector_asc": [7.0], "vector_desc": [5.0], "int": 1, "text": "term 7" }
          { "index": {"_id" : "8"} }
          { "vector_asc": [8.0], "vector_desc": [4.0], "int": 2, "text": "term 8" }
          { "index": {"_id" : "9"} }
          { "vector_asc": [9.0], "vector_desc": [3.0], "int": 3, "text": "term 9" }
          { "index": {"_id" : "10"} }
          { "vector_asc": [10.0], "vector_desc": [2.0], "int": 1, "text": "term 10" }
          { "index": {"_id" : "11"} }
          { "vector_asc": [11.0], "vector_desc": [1.0], "int": 2, "text": "term 11" }

---
"RRF using single knn and single BM25 with a scripted metric aggregation":

  - requires:
      cluster_features: ["gte_v8.16.0"]
      reason: "deprecation added in 8.16"
      test_runner_features: warnings

  - do:
      warnings:
        - "Deprecated field [rank] used, replaced by [retriever]"
      search:
        index: test
        body:
          track_total_hits: true
          fields: [ "text" ]
          knn: [
            {
              field: vector_asc,
              query_vector: [ 5.0 ],
              k: 5,
              num_candidates: 11
            }
          ]
          query:
            bool:
              should:
                - term:
                    text:
                      value: "6"
                      boost: 10.0
                - term:
                    text:
                      value: "5"
                      boost: 7.0
                - term:
                    text:
                      value: "7"
                      boost: 7.0
                - term:
                    text:
                      value: "4"
                      boost: 3.0
                - term:
                    text:
                      value: "3"
                      boost: 2.0
          aggs:
            sums:
              scripted_metric:
                init_script: |
                  state['sums'] = ['asc': [], 'text': []]
                map_script: |
                  state['sums']['asc'].add($('vector_asc', null).getVector()[0]);
                  state['sums']['text'].add(Integer.parseInt($('text', null).substring(5)));
                combine_script: |
                  [
                    'asc_total': state['sums']['asc'].stream().mapToDouble(v -> v).sum(),
                    'text_total': state['sums']['text'].stream().mapToInt(v -> v).sum()
                  ]
                reduce_script: |
                  [
                    'asc_total': states.stream().mapToDouble(v -> v['asc_total']).sum(),
                    'text_total': states.stream().mapToInt(v -> v['text_total']).sum()
                  ]
          rank:
            rrf:
              rank_window_size: 100
              rank_constant: 1
          size: 5

  - match: { hits.hits.0._id: "5" }
  - match: { hits.hits.1._id: "6" }
  - match: { hits.hits.2._id: "4" }
  - match: { hits.hits.3._id: "7" }
  - match: { hits.hits.4._id: "3" }

  - close_to: { aggregations.sums.value.asc_total: { value: 25.0, error: 0.001 }}
  - match: { aggregations.sums.value.text_total: 25 }

---
"RRF using multi-knn only with a scripted metric aggregation":

  - requires:
      cluster_features: ["gte_v8.16.0"]
      reason: "deprecation added in 8.16"
      test_runner_features: warnings

  - do:
      warnings:
        - "Deprecated field [rank] used, replaced by [retriever]"
      search:
        index: test
        body:
          track_total_hits: true
          fields: [ "text" ]
          knn: [
            {
              field: vector_asc,
              query_vector: [ 6.0 ],
              k: 5,
              num_candidates: 11
            },
            {
              field: vector_desc,
              query_vector: [ 8.0 ],
              k: 3,
              num_candidates: 11
            }
          ]
          aggs:
            sums:
              scripted_metric:
                init_script: |
                  state['sums'] = ['asc': [], 'desc': []]
                map_script: |
                  state['sums']['asc'].add($('vector_asc', null).getVector()[0]);
                  state['sums']['desc'].add($('vector_desc', null).getVector()[0])
                combine_script: |
                  [
                    'asc_total': state['sums']['asc'].stream().mapToDouble(v -> v).sum(),
                    'desc_total': state['sums']['desc'].stream().mapToDouble(v -> v).sum()
                  ]
                reduce_script: |
                  [
                    'asc_total': states.stream().mapToDouble(v -> v['asc_total']).sum(),
                    'desc_total': states.stream().mapToDouble(v -> v['desc_total']).sum()
                  ]
          rank:
            rrf:
              rank_window_size: 3
              rank_constant: 1
          size: 1

  - match: { hits.total.value: 5 }

  - match: { hits.hits.0._id: "5" }

  - close_to: { aggregations.sums.value.asc_total: { value: 25.0, error: 0.001 }}
  - close_to: { aggregations.sums.value.desc_total: { value: 35.0, error: 0.001 }}


---
"RRF using multi-knn and single BM25 with a scripted metric aggregation":

  - requires:
      cluster_features: ["gte_v8.16.0"]
      reason: "deprecation added in 8.16"
      test_runner_features: warnings

  - do:
      warnings:
        - "Deprecated field [rank] used, replaced by [retriever]"
      search:
        index: test
        body:
          track_total_hits: true
          fields: [ "text" ]
          knn: [
            {
              field: vector_asc,
              query_vector: [ 6.0 ],
              k: 5,
              num_candidates: 11
            },
            {
              field: vector_desc,
              query_vector: [ 6.0 ],
              k: 5,
              num_candidates: 11
            }
          ]
          query:
            bool:
              should:
                - term:
                    text:
                      value: "6"
                      boost: 10.0
                - term:
                    text:
                      value: "5"
                      boost: 7.0
                - term:
                    text:
                      value: "7"
                      boost: 7.0
                - term:
                    text:
                      value: "4"
                      boost: 3.0
          aggs:
            sums:
              scripted_metric:
                init_script: |
                  state['sums'] = ['asc': [], 'desc': [], 'text': []]
                map_script: |
                  state['sums']['asc'].add($('vector_asc', null).getVector()[0]);
                  state['sums']['desc'].add($('vector_asc', null).getVector()[0]);
                  state['sums']['text'].add(Integer.parseInt($('text', null).substring(5)));
                combine_script: |
                  [
                    'asc_total': state['sums']['asc'].stream().mapToDouble(v -> v).sum(),
                    'desc_total': state['sums']['asc'].stream().mapToDouble(v -> v).sum(),
                    'text_total': state['sums']['text'].stream().mapToInt(v -> v).sum()
                  ]
                reduce_script: |
                  [
                    'asc_total': states.stream().mapToDouble(v -> v['asc_total']).sum(),
                    'desc_total': states.stream().mapToDouble(v -> v['desc_total']).sum(),
                    'text_total': states.stream().mapToInt(v -> v['text_total']).sum()
                  ]
          rank:
            rrf:
              rank_window_size: 100
              rank_constant: 1
          size: 5

  - match: { hits.hits.0._id: "6" }
  - match: { hits.hits.1._id: "5" }
  - match: { hits.hits.2._id: "7" }
  - match: { hits.hits.3._id: "4" }
  - match: { hits.hits.4._id: "8" }
  - close_to: { aggregations.sums.value.asc_total: { value: 30.0, error: 0.001 }}
  - close_to: { aggregations.sums.value.desc_total: { value: 30.0, error: 0.001 }}
  - match: { aggregations.sums.value.text_total: 30 }
