package auth

import (
	"context"
)

// --------- handler -------------------

type AccessDecisionHandler interface {
	Handle(ctx context.Context, param *AccessParam) (*AccessResult, error)
}

// ------ plugin ---------------

type RequestPlugin interface {
	ReleaseRequest(ctx context.Context, param *AccessParam) (*RequestRet, error)
}

type IdentityPlugin interface {
	GetIdentity(ctx context.Context, param *AccessParam) (*IdentityRet, error)
}

type ResourcePlugin interface {
	GetResource(ctx context.Context, param *AccessParam) (*ResourceRet, error)
}

type ResourceCascadePlugin interface {
	CheckCascadeResource(ctx context.Context, param *ResourceCascadeParam) (*ResourceCascadeRet, error)
}

type PermissionPlugin interface {
	HasPermission(ctx context.Context, param *PermissionParam) (*PermissionRet, error)
}

// ------ helper func ---------------

type GetIdentityFunc func(ctx context.Context, param *AccessParam) (*IdentityRet, error)

func (f GetIdentityFunc) GetIdentity(ctx context.Context, param *AccessParam) (*IdentityRet, error) {
	return f(ctx, param)
}

type GetResourceFunc func(ctx context.Context, param *AccessParam) (*ResourceRet, error)

func (f GetResourceFunc) GetResource(ctx context.Context, param *AccessParam) (*ResourceRet, error) {
	return f(ctx, param)
}

type ReleaseRequestFunc func(ctx context.Context, param *AccessParam) (*RequestRet, error)

func (f ReleaseRequestFunc) ReleaseRequest(ctx context.Context, param *AccessParam) (*RequestRet, error) {
	return f(ctx, param)
}

type CheckCascadeResourceFunc func(ctx context.Context, param *ResourceCascadeParam) (*ResourceCascadeRet, error)

func (f CheckCascadeResourceFunc) CheckCascadeResource(ctx context.Context, param *ResourceCascadeParam) (*ResourceCascadeRet, error) {
	if f == nil {
		ret := ResourceCascadeRet{
			Matched: true,
			Message: "not set CheckCascadeResourceFunc",
		}
		return &ret, nil
	}
	ret, err := f(ctx, param)
	if err != nil {
		return nil, err
	}
	return ret, nil
}

type HasPermissionFunc func(ctx context.Context, param *PermissionParam) (*PermissionRet, error)

func (f HasPermissionFunc) HasPermission(ctx context.Context, param *PermissionParam) (*PermissionRet, error) {
	return f(ctx, param)
}

type AccessParam struct {
	Metadata map[string]interface{}
	Req      interface{}
}

type AccessResult struct {
	Code int32
	Msg  string
	Data interface{}
}

type RequestRet struct {
	Released bool
	Message  string
}

type IdentityRet struct {
	IdentityValue string
	IdentityType  AccessIdentityType
}

type ResourceRet struct {
	ReqUri      string
	ResourceUri string
}

type PermissionParam struct {
	IdentityType AccessIdentityType
	IdentityVal  string
	ResourceUri  string
	ReqUri       string
}

type PermissionRet struct {
	HasPermission bool
	Message       string
}

type ResourceCascadeParam struct {
	ReqUri string // orgs/1/projects/2/clusters/3/update
}

type ResourceCascadeRet struct {
	Matched bool
	Message string
}

type PermissionCheckerOption struct {
	PermissionCheckClosed bool
	EnableLog             bool
}
