package auth

import (
	"context"
	"errors"
	"fmt"
	"github.com/tidbcloud/account/idl/pbgen/proto/account"
)

type defaultPermissionPlugin struct {
}

func NewDefaultPermissionPlugin() (PermissionPlugin, error) {
	return &defaultPermissionPlugin{}, nil
}

func (d *defaultPermissionPlugin) HasPermission(ctx context.Context, param *PermissionParam) (*PermissionRet, error) {
	tye, err := convAccessIdentityType2RbacIdentityType(param.IdentityType)
	if err != nil {
		return nil, err
	}
	if param.IdentityVal == "" {
		return nil, errors.New("access identity_val is empty")
	}
	if param.ReqUri == "" {
		return nil, errors.New("access req_uri is empty")
	}
	if param.ResourceUri == "" {
		return nil, errors.New("access resource_uri is empty")
	}

	client, err := getStoredAccountClient()
	if err != nil {
		return nil, err
	}
	tctx, cf := context.WithTimeout(ctx, accountReadTimeout)
	defer cf()
	req := account.RbacIdentityPermissionRequest{
		IdentityType:    tye,
		Identity:        param.IdentityVal,
		ResourceUri:     param.ReqUri,
		PureResourceUri: param.ResourceUri,
	}

	rsp, err := client.HasPermissionForIdentity(tctx, &req)
	if err != nil {
		return nil, err
	}

	ret := PermissionRet{
		HasPermission: rsp.AuthResult,
		Message:       rsp.AuthMessage,
	}

	return &ret, nil
}

func convAccessIdentityType2RbacIdentityType(tye AccessIdentityType) (account.RbacIdentityType, error) {
	if tye == AccessIdentityTypeAccessToken {
		return account.RbacIdentityType_RBAC_IDENTITY_TYPE_ACCESSTOKEN, nil
	}
	if tye == AccessIdentityTypeUserID {
		return account.RbacIdentityType_RBAC_IDENTITY_TYPE_USER, nil
	}
	if tye == AccessIdentityTypeApiKeyAK {
		return account.RbacIdentityType_RBAC_IDENTITY_TYPE_APIKEY, nil
	}
	return account.RbacIdentityType_RBAC_IDENTITY_TYPE_UNSPECIFIED, errors.New(fmt.Sprintf("not support access identity_type %s", tye))

}
