package service

import (
	"context"
	"fmt"
	"strings"

	apiv1 "github.com/tidbcloud/cluster-service-ng/api/tidbcloud/cluster-agent/v1"

	"github.com/tidbcloud/cluster-service-ng/internal/cluster-agent/internal/sqlexec"
	"github.com/tidbcloud/cluster-service-ng/internal/cluster-agent/internal/utils"
)

type storageURIExecutor interface {
	Execute(ctx context.Context, clusterID string, cmd sqlexec.Command) (sqlexec.Result, error)
}

var newStorageURIExecutor = func(
	resolver utils.AddressResolver,
	auth sqlexec.DBAuth,
	tlsProvider sqlexec.TLSConfigProvider,
) storageURIExecutor {
	return sqlexec.NewDirectTiDBExecutor(resolver, auth, tlsProvider)
}

func (s *AgentService) SetGlobalCloudStorageURI(
	ctx context.Context,
	req *apiv1.SetGlobalCloudStorageURIRequest,
) (*apiv1.SetGlobalCloudStorageURIResponse, error) {
	if req == nil {
		err := fmt.Errorf("request is nil")
		return &apiv1.SetGlobalCloudStorageURIResponse{Message: err.Error()}, err
	}
	if err := validateAuditLogCommonFields(req.ClusterId, req.EncryptedUsername, req.EncryptedPassword); err != nil {
		return &apiv1.SetGlobalCloudStorageURIResponse{Message: err.Error()}, err
	}
	if strings.TrimSpace(req.CloudStorageUri) == "" {
		err := fmt.Errorf("cloud storage uri is empty")
		return &apiv1.SetGlobalCloudStorageURIResponse{Message: err.Error()}, err
	}

	cmd := &sqlexec.SetGlobalCloudStorageURICommand{URI: req.CloudStorageUri}
	if err := cmd.Validate(); err != nil {
		return &apiv1.SetGlobalCloudStorageURIResponse{Message: err.Error()}, err
	}

	resolver, auth, tlsProvider, err := s.decryptDBCredentials(req.EncryptedUsername, req.EncryptedPassword)
	if err != nil {
		return &apiv1.SetGlobalCloudStorageURIResponse{Message: err.Error()}, err
	}

	exec := newStorageURIExecutor(resolver, auth, tlsProvider)
	if _, err := exec.Execute(ctx, req.ClusterId, cmd); err != nil {
		return &apiv1.SetGlobalCloudStorageURIResponse{Message: err.Error()}, err
	}

	return &apiv1.SetGlobalCloudStorageURIResponse{Message: "success"}, nil
}
