package user

import (
	"encoding/json"
	"net/http"
	"time"
	"math/rand"

	"github.com/azukaar/cosmos-server/src/utils"
	"github.com/pquerna/otp/totp"
)

func New2FA(w http.ResponseWriter, req *http.Request) {
	if utils.LoggedInWeakOnly(w, req) != nil {
		return
	}
	time.Sleep(time.Duration(rand.Float64()*2)*time.Second)

	nickname := req.Header.Get("x-cosmos-user")

	key, err := totp.Generate(totp.GenerateOpts{
		Issuer:      "Cosmos " + utils.GetMainConfig().HTTPConfig.Hostname,
		AccountName: nickname,
	})

	if err != nil {
		utils.Error("2FA: Cannot generate key", err)
		utils.HTTPError(w, "2FA Error", http.StatusInternalServerError, "2FA001")
		return
	}

	utils.Log("2FA: New key generated for " + nickname)
	
	toSet := map[string]interface{}{
		"MFAKey": key.Secret(),
		"Was2FAVerified": false,
	}

	c, errCo := utils.GetCollection(utils.GetRootAppId(), "users")
	if errCo != nil {
		utils.Error("Database Connect", errCo)
		utils.HTTPError(w, "Database", http.StatusInternalServerError, "DB001")
		return
	}

	userInBase := utils.User{}

	err = c.FindOne(nil, map[string]interface{}{
		"Nickname": nickname,
	}).Decode(&userInBase)

	if err != nil {
		utils.Error("UserGet: Error while getting user", err)
		utils.HTTPError(w, "User Get Error", http.StatusInternalServerError, "UD001")
		return
	}

	if(userInBase.MFAKey != "" && userInBase.Was2FAVerified) {
		if utils.LoggedInOnly(w, req) != nil {
			return
		}
	}

	_, err = c.UpdateOne(nil, map[string]interface{}{
		"Nickname": nickname,
	}, map[string]interface{}{
		"$set": toSet,
	})

	if err != nil {
		utils.Error("2FA: Cannot update user", err)
		utils.HTTPError(w, "2FA Error", http.StatusInternalServerError, "2FA002")
		return
	}

	utils.Log("2FA: User " + nickname + " updated")

	json.NewEncoder(w).Encode(map[string]interface{}{
		"status": "OK",
		"data": map[string]interface{}{
			"key": key.URL(),
		},
	})
}