package jumper

import (
	"github.com/onsi/ginkgo/v2"
	"github.com/onsi/gomega"
	"github.com/tidbcloud/devops/pkg/infra/config"
	globalcommonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	"k8s.io/client-go/tools/clientcmd"
)

var _ = ginkgo.Describe("[PremiumAzure]", func() {
	ginkgo.Describe("newPremiumAKSAuth", func() {
		ginkgo.It("uses premium AKS auth when both premium and dedicated are configured", func() {
			auth := newPremiumAKSAuth(config.JumpServiceConfig{
				Premium: config.JumpServicePremiumConfig{
					PremiumAKSAuth: &config.JumpServiceDestinationAzureAuth{
						TenantID:               "premium-tenant",
						ClientID:               "premium-client",
						FederatedTokenFilepath: "/premium/token",
					},
				},
				Dedicated: config.JumpServiceDedicatedConfig{
					DedicatedAKSAuth: &config.JumpServiceDestinationAzureAuth{
						TenantID:               "dedicated-tenant",
						ClientID:               "dedicated-client",
						FederatedTokenFilepath: "/dedicated/token",
					},
				},
			})

			gomega.Expect(auth).ToNot(gomega.BeNil())
			gomega.Expect(auth.TenantID).To(gomega.Equal("premium-tenant"))
			gomega.Expect(auth.ClientID).To(gomega.Equal("premium-client"))
			gomega.Expect(auth.FederatedTokenFile).To(gomega.Equal("/premium/token"))
		})

		ginkgo.It("falls back to dedicated AKS auth when premium is not configured", func() {
			auth := newPremiumAKSAuth(config.JumpServiceConfig{
				Dedicated: config.JumpServiceDedicatedConfig{
					DedicatedAKSAuth: &config.JumpServiceDestinationAzureAuth{
						TenantID:               "tenant-id",
						ClientID:               "client-id",
						FederatedTokenFilepath: "/tmp/token",
					},
				},
			})

			gomega.Expect(auth).ToNot(gomega.BeNil())
			gomega.Expect(auth.TenantID).To(gomega.Equal("tenant-id"))
			gomega.Expect(auth.ClientID).To(gomega.Equal("client-id"))
			gomega.Expect(auth.FederatedTokenFile).To(gomega.Equal("/tmp/token"))
		})

		ginkgo.It("returns nil when neither premium nor dedicated AKS auth is configured", func() {
			auth := newPremiumAKSAuth(config.JumpServiceConfig{})
			gomega.Expect(auth).To(gomega.BeNil())
		})
	})

	ginkgo.Describe("buildPremiumDataplaneConfig", func() {
		ginkgo.It("builds Azure config with kubelogin and workload identity args", func() {
			rawConfig, err := clientcmd.Load([]byte(testKubeconfig("https://aks-premium.example.com")))
			gomega.Expect(err).ToNot(gomega.HaveOccurred())

			cfg, err := buildPremiumDataplaneConfig(premiumDataplaneConfigInput{
				ProviderID: globalcommonv1.CloudProvider_AZURE,
				K8sName:    "aks-premium",
				Endpoint:   "https://aks-premium.example.com",
				RawConfig:  rawConfig,
				AKSAuth: newPremiumAKSAuth(config.JumpServiceConfig{
					Premium: config.JumpServicePremiumConfig{
						PremiumAKSAuth: &config.JumpServiceDestinationAzureAuth{
							TenantID:               "tenant-id",
							ClientID:               "client-id",
							FederatedTokenFilepath: "/tmp/token",
						},
					},
				}),
			})
			gomega.Expect(err).ToNot(gomega.HaveOccurred())
			gomega.Expect(cfg.CurrentContext).To(gomega.Equal("aks-premium"))
			gomega.Expect(cfg.Clusters["aks-premium"].Server).To(gomega.Equal("https://aks-premium.example.com"))
			gomega.Expect(cfg.AuthInfos["aks-premium"].Exec.Command).To(gomega.Equal("kubelogin"))
			gomega.Expect(cfg.AuthInfos["aks-premium"].Exec.Args).To(gomega.ContainElement("workloadidentity"))
			gomega.Expect(cfg.AuthInfos["aks-premium"].Exec.Args).To(gomega.ContainElement("tenant-id"))
			gomega.Expect(cfg.AuthInfos["aks-premium"].Exec.Args).To(gomega.ContainElement("client-id"))
			gomega.Expect(cfg.AuthInfos["aks-premium"].Exec.Args).To(gomega.ContainElement("/tmp/token"))
		})

		ginkgo.It("returns explicit error for Azure when AKS auth is missing", func() {
			rawConfig, err := clientcmd.Load([]byte(testKubeconfig("https://aks-premium.example.com")))
			gomega.Expect(err).ToNot(gomega.HaveOccurred())

			_, err = buildPremiumDataplaneConfig(premiumDataplaneConfigInput{
				ProviderID: globalcommonv1.CloudProvider_AZURE,
				K8sName:    "aks-premium",
				Endpoint:   "https://aks-premium.example.com",
				RawConfig:  rawConfig,
			})
			gomega.Expect(err).To(gomega.MatchError("premium aks auth is not configured"))
		})

		ginkgo.It("builds AWS config with aws-iam-authenticator args", func() {
			rawConfig, err := clientcmd.Load([]byte(testKubeconfig("https://eks.example.com")))
			gomega.Expect(err).ToNot(gomega.HaveOccurred())

			cfg, err := buildPremiumDataplaneConfig(premiumDataplaneConfigInput{
				ProviderID:        globalcommonv1.CloudProvider_AWS,
				Region:            "us-east-1",
				K8sName:           "eks-premium",
				Endpoint:          "https://eks.example.com",
				RawConfig:         rawConfig,
				NewArchAccessRole: "arn:aws:iam::123456789:role/jump",
			})
			gomega.Expect(err).ToNot(gomega.HaveOccurred())
			gomega.Expect(cfg.CurrentContext).To(gomega.Equal("eks-premium"))
			gomega.Expect(cfg.Clusters["eks-premium"].Server).To(gomega.Equal("https://eks.example.com"))
			eksAuth := cfg.AuthInfos["eks-premium"].Exec
			gomega.Expect(eksAuth.Command).To(gomega.Equal("aws-iam-authenticator"))
			gomega.Expect(eksAuth.Args).To(gomega.ContainElement("eks-premium"))
			gomega.Expect(eksAuth.Args).To(gomega.ContainElement("us-east-1"))
			gomega.Expect(eksAuth.Args).To(gomega.ContainElement("arn:aws:iam::123456789:role/jump"))
		})

		ginkgo.It("returns unsupported cloud provider error for non-Azure/AWS provider", func() {
			rawConfig, err := clientcmd.Load([]byte(testKubeconfig("https://k8s.example.com")))
			gomega.Expect(err).ToNot(gomega.HaveOccurred())

			_, err = buildPremiumDataplaneConfig(premiumDataplaneConfigInput{
				ProviderID: globalcommonv1.CloudProvider_GCP,
				K8sName:    "gke-premium",
				Endpoint:   "https://k8s.example.com",
				RawConfig:  rawConfig,
			})
			gomega.Expect(err).To(gomega.HaveOccurred())
			gomega.Expect(err.Error()).To(gomega.ContainSubstring("unsupported cloud provider"))
		})
	})
})

func testKubeconfig(server string) string {
	return "apiVersion: v1\n" +
		"clusters:\n" +
		"- cluster:\n" +
		"    server: " + server + "\n" +
		"  name: cluster\n" +
		"contexts:\n" +
		"- context:\n" +
		"    cluster: cluster\n" +
		"    user: user\n" +
		"  name: ctx\n" +
		"current-context: ctx\n" +
		"kind: Config\n" +
		"users:\n" +
		"- name: user\n" +
		"  user: {}\n"
}
