const moment = require('moment-jalaali')
const { body, validationResult } = require('express-validator')
const PieceRequest = require('../models/PieceRequest')
const { _sr } = require('../plugins/serverResponses')
const {
  res404,
  res406,
  res500,
  checkValidations,
  generateRandomDigits
} = require('../plugins/controllersHelperFunctions')
const { SMS } = require('../plugins/SMS_Module')
const { notifyAdmin } = require('../WebSocket/controllers/admin_EventsController')
const _faSr = _sr.fa

// date formaters
function ArpaDateFormat(date) {
  return moment(date).format('YYYY-MM-DD HH:mm:ss')
}

function SmsDateFormat(date) {
  return moment(date).format('jYYYY/jMM/jDD')
}

/// ///////////////// agent
module.exports.add_piece_request = [
  async (req, res) => {
    try {
      const { user_id, agent_id } = req
      const thisTime = Date.now()

      const data = {
        user_id,
        agent_id,
        createDate: ArpaDateFormat(thisTime),
        statusHistory: [{ status: 'temp', date: thisTime }]
      }

      const pr = PieceRequest(data)
      await pr.save()
      return res.json({ message: _faSr.response.success_save })
    } catch (e) {
      return res500(res, e)
    }
  }
]

module.exports.add_pieces_to_pr = [
  [
    body('ItemReceptionTransDate').notEmpty().withMessage('تاریخ پذیرش را مشخص کنید'),

    body('ItemName').notEmpty().withMessage('نام کالا را مشخص کنید'),

    body('ItemID').notEmpty().withMessage('Include ItemID'),

    body('ItemCode').notEmpty().withMessage('Include ItemCode'),

    body('gStatus').notEmpty().withMessage('وضعیت گارانتی را مشخص کنید'),

    body('pieceName').notEmpty().withMessage('نام قطعه را مشخص کنید'),

    body('pieceQuantity')
      .notEmpty()
      .withMessage('تعداد قطعه را مشخص کنید')
      .isNumeric()
      .withMessage(_faSr.format.number),

    body('pieceCode').notEmpty().withMessage('Include pieceCode'),

    body('pieceId').notEmpty().withMessage('Include pieceId')
  ],
  checkValidations(validationResult),
  async (req, res) => {
    try {
      const prId = req.params?.prId
      const {
        ItemReceptionTransDate,
        ItemName,
        SerialNo1,
        ItemID,
        ItemCode,
        gStatus,
        pieceName,
        pieceCode,
        pieceQuantity,
        pieceId
      } = req.body

      const data = {
        ItemReceptionTransDate,
        ItemName,
        SerialNo1,
        ItemID,
        ItemCode,
        gStatus,
        pieceName,
        pieceCode,
        pieceQuantity,
        pieceId
      }

      const pr = await PieceRequest.findById(prId)
      pr.items.push(data)
      await pr.save()
      return res.json({ message: _faSr.response.success_save })
    } catch (e) {
      return res404(res, e)
    }
  }
]

module.exports.remove_piece_from_pr = [
  async (req, res) => {
    try {
      const pieceItemId = req.params?.pieceItemId
      if (!pieceItemId) throw new Error('invalid id')
      const pr = await PieceRequest.findOne({ 'items._id': pieceItemId })
      pr.items.id(pieceItemId).remove()
      await pr.save()
      return res.json({ message: _faSr.response.success_remove })
    } catch (e) {
      console.log(e)

      return res500(res, e)
    }
  }
]

module.exports.update_pr_description = [
  (req, res) => {
    const { description } = req.body
    const data = {
      description
    }
    PieceRequest.findByIdAndUpdate(req.params?.id, data, (err, oldData) => {
      if (err) return res404(res, 'invalid id')
      return res.json({ message: _faSr.response.success_save })
    })
  }
]

module.exports.get_all_pr_for_agent = [
  (req, res) => {
    const agent_id = req.agent_id
    PieceRequest.find({ agent_id }, (err, data) => {
      if (err) return res500(res, err)
      else return res.json(data)
    })
  }
]

module.exports.get_one_pr_for_agent = [
  (req, res) => {
    PieceRequest.findById(req.params.id)
      .populate(
        'agent_id',
        'full_name province_name city_name address agent_code postal_code tel_number fax_number mobile_number'
      )
      .exec((err, data) => {
        if (err || !data) return res404(res, err)
        else return res.json(data)
      })
  }
]

module.exports.delete_pr = [
  async (req, res) => {
    try {
      const pr = await PieceRequest.findById(req.params?.id)
      if (pr.status !== 'temp') return res406(res, 'نمیتوانید درخواست ارسال شده را حذف کنید')
      await pr.remove()
      return res.json({ message: _faSr.response.success_remove })
    } catch (e) {
      return res404(res, 'invalid id')
    }
  }
]

module.exports.change_pr_status_to_sent_by_agent = [
  async (req, res) => {
    try {
      const thisTime = Date.now()

      const pr = await PieceRequest.findById(req.params?.id).populate('agent_id')
      if (!pr) throw new Error('invalid pr id')
      const totalPr = await PieceRequest.find({ status: { $ne: 'temp' } })

      if (pr.status !== 'temp') return res406(res, 'این فرم قبلا برای آسان سرویس ارسال شده')
      if (!pr.items.length) return res406(res, 'هیچ قطعه ای به فرم اضافه نکرده اید')

      // generate tracking code
      const trackingCode = 'PR' + totalPr.length.toString().padStart(4, '0') + generateRandomDigits(2)

      // modify pr
      pr.status = 'sent'
      pr.statusHistory.push({ status: 'sent', date: thisTime })
      pr.trackingCode = trackingCode
      pr.sendDate = ArpaDateFormat(thisTime)

      // send sms for agent
      const smsMsg = [
        ' نماینده گرامی درخواست قطعه شما در تاریخ ',
        SmsDateFormat(thisTime),
        ' با کد پیگیری ',
        trackingCode,
        ' برای شرکت ارسال شد. '
      ]

      SMS([pr.agent_id.mobile_number], smsMsg.join(''))

      await pr.save()
      notifyAdmin('updateNewPieceRequests')
      return res.json({ message: 'درخواست قطعه ارسال شد' })
    } catch (e) {
      console.log(e)

      return res404(res, e)
    }
  }
]

/// ///////////////// admin
module.exports.get_all_pr_for_admin = [
  async (req, res) => {
    try {
      const prList = await PieceRequest.find({ status: { $ne: 'temp' } }).populate(
        'agent_id',
        'full_name agent_code mobile_number national_code province_name city_name province_id city_id'
      )
      return res.json(prList)
    } catch (e) {
      return res500(res, e)
    }
  }
]

module.exports.get_oneAgent_pr_for_admin = [
  async (req, res) => {
    const agent_id = req.params?.agent_id
    try {
      const prList = await PieceRequest.find({ status: { $ne: 'temp' }, agent_id }).populate(
        'agent_id',
        'full_name agent_code mobile_number national_code province_name city_name'
      )
      return res.json(prList)
    } catch (e) {
      return res500(res, e)
    }
  }
]

module.exports.get_one_pr_for_admin = [
  async (req, res) => {
    try {
      const { user_id } = req
      const thisTime = Date.now()
      const pr = await PieceRequest.findById(req.params?.id)
        .populate(
          'agent_id',
          'agent_code full_name mobile_number fax_number tel_number province_name city_name national_code address postal_code store_name'
        )
        .populate('_openedBy', 'username first_name last_name')
        .populate('_updatedBy', 'username first_name last_name')
      if (!pr.seen) {
        pr.seen = true
        pr._openedBy = user_id
        pr.status = 'ongoing'
        pr.statusHistory.push({ status: 'ongoing', date: thisTime })
        await pr.save()

        const smsMsg = [
          ' نماینده گرامی درخواست قطعه شما با کد پیگیری ',
          pr.trackingCode,
          ' در تاریخ ',
          SmsDateFormat(thisTime),
          ' در دست اقدام قرار گرفت. '
        ]

        SMS([pr.agent_id.mobile_number], smsMsg.join(''))
        notifyAdmin('updateNewPieceRequests')
      }
      return res.json(pr)
    } catch (e) {
      return res500(res, e)
    }
  }
]

module.exports.change_pr_status_by_admin = [
  [
    body('status')
      .notEmpty()
      .withMessage('status is required')
      .bail()
      .custom((value, { req }) => {
        const acceptablvalues = ['waiting', 'delivered']
        if (!acceptablvalues.includes(value)) return Promise.reject(new Error('invalid status'))
        else return true
      })
  ],
  checkValidations(validationResult),
  async (req, res) => {
    const { user_id } = req
    const { status, deliveryCode } = req.body
    const thisTime = Date.now()

    try {
      const pr = await PieceRequest.findById(req.params?.id).populate('agent_id')
      if (!pr) throw new Error('invalid pr id')

      // check statuses
      const statusErrMsg = 'invalid status for this time'
      if (pr.status === 'delivered') return res406(res, statusErrMsg)
      if (pr.status === 'waiting' && status === 'waiting') return res406(res, statusErrMsg)

      // save status
      pr._updatedBy = user_id
      pr.status = status
      pr.statusHistory.push({ status, date: thisTime })

      let smsMessage
      // differenet status methods
      if (status === 'waiting') {
        smsMessage = [
          ' نماینده گرامی درخواست قطعه شما با کد پیگیری ',
          pr.trackingCode,
          ' در تاریخ ',
          SmsDateFormat(thisTime),
          ' در انتظار قطعه میباشد. '
        ]
      }

      if (status === 'delivered') {
        if (deliveryCode) pr.deliveryCode = deliveryCode

        function deliveryCodePhrase() {
          if (deliveryCode.length) return `کد پیگیری مرسوله: ${deliveryCode}` + '\n'
          else return ''
        }

        smsMessage = [
          ' نماینده گرامی درخواست قطعه شما با کد پیگیری ',
          pr.trackingCode,
          ' در تاریخ ',
          SmsDateFormat(thisTime),
          ' تحویل شد. ',
          '\n',
          deliveryCodePhrase()
        ]
      }

      await SMS([pr.agent_id.mobile_number], smsMessage.join(''))
      await pr.save()
      return res.json({ message: _faSr.response.success_save })
    } catch (e) {
      return res500(res, e)
    }
  }
]
