package gitopsmigrate

import (
	"context"
	"errors"
	"fmt"
	"strings"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"k8s.io/apimachinery/pkg/labels"

	"sigs.k8s.io/controller-runtime/pkg/client"

	pb "github.com/tidbcloud/config-center/proto/config_center"
)

func ccformat(configType string) pb.Format {
	switch configType {
	case "backup", "restore":
		return pb.Format_JSON
	default:
		return pb.Format_TOML
	}
}

func toGitopsFilename(name string) string {
	switch name {
	case "tidb", "tikv", "tiflash", "pd", "ticdc", "tiproxy":
		return name + ".toml"
	case "tiflash_learner":
		return "tiflash-learner.toml"
	case "restore", "backup":
		return name + ".yaml"
	case  "tidb-lightning":
		return "lightning.toml"
	}
	panic("unknown filename " + name)
}

func toGitopsFormat(name string) string {
	return toGitopsFilename(name)[len(name)+1:]
}

func fromGitopsFilename(name string) string {
	switch name {
	case "tidb.toml", "tikv.toml", "tiflash.toml", "pd.toml", "ticdc.toml", "tiproxy.toml":
		return strings.TrimSuffix(name, ".toml")
	case "tiflash-learner.toml":
		return "tiflash_learner"
	case "restore.yaml", "backup.yaml":
		return strings.TrimSuffix(name, ".yaml")
	case "lightning.toml":
		return "tidb-lightning"
	}
	panic("unknown filename " + name)
}

func getComponentFromSlice(components []*pb.ClusterComponent, name string) *pb.ClusterComponent {
	for _, c := range components {
		if c.ComponentName == name {
			return c
		}
	}
	return nil
}

func getConfigFromSlice(configs []*pb.ConfigurationFile, name string) *pb.ConfigurationFile {
	for _, c := range configs {
		if c.ConfigurationType == name {
			return c
		}
	}
	return nil
}

func GetConfigRevisionByCluster(ctx context.Context, cli client.Client, cluster *cloudv1.Cluster) (*cloudv1.ConfigRevision, error) {
	if cluster.Spec.ConfigRevisionRef == nil || cluster.Spec.ConfigRevisionRef.Name == "" {
		return nil, errors.New("cluster has no config revision")
	}

	cr := &cloudv1.ConfigRevision{}
	key := client.ObjectKey{Name: cluster.Spec.ConfigRevisionRef.Name}
	if err := cli.Get(ctx, key, cr); err != nil {
		return nil, fmt.Errorf("failed to get config revision %s: %s", key, err)
	}

	return cr, nil
}

func GetInfraCluster(ctx context.Context, cli client.Client, clusterId string, projectID uint64) (*cloudv1.Cluster, error) {
	var list cloudv1.ClusterList
	if err := cli.List(ctx, &list, client.MatchingLabelsSelector{
		Selector: labels.Set{
			cloudv1.ClusterTagKey: clusterId,
		}.AsSelector(),
	}, &client.ListOptions{Namespace: fmt.Sprintf("prod-%d", projectID)}); err != nil {
		return nil, fmt.Errorf("failed to list clusters: %w", err)
	}

	if len(list.Items) == 0 {
		return nil, fmt.Errorf("found zero cluster with label %s=%s", cloudv1.ClusterTagKey, clusterId)
	}

	if len(list.Items) > 1 {
		return nil, fmt.Errorf("found more than one cluster with label %s=%s", cloudv1.ClusterTagKey, clusterId)
	}

	return &list.Items[0], nil
}
