const moment = require('moment-jalaali')
const { body, validationResult } = require('express-validator')
const OldPieceRequest = require('../models/OldPieceRequest')
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_oldPiece_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 opr = OldPieceRequest(data)
      await opr.save()
      return res.json({ message: _faSr.response.success_save })
    } catch (e) {
      return res500(res, e)
    }
  }
]

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

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

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

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

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

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

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

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

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

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

      return res500(res, e)
    }
  }
]

module.exports.update_opr_description = [
  (req, res) => {
    const { description } = req.body
    const data = {
      description
    }
    OldPieceRequest.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_opr_for_agent = [
  (req, res) => {
    const agent_id = req.agent_id
    OldPieceRequest.find({ agent_id }, (err, data) => {
      if (err) return res500(res, err)
      else return res.json(data)
    })
  }
]

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

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

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

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

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

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

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

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

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

      return res404(res, e)
    }
  }
]

/// ///////////////// admin
module.exports.get_all_opr_for_admin = [
  async (req, res) => {
    try {
      const oprList = await OldPieceRequest.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(oprList)
    } catch (e) {
      return res500(res, e)
    }
  }
]

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

module.exports.get_one_opr_for_admin = [
  async (req, res) => {
    try {
      const { user_id } = req
      const thisTime = Date.now()
      const opr = await OldPieceRequest.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 (!opr.seen) {
        opr.seen = true
        opr._openedBy = user_id
        opr.status = 'ongoing'
        opr.statusHistory.push({ status: 'ongoing', date: thisTime })
        await opr.save()

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

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

module.exports.change_opr_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 opr = await OldPieceRequest.findById(req.params?.id).populate('agent_id')
      if (!opr) throw new Error('invalid opr id')

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

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

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

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

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

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

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