text: const mongoose = require('mongoose');
  const bcrypt = require('bcrypt');
  const jwt = require('jsonwebtoken');
  const {
      AuthenticationError,
      ForbiddenError
  } = require('apollo-server-express');
  require('dotenv').config();
  
  const gravatar = require('../util/gravatar');
  
  module.exports = {
      newNote: async (parent, args, { models, user }) => {
          //if there is not user on the context, throw authentication error
          if(!user){
              throw new AuthenticationError('You must be signed in to create a new note');
          }
          return await models.Note.create({
              content: args.content,
              author: mongoose.Types.ObjectId(user.id)
          });
      },
      deleteNote: async (parent, { id }, { models, user }) => {
          //if not a user, Auth error
          if(!user){
              throw new AuthenticationError('You must be signed in to delete a note!');
          }
          //find the note
          const note = await models.Note.findById(id);
          //if the note owner and current user don't match, throw a forbidden error
          if (note && String(note.author) !== user.id) {
              throw new ForbiddenError("You do not have permission to delete this note");
          }
          try {
              //if everything checks out
              await note.remove();
              return true;
          } catch (err) {
              //if there is an error along the way
              return false;
          }
      },
      updateNote: async (parent, { content, id }, { models, user }) => {
          //if not a user, auth error
          if (!user){
              throw new AuthenticationError('You must be signed in to update a note');
          }
          //find the note
          const note = await models.Note.findById(id);
          if (note && String(note.author) !== user.id){
              throw new ForbiddenError("You don't have permissions to update the note");
          }
          //Update the note in the db and return the updated note
          return await models.Note.findOneAndUpdate(
              {
                  _id: id,
              },
              {
                  $set: {
                      content
                  }
              },
              {
                  new: true
              }
          );
      },
      signUp: async (parent, { username, email, password }, { models }) => {
          //normalize email address
          email = email.trim().toLowerCase();
          //hash the password
          const hashed = await bcrypt.hash(password, 10);
          //create the gravatar url
          const avatar = gravatar(email);
          try {
              const user = await models.User.create({
                  username,
                  email,
                  avatar,
                  password: hashed
              });
              //create and return the json web token
              return jwt.sign({ id: user._id }, process.env.JWT_SECRET);
          } catch (err) {
              console.log(err);
              //if there is a problem creating the account, throw an error
              throw new Error('Error creating account');
          }
      },
      signIn: async (parent, { username, email, password }, { models }) => {
          if (email) {
              //normalize email address
              email = email.trim().toLowerCase();
          }
  
          const user = await models.User.findOne({
              $or: [{ email }, { username }]
          });
          //if no user is found throw authentication error
          if (!user) {
              throw new AuthenticationError('Sign in error!');
          }
          //if the passwords don't match, throw auth error
          const valid = await bcrypt.compare(password, user.password);
          if(!valid) {
              throw new AuthenticationError('Sign in error!');
          }
          //create and return the jwt
          return jwt.sign({ id: user._id }, process.env. JWT_SECRET);
      },
      toggleFavorite: async (parent, { id }, { models, user }) => {
          //if no user context passed, throw auth error
          if (!user) {
              throw new AuthenticationError();
          }
          //check if user has already favorited the note
          let noteCheck = await models.Note.findById(id);
          const hasUser = noteCheck.favoritedBy.indexOf(user.id);
          //if the user exists in the list
          //pull them from the list and reduce the favoriteCount by 1
          if (hasUser >= 0) {
              return await models.Note.findByIdAndUpdate(
                  id, {
                      $pull: {
                          favoritedBy: mongoose.Types.ObjectId(user.id)
                      },
                      $inc: {
                          favoriteCount: -1
                      }
                  },
                  {
                      //set new to true to return the update doc
                      new: true
                  }
              );
          } else {
              //if the user doesn't exist in the list
              //add them to the list and incrememnt favoriteCount by 1
              return await models.Note.findByIdAndUpdate(
                  id,
                  {
                      $push: {
                          favoritedBy: mongoose.Types.ObjectId(user.id)
                      },
                      $inc: {
                          favoriteCount: 1
                      }
                  },
                  {
                      new: true
                  }
              );
          }
      },
  }