package service

import (
	"context"
	"encoding/json"
	"strconv"

	"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"`
}

// 解析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
	}

	// 安全获取 metadata 中的值
	identityValues := md.Get("authorization_identity")
	clientValues := md.Get("client")

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

	meta := &Meta{
		IDENTITY: md["authorization_identity"][0],
		CLIENT:   md["client"][0],
	}

	if id, err := strconv.Atoi(md["authorization_id"][0]); err != nil {
		return nil, errcode.ErrJWTAuthKeyId
	} else {
		meta.ID = uint(id)
	}

	data := make(map[string]string)
	if err := json.Unmarshal([]byte(md["authorization_extend"][0]), &data); err == nil {
		meta.EXTEND = data
	}

	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
	}
}