package utils

import (
	"context"
	"errors"

	"github.com/pingcap/log"
	"github.com/tidbcloud/config-service/api/v1alpha1"
	"go.uber.org/zap"
	"k8s.io/apimachinery/pkg/types"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

// findClusterConfig find cluster config cr by tenant and cluster name
func findClusterConfig(c client.Client, tenant, cluster string) (*v1alpha1.ClusterConfig, error) {
	ccs := &v1alpha1.ClusterConfigList{}
	ctx := context.Background()
	labels := map[string]string{v1alpha1.TenentLabel: tenant}
	if cluster != "" {
		labels[v1alpha1.ClusterLabel] = cluster
		if err := c.List(ctx, ccs, client.MatchingLabels(labels)); err != nil {
			return nil, err
		}
		if len(ccs.Items) == 1 {
			return &ccs.Items[0], nil
		}
	}

	labels[v1alpha1.ClusterLabel] = v1alpha1.AllCluster
	if err := c.List(ctx, ccs, client.MatchingLabels(labels)); err != nil {
		return nil, err
	}
	if len(ccs.Items) == 1 {
		return &ccs.Items[0], nil
	}

	cc := &v1alpha1.ClusterConfig{}
	if err := c.Get(ctx, types.NamespacedName{
		Name: v1alpha1.BaseClusterConfig,
	}, cc); err != nil {
		return nil, err
	}
	return cc, nil
}

func validateClusterConfig(cc *v1alpha1.ClusterConfig) error {
	if cc.Spec.ConfigMeta == nil {
		// should not nil
		log.Warn("malformed cluster config, config meta is nil", zap.String("name", cc.Name))
		return errors.New("malformed cluster config, config meta is nil")
	}
	return nil
}

// FindAndValidateClusterConfig will find and validate cluster config.
func FindAndValidateClusterConfig(c client.Client, tenant, cluster string) (*v1alpha1.ClusterConfig, error) {
	cc, err := findClusterConfig(c, tenant, cluster)
	if err != nil {
		return nil, err
	}
	if err := validateClusterConfig(cc); err != nil {
		return nil, err
	}
	return cc, nil
}
