package dbhubsdk

import (
	"context"
	"dataservices/commons/config"
	"dataservices/commons/constants"
	"dataservices/internal/repository_ddb"
	"fmt"

	"github.com/aws/aws-sdk-go-v2/service/dynamodb"
)

type UserMetaProvider interface {
	// UserMetaProvider decouples connection target lookup from the caller so AWS
	// can keep the DDB-backed lookup while AliCloud regional uses static routes.
	GetUserMeta(ctx context.Context, projectId, clusterId uint64) (*TidbUserMeta, error)
}

type ddbUserMetaProvider struct {
	client *dynamodb.Client
}

// staticRouteUserMetaProvider is the AliCloud V2 path: regional no longer reads
// DDB for serverless routing and instead resolves host/port from local config.
type staticRouteUserMetaProvider struct{}

func NewStaticRouteUserMetaProvider() UserMetaProvider {
	return &staticRouteUserMetaProvider{}
}

func (p *ddbUserMetaProvider) GetUserMeta(ctx context.Context, projectId, clusterId uint64) (*TidbUserMeta, error) {
	if p.client == nil {
		return nil, fmt.Errorf("DBHubSdkImpl ddb client doesn't initialize")
	}

	// Legacy AWS path: resolve the actual connect target from user_cluster_info in DDB.
	info, err := repository_ddb.GetUserClusterInfo(ctx, p.client, projectId, clusterId)
	if err != nil {
		return nil, err
	}
	host := info.Host
	port := int(info.Port)
	if info.IsDedicate {
		if info.PrivateDNS == "" {
			return nil, fmt.Errorf("dedicate cluster %v doesn't have available privale link", clusterId)
		}
		host = info.PrivateDNS
	} else if port == 0 {
		return nil, fmt.Errorf("serverless cluster %v doesn't have port in ddb", clusterId)
	}
	return &TidbUserMeta{
		Host:       host,
		Port:       port,
		ClusterId:  clusterId,
		IsDedicate: info.IsDedicate,
		Cloud:      info.Cloud,
	}, nil
}

func (p *staticRouteUserMetaProvider) GetUserMeta(ctx context.Context, projectId, clusterId uint64) (*TidbUserMeta, error) {
	// AliCloud V2 path: project_id + cluster_id are mapped to a preloaded static route.
	route, ok := config.Global().ServerlessConf.FindStaticRoute(projectId, clusterId)
	if !ok {
		return nil, fmt.Errorf("static route not found for project_id=%d cluster_id=%d", projectId, clusterId)
	}
	useTLS := route.UseTLS
	cloud := route.Cloud
	if cloud == "" {
		cloud = constants.ClusterCloudProviderAliCloud
	}
	return &TidbUserMeta{
		Host:       route.Host,
		Port:       route.Port,
		ClusterId:  clusterId,
		IsDedicate: false,
		Cloud:      cloud,
		UseTLS:     &useTLS,
	}, nil
}
