package k8s

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

	apiresource "github.com/pingcap/test-infra/common/model/resource"
)

var baseClusterConfig = []byte(`apiVersion: ops.tidbcloud.com/v1alpha1
kind: ClusterConfig
metadata:
  labels:
    tidbcloud.com/cluster: "clusterid"
    tidbcloud.com/managed-by: test-infra
    tidbcloud.com/module: tidb-configuration
    tidbcloud.com/tenant: "tenantid"
  name: base--ttenantid--cclusterid
spec:
  backup:
    baseImage: gcr.io/pingcap-public/dbaas/br
    config: |
      concurrency = 32
    tag: v5.4.1-20220531-1653926400
  configMeta:
    configVersion: 1655104964
    gitCommitID: hacked-by-test-infra
  pd:
    baseImage: gcr.io/pingcap-public/dbaas/pd
    config: |2

      [dashboard]
      enable-telemetry = false
      internal-proxy = true

      [replication]
      location-labels = ["failure-domain.beta.kubernetes.io/region", "failure-domain.beta.kubernetes.io/zone", "kubernetes.io/hostname"]
      max-replicas = 3

      [security]
      redact-info-log = true
    tag: v5.4.1-20220513
  restore:
    baseImage: gcr.io/pingcap-public/dbaas/br
    config: ""
    tag: v5.4.1-20220531-1653926400
  tidb:
    baseImage: gcr.io/pingcap-public/dbaas/tidb
    config: |
      enable-telemetry = false
      new_collations_enabled_on_first_bootstrap = true

      [log]

      [log.file]
      max-backups = 3

      [top-sql]
      receiver-address = "localhost:10000"
    overlays:
    - config: |
        enable-telemetry = false
        mem-quota-query = 1073741824
        new_collations_enabled_on_first_bootstrap = true

        [log]

        [log.file]
        max-backups = 3

        [performance]
        txn-total-size-limit = 2147483648

        [tikv-client]

        [tikv-client.copr-cache]
        capacity-mb = 0.0

        [top-sql]
        receiver-address = "localhost:10000"
      instanceType: aws.c5.2xlarge
    - config: |
        enable-telemetry = false
        mem-quota-query = 2147483648
        new_collations_enabled_on_first_bootstrap = true

        [log]

        [log.file]
        max-backups = 3

        [performance]
        txn-total-size-limit = 4294967296

        [top-sql]
        receiver-address = "localhost:10000"
      instanceType: aws.c5.4xlarge
    tag: v5.4.1-20220514
  tiflash:
    baseImage: gcr.io/pingcap-public/dbaas/tiflash
    config: |
      delta_index_cache_size = 3221225472
      mark_cache_size = 2147483648
      minmax_index_cache_size = 2147483648

      [profiles]

      [profiles.default]
      dt_enable_logical_split = false
      max_memory_usage_for_all_queries = 32212254720

      [security]
      redact_info_log = true

      [storage]

      [storage.main]
      dir = ["/data0/db"]
    overlays:
    - config: |
        delta_index_cache_size = 3221225472
        mark_cache_size = 2147483648
        minmax_index_cache_size = 2147483648

        [profiles]

        [profiles.default]
        dt_enable_logical_split = false
        max_memory_usage_for_all_queries = 32212254720

        [security]
        redact_info_log = true

        [storage]

        [storage.io_rate_limit]
        max_bytes_per_sec = 301465600

        [storage.main]
        dir = ["/data0/db"]
      instanceType: aws.r5.2xlarge
    tag: v5.4.1-20220513
  tikv:
    baseImage: gcr.io/pingcap-public/dbaas/tikv
    config: |2

      [resource-metering]
      receiver-address = "localhost:10000"

      [security]
      redact-info-log = true
    overlays:
    - config: |2

        [raftstore]
        apply-pool-size = 1
        store-pool-size = 1

        [resource-metering]
        receiver-address = "localhost:10000"

        [rocksdb]
        max-background-jobs = 8
        max-sub-compactions = 2

        [rocksdb.defaultcf]
        max-write-buffer-number = 10

        [rocksdb.lockcf]
        max-write-buffer-number = 10

        [rocksdb.writecf]
        max-write-buffer-number = 10

        [security]
        redact-info-log = true

        [server]
        grpc-concurrency = 3
      instanceType: aws.i3.2xlarge
    - config: |2

        [import]
        num-threads = 16

        [raftstore]
        apply-pool-size = 2
        store-pool-size = 2

        [resource-metering]
        receiver-address = "localhost:10000"

        [rocksdb]

        [rocksdb.defaultcf]
        max-write-buffer-number = 10

        [rocksdb.lockcf]
        max-write-buffer-number = 10

        [rocksdb.writecf]
        max-write-buffer-number = 10

        [security]
        redact-info-log = true

        [server]
        grpc-concurrency = 5
      instanceType: aws.i3.4xlarge
    tag: v5.4.1-20220513
  updatePolicy: Immediate
  version: v5.4.1
`)

func newClusterConfig() *unstructured.Unstructured {
	clusterConfigOrigin := new(unstructured.Unstructured)
	mustUnmarshalYaml(baseClusterConfig, &clusterConfigOrigin.Object)
	return clusterConfigOrigin
}

func TestApplyClusterConfig(t *testing.T) {
	var clusterConfig = apiresource.TiDBCloudClusterConfigSpec{
		TiKV: &apiresource.TiDBCloudConfiguration{
			Config: &apiresource.GenericConfig{MP: map[string]interface{}{}},
		},
	}
	clusterConfigOrigin := newClusterConfig()
	clusterConfig.Version = "v6.1.0"
	clusterConfig.TiKV.BaseImage = "gcr.io/pingcap-public/dbaas/tikv"
	tag := "v6.1.0-20220613-1655093617"
	clusterConfig.TiKV.Tag = &tag
	clusterConfig.TiKV.Config.Set("log-level", "debug")

	genericCfg := apiresource.GenericConfig{MP: map[string]interface{}{}}

	_, err := applyClusterConfig(clusterConfig, clusterConfigOrigin)
	assert.NoError(t, err)

	// config
	cfg, found, err := unstructured.NestedString(clusterConfigOrigin.Object, "spec", "tikv", "config")
	assert.NoError(t, err)
	assert.Equal(t, true, found)
	assert.NoError(t, genericCfg.UnmarshalTOML([]byte(cfg)))
	assert.Equal(t, "debug", genericCfg.MP["log-level"])

	// overlay
	overlays, found, err := unstructured.NestedSlice(clusterConfigOrigin.Object, "spec", "tikv", "overlays")
	assert.NoError(t, err)
	assert.Equal(t, true, found)

	assert.Equal(t, "aws.i3.2xlarge", overlays[0].(map[string]interface{})["instanceType"])
	cfg = overlays[0].(map[string]interface{})["config"].(string)
	assert.NoError(t, genericCfg.UnmarshalTOML([]byte(cfg)))
	assert.Equal(t, "debug", genericCfg.MP["log-level"])
	assert.Equal(t, int64(1), genericCfg.MP["raftstore"].(map[string]interface{})["apply-pool-size"])

	assert.Equal(t, "aws.i3.4xlarge", overlays[1].(map[string]interface{})["instanceType"])
	cfg = overlays[1].(map[string]interface{})["config"].(string)
	assert.NoError(t, genericCfg.UnmarshalTOML([]byte(cfg)))
	assert.Equal(t, "debug", genericCfg.MP["log-level"])
	assert.Equal(t, int64(2), genericCfg.MP["raftstore"].(map[string]interface{})["apply-pool-size"])

	// baseImage
	baseImage, found, err := unstructured.NestedString(clusterConfigOrigin.Object, "spec", "tikv", "baseImage")
	assert.NoError(t, err)
	assert.Equal(t, true, found)
	assert.Equal(t, "gcr.io/pingcap-public/dbaas/tikv", baseImage)

	// tag
	_tag, found, err := unstructured.NestedString(clusterConfigOrigin.Object, "spec", "tikv", "tag")
	assert.NoError(t, err)
	assert.Equal(t, true, found)
	assert.Equal(t, tag, _tag)

	// version
	version, found, err := unstructured.NestedString(clusterConfigOrigin.Object, "spec", "version")
	assert.NoError(t, err)
	assert.Equal(t, true, found)
	assert.Equal(t, "v6.1.0", version)
}
