package helperimpl

import (
	"context"
	"errors"
	"regexp"

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

var DefaultRegionMetadataStoreResourceHelper = NewRegionMetadataStoreResourceHelper()

type regionMetadataStoreResourceHelper struct {
}

func NewRegionMetadataStoreResourceHelper() common.RegionResourceHelper {
	return &regionMetadataStoreResourceHelper{}
}

// GetResourceAndAppID return the resource and appID from metadata
// This method only check if the METADATA_RESOURCE_PARAM is matched with the METADATA_RESOURCE, and return the METADATA_RESOURCE
func (d *regionMetadataStoreResourceHelper) GetResourceAndAppID(_ context.Context, req *common.AccessParam) (string, string, error) {
	mResource, ok := req.Metadata[common.METADATA_RESOURCE]
	if !ok {
		return "", "", errors.New("metadataStoreResourceHelper: resource not found int metadata")
	}
	resource, ok := mResource.(string)
	if !ok {
		return "", "", errors.New("metadataStoreResourceHelper: resource type not string")
	}

	mResouceParam, ok := req.Metadata[common.METADATA_RESOURCE_PARAM]
	if !ok {
		return "", "", errors.New("metadataStoreResourceHelper: resource param not found int metadata")
	}
	resourceParam, ok := mResouceParam.(map[string]string)
	if !ok {
		return "", "", errors.New("metadataStoreResourceHelper: resource param type not map[string]string")
	}
	appID, ok := resourceParam[common.DATA_APP_ID_KEY]
	if !ok {
		return "", "", errors.New("metadataStoreResourceHelper: resource param app_id not found")
	}
	resourceGroups := regexp.MustCompile(common.RESOURCE_EXPR_NO).FindAllString(resource, -1)
	if resourceGroups != nil && len(resourceGroups) > 0 {
		mParams, ok := req.Metadata[common.METADATA_RESOURCE_PARAM]
		if !ok {
			return "", "", errors.New("metadataStoreResourceHelper: resource params not found int metadata")
		}
		params, ok := mParams.(map[string]string)
		if !ok {
			return "", "", errors.New("metadataStoreResourceHelper: resource params type not map[string]string")
		}
		// check if the resource param is matched with the resource
		for _, group := range resourceGroups {
			variable := group[1 : len(group)-1]
			_, ok := params[variable]
			if !ok {
				return "", "", errors.New("metadataStoreResourceHelper: resource variable not found value in resource params")
			}
		}
	}

	return resource, appID, nil
}
