package metadata

import (
	"errors"
	"fmt"

	"github.com/samber/lo"
)

// grpc metadata keys from portal http headers
const (
	OrgIDHeaderKey            = "x-org-id"
	DefaultProjectIDHeaderKey = "x-default-project-id"
	UserIDHeaderKey           = "x-user-id"
	UserEmailHeaderKey        = "x-user-email"
	ApiKeyHeaderKey           = "x-public-key"
	ApiKeyHeaderKeyId         = "x-public-key-id"
	AccessTokenKey            = "x-access-token"
	ProjectListHeaderKey      = "x-project-id-list" // ProjectListHeaderKey is the ids of valid projects under the user's organization
	ClusterIDHeaderKey        = "x-cluster-id"
	IsCheckPermissionKey      = "x-check-permission"
	ResourceIDKey             = "x-resource-id" // request resource id, exclude cluster id
	IgnoreCustomStatusIDKey   = "x-ignore-custom-status-id"
	NoProjectRequiredKey      = "x-no-project-required"
)

type RequestMeta struct {
	OrgID                uint64
	DefaultProjectID     uint64
	ClusterID            uint64
	UserID               string
	Email                string
	ApiPublicKey         string
	ApiPublicKeyId       uint64
	AccessToken          string
	ValidProjectList     []uint64
	IsCheckPermission    *bool
	ResourceID           string // request resource id, exclude cluster id
	IgnoreCustomStatusID uint64
	NoProjectRequired    bool
}

func (meta *RequestMeta) GetIsCheckPermission() bool {
	if meta.IsCheckPermission == nil {
		return false
	}
	return *meta.IsCheckPermission
}

// CheckProjectIDsPermission checks the user's permission to access the project.
// Permission rule is same as the TiDB Cloud web console.
// BTW, there is a new permission model proposal for TiDB Cloud web console, refer to https://pingcap.feishu.cn/wiki/wikcnrZFlmVYTFqpnSDizUfhQKb.
//
// The reason that we don't check project permission in mgmt-portal is that mgmt-portal can't extract resource's project easily.
func (meta *RequestMeta) CheckProjectIDsPermission(projectIDs ...uint64) error {
	if len(projectIDs) == 0 {
		return errors.New("project id is not provided")
	}

	if !lo.Every(meta.ValidProjectList, projectIDs) {
		return fmt.Errorf("project id %d is not valid", projectIDs)
	}
	return nil
}
