package log_agent

import (
	"context"

	"github.com/pingcap/errors"
	corev1 "k8s.io/api/core/v1"
	v1 "k8s.io/api/scheduling/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-api/pkg/consts"
	"github.com/tidbcloud/infra-api/pkg/o11y"
)

const (
	loggingNamespace = "logging"
)

func AddO11yIDToNetwork(c *cloudv1.Network, o11yID string) {
	if c.Annotations == nil {
		c.Annotations = make(map[string]string)
	}
	c.Annotations[consts.O11yIDAnnotationKey] = o11yID
}

func GetLogStorageInfo(storages []o11y.StorageInfo) (bucket string, err error) {
	for _, storage := range storages {
		if storage.Category == o11y.LOGS {
			return storage.BucketName, nil
		}
	}
	return "", errors.New("no log storage found")
}

func EnsureAgentPriorityClass(ctx context.Context, shootClient client.Client) error {
	priorityClass := &v1.PriorityClass{
		ObjectMeta: metav1.ObjectMeta{
			Name: NodeCriticalPriorityClassName,
		},
		// Maximum allowed value of a user defined priority is 1000000000
		Value:         1000000000 - 1,
		GlobalDefault: false,
		Description:   "Priority class for o11y log agent",
	}
	_, err := controllerutil.CreateOrUpdate(ctx, shootClient, priorityClass, func() error { return nil })
	if err != nil {
		return errors.Annotate(err, "fail to create or update priority class")
	}
	return nil
}

// tenantID fallbacks to "unknown", projectID fallbacks to "network.name"
func GetIDsFromNetworkCRD(n *cloudv1.Network) (tenantID, projectID string) {
	if v, ok := n.Labels[consts.ProjectTagKey]; ok && v != "" {
		projectID = v
	} else {
		projectID = n.Name
	}
	if v, ok := n.Labels[consts.TenantTagKey]; ok && v != "" {
		tenantID = v
	} else {
		tenantID = o11y.DefaultTenantLabelValue
	}
	return tenantID, projectID
}

func EnsureLoggingNamespace(ctx context.Context, shootClient client.Client) error {
	ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: loggingNamespace}}
	err := shootClient.Create(ctx, &ns)
	if err != nil && !apierrors.IsAlreadyExists(err) {
		return errors.Annotate(err, "failed to create logging namespace")
	}
	return nil
}
