package infraapi

import (
	"context"
	"strconv"

	"github.com/pingcap/errors"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/pkgv2/tracing"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
)

// GetRestore gets the restore CR for the project and name.
func (a *API) GetRestore(ctx context.Context, projectID uint64, restoreName string) (*cloudv1.Restore, error) {
	var (
		ns      = Namespace(a.projectName, projectID)
		restore cloudv1.Restore
	)
	err := a.client.Get(ctx, types.NamespacedName{Namespace: ns, Name: restoreName}, &restore)
	if err != nil {
		return nil, errors.Annotatef(err, "get restore CR %q in namespace %q failed", restoreName, ns)
	}
	return &restore, nil
}

// CreateRestoreIgnoreExists creates the restore CR for the cluster and backup, and ignore the already exists error.
func (a *API) CreateRestoreIgnoreExists(ctx context.Context, tenantID, projectID, clusterID uint64, clusterName, backupName, restoreName string) (err error) {
	ctx, span := Tracer.Start(ctx, "API.CreateRestoreIgnoreExists")
	defer func() { tracing.EndSpan(span, err) }()
	restore := &cloudv1.Restore{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: Namespace(a.projectName, projectID),
			Name:      restoreName,
			Labels: map[string]string{
				tenantLabel:  strconv.FormatUint(tenantID, 10),
				projectLabel: strconv.FormatUint(projectID, 10),
				clusterLabel: strconv.FormatUint(clusterID, 10),
			},
		},
		Spec: cloudv1.RestoreSpec{
			ClusterName: clusterName,
			From: cloudv1.From{
				Backup: backupName,
			},
		},
	}
	err = a.client.Create(ctx, restore)
	if err != nil && !apierrors.IsAlreadyExists(err) {
		return errors.Annotatef(err, "create restore CR %q for cluster %q in namespace %q failed", restore.Name, restore.Spec.ClusterName, restore.Namespace)
	}
	return nil
}

// DeleteRestoreIgnoreNotFound deletes the restore CR and ignore the not found error.
func (a *API) DeleteRestoreIgnoreNotFound(ctx context.Context, projectID uint64, restoreName string) error {
	restore := &cloudv1.Restore{ObjectMeta: metav1.ObjectMeta{
		Namespace: Namespace(a.projectName, projectID),
		Name:      restoreName,
	}}
	err := a.client.Delete(ctx, restore)
	if err != nil && !apierrors.IsNotFound(err) {
		return errors.Annotatef(err, "delete restore CR %q in namespace %q failed", restoreName, restore.Namespace)
	}
	return nil
}
