package vault

import (
	"fmt"
	"strings"
	"time"

	"github.com/tidbcloud/pkgv2/secret/encrypt"
)

// DefaultKey is the key used by the Encrypt operation
const DefaultKey = "dbaas"

// Secret is an alias of encrypt.Secret
type Secret = encrypt.Secret

// Namespace is a namespace in a provider id, like a k8s namespace
type Namespace string

func (n Namespace) String() string {
	return string(n)
}

// ProviderID is an identity for the secret in the provider system
type ProviderID struct {
	Namespace Namespace
	ID        string
}

func (p ProviderID) String() string {
	return fmt.Sprintf("%s/%s", p.Namespace, p.ID)
}

// MakeProviderID takes a Namespace and a secret name
func MakeProviderID(ns Namespace, id string) ProviderID {
	return ProviderID{Namespace: ns, ID: id}
}

// FmtProviderID format the provider ID
func FmtProviderID(p ProviderID) string {
	return string(p.Namespace) + "/" + p.ID
}

// ToProviderID converts a string to a ProviderID
// This can be of the form namespace/name
func ToProviderID(id string) ProviderID {
	namespace := Namespace("")
	pieces := strings.Split(id, "/")
	if len(pieces) == 2 {
		namespace = Namespace(pieces[0])
		id = pieces[1]
	}
	return ProviderID{Namespace: namespace, ID: id}
}

// Vault can store and retrieve a secret.
// We use Kubernetes to fulfill this interface.
type Vault interface {
	// Encrypt the secret with the given name. The returned ProviderID can be used to decrypt.
	// Multiple secrets of the same name can be given and they will have different Vault IDs.
	Encrypt(ProviderID, Secret, map[string]string) error
	Decrypt(ProviderID) (Secret, map[string]string, error)
	AddLabels(ProviderID, map[string]string) error
	EncryptMap(ProviderID, map[string]Secret, map[string]string) error
	DecryptMap(ProviderID) (map[string][]byte, error)
	Exists(ProviderID) (bool, error)
	Delete(ProviderID) error
	AlterMap(ProviderID, func(map[string][]byte) error) error
	AlterLabels(ProviderID, func(map[string]string)) error
	ProviderIDs(Namespace, time.Duration) ([]ProviderID, error)
}
