package loader

import (
	"context"
	"fmt"

	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/config"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/secret"

	"gopkg.in/yaml.v3"
)

type ConfigurationSourceSecret[T any] struct {
	getConf         func(pre *T) (string, config.Secret)
	newSecretSource func(config.Secret) (secret.SecretSource, error)
}

func NewConfigurationSourceSecret[T any](
	getConf func(pre *T) (string, config.Secret),
) *ConfigurationSourceSecret[T] {
	return &ConfigurationSourceSecret[T]{
		getConf:         getConf,
		newSecretSource: secret.NewSecretSource,
	}
}

func (s *ConfigurationSourceSecret[T]) Load(ctx context.Context, pre *T) (*T, error) {
	if s.getConf == nil {
		return nil, fmt.Errorf("secret config getter is nil")
	}

	secretName, secretConf := s.getConf(pre)
	if secretName == "" {
		return nil, nil
	}

	newSecretSource := s.newSecretSource
	if newSecretSource == nil {
		newSecretSource = secret.NewSecretSource
	}

	source, err := newSecretSource(secretConf)
	if err != nil {
		return nil, fmt.Errorf("build secret source failed: %w", err)
	}

	secretData, err := source.GetSecretValue(ctx, secretName)
	if err != nil {
		return nil, fmt.Errorf("failed to get secret value of root config: %w", err)
	}

	secrets := new(T)
	if err := yaml.Unmarshal([]byte(secretData), secrets); err != nil {
		return nil, fmt.Errorf("failed to unmarshal secret: %w", err)
	}

	return secrets, nil
}
