package secretsource

import (
	"context"
	"fmt"
	"io"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	osscred "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
	credential "github.com/aliyun/credentials-go/credentials"

	"github.com/tidbcloud/devops/pkg/infra/config"
	"github.com/tidbcloud/devops/pkg/infra/utils/pointer"
)

type sourceAliyunOSS struct {
	bucket string
	client *oss.Client
}

func NewSourceAliyunOSS(conf config.SecretSourceAliyunOSS) (SecretSource, error) {
	cred, err := credential.NewCredential(nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create aliyun credential: %w", err)
	}

	credentialsProvider := osscred.CredentialsProviderFunc(func(context.Context) (osscred.Credentials, error) {
		credModel, err := cred.GetCredential()
		if err != nil {
			return osscred.Credentials{}, fmt.Errorf("failed to get aliyun credential from pod environment: %w", err)
		}
		if credModel.AccessKeyId == nil || credModel.AccessKeySecret == nil {
			return osscred.Credentials{}, fmt.Errorf("aliyun credential from pod environment is invalid")
		}

		credentials := osscred.Credentials{
			AccessKeyID:     *credModel.AccessKeyId,
			AccessKeySecret: *credModel.AccessKeySecret,
		}
		if credModel.SecurityToken != nil {
			credentials.SecurityToken = *credModel.SecurityToken
		}
		return credentials, nil
	})

	ossConfig := oss.LoadDefaultConfig().
		WithRegion(conf.Region).
		WithCredentialsProvider(credentialsProvider)
	client := oss.NewClient(ossConfig)

	return &sourceAliyunOSS{
		bucket: conf.Bucket,
		client: client,
	}, nil
}

func (s *sourceAliyunOSS) GetSecretValue(ctx context.Context, name string) (string, error) {
	request := &oss.GetObjectRequest{
		Bucket: pointer.Pointer(s.bucket),
		Key:    pointer.Pointer(name),
	}
	response, err := s.client.GetObject(ctx, request)
	if err != nil {
		return "", fmt.Errorf("failed to get config object from aliyun oss: %w", err)
	}
	defer response.Body.Close()

	secretData, err := io.ReadAll(response.Body)
	if err != nil {
		return "", fmt.Errorf("failed to read config object body from aliyun oss: %w", err)
	}

	return string(secretData), nil

}
