import { Recipe, User } from '../models';

/**
 * Class Definition for the Search Recipe Object
 *
 * @export
 * @class Search
 */
export default class Search {
  /**
   * Fetch list of recipes ordered (descending) by number of upvotes
   *
   * @param {object} req - HTTP Request
   * @param {object} res - HTTP Response
   * @returns {object} Class instance
   * @memberof Search
   */
  sortMostUpvotes(req, res) {
    Recipe
      .findAll({
        include: [
          { model: User, attributes: ['name', 'updatedAt'] }
        ],
        order: [
          ['upvotes', 'DESC']
        ]
      })
      .then((foundRecipes) => {
        if (!foundRecipes) {
          return res.status(404).json({
            success: true,
            message: 'No Stored Recipes found',
          });
        }

        return res.status(201).json({
          success: true,
          message: 'Recipe(s) found',
          recipe: foundRecipes
        });
      })
      .catch(() => res.status(500).json({
        success: false,
        message: 'Unable to fetch recipes'
      }));

    return this;
  }

  /**
   * Search for recipe by Recipe name, Ingredients or Name of User
   *
   * @param {object} req - HTTP Request
   * @param {object} res - HTTP Response
   * @returns {object} Class instance
   * @memberof Search
   */
  searchAll(req, res) {
    let results;
    const { search } = req.query;

    Recipe
      .findAll({
        where: {
          $or: [
            {
              name: {
                $iLike: `%${search}%`
              }
            },
            {
              ingredients: {
                $iLike: `%${search}%`
              }
            }
          ]
        },
        include: [
          { model: User, attributes: ['name', 'updatedAt'] }
        ]
      })
      .then((foundRecipes) => {
        results = foundRecipes.slice(0);
      })
      .then(() => {
        User
          .findAll({
            attributes: ['name'],
            where: {
              $or: [
                {
                  name: {
                    $iLike: `%${search}%`
                  }
                },
                {
                  username: {
                    $iLike: search
                  }
                },
                {
                  email: {
                    $iLike: search
                  }
                },
              ]
            },
            include: [
              { model: Recipe }
            ]
          })
          .then(recipes => res.status(201).json({
            success: true,
            message: 'Recipe(s) found',
            recipe: results.concat(recipes)
          }));
      })
      .catch(() => res.status(500).json({
        success: false,
        message: 'Unable to search recipes'
      }));

    return this;
  }

  /**
   * Fetch list of recipes based ingredients supplied
   *
   * @param {object} req - HTTP Request
   * @param {object} res - HTTP Response
   * @returns {object} Class instance
   * @memberof Search
   */
  searchByIngredients(req, res) {
    const ingredients = req.query.ingredients.split(' ');

    const queryClause = ingredients.map(item => ({
      ingredients: { $iLike: `%${item}%` }
    }));

    Recipe
      .findAll({
        where: {
          $or: queryClause
        },
        include: [
          { model: User, attributes: ['name', 'updatedAt'] }
        ]
      })
      .then((foundRecipes) => {
        if (!foundRecipes) {
          return res.status(404).json({
            success: true,
            message: 'Nothing found',
          });
        }

        return res.status(201).json({
          success: true,
          message: 'Recipe(s) found',
          recipe: foundRecipes,
        });
      })
      .catch(() => res.status(500).json({
        success: false,
        message: 'Unable to search recipes'
      }));

    return this;
  }

  /**
   * Fetch list of recipes based on name supplied
   *
   * @param {any} req
   * @param {any} res
   * @returns {object} Classs instance
   * @memberof Search
   */
  searchByName(req, res) {
    const { recipes } = req.query;

    Recipe
      .findAll({
        where: {
          name: { $iLike: `%${recipes}%` }
        },
        include: [
          { model: User, attributes: ['name', 'updatedAt'] }
        ]
      })
      .then((foundRecipes) => {
        if (!foundRecipes) {
          return res.status(404).json({
            success: true,
            message: 'Nothing found',
          });
        }

        return res.status(201).json({
          success: true,
          message: 'Recipe(s) found',
          recipe: foundRecipes,
        });
      })
      .catch(() => res.status(500).json({
        success: false,
        message: 'Unable to search recipes'
      }));

    return this;
  }
}


@@ -407,24 +407,150 @@
 req, res) %7B%0A
+    const limit = req.query.limit %7C%7C 5,%0A      currentPage = (req.query.page %7C%7C 1),%0A      offset = (currentPage - 1) * limit;%0A%0A
     Recipe%0A 
@@ -552,32 +552,40 @@
 ipe%0A      .findA
+ndCountA
 ll(%7B%0A        inc
@@ -712,32 +712,63 @@
 DESC'%5D%0A        %5D
+,%0A        limit,%0A        offset
 %0A      %7D)%0A      
@@ -801,32 +801,276 @@
         
-if (!foundRecipe
+const totalRecords = foundRecipes.count;%0A        const totalPages = Math.ceil(totalRecords / limit);%0A        const newRecipes = Object.assign(%7B%7D,%0A          %7B currentPage, totalPages, totalRecords, recipe: foundRecipes.rows %7D%0A        );%0A        if (!totalRecord
 s) %7B%0A   
@@ -1319,31 +1319,30 @@
       recipe
+s
 : 
-found
+new
 Recipes%0A    
@@ -3627,24 +3627,57 @@
 %7D%0A    %7D));%0A%0A
+    // TODO implement pagination%0A
     Recipe%0A 
@@ -4562,32 +4562,65 @@
 %7D = req.query;%0A%0A
+    // TODO implement pagination%0A
     Recipe%0A     

Implement pagination when fetching recipes by most upvotes