const fs = require('fs')
const mongoose = require('mongoose')
const { body, validationResult } = require('express-validator')
const jimp = require('jimp')
const Download = require('../models/download/Download')
const DownloadCategory = require('../models/download/DownloadCategory')
const { _sr } = require('../plugins/serverResponses')
const { res404, res500, checkValidations } = require('../plugins/controllersHelperFunctions')
const _faSr = _sr.fa

const imageWidth = 400
const imageHeight = 400
const imageQuality = 100
const shortDescriptionLength = 200

const paginateLimit = 8

module.exports.create = [
  [
    body('title')
      .notEmpty()
      .withMessage(_faSr.required.title)
      .bail()
      .custom((value, { req }) => {
        return Download.findOne({ title: value }).then(item => {
          if (item) return Promise.reject(_faSr.duplicated.title)
          else return true
        })
      }),

    body('short_description').notEmpty().withMessage(_faSr.required.description),

    body('description').notEmpty().withMessage(_faSr.required.description),

    body('category').notEmpty().withMessage(_faSr.required.category)
  ],
  checkValidations(validationResult),
  (req, res) => {
    if (!req.files || !req.files.image)
      return res.status(422).json({ validation: { image: { msg: _faSr.required.image } } })

    const data = {
      _creator: req.user_id,
      title: req.body.title,
      short_description: req.body.short_description.slice(0, shortDescriptionLength),
      description: req.body.description,
      category: req.body.category
    }

    const image = req.files.image
    // validate image format
    const supportedFormats = ['jpg', 'jpeg', 'png', 'webp']
    if (!supportedFormats.includes(image.mimetype.split('/')[1])) {
      return res.status(422).json({ validation: { image: { msg: _faSr.format.image } } })
    }

    const imageName = 'download_' + Date.now() + '.' + image.mimetype.split('/')[1]
    data.image = imageName

    jimp
      .read(image.data)
      .then(img => {
        img.cover(imageWidth, imageHeight)
        img.quality(imageQuality)
        img.write(`./static/uploads/images/downloads/${imageName}`, err => {
          if (err) console.log(err)
        })
      })
      .catch(err => {
        console.log(err)
      })

    const download = new Download(data)
    download.save((err, data) => {
      if (err) console.log(err)
      return res.json(data)
    })
  }
]

module.exports.getAll = [
  async (req, res) => {
    try {
      if (req.params.category === 'all') {
        const downloads = await Download.paginate({}, { page: req.params.page, limit: paginateLimit })
        if (!downloads.docs.length && Number(req.params.page) !== 1)
          return res.status(404).json({ message: _faSr.not_found.item_id })
        return res.json(downloads)
      } else {
        let catID
        if (mongoose.isValidObjectId(req.params.category)) catID = req.params.category
        else {
          const category = await DownloadCategory.findOne({ name: req.params.category })
          if (!category) return res.status(404).json({ message: _faSr.not_found.item_id })
          catID = category._id
        }
        const downloads = await Download.paginate({ category: catID }, { page: req.params.page, limit: paginateLimit })
        if (!downloads.docs.length && Number(req.params.page) !== 1)
          return res.status(404).json({ message: _faSr.not_found.item_id })
        return res.json(downloads)
      }
    } catch (e) {
      return res.status(404).json({ message: _faSr.not_found.item_id })
    }
  }
]

module.exports.getNewest = [
  (req, res) => {
    Download.find({})
      .sort({ _id: -1 })
      .limit(3)
      .exec((err, data) => {
        if (err) return res500(res, err)
        return res.json(data)
      })
  }
]

module.exports.getOne = [
  (req, res) => {
    const query = {}
    if (mongoose.isValidObjectId(req.params.id)) query._id = req.params.id
    else query.title = req.params.id
    Download.findOne(query)
      .populate('_creator', 'first_name last_name')
      .exec((err, item) => {
        if (err) return res.status(404).json({ message: err })
        return res.json(item)
      })
  }
]

module.exports.update = [
  [
    body('title')
      .notEmpty()
      .withMessage(_faSr.required.title)
      .bail()
      .custom((value, { req }) => {
        return Download.findOne({ title: value }).then(item => {
          if (item && item._id.toString() !== req.params.id) return Promise.reject(_faSr.duplicated.title)
          else return true
        })
      }),

    body('short_description').notEmpty().withMessage(_faSr.required.description),

    body('description').notEmpty().withMessage(_faSr.required.description),

    body('category').notEmpty().withMessage(_faSr.required.category)
  ],
  checkValidations(validationResult),
  (req, res) => {
    const data = {
      _creator: req.user_id,
      title: req.body.title,
      short_description: req.body.short_description.slice(0, shortDescriptionLength),
      description: req.body.description,
      category: req.body.category
    }

    if (req.files && req.files.image) {
      const image = req.files.image
      // validate image format
      const supportedFormats = ['jpg', 'jpeg', 'png', 'webp']
      if (!supportedFormats.includes(image.mimetype.split('/')[1])) {
        return res.status(422).json({ validation: { image: { msg: _faSr.format.image } } })
      }

      const imageName = 'download_' + Date.now() + '.' + image.mimetype.split('/')[1]
      data.image = imageName

      jimp
        .read(image.data)
        .then(img => {
          img.cover(imageWidth, imageHeight)
          img.quality(imageQuality)
          img.write(`./static/uploads/images/downloads/${imageName}`, err => {
            if (err) console.log(err)
          })
        })
        .catch(err => {
          console.log(err)
        })
    }

    Download.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
      if (err) return res.status(404).json({ message: _faSr.not_found.item_id })
      if (req.files && req.files.image) {
        fs.unlink(`./static/${oldData.image}`, err => {
          if (err) console.log(err)
        })
      }
      Download.findById(oldData._id, (err, result) => {
        if (err) return res.status(404).json({ message: _faSr.not_found.item_id })
        return res.json(result)
      })
    })
  }
]

module.exports.delete = [
  (req, res) => {
    Download.findByIdAndDelete(req.params.id, (err, data) => {
      if (err) return res.status(404).json({ message: _faSr.not_found.item_id })
      data.files.forEach(item => {
        fs.unlink(`./static/${item.file}`, err => {
          if (err) console.log(err)
        })
      })
      return res.json({ message: _faSr.response.success_remove })
    })
  }
]
/// /////////////////////////////////////////////////////////// add files
module.exports.addFile = [
  [
    body('name').notEmpty().withMessage(_faSr.required.name),

    body('os').notEmpty().withMessage(_faSr.required.category)
  ],
  checkValidations(validationResult),
  (req, res) => {
    if (!req.files || !req.files.file)
      return res.status(422).json({ validation: { file: { msg: _faSr.required.file } } })

    const file = req.files.file
    const fileName = 'AsanService-' + Math.ceil(Math.random() * 1000) + '_' + file.name
    file.mv(`./static/uploads/apps/${fileName}`)

    const data = {
      _creator: req.user_id,
      name: req.body.name,
      os: req.body.os,
      file: fileName
    }

    Download.findById(req.body.page_id, (err, page) => {
      if (err || !page) return res404(res, err)
      page.files.push(data)
      page.save(err => {
        if (err) console.log(err)
        return res.json(page.files)
      })
    })
  }
]

module.exports.deletFile = [
  (req, res) => {
    Download.findOne({ 'files._id': req.params.id }, (err, page) => {
      if (err || !page) return res404(res, err)
      const app = page.files.id(req.params.id)
      app.remove(err => {
        if (err) console.log(err)
        fs.unlink(`./static/${app.file}`, err => {
          if (err) console.log(err)
        })
      })
      page.save(err => {
        if (err) console.log(err)
        return res.json({ message: _faSr.response.success_remove })
      })
    })
  }
]
