---
"Update a document using update_by_query":
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "user": "kimchy" }
  - do:
      indices.refresh: {}

  - do:
      update_by_query:
        index:   twitter
        refresh: true
        body:
          script:
            lang: painless
            source: ctx._source.user = "not" + ctx._source.user
  - match: {updated: 1}
  - match: {noops: 0}

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            match:
              user: notkimchy
  - match: { hits.total: 1 }

---
"Update document using short `script` form":
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "user": "kimchy" }
  - do:
        indices.refresh: {}

  - do:
      update_by_query:
        index:   twitter
        refresh: true
        body:    { "script": "ctx._source.user = \"not\" + ctx._source.user" }
  - match: {updated: 1}
  - match: {noops: 0}

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            match:
              user: notkimchy
  - match: { hits.total: 1 }

---
"Noop one doc":
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "user": "kimchy" }
  - do:
      index:
        index:  twitter
        id:     "2"
        body:   { "user": "foo" }
  - do:
      indices.refresh: {}

  - do:
      update_by_query:
        refresh: true
        index:   twitter
        body:
          script:
            lang: painless
            source: if (ctx._source.user == "kimchy") {ctx._source.user = "not" + ctx._source.user} else {ctx.op = "noop"}
  - match: {updated: 1}
  - match: {noops: 1}

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            match:
              user: notkimchy
  - match: { hits.total: 1 }

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            match:
              user: notfoo
  - match: { hits.total: 0 }

---
"Noop all docs":
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "user": "kimchy" }
  - do:
      index:
        index:  twitter
        id:     "2"
        body:   { "user": "foo" }
  - do:
      indices.refresh: {}

  - do:
      update_by_query:
        refresh: true
        index:   twitter
        body:
          script:
            lang: painless
            source: ctx.op = "noop"
  - match: {updated: 0}
  - match: {noops: 2}
  - match: {batches: 1}

---
"Setting bogus context is an error":
  - requires:
      cluster_features: ["gte_v8.5.0"]
      reason: "error message changed in 8.5"
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "user": "kimchy" }
  - do:
      indices.refresh: {}

  - do:
      catch: /Cannot put key \[junk\] with value \[stuff\] into ctx/
      update_by_query:
        index: twitter
        body:
          script:
            lang: painless
            source: ctx.junk = "stuff"

---
"Can't change _id":
  - requires:
      cluster_features: ["gte_v8.5.0"]
      reason: "error message changed in 8.5"
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "user": "kimchy" }
  - do:
      indices.refresh: {}

  - do:
      catch: /_id cannot be updated/
      update_by_query:
        index: twitter
        body:
          script:
            lang: painless
            source: ctx._id = "stuff"

---
"Update all docs with one doc deletion":
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "level": 9, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      index:
        index:  twitter
        id:     "2"
        body:   { "level": 10, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      index:
        index:  twitter
        id:     "3"
        body:   { "level": 11, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      index:
        index:  twitter
        id:     "4"
        body:   { "level": 12, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      indices.refresh: {}

  - do:
      update_by_query:
        refresh: true
        index:   twitter
        body:
          script:
            lang: painless
            source: if (ctx._source.level != 11) {ctx._source.last_updated = "2016-01-02T00:00:00Z"} else {ctx.op = "delete"}
  - match: {updated: 3}
  - match: {deleted: 1}
  - match: {noops: 0}

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            match:
              last_updated: "2016-01-02T00:00:00Z"
  - match: { hits.total: 3 }

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            term:
              level: 11
  - match: { hits.total: 0 }

  - do:
      count:
        index: twitter
  - match: {count: 3}

---
"Update all docs with one deletion and one noop":
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "level": 9, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      index:
        index:  twitter
        id:     "2"
        body:   { "level": 10, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      index:
        index:  twitter
        id:     "3"
        body:   { "level": 11, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      index:
        index:  twitter
        id:     "4"
        body:   { "level": 12, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      indices.refresh: {}

  - do:
      update_by_query:
        refresh: true
        index:   twitter
        body:
          script:
            lang: painless
            source: |
              int choice = ctx._source.level % 3;
              if (choice == 0) {
                ctx._source.last_updated = "2016-01-02T00:00:00Z";
              } else if (choice == 1) {
                ctx.op = "noop";
              } else {
                ctx.op = "delete";
              }
  - match: {updated: 2}
  - match: {deleted: 1}
  - match: {noops: 1}

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            match:
              last_updated: "2016-01-02T00:00:00Z"
  - match: { hits.total: 2 }

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            match:
              last_updated: "2016-01-01T12:10:30Z"
  - match: { hits.total: 1 }

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            term:
              level: 11
  - match: { hits.total: 0 }

---
"Set unsupported operation type":
  - requires:
      cluster_features: ["gte_v8.5.0"]
      reason: "error message changed in 8.5"
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "user": "kimchy" }
  - do:
      index:
        index:  twitter
        id:     "2"
        body:   { "user": "foo" }
  - do:
      indices.refresh: {}

  - do:
      catch: /\[op\] must be one of delete, index, noop, not \[junk\]/
      update_by_query:
        refresh: true
        index:   twitter
        body:
          script:
            lang: painless
            source: if (ctx._source.user == "kimchy") {ctx.op = "index"} else {ctx.op = "junk"}

---
"Update all docs with one deletion and one noop using a stored script":
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "level": 9, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      index:
        index:  twitter
        id:     "2"
        body:   { "level": 10, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      index:
        index:  twitter
        id:     "3"
        body:   { "level": 11, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      index:
        index:  twitter
        id:     "4"
        body:   { "level": 12, "last_updated": "2016-01-01T12:10:30Z" }
  - do:
      indices.refresh: {}
  - do:
      put_script:
        id: "my_update_script"
        body: { "script": {"lang": "painless",
                "source": "int choice = ctx._source.level % 3;
                               if (choice == 0) {
                                   ctx._source.last_updated = '2016-01-02T00:00:00Z';
                               } else if (choice == 1) {
                                   ctx.op = 'noop';
                               } else {
                                   ctx.op = 'delete';
                               }" } }
  - match: { acknowledged: true }

  - do:
      update_by_query:
        refresh: true
        index:   twitter
        body:
          script:
             id: "my_update_script"

  - match: {updated: 2}
  - match: {deleted: 1}
  - match: {noops: 1}

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            match:
              last_updated: "2016-01-02T00:00:00Z"
  - match: { hits.total: 2 }

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            match:
              last_updated: "2016-01-01T12:10:30Z"
  - match: { hits.total: 1 }

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        body:
          query:
            term:
              level: 11
  - match: { hits.total: 0 }

---
"Totally broken scripts report the error properly":
  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "user": "kimchy" }
  - do:
      indices.refresh: {}

  - do:
      catch: bad_request
      update_by_query:
        index:   twitter
        refresh: true
        body:
          script:
            lang: painless
            source: syntax errors are fun!
  - match: {error.reason: 'compile error'}

---
"Can read version":
  - requires:
      cluster_features: ["gte_v8.4.0"]
      reason: fixed in 8.4.0

  - do:
      index:
        index:  twitter
        id:     "1"
        body:   { "user": "kimchy" }
        version: 500
        version_type: "external"
  - do:
      indices.refresh: {}

  - do:
      update_by_query:
        refresh: true
        index:   twitter
        version: true
        body:
          script:
            lang: painless
            source: |
              ctx._source.old_version = ctx._version;

  - match: {updated: 1}

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        version: true
        body:
          query:
            match_all: {}

  - match: { hits.total: 1 }
  - match: { hits.hits.0._source.old_version: 500 }

  - do:
      update_by_query:
        refresh: true
        index:   twitter
        # no version
        body:
          script:
            lang: painless
            source: |
              ctx._source.old_version = ctx._version;

  - match: {updated: 1}

  - do:
      search:
        rest_total_hits_as_int: true
        index: twitter
        version: true
        body:
          query:
            match_all: {}

  - match: { hits.total: 1 }
  - match: { hits.hits.0._source.old_version: -1 }

---
"Script Write Field":
  - requires:
      cluster_features: ["gte_v8.5.0"]
      reason: "Write fields api introduced in 8.5.0"

  - do:
      index:
        index: testw1
        id: "1"
        body:
          foo: bar
          count: 1

  - do:
      indices.refresh: {}

  - do:
      update_by_query:
        refresh: true
        index: testw1
        body:
          script:
            source: field('foo').transform(x -> x + '-baz'); field('nest').doc().field('bar').set(200)
            lang: painless

  - do:
      get:
        index: testw1
        id: "1"

  - match: { _source.foo: bar-baz }
  - match: { _source.nest.bar: 200 }
  - match: { found: true }
