package jose

import (
	"encoding/json"
	"errors"
	"github.com/beego/beego/v2/core/logs"
	josev3 "github.com/go-jose/go-jose/v3"
	"github.com/go-jose/go-jose/v3/jwt"
	"io"
	"net/http"
	"strings"
)

type JWKResponse struct {
	Kty string `json:"kty"`
	Crv string `json:"crv"`
	X   string `json:"x"`
	Y   string `json:"y"`
	Kid string `json:"kid"`
}

type JWKS struct {
	Keys []JWKResponse `json:"keys"`
}

type AIClaims struct {
	Iat     int64  `json:"iat"`
	Aud     string `json:"aud"`
	Nonce   string `json:"nonce"`
	Iss     string `json:"iss"`
	Wallets []struct {
		PublicKey string `json:"public_key"`
		Type      string `json:"type"`
		Curve     string `json:"curve"`
	} `json:"wallets"`
	Email             string `json:"email"`
	Name              string `json:"name"`
	ProfileImage      string `json:"profileImage"`
	Verifier          string `json:"verifier"`
	VerifierId        string `json:"verifierId"`
	AggregateVerifier string `json:"aggregateVerifier"`
	Exp               int64  `json:"exp"`
}

func Verify(url string, publicKey string, idToken string) (*AIClaims, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	logs.Debug("Verify", string(body))
	var response1 JWKS
	var jwkTokens []josev3.JSONWebKey
	if err = json.Unmarshal(body, &response1); err != nil {
		return nil, err
	}
	for _, value := range response1.Keys {
		logs.Debug("Verify value", value)
		bytes, err := json.Marshal(value)
		if err != nil {
			continue
		}
		var jwk2 josev3.JSONWebKey
		err = jwk2.UnmarshalJSON(bytes)
		if err != nil {
			continue
		}
		jwkTokens = append(jwkTokens, jwk2)
	}

	jwks := &josev3.JSONWebKeySet{
		Keys: jwkTokens,
	}

	tok, err := jwt.ParseSigned(idToken)
	if err != nil {
		return nil, err
	}

	var cl AIClaims
	err = tok.Claims(jwks, &cl)
	if err != nil {
		return nil, err
	}
	if len(cl.Wallets) > 0 {
		if strings.Compare(cl.Wallets[0].PublicKey, publicKey) != 0 {
			return nil, errors.New("PublicKey verify failed")
		}
	}
	//err = tok.Claims(*jwks, &cl)
	//if err != nil {
	//	return nil, err
	//}
	return &cl, nil
}
