package server

import (
	"context"
	"crypto/sha256"
	"encoding/base64"
	"github.com/1f349/lavender/database"
	"github.com/1f349/mjwt"
	"github.com/1f349/mjwt/auth"
	"github.com/go-oauth2/oauth2/v4"
	"github.com/golang-jwt/jwt/v4"
	"github.com/google/uuid"
	"strings"
)

type JWTAccessGenerate struct {
	signer *mjwt.Issuer
	db     *database.Queries
}

func NewJWTAccessGenerate(signer *mjwt.Issuer, db *database.Queries) *JWTAccessGenerate {
	return &JWTAccessGenerate{signer, db}
}

var _ oauth2.AccessGenerate = &JWTAccessGenerate{}

func (j *JWTAccessGenerate) Token(ctx context.Context, data *oauth2.GenerateBasic, isGenRefresh bool) (access, refresh string, err error) {
	roles, err := j.db.GetUserRoles(ctx, data.UserID)
	if err != nil {
		return "", "", err
	}

	ps := auth.ParsePermStorage(roles)
	out := auth.NewPermStorage()
	ForEachRole(data.Client.(interface{ UsePerms() string }).UsePerms(), func(role string) {
		for _, i := range ps.Filter(strings.Split(role, " ")).Dump() {
			out.Set(i)
		}
	})

	access, err = j.signer.GenerateJwt(data.UserID, "", jwt.ClaimStrings{data.TokenInfo.GetClientID()}, data.TokenInfo.GetAccessExpiresIn(), auth.AccessTokenClaims{
		Perms: out,
	})

	if isGenRefresh {
		t := uuid.NewHash(sha256.New(), uuid.New(), []byte(access), 5).String()
		refresh = base64.URLEncoding.EncodeToString([]byte(t))
		refresh = strings.ToUpper(strings.TrimRight(refresh, "="))
	}

	return
}
