/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the "Elastic License
 * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
 * Public License v 1"; you may not use this file except in compliance with, at
 * your election, the "Elastic License 2.0", the "GNU Affero General Public
 * License v3.0 only", or the "Server Side Public License, v 1".
 */

import org.elasticsearch.gradle.Version
import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask

apply plugin: 'elasticsearch.internal-testclusters'
apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.bwc-test'
apply plugin: 'elasticsearch.rest-resources'

buildParams.bwcVersions.withWireCompatible { bwcVersion, baseName ->

  /**
   * We execute tests 3 times.
   * - The local cluster is unchanged and it consists of an old version node and a new version node.
   * - Nodes in the remote cluster are upgraded one by one in three steps.
   * - Only node-0 and node-2 of the remote cluster can accept remote connections. This can creates a test
   *   scenario where a query request and fetch request are sent via **proxy nodes** that have different version.
   */
  def localCluster = testClusters.register("${baseName}-local") {
    numberOfNodes = 2
    versions = [bwcVersion.toString(), project.version]
    setting 'cluster.remote.node.attr', 'gateway'
    setting 'xpack.security.enabled', 'false'
  }
  def remoteCluster = testClusters.register("${baseName}-remote") {
    numberOfNodes = 3
    versions = [bwcVersion.toString(), project.version]
    firstNode.setting 'node.attr.gateway', 'true'
    lastNode.setting 'node.attr.gateway', 'true'
    setting 'xpack.security.enabled', 'false'
  }


  tasks.withType(StandaloneRestIntegTestTask).matching { it.name.startsWith("${baseName}#") }.configureEach {
    useCluster localCluster
    useCluster remoteCluster
    systemProperty 'tests.upgrade_from_version', bwcVersion.toString().replace('-SNAPSHOT', '')
    nonInputProperties.systemProperty('tests.rest.cluster', getClusterInfo(localCluster.name).map { it.allHttpSocketURI.join(",") })
    nonInputProperties.systemProperty('tests.rest.remote_cluster', getClusterInfo(remoteCluster.name).map { it.allHttpSocketURI.join(",") })

    def fipsDisabled = buildParams.inFipsJvm == false
    onlyIf("FIPS mode disabled") { fipsDisabled }
  }

  tasks.register("${baseName}#oldClusterTest", StandaloneRestIntegTestTask) {
    dependsOn "processTestResources"
    mustRunAfter("precommit")
    doFirst {
      def cluster = localCluster.get()
      cluster.nodes.forEach { node ->
        node.getAllTransportPortURI()
      }
      getRegistry().get().nextNodeToNextVersion(cluster)
    }
  }

  tasks.register("${baseName}#oneThirdUpgraded", StandaloneRestIntegTestTask) {
    dependsOn "${baseName}#oldClusterTest"
    doFirst {
      getRegistry().get().nextNodeToNextVersion(remoteCluster)
    }
  }

  tasks.register("${baseName}#twoThirdUpgraded", StandaloneRestIntegTestTask) {
    dependsOn "${baseName}#oneThirdUpgraded"
    doFirst {
      getRegistry().get().nextNodeToNextVersion(remoteCluster)
    }
  }

  tasks.register("${baseName}#fullUpgraded", StandaloneRestIntegTestTask) {
    dependsOn "${baseName}#twoThirdUpgraded"
    doFirst {
      getRegistry().get().nextNodeToNextVersion(remoteCluster)
    }
  }

  tasks.register(bwcTaskName(bwcVersion)) {
    dependsOn tasks.named("${baseName}#fullUpgraded")
  }
}
