package svc

import (
	"crypto/rand"
	"encoding/hex"
	"errors"
	"net/http"

	"github.com/qsfera/server/services/ocs/pkg/service/v0/data"
	"github.com/qsfera/server/services/ocs/pkg/service/v0/response"
	revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
	"go-micro.dev/v4/store"
)

// GetSigningKey returns the signing key for the current user. It will create it on the fly if it does not exist
// The signing key is part of the user settings and is used by the proxy to authenticate requests
// Currently, the username is used as the OC-Credential
func (o Ocs) GetSigningKey(w http.ResponseWriter, r *http.Request) {
	u, ok := revactx.ContextGetUser(r.Context())
	if !ok {
		//o.logger.Error().Msg("missing user in context")
		o.mustRender(w, r, response.ErrRender(data.MetaBadRequest.StatusCode, "missing user in context"))
		return
	}

	// use the user's UUID
	userID := u.Id.OpaqueId

	res, err := o.store.Read(userID)
	if err == nil && len(res) > 0 {
		o.mustRender(w, r, response.DataRender(&data.SigningKey{
			User:       userID,
			SigningKey: string(res[0].Value),
		}))
		return
	}
	if err != nil {
		if errors.Is(err, store.ErrNotFound) {
			// not found is ok, so we can continue and generate the key on the fly
		} else {
			o.logger.Error().Err(err).Msg("error reading from server")
			o.mustRender(w, r, response.ErrRender(data.MetaServerError.StatusCode, "error reading from store"))
			return
		}
	}

	// try creating it
	key := make([]byte, 64)
	_, err = rand.Read(key[:])
	if err != nil {
		o.mustRender(w, r, response.ErrRender(data.MetaServerError.StatusCode, "could not generate signing key"))
		return
	}
	signingKey := hex.EncodeToString(key)

	err = o.store.Write(&store.Record{Key: userID, Value: []byte(signingKey)})
	if err != nil {
		o.mustRender(w, r, response.ErrRender(data.MetaServerError.StatusCode, "could not persist signing key"))
		return
	}

	o.mustRender(w, r, response.DataRender(&data.SigningKey{
		User:       userID,
		SigningKey: signingKey,
	}))
}
