package sharedmodel

import (
	"crypto"
	"fmt"

	"google.golang.org/protobuf/types/known/structpb"
	"gorm.io/gorm"
	"src.whiteboxsystems.nl/DECOZO/okapi"
	"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen"
)

const AuthMethodDecozoMTLS = "http://decozo.org/proto/auth/mtls"
const AuthMethodDecozoBearerToken = "http://decozo.org/proto/auth/bearer-token"

type AuthConfig struct {
	gorm.Model
	Raw    string
	Method string
}

func (cfg AuthConfig) Clone() *AuthConfig {
	return &AuthConfig{
		Raw:    cfg.Raw,
		Method: cfg.Method,
	}
}

func (cfg AuthConfig) ToOkapi() *okapi.ProtocolAuthConfiguration {
	conf := &structpb.Struct{}

	switch cfg.Method {
	case AuthMethodDecozoBearerToken:
		conf, _ = structpb.NewStruct(map[string]interface{}{
			"token": cfg.Raw,
		})
	case AuthMethodDecozoMTLS:
		conf, _ = structpb.NewStruct(map[string]interface{}{
			"publicKey": cfg.Raw,
		})
	}

	return &okapi.ProtocolAuthConfiguration{
		Method:        cfg.Method,
		Configuration: conf,
	}
}

func NewAuthConfig(cfg *okapi.ProtocolAuthConfiguration) *AuthConfig {
	authConfig := &AuthConfig{
		Method: cfg.Method,
	}

	switch cfg.Method {
	case AuthMethodDecozoBearerToken:
		authConfig.Raw, _ = cfg.GetConfiguration().AsMap()["token"].(string)
	case AuthMethodDecozoMTLS:
		k, _ := cfg.GetConfiguration().AsMap()["publicKey"].(string)
		jwk, _ := certgen.StringToJWK(k)
		if jwk != nil {
			rawBytes, _ := jwk.Thumbprint(crypto.SHA256)
			authConfig.Raw = fmt.Sprintf("%X", rawBytes)
		}
	}

	return authConfig
}

type XISAuthConfig struct {
	gorm.Model
	Raw    string
	Method int32
}

func (cfg XISAuthConfig) Clone() *XISAuthConfig {
	return &XISAuthConfig{
		Raw:    cfg.Raw,
		Method: cfg.Method,
	}
}
