package helperimpl

import (
	"context"
	"errors"

	"github.com/tidbcloud/tiinf/sdk/rbac/common"
)

var DefaultMetadataStoreIdentityHelper = NewMetadataStoreIdentityHelper()

type metadataStoreIdentityHelper struct {
}

func NewMetadataStoreIdentityHelper() common.IdentityHelper {
	return &metadataStoreIdentityHelper{}
}

func (d *metadataStoreIdentityHelper) GetIdentity(_ context.Context, param *common.AccessParam) (string, error) {
	mIdent, ok := param.Metadata[common.METADATA_IDENTITY]
	if !ok {
		return "", errors.New("metadataStoreIdentityHelper: identity not found in metadata")
	}
	identity, ok := mIdent.(string)
	if !ok {
		return "", errors.New("metadataStoreIdentityHelper: identity type not string")
	}
	return identity, nil
}

type contextStoreIdentityHelper struct {
	ctxIdentityKey interface{}
}

func NewContextStoreIdentityHelper(ctxIdentityKey interface{}) common.IdentityHelper {
	return &contextStoreIdentityHelper{
		ctxIdentityKey: ctxIdentityKey,
	}
}

func NewContextStoreGetIdentityFunc(ctxDataKey interface{}) common.GetIdentityFunc {
	helper := NewContextStoreIdentityHelper(ctxDataKey)
	return func(ctx context.Context, param *common.AccessParam) (string, error) {
		return helper.GetIdentity(ctx, param)
	}
}

func (d *contextStoreIdentityHelper) GetIdentity(ctx context.Context, _ *common.AccessParam) (string, error) {
	value := ctx.Value(d.ctxIdentityKey)
	if value == nil {
		return "", errors.New("contextStoreIdentityHelper: identity not found in context")
	}
	identity, ok := value.(string)
	if !ok {
		return "", errors.New("contextStoreIdentityHelper: identity type not string")
	}
	return identity, nil
}
