package common

import (
	"context"
	"errors"
	"fmt"

	"github.com/pingcap-inc/clinic/clinic_data_service/pkg/cache"
	"github.com/pingcap-inc/clinic/clinic_data_service/pkg/log"
	"github.com/pingcap-inc/clinic/clinic_data_service/pkg/model"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

func GetCluster(ctx context.Context, clusterID string) (*model.Cluster, error) {
	cacheKey := fmt.Sprintf("cluster:%s", clusterID)

	return cache.GetWithCache(ctx, cache.ClusterCache, cacheKey, func() (*model.Cluster, error) {
		return getClusterFromDB(ctx, clusterID)
	})
}
func GetOrgId(ctx context.Context, clusterID string) (string, error) {

	cluster, err := GetCluster(ctx, clusterID)
	if err != nil {
		log.Error(ctx, "get cluster org id from db failed", zap.Error(err))
		return "", err
	}
	return cluster.OrgID, nil
}

func getClusterFromDB(ctx context.Context, clusterID string) (*model.Cluster, error) {
	dao := NewCommonDAO()
	var out model.Cluster
	err := dao.GetEntity(ctx, ComFilter{
		ModelFilters: model.Cluster{ClusterID: clusterID},
	}, &out)

	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, err
		}
		log.Error(ctx, "get cluster system failed", zap.Error(err))
		return nil, err
	}
	return &out, nil
}

// ListOrgClusters lists all clusters in the database
// ListOrgClusters lists all clusters in the database.
// It returns a map of org ID to cluster.
func ListOrgClusters(ctx context.Context) (map[string][]model.Cluster, error) {
	var clusters []model.Cluster
	err := NewCommonDAO().ListEntities(ctx, ListParams{
		ModelFilters: model.Cluster{SkipCheck: false},
	}, &clusters)
	if err != nil {
		log.Error(ctx, "list clusters failed: %v", zap.Error(err))
		return nil, err
	}
	clusterMap := make(map[string][]model.Cluster)
	for _, cluster := range clusters {
		clusterMap[cluster.OrgID] = append(clusterMap[cluster.OrgID], cluster)
	}
	return clusterMap, nil
}
