package action

import (
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/cluster-service-ng/pkg/template/render"
)

func Test_RenderPDGroup_AzureClientIDEnv(t *testing.T) {
	tl := initTemplateLibrary(t, []string{"pd_group"})

	baseArgs := map[string]string{
		"ClusterId":                    "123",
		"SharedPoolId":                 "sp-1",
		"ComponentType":                "pd",
		"ComponentGroup":               "db-pd",
		"NodeSpec":                     "2c4g",
		"MinNodeCount":                 "1",
		"MaxNodeCount":                 "3",
		"Replicas":                     "3",
		"Topologies":                   "- topologyKey: topology.kubernetes.io/zone",
		"Version":                      "v9.0.0",
		"Image":                        "pd:v9.0.0",
		"Config":                       "[pd]",
		"DataStorageSize":              "10",
		"DataStorageClass":             "standard",
		"DataVolumeAttributesClass":    "vac",
		"RemoteWorkerGroup":            "db-pd-default",
		"RemoteCoprocessorWorkerGroup": "db-pd-coprocessor",
		"ImagePullPolicy":              "IfNotPresent",
		"NodeVersion":                  "1.30",
		"PDMode":                       "ms",
	}

	t.Run("with AZURE_CLIENT_ID", func(t *testing.T) {
		args := copyStringMap(baseArgs)
		args["AZURE_CLIENT_ID"] = "azure-client-id-1"
		yamlStr, err := tl.Render("pd_group", args)
		require.NoError(t, err)
		assert.Contains(t, yamlStr, "name: AZURE_CLIENT_ID")
		assert.Contains(t, yamlStr, "value: azure-client-id-1")
	})

	t.Run("without AZURE_CLIENT_ID", func(t *testing.T) {
		yamlStr, err := tl.Render("pd_group", baseArgs)
		require.NoError(t, err)
		assert.NotContains(t, yamlStr, "name: AZURE_CLIENT_ID")
	})
}

func Test_RenderTiDBGroup_AzureClientIDEnv(t *testing.T) {
	tl := initTemplateLibrary(t, []string{"tidb_group"})

	baseArgs := map[string]string{
		"ClusterId":                    "123",
		"SharedPoolId":                 "sp-1",
		"ComponentType":                "tidb",
		"ComponentGroup":               "db-tidb",
		"NodeSpec":                     "2c4g",
		"MinNodeCount":                 "1",
		"MaxNodeCount":                 "3",
		"Replicas":                     "3",
		"Topologies":                   "- topologyKey: topology.kubernetes.io/zone",
		"Version":                      "v9.0.0",
		"Image":                        "tidb:v9.0.0",
		"UserClusterId":                "cluster-1",
		"UserTenantId":                 "tenant-1",
		"Config":                       "[tidb]",
		"SlowLogImage":                 "busybox:1.0",
		"AuditLogImage":                "audit-ng:1.0",
		"ImagePullPolicy":              "IfNotPresent",
		"GOMEMLIMIT":                   "1024",
		"SlowLogStoragePath":           "/var/log/tidb",
		"SlowLogStorageSize":           "10",
		"SlowLogStorageClass":          "standard",
		"SlowLogVolumeAttributesClass": "vac",
		"PreStopSleepSeconds":          "35",
		"AuditLogConfig":               "logDir: /var/log/auditlog",
		"NodeVersion":                  "1.30",
	}

	t.Run("with AZURE_CLIENT_ID", func(t *testing.T) {
		args := copyStringMap(baseArgs)
		args["AZURE_CLIENT_ID"] = "azure-client-id-1"
		yamlStr, err := tl.Render("tidb_group", args)
		require.NoError(t, err)
		assert.Equal(t, 2, strings.Count(yamlStr, "name: AZURE_CLIENT_ID"))
		assert.Contains(t, yamlStr, "value: azure-client-id-1")
	})

	t.Run("without AZURE_CLIENT_ID", func(t *testing.T) {
		yamlStr, err := tl.Render("tidb_group", baseArgs)
		require.NoError(t, err)
		assert.NotContains(t, yamlStr, "name: AZURE_CLIENT_ID")
	})
}

func Test_RenderTiDBWorkerGroup_AzureClientIDEnv(t *testing.T) {
	tl := initTemplateLibrary(t, []string{"tidb_worker_group"})

	baseArgs := map[string]string{
		"ClusterId":       "123",
		"SharedPoolId":    "sp-1",
		"ComponentType":   "tidb-worker",
		"ComponentGroup":  "db-tidb-worker",
		"NodeSpec":        "2c4g",
		"MinNodeCount":    "1",
		"MaxNodeCount":    "3",
		"Replicas":        "3",
		"Topologies":      "- topologyKey: topology.kubernetes.io/zone",
		"Version":         "v9.0.0",
		"Image":           "tidb:v9.0.0",
		"Config":          "[tidb]",
		"SlowLogImage":    "busybox:1.0",
		"ImagePullPolicy": "IfNotPresent",
		"GOMEMLIMIT":      "1024",
		"NodeVersion":     "1.30",
	}

	t.Run("with AZURE_CLIENT_ID", func(t *testing.T) {
		args := copyStringMap(baseArgs)
		args["AZURE_CLIENT_ID"] = "azure-client-id-1"
		yamlStr, err := tl.Render("tidb_worker_group", args)
		require.NoError(t, err)
		assert.Contains(t, yamlStr, "name: AZURE_CLIENT_ID")
		assert.Contains(t, yamlStr, "value: azure-client-id-1")
	})

	t.Run("without AZURE_CLIENT_ID", func(t *testing.T) {
		yamlStr, err := tl.Render("tidb_worker_group", baseArgs)
		require.NoError(t, err)
		assert.NotContains(t, yamlStr, "name: AZURE_CLIENT_ID")
	})
}

func Test_RenderTiProxyGroup_AzureClientIDEnv(t *testing.T) {
	tl := initTemplateLibrary(t, []string{"tiproxy_group"})

	baseArgs := map[string]string{
		"ClusterId":       "123",
		"SharedPoolId":    "sp-1",
		"ComponentType":   "tiproxy",
		"ComponentGroup":  "db-tiproxy",
		"NodeSpec":        "2c4g",
		"MinNodeCount":    "1",
		"MaxNodeCount":    "3",
		"Replicas":        "3",
		"Topologies":      "- topologyKey: topology.kubernetes.io/zone",
		"Version":         "v9.0.0",
		"Image":           "tiproxy:v9.0.0",
		"Config":          "[tiproxy]",
		"ImagePullPolicy": "IfNotPresent",
		"NodeVersion":     "1.30",
		"UserClusterId":   "cluster-1",
		"UserTenantId":    "tenant-1",
		"TiProxyGracefulShutdownDeleteDelaySeconds": "86400",
		"TiProxyGracefulRestartMaxSurge":            "1024",
	}

	t.Run("with AZURE_CLIENT_ID", func(t *testing.T) {
		args := copyStringMap(baseArgs)
		args["AZURE_CLIENT_ID"] = "azure-client-id-1"
		yamlStr, err := tl.Render("tiproxy_group", args)
		require.NoError(t, err)
		assert.Contains(t, yamlStr, "name: AZURE_CLIENT_ID")
		assert.Contains(t, yamlStr, "value: azure-client-id-1")
		assert.Contains(t, yamlStr, `core.pingcap.com/tiproxy-graceful-shutdown-delete-delay-seconds: "86400"`)
		assert.Contains(t, yamlStr, "maxSurge: 1024")
	})

	t.Run("without AZURE_CLIENT_ID", func(t *testing.T) {
		yamlStr, err := tl.Render("tiproxy_group", baseArgs)
		require.NoError(t, err)
		assert.NotContains(t, yamlStr, "name: AZURE_CLIENT_ID")
	})
}

func initTemplateLibrary(t *testing.T, templates []string) *render.TemplateLibrary {
	t.Helper()
	tplPath := "../../../deployments/templates"
	templateLib := render.NewTemplateLibrary()

	for _, tpl := range templates {
		data, err := os.ReadFile(filepath.Join(tplPath, tpl+".templ"))
		require.NoError(t, err, "Failed to read template file: %s", tplPath)
		templateLib.SafeNewTemplate(tpl, string(data))
	}

	return templateLib
}

func copyStringMap(in map[string]string) map[string]string {
	out := make(map[string]string, len(in))
	for k, v := range in {
		out[k] = v
	}
	return out
}
