package service

import (
	"context"

	"git.apinb.com/bsm-sdk/core/crypto/encipher"
	"git.apinb.com/bsm-sdk/core/errcode"
	"git.apinb.com/bsm-sdk/core/utils"
	"google.golang.org/grpc/metadata"
)

type Meta struct {
	ID       uint              `json:"id"`
	IDENTITY string            `json:"identity"`
	EXTEND   map[string]string `json:"extend"`
	CLIENT   string            `json:"client"`
	ROLE     string            `json:"role"`
}

// 解析Context中MetaData的数据
type ParseOptions struct {
	RoleValue        string // 判断角色的值
	MustPrivateAllow bool   // 是否只允许私有IP访问
}

func ParseMetaCtx(ctx context.Context, opts *ParseOptions) (*Meta, error) {
	// 解析metada中的信息并验证
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil, errcode.ErrJWTAuthNotFound
	}

	var Authorizations []string = md.Get("authorization")
	if len(Authorizations) == 0 || Authorizations[0] == "" {
		return nil, errcode.ErrJWTAuthNotFound
	}

	claims, err := encipher.ParseTokenAes(Authorizations[0])
	if err != nil {
		return nil, err
	}

	clientValues := md.Get("client")

	if len(clientValues) == 0 {
		return nil, errcode.ErrJWTAuthNotFound
	}

	meta := &Meta{
		ID:       claims.ID,
		IDENTITY: claims.Identity,
		CLIENT:   md["client"][0],
		EXTEND:   claims.Extend,
		ROLE:     claims.Role,
	}

	if opts != nil {
		if !meta.CheckRole("role", opts.RoleValue) {
			return nil, errcode.ErrPermissionDenied
		}
		if opts.MustPrivateAllow {
			if utils.IsPublicIP(meta.CLIENT) {
				return nil, errcode.ErrPermissionDenied
			}
		}
	}

	return meta, nil

}

func (m *Meta) CheckRole(roleKey, roleValue string) bool {
	if roleValue == "" {
		return true
	}
	if role, exists := m.EXTEND[roleKey]; !exists || role != roleValue {
		return false
	} else {
		return true
	}
}