package dataplane

import (
	"context"

	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
	"sigs.k8s.io/controller-runtime/pkg/client"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	compatcst "github.com/tidbcloud/infra-provider/pkg/compat/consts"
	"github.com/tidbcloud/infra-provider/pkg/k8s"
)

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

type eksTenantClientMngr struct {
	network cloudv1.Network
	option  client.Options
}

func NewEKSClientManager(network cloudv1.Network, opt client.Options) k8s.ClientManager {
	return &eksTenantClientMngr{
		network: network,
		option:  opt,
	}
}

func NewEKSClientManagerCompat(cli client.Client, network cloudv1.Network, opt client.Options) k8s.ClientManager {
	_, ok := network.Annotations[compatcst.CompatFlagAnnotation]
	if !ok {
		// If the network is not a compat network, use the original network manager.
		return k8s.NewEKSClientManager(cli, opt)
	}
	return NewEKSClientManager(network, opt)
}

func (t *eksTenantClientMngr) GetClient(ctx context.Context, cluster client.ObjectKey) (client.Client, error) {
	restCfg, err := t.GetConfig(ctx, cluster)
	if err != nil {
		return nil, err
	}
	cli, err := client.New(restCfg, t.option)
	if err != nil {
		return nil, err
	}
	return cli, nil
}

func (t *eksTenantClientMngr) GetConfig(ctx context.Context, eksKey client.ObjectKey) (*rest.Config, error) {
	region := t.network.Spec.Region
	eksname := eksKey.Name
	args := []string{
		"token",
		"--region", region,
		"--cluster-id", eksname,
	}

	if role, ok := t.network.Annotations[compatcst.CompatAWSDataPlaneAssumeRoleArn]; ok {
		args = append(args, "--role", role)
	}
	if externalId, ok := t.network.Annotations[compatcst.CompatAWSDataPlaneAssumeExternalId]; ok {
		args = append(args, "--external-id", externalId)
	}

	cfg := clientcmdapi.NewConfig()

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

	cluster := clientcmdapi.NewCluster()
	ca, ok := t.network.Annotations[compatcst.CompatK8SCAAnnotation]
	if ok {
		// compat api will return ca not as base64 encoded
		cluster.CertificateAuthorityData = []byte(ca)
	} else {
		cluster.InsecureSkipTLSVerify = true
	}

	cluster.Server = t.network.Annotations[compatcst.CompatK8SEndpointAnnotation]

	auth := clientcmdapi.NewAuthInfo()
	auth.Exec = &clientcmdapi.ExecConfig{
		APIVersion:      execConfigAPIVersion,
		InteractiveMode: clientcmdapi.NeverExecInteractiveMode,
		Command:         "aws-iam-authenticator",
		Args:            args,
	}

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

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

var _ k8s.ClientManager = &eksTenantClientMngr{}
