package common

import (
	"strings"
	"testing"

	"github.com/stretchr/testify/require"
	"helm.sh/helm/v3/pkg/chart/loader"
	"helm.sh/helm/v3/pkg/chartutil"
	"helm.sh/helm/v3/pkg/engine"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-provider/pkg/config"
)

func TestClusterAgentHelmTemplateIncludesGKEPolicyControlStartupArgs(t *testing.T) {
	cfg := &ClusterAgentConfig{
		agentConf: config.ClusterAgentConfig{},
		cluster: &cloudv1.Cluster{
			ObjectMeta: metav1.ObjectMeta{
				Name: "123",
				Labels: map[string]string{
					cloudv1.ProviderTypeLabel: cloudv1.ProviderTypeGKE,
					cloudv1.RegionLabel:       "us-west1",
				},
			},
			Spec: cloudv1.ClusterSpec{
				Kubernetes: cloudv1.Kubernetes{
					Account: "cluster-project",
					Name:    "dedicated-dev-us-west1-abc",
				},
			},
		},
		tidbOperatorVersion: "v1",
	}
	values := cfg.ToHelmValues()
	clusterAgentValues := values["clusterAgent"].(map[string]interface{})
	args := clusterAgentValues["args"].(map[string]interface{})
	serviceAccountValues := values["serviceAccount"].(map[string]interface{})
	require.Equal(t, "cluster-project", args["gkePolicyControlProjectID"])
	require.Equal(t, "us-west1", args["gkePolicyControlLocation"])
	require.Equal(t, "dedicated-dev-us-west1-abc", args["gkePolicyControlClusterName"])
	require.Equal(t, "cluster-project", args["gkePolicyControlFleetProjectID"])
	require.NotContains(t, args, "gkePolicyControlMembershipID")
	require.Equal(t, "cluster-agent-123", serviceAccountValues["name"])

	ch, err := loader.Load("../../../../../helm-charts/cluster-agent")
	require.NoError(t, err)
	renderValues, err := chartutil.ToRenderValues(ch, values, chartutil.ReleaseOptions{
		Name:      cfg.GetName(),
		Namespace: "tidb123",
		Revision:  1,
		IsInstall: true,
	}, nil)
	require.NoError(t, err)
	rendered, err := engine.Render(ch, renderValues)
	require.NoError(t, err)

	var deployment string
	var roleBinding string
	var clusterRoleBinding string
	for name, content := range rendered {
		if strings.HasSuffix(name, "/templates/deployment.yaml") {
			deployment = content
		}
		if strings.HasSuffix(name, "/templates/rolebinding.yaml") {
			roleBinding = content
		}
		if strings.HasSuffix(name, "/templates/clusterrolebinding.yaml") {
			clusterRoleBinding = content
		}
	}
	require.NotEmpty(t, deployment)
	require.NotEmpty(t, roleBinding)
	require.NotEmpty(t, clusterRoleBinding)
	require.Contains(t, deployment, "--gke-policy-control-project-id")
	require.Contains(t, deployment, "--gke-policy-control-location")
	require.Contains(t, deployment, "--gke-policy-control-cluster-name")
	require.Contains(t, deployment, "--gke-policy-control-fleet-project-id")
	require.Contains(t, deployment, "serviceAccountName: cluster-agent-123")
	require.Contains(t, roleBinding, "- kind: ServiceAccount\n  name: cluster-agent-123\n  namespace: tidb123")
	require.Contains(t, clusterRoleBinding, "- kind: ServiceAccount\n    name: cluster-agent-123\n    namespace: tidb123")
}

func TestClusterAgentHelmTemplateRejectsReservedEnvOverrides(t *testing.T) {
	ch, err := loader.Load("../../../../../helm-charts/cluster-agent")
	require.NoError(t, err)

	values := map[string]interface{}{
		"clusterAgent": map[string]interface{}{
			"env": []map[string]interface{}{
				{
					"name":  "POD_NAMESPACE",
					"value": "tidb-other",
				},
			},
		},
	}
	renderValues, err := chartutil.ToRenderValues(ch, values, chartutil.ReleaseOptions{
		Name:      "cluster-agent-123",
		Namespace: "tidb123",
		Revision:  1,
		IsInstall: true,
	}, nil)
	require.NoError(t, err)

	_, err = engine.Render(ch, renderValues)
	require.ErrorContains(t, err, "clusterAgent.env must not set reserved environment variable POD_NAMESPACE")
}
