package api

import (
	"context"
	"encoding/base64"

	"github.com/tidbcloud/pkgv2/log"
	"github.com/tidbcloud/ticdc-service/pkg/clusterproxy/client"
)

var _ SQLClient = &sqlClientImpl{}

// SQLClient defines the interface for SQL operations
type SQLClient interface {
	// QuerySQL sends a SQL query to the target cluster and returns the result
	QuerySQL(ctx context.Context, operator *ClusterOperator, sql string, dest interface{}) error
}

// SQLClientGetter defines the interface for getting a SQL client
type SQLClientGetter interface {
	SQLClient() SQLClient
}

type AuthMethod string

const (
	querySQLPATH = "/v1beta1/query"

	// AuthMethodPassword is the password auth method
	AuthMethodPassword AuthMethod = "password"
	AuthMethodToken    AuthMethod = "token"
)

type sqlClientImpl struct {
	client client.Client
}

// NewSQLClient creates a new instance of the SQLClient with the given client
func NewSQLClient(client client.Client) SQLClient {
	return &sqlClientImpl{
		client: client,
	}
}

func (p *sqlClientImpl) QuerySQL(ctx context.Context, operator *ClusterOperator, sql string, dest interface{}) error {
	ctx, span := Tracer.Start(ctx, "QuerySQL")
	defer span.End()

	m := &QuerySQLModel{
		Operator: p.amendOperator(ctx, operator),
		Cluster: Cluster{
			ClusterID: p.client.GetClusterID(),
		},
		Query: sql,
	}
	return p.client.Request(ctx, "POST", querySQLPATH, m, dest)
}

func (p *sqlClientImpl) amendOperator(ctx context.Context, operator *ClusterOperator) *ClusterOperator {
	logger := log.WithContextS(ctx)

	out := &ClusterOperator{
		Username:   operator.Username,
		AuthMethod: operator.AuthMethod,
		Credential: base64.URLEncoding.EncodeToString([]byte(operator.Credential)),
	}
	logger.Infof("auth_method=%s", out.AuthMethod)
	return out
}

type Cluster struct {
	ClusterID uint64 `json:"clusterID"`
}

type QuerySQLModel struct {
	Operator *ClusterOperator `json:"operator"`
	Cluster
	Query string `json:"query"`
}

type ClusterOperator struct {
	Username   string
	AuthMethod AuthMethod
	Credential string // TOKEN, PASSWORD
}
