package k8s

import (
	"context"
	"net/url"
	"path"

	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/types"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
	AWSRoleARNEnvKey              = "AWS_ROLE_ARN"
	AWSWebIdentityTokenFileEnvKey = "AWS_WEB_IDENTITY_TOKEN_FILE" // #nosec G101
)

// PrepareGCP2AWSIdentitySidecar constructs a side-car container for GCP to AWS auth
// ref https://github.com/tidbcloud/dbaas/blob/5e2e94e1a32f5757b0542eab715192cf0dce43d5/pkg/k8s/k8sutils/k8sutils.go#L80
func PrepareGCP2AWSIdentitySidecar(
	roleArn string,
	identityImage string,
) (sidecar corev1.Container, vol corev1.Volume, volMount corev1.VolumeMount, envs []corev1.EnvVar) {
	vol = corev1.Volume{
		Name: "identity",
		VolumeSource: corev1.VolumeSource{
			EmptyDir: &corev1.EmptyDirVolumeSource{},
		},
	}

	envs = []corev1.EnvVar{{
		Name:  AWSWebIdentityTokenFileEnvKey,
		Value: "/identity/token",
	}, {
		Name:  AWSRoleARNEnvKey,
		Value: roleArn,
	}}

	volMount = corev1.VolumeMount{
		Name:      "identity",
		MountPath: "/identity",
	}

	sidecar = corev1.Container{
		Name:  "auth",
		Image: identityImage,
		Env: []corev1.EnvVar{{
			Name:  AWSWebIdentityTokenFileEnvKey,
			Value: "/identity/token",
		}},
		VolumeMounts: []corev1.VolumeMount{{
			Name:      "identity",
			MountPath: "/identity",
		}},
	}

	return sidecar, vol, volMount, envs
}

func URLJoint(base string, apiPath string) (string, error) {
	u, err := url.Parse(base)

	if err != nil {
		return "", err
	}

	u.Path = path.Join(u.Path, apiPath)
	taskURL := u.String()
	return taskURL, nil
}

// IsObjDeleted checks if the given object has been deleted.
func IsObjDeleted(ctx context.Context,
	infraCli client.Client,
	nsName types.NamespacedName, obj client.Object) (bool, error) {
	if err := infraCli.Get(ctx, nsName, obj); err != nil {
		if errors.IsNotFound(err) {
			return true, nil
		}
		return false, err
	}
	return false, nil
}

// IsDeploymentReady checks if the deployment is ready,
// i.e., availableReplicas == replicas
func IsDeploymentReady(ctx context.Context,
	tenantCli client.Client,
	nsName types.NamespacedName) (bool, error) {
	dp := appsv1.Deployment{}
	if err := tenantCli.Get(ctx, types.NamespacedName{
		Namespace: nsName.Namespace,
		Name:      nsName.Name,
	}, &dp); err != nil {
		return false, err
	}
	return dp.Status.ReadyReplicas == *dp.Spec.Replicas, nil
}
