
// createReviews provides a function to create moderator reviews

package createReviews

// We encode each attribute as an integer in MessagePack:

// ReviewVersion = 1
// NetworkType = 2
// IdentityKey = 3
// CreationTime = 4
// ReviewedHash = 5
// Verdict = 6
// Reason = 7
// MessageCipherKey = 8
// ErrantProfiles = 9
// ErrantMessages = 10
// ErrantReviews = 11
// ErrantAttributes = 12

import "seekia/internal/appValues"
import "seekia/internal/cryptography/blake3"
import "seekia/internal/cryptography/edwardsKeys"
import "seekia/internal/encoding"
import "seekia/internal/helpers"
import "seekia/internal/moderation/readReviews"

import messagepack "github.com/vmihailenco/msgpack/v5"

import "errors"
import "time"

func CreateReview(identityPublicKey [32]byte, identityPrivateKey [64]byte, reviewMap map[string]string)([]byte, error){

	reviewVersion := appValues.GetReviewVersion()

	networkTypeString, exists := reviewMap["NetworkType"]
	if (exists == false){
		return nil, errors.New("CreateReview called with reviewMap missing NetworkType")
	}

	networkType, err := helpers.ConvertNetworkTypeStringToByte(networkTypeString)
	if (err != nil){
		return nil, errors.New("CreateReview called with reviewMap containing invalid NetworkType: " + networkTypeString)
	}

	creationTime := time.Now().Unix()

	reviewedHashString, exists := reviewMap["ReviewedHash"]
	if (exists == false){
		return nil, errors.New("CreateReview called with reviewMap missing ReviewedHash")
	}

	reviewVerdict, exists := reviewMap["Verdict"]
	if (exists == false){
		return nil, errors.New("CreateReview called with reviewMap missing Verdict")
	}

	reviewedHashBytes, reviewType, err := helpers.ReadReviewedHashString(reviewedHashString)
	if (err != nil) {
		return nil, errors.New("CreateReview called with reviewMap containing invalid reviewedHash: " + reviewedHashString)
	}

	reviewVersionEncoded, err := encoding.EncodeMessagePackBytes(reviewVersion)
	if (err != nil) { return nil, err }

	networkTypeEncoded, err := encoding.EncodeMessagePackBytes(networkType)
	if (err != nil) { return nil, err }

	identityKeyEncoded, err := encoding.EncodeMessagePackBytes(identityPublicKey)
	if (err != nil) { return nil, err }

	creationTimeEncoded, err := encoding.EncodeMessagePackBytes(creationTime)
	if (err != nil) { return nil, err }

	reviewedHashEncoded, err := encoding.EncodeMessagePackBytes(reviewedHashBytes)
	if (err != nil) { return nil, err }

	reviewVerdictEncoded, err := encoding.EncodeMessagePackBytes(reviewVerdict)
	if (err != nil) { return nil, err }

	reviewContentMap := map[int]messagepack.RawMessage{
		1: reviewVersionEncoded,
		2: networkTypeEncoded,
		3: identityKeyEncoded,
		4: creationTimeEncoded,
		5: reviewedHashEncoded,
		6: reviewVerdictEncoded,
	}

	reviewReason, exists := reviewMap["Reason"]
	if (exists == true){

		reviewReasonEncoded, err := encoding.EncodeMessagePackBytes(reviewReason)
		if (err != nil) { return nil, err }

		reviewContentMap[7] = reviewReasonEncoded
	}

	if (reviewType == "Message"){

		messageCipherKeyString, exists := reviewMap["MessageCipherKey"]
		if (exists == false){
			return nil, errors.New("CreateReview called with message reviewMap missing MessageCipherKey")
		}
		messageCipherKey, err := encoding.DecodeHexStringToBytes(messageCipherKeyString)
		if (err != nil){
			return nil, errors.New("CreateReview called with reviewMap containing invalid messageCipherKey: Not Hex: " + messageCipherKeyString)
		}

		messageCipherKeyEncoded, err := encoding.EncodeMessagePackBytes(messageCipherKey)
		if (err != nil){ return nil, err }

		reviewContentMap[8] = messageCipherKeyEncoded
	}

	//TODO: ErrantProfiles, ErrantMessages, ErrantReviews, ErrantAttributes

	reviewContentMessagepack, err := encoding.EncodeMessagePackBytes(reviewContentMap)
	if (err != nil) {
		return nil, errors.New("Failed to create review: " + err.Error())
	}

	contentHash, err := blake3.Get32ByteBlake3Hash(reviewContentMessagepack)
	if (err != nil) {
		return nil, errors.New("Failed to create review: " + err.Error())
	}

	reviewSignature := edwardsKeys.CreateSignature(identityPrivateKey, contentHash)

	signatureEncoded, err := encoding.EncodeMessagePackBytes(reviewSignature)
	if (err != nil) { return nil, err }

	reviewSlice := []messagepack.RawMessage{signatureEncoded, reviewContentMessagepack}

	reviewBytes, err := encoding.EncodeMessagePackBytes(reviewSlice)
	if (err != nil) {
		return nil, errors.New("Failed to create review: " + err.Error())
	}

	isValid, err := readReviews.VerifyReview(reviewBytes)
	if (err != nil) { return nil, err }
	if (isValid == false){
		return nil, errors.New("Cannot create review: Resulting review is invalid.")
	}

	return reviewBytes, nil
}




