package dataplane

import (
	"context"
	"fmt"

	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

const (
	execConfigAPIVersion = "client.authentication.k8s.io/v1beta1"
)

func NewRESTConfigForEKS(k8sName, endpoint, region, roleARN, externalId string, ca []byte) (*rest.Config, error) {
	args := []string{
		"token",
		"--cluster-id", k8sName,
	}

	if region != "" {
		args = append(args, "--region", region)
	}

	if roleARN != "" {
		args = append(args, "--role", roleARN)
	}

	if externalId != "" {
		args = append(args, "--external-id", externalId)
	}

	cfg := clientcmdapi.NewConfig()

	cfgctx := clientcmdapi.NewContext()
	cfgctx.Cluster = k8sName
	cfgctx.AuthInfo = k8sName

	cluster := clientcmdapi.NewCluster()
	if len(ca) != 0 {
		cluster.CertificateAuthorityData = ca
	} else {
		cluster.InsecureSkipTLSVerify = true
	}

	cluster.Server = endpoint

	auth := clientcmdapi.NewAuthInfo()
	// TODO: use aws cli to replace aws-iam-authenticator?
	auth.Exec = &clientcmdapi.ExecConfig{
		APIVersion:      execConfigAPIVersion,
		InteractiveMode: clientcmdapi.NeverExecInteractiveMode,
		Command:         "aws-iam-authenticator",
		Args:            args,
	}

	cfg.Contexts[k8sName] = cfgctx
	cfg.Clusters[k8sName] = cluster
	cfg.AuthInfos[k8sName] = auth
	cfg.CurrentContext = k8sName

	kubecfg, err := clientcmd.NewDefaultClientConfig(*cfg, nil).ClientConfig()
	if err != nil {
		tilog.Error(context.Background(), "new default client config", zap.Any("args", args), zap.Error(err))
		return nil, fmt.Errorf("new default client config: %w", err)
	}
	return kubecfg, nil
}

func NewRESTConfigForGKE(name, endpoint string, ca []byte) (*rest.Config, error) {
	cfg := clientcmdapi.NewConfig()

	cfgctx := clientcmdapi.NewContext()
	cfgctx.Cluster = name
	cfgctx.AuthInfo = name

	cluster := clientcmdapi.NewCluster()
	if len(ca) != 0 {
		cluster.CertificateAuthorityData = ca
	} else {
		cluster.InsecureSkipTLSVerify = true
	}
	cluster.Server = endpoint

	auth := clientcmdapi.NewAuthInfo()
	auth.Exec = &clientcmdapi.ExecConfig{
		APIVersion:      execConfigAPIVersion,
		InteractiveMode: clientcmdapi.NeverExecInteractiveMode,
		Command:         "gke-gcloud-auth-plugin",
		Args:            []string{"--use_application_default_credentials"},
	}

	cfg.Contexts[name] = cfgctx
	cfg.Clusters[name] = cluster
	cfg.AuthInfos[name] = auth
	cfg.CurrentContext = name

	return clientcmd.NewDefaultClientConfig(*cfg, nil).ClientConfig()
}

func NewRESTConfigForKubeConfig(
	kubeconfigData []byte,
) (*rest.Config, error) {
	config, err := clientcmd.Load(kubeconfigData)
	if err != nil {
		return nil, err
	}

	return clientcmd.NewDefaultClientConfig(*config, &clientcmd.ConfigOverrides{}).ClientConfig()
}
