package clusterproxy

import (
	"context"

	"github.com/tidbcloud/pkgv2/clusterproxy"

	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

//go:generate go run go.uber.org/mock/mockgen@latest -source=$GOFILE -package=mock_$GOPACKAGE -destination=./mock_$GOPACKAGE/mock_$GOFILE
type Provider interface {
	GetClusterProxy(
		ctx context.Context,
		clusterID uint64,
		proxyBaseUrl, tidbVersion string,
		proxyOp *clusterproxy.ClusterOperator,
	) (ClusterProxy, bizerr.BizError)
}

type clusterProxyProviderImp struct {
	awsPcaArn,
	auth0Domain,
	auth0ClientID,
	auth0ClientSecret,
	auth0Audience string
}

type nextGenClusterProxyProviderImp struct {
	auth0Domain,
	auth0ClientID,
	auth0ClientSecret,
	auth0Audience string
}

func NewNextGenClusterProxyProvider(
	auth0Domain,
	auth0ClientID,
	auth0ClientSecret,
	auth0Audience string,
) Provider {
	return &nextGenClusterProxyProviderImp{
		auth0Domain:       auth0Domain,
		auth0ClientID:     auth0ClientID,
		auth0ClientSecret: auth0ClientSecret,
		auth0Audience:     auth0Audience,
	}
}

func NewClusterProxyProvider(
	awsPcaArn,
	auth0Domain,
	auth0ClientID,
	auth0ClientSecret,
	auth0Audience string,
) Provider {
	return &clusterProxyProviderImp{
		awsPcaArn:         awsPcaArn,
		auth0Domain:       auth0Domain,
		auth0ClientID:     auth0ClientID,
		auth0ClientSecret: auth0ClientSecret,
		auth0Audience:     auth0Audience,
	}
}

func (c *nextGenClusterProxyProviderImp) GetClusterProxy(
	ctx context.Context,
	clusterID uint64,
	proxyBaseUrl, tidbVersion string,
	proxyOp *clusterproxy.ClusterOperator,
) (ClusterProxy, bizerr.BizError) {
	if proxyBaseUrl == "" || tidbVersion == "" {
		return nil, bizerr.New(bizerr.ErrCodeUnknown, "the clusterCr is not ready for access it via proxy")
	}

	input := &Input{
		Cfg: ProxyConfig{
			Auth0Domain:       c.auth0Domain,
			Auth0ClientID:     c.auth0ClientID,
			Auth0ClientSecret: c.auth0ClientSecret,
			Auth0Audience:     c.auth0Audience,
		},
		ClusterID: clusterID,
		BaseURL:   proxyBaseUrl,
		Version:   tidbVersion,
		Timeout:   30,
	}

	proxy, err := NewNextGenClusterProxy(ctx, input, proxyOp)
	if err != nil {
		return nil, bizerr.WrapError(err, "get nextgen cluster proxy failed")
	}

	return proxy, nil
}

func (c *clusterProxyProviderImp) GetClusterProxy(
	ctx context.Context,
	clusterID uint64,
	proxyBaseUrl, tidbVersion string,
	proxyOp *clusterproxy.ClusterOperator,
) (ClusterProxy, bizerr.BizError) {
	if proxyBaseUrl == "" || tidbVersion == "" {
		return nil, bizerr.New(bizerr.ErrCodeUnknown, "the clusterCr is not ready for access it via proxy")
	}

	p, err := NewClusterProxy(
		ctx,
		&Input{
			PcaARN: c.awsPcaArn,
			Cfg: ProxyConfig{
				Auth0Domain:       c.auth0Domain,
				Auth0ClientID:     c.auth0ClientID,
				Auth0ClientSecret: c.auth0ClientSecret,
				Auth0Audience:     c.auth0Audience,
			},
			ClusterID: clusterID,
			BaseURL:   proxyBaseUrl,
			Version:   tidbVersion,
			Timeout:   30,
		},
		proxyOp,
	)
	if err != nil {
		return nil, bizerr.WrapError(err, "get cluster proxy failed")
	}

	return p, nil
}
