package controller

import (
	"github.com/pingcap/tidb-operator/pkg/backup/constants"
	"github.com/pingcap/tidb-operator/pkg/label"
	corev1 "k8s.io/api/core/v1"
	rbacv1beta1 "k8s.io/api/rbac/v1beta1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (c *Controller) CreateTiDBBackupRBAC(namespace string) error {
	err := c.CreateServiceAccount(constants.DefaultServiceAccountName, namespace)
	if err != nil {
		return err
	}

	err = c.CreateTiDBBackupRole(namespace)
	if err != nil {
		return err
	}

	err = c.CreateTiDBBackupRoleBinding(namespace)
	if err != nil {
		return err
	}

	return nil
}

func (c *Controller) CreateServiceAccount(name, namespace string) error {
	sa := &corev1.ServiceAccount{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
		},
	}

	_, err := c.kubeCli.CoreV1().ServiceAccounts(namespace).Create(sa)
	if err != nil && !errors.IsAlreadyExists(err) {
		return err
	}
	return nil
}

func (c *Controller) CreateTiDBBackupRole(namespace string) error {
	role := &rbacv1beta1.Role{
		ObjectMeta: metav1.ObjectMeta{
			Name:   constants.DefaultServiceAccountName,
			Labels: map[string]string{label.ComponentLabelKey: constants.DefaultServiceAccountName},
		},
		Rules: []rbacv1beta1.PolicyRule{
			{
				APIGroups: []string{""},
				Resources: []string{"events"},
				Verbs:     []string{"*"},
			},
			{
				APIGroups: []string{"pingcap.com"},
				Resources: []string{"backups", "restores"},
				Verbs:     []string{"get", "watch", "list", "update"},
			},
		},
	}

	_, err := c.kubeCli.RbacV1beta1().Roles(namespace).Create(role)
	if err != nil {
		return err
	}
	return nil
}

func (c *Controller) CreateTiDBBackupRoleBinding(namespace string) error {
	roleBinding := &rbacv1beta1.RoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name:   constants.DefaultServiceAccountName,
			Labels: map[string]string{label.ComponentLabelKey: constants.DefaultServiceAccountName},
		},
		Subjects: []rbacv1beta1.Subject{
			{
				Kind: rbacv1beta1.ServiceAccountKind,
				Name: constants.DefaultServiceAccountName,
			},
		},
		RoleRef: rbacv1beta1.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "Role",
			Name:     constants.DefaultServiceAccountName,
		},
	}

	_, err := c.kubeCli.RbacV1beta1().RoleBindings(namespace).Create(roleBinding)
	if err != nil {
		return err
	}
	return nil
}
