const fs = require('fs')
const { body, validationResult } = require('express-validator')
const moment = require('moment-jalaali')
const Mongoose = require('mongoose')
const Representation = require('../models/Representation')
const User = require('../models/User')
const { SMS } = require('../plugins/SMS_Module')
const { phrases } = require('../plugins/SMS_Phrases')
const { _sr } = require('../plugins/serverResponses')
const { notifyAdmin } = require('../WebSocket/controllers/admin_EventsController')
const {
  res404,
  res406,
  res500,
  checkValidations,
  checkMobileNumber,
  checkNationalCode,
  isPersian,
  isPersianWithDigits
} = require('../plugins/controllersHelperFunctions')

const _faSr = _sr.fa

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

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

module.exports.add_representation = [
  [
    body('representation_type')
      .notEmpty()
      .withMessage('نوع نمایندگی را مشخص کنید')
      .bail()
      .custom((value, { req }) => {
        const acceptedValues = ['verity', 'panatech', 'both']
        if (!acceptedValues.includes(value)) return Promise.reject(new Error('invalid value'))
        else return true
      }),

    body('full_name')
      .notEmpty()
      .withMessage(_faSr.required.name)
      .bail()
      .custom((value, { req }) => {
        if (!isPersian(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('birth_date').notEmpty().withMessage(_faSr.required.birthdate),

    body('id_number').notEmpty().withMessage(_faSr.required.field).isNumeric().withMessage(_faSr.format.number),

    body('place_of_issue')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersianWithDigits(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('national_code')
      .notEmpty()
      .withMessage(_faSr.required.national_code)
      .custom((value, { req }) => {
        if (!checkNationalCode(value)) return Promise.reject(_faSr.format.national_code)
        else return Promise.resolve()
      }),

    body('fathers_name')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersian(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('education_level').notEmpty().withMessage(_faSr.required.field),

    body('military_status')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersianWithDigits(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('store_name').notEmpty().withMessage(_faSr.required.field),

    body('province_name').notEmpty().withMessage(_faSr.required.field),

    body('province_id').notEmpty().withMessage(_faSr.required.field),

    body('city_name').notEmpty().withMessage(_faSr.required.field),

    body('city_id').notEmpty().withMessage(_faSr.required.field),

    body('postal_code').notEmpty().withMessage(_faSr.required.field).isNumeric().withMessage(_faSr.format.number),

    body('mobile_number')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .isNumeric()
      .withMessage(_faSr.format.number)
      .custom((value, { req }) => {
        if (!checkMobileNumber(value)) return Promise.reject(new Error('فرمت شماره موبایل درست نمیباشد'))
        else return Promise.resolve()
      }),

    body('tel_number').notEmpty().withMessage(_faSr.required.field).isNumeric().withMessage(_faSr.format.number),

    body('email').notEmpty().withMessage(_faSr.required.field).bail().isEmail().withMessage(_faSr.format.email),

    body('address')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersianWithDigits(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('business_license')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .isBoolean()
      .withMessage(_faSr.format.boolean),

    body('ownership_type').notEmpty().withMessage(_faSr.required.field),

    body('total_area').notEmpty().withMessage(_faSr.required.field),

    body('repair_area').notEmpty().withMessage(_faSr.required.field),

    body('stock_area').notEmpty().withMessage(_faSr.required.field),

    body('customer_reference_floor').notEmpty().withMessage(_faSr.required.field),

    body('place_location').notEmpty().withMessage(_faSr.required.field),

    body('geo_location').notEmpty().withMessage(_faSr.required.field),

    body('banner_info').notEmpty().withMessage(_faSr.required.field),

    body('repair_technicians').notEmpty().withMessage(_faSr.required.field),

    body('repair_masters').notEmpty().withMessage(_faSr.required.field),

    body('office_workers').notEmpty().withMessage(_faSr.required.field),

    body('bike_deliveries').notEmpty().withMessage(_faSr.required.field),

    body('computer_repair_exp').notEmpty().withMessage(_faSr.required.field),

    body('multimedia_repair_exp').notEmpty().withMessage(_faSr.required.field),

    body('business_exp').notEmpty().withMessage(_faSr.required.field),

    body('know_asanServ_from').notEmpty().withMessage(_faSr.required.field),

    body('asanServ_products_knowledge').notEmpty().withMessage(_faSr.required.field),

    body('computer_saling_exp').notEmpty().withMessage(_faSr.required.field)
  ],
  checkValidations(validationResult),
  async (req, res) => {
    const { user_id } = req
    if (!user_id) throw new Error('invalid user id')
    const {
      representation_type,
      full_name,
      birth_date,
      id_number,
      place_of_issue,
      national_code,
      fathers_name,
      education_level,
      military_status,
      certificates,
      store_name,
      province_name,
      province_id,
      city_name,
      city_id,
      postal_code,
      mobile_number,
      tel_number,
      fax_number,
      economic_code,
      email,
      address,
      business_license,
      ownership_type,
      total_area,
      repair_area,
      stock_area,
      customer_reference_floor,
      place_location,
      geo_location,
      banner_info,
      repair_technicians,
      repair_masters,
      office_workers,
      bike_deliveries,
      computer_repair_exp,
      multimedia_repair_exp,
      business_exp,
      know_asanServ_from,
      introducer_info,
      asanServ_products_knowledge,
      computer_saling_exp,
      computer_saling_description,
      other_representations,
      more_descriptions
    } = req.body
    const data = {
      user_id,
      representation_type,
      full_name,
      birth_date,
      id_number,
      place_of_issue,
      national_code,
      fathers_name,
      education_level,
      military_status,
      certificates,
      store_name,
      province_name,
      province_id,
      city_name,
      city_id,
      postal_code,
      mobile_number,
      tel_number,
      fax_number,
      economic_code,
      email,
      address,
      business_license,
      ownership_type,
      total_area,
      repair_area,
      stock_area,
      customer_reference_floor,
      place_location,
      geo_location,
      banner_info,
      repair_technicians,
      repair_masters,
      office_workers,
      bike_deliveries,
      computer_repair_exp,
      multimedia_repair_exp,
      business_exp,
      know_asanServ_from,
      introducer_info,
      asanServ_products_knowledge,
      computer_saling_exp,
      computer_saling_description,
      other_representations,
      more_descriptions
    }

    try {
      const checkUserRepresentations = await Representation.find({ user_id, archived: false })
      if (checkUserRepresentations.length)
        return res406(res, 'تا زمانی که درخواست قبلی توسط کارشناسان تعیین وضعیت نشود نمیتوانید درخواست جدیدی ثبت کنید.')
      const allRepresentations = await Representation.find()
      const representation_code =
        'ASAREP' +
        moment(Date.now()).format('jMMM').toUpperCase() +
        allRepresentations.length.toString().padStart(4, '0')

      data.representation_code = representation_code

      const representation = new Representation(data)
      await representation.save()
      const user = await User.findById(user_id)
      user.askedForRepresentation = true
      user.representation_code = representation_code
      await user.save()

      const smsMessage = [
        ' متقاضی گرامی درخواست شما با کد پیگیری ',
        representation_code,
        ' در تاریخ ',
        SmsDateFormat(Date.now()),
        ' در سامانه ثبت شد. ',
        '\n',
        ' بعد از بررسی مدارک توسط کارشناسان نتیجه از طریق پیامک برای شما ارسال خواهد شد، همچنین میتوانید با کد پیگیری از طریق نشانی زیر وضعیت درخواست خود را بررسی کند. ',
        '\n',
        'https://asan-service.com/representation',
        '\n',
        phrases.signature
      ]

      const responseMsg = ['درخواست شما باموفقیت ثبت شد.', '\n', ' کد پیگیری: ', representation_code]

      SMS([mobile_number], smsMessage.join(''))
      notifyAdmin('updateNewRepresentations')
      return res.json({ message: responseMsg.join('') })
    } catch (e) {
      return res500(res, e)
    }
  }
]

module.exports.edit_representation_by_user = [
  [
    body('representation_type')
      .notEmpty()
      .withMessage('نوع نمایندگی را مشخص کنید')
      .bail()
      .custom((value, { req }) => {
        const acceptedValues = ['verity', 'panatech', 'both']
        if (!acceptedValues.includes(value)) return Promise.reject(new Error('invalid value'))
        else return true
      }),

    body('full_name')
      .notEmpty()
      .withMessage(_faSr.required.name)
      .bail()
      .custom((value, { req }) => {
        if (!isPersian(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('birth_date').notEmpty().withMessage(_faSr.required.birthdate),

    body('id_number').notEmpty().withMessage(_faSr.required.field).isNumeric().withMessage(_faSr.format.number),

    body('place_of_issue')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersianWithDigits(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('national_code')
      .notEmpty()
      .withMessage(_faSr.required.national_code)
      .custom((value, { req }) => {
        if (!checkNationalCode(value)) return Promise.reject(_faSr.format.national_code)
        else return Promise.resolve()
      }),

    body('fathers_name')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersian(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('education_level').notEmpty().withMessage(_faSr.required.field),

    body('military_status')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersianWithDigits(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('store_name').notEmpty().withMessage(_faSr.required.field),

    body('province_name').notEmpty().withMessage(_faSr.required.field),

    body('province_id').notEmpty().withMessage(_faSr.required.field),

    body('city_name').notEmpty().withMessage(_faSr.required.field),

    body('city_id').notEmpty().withMessage(_faSr.required.field),

    body('postal_code').notEmpty().withMessage(_faSr.required.field).isNumeric().withMessage(_faSr.format.number),

    body('mobile_number')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .isNumeric()
      .withMessage(_faSr.format.number)
      .custom((value, { req }) => {
        if (!checkMobileNumber(value)) return Promise.reject(new Error('فرمت شماره موبایل درست نمیباشد'))
        else return Promise.resolve()
      }),

    body('tel_number').notEmpty().withMessage(_faSr.required.field).isNumeric().withMessage(_faSr.format.number),

    body('email').notEmpty().withMessage(_faSr.required.field).bail().isEmail().withMessage(_faSr.format.email),

    body('address')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersianWithDigits(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('business_license')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .isBoolean()
      .withMessage(_faSr.format.boolean),

    body('ownership_type').notEmpty().withMessage(_faSr.required.field),

    body('total_area').notEmpty().withMessage(_faSr.required.field),

    body('repair_area').notEmpty().withMessage(_faSr.required.field),

    body('stock_area').notEmpty().withMessage(_faSr.required.field),

    body('customer_reference_floor').notEmpty().withMessage(_faSr.required.field),

    body('place_location').notEmpty().withMessage(_faSr.required.field),

    body('geo_location').notEmpty().withMessage(_faSr.required.field),

    body('banner_info').notEmpty().withMessage(_faSr.required.field),

    body('repair_technicians').notEmpty().withMessage(_faSr.required.field),

    body('repair_masters').notEmpty().withMessage(_faSr.required.field),

    body('office_workers').notEmpty().withMessage(_faSr.required.field),

    body('bike_deliveries').notEmpty().withMessage(_faSr.required.field),

    body('computer_repair_exp').notEmpty().withMessage(_faSr.required.field),

    body('multimedia_repair_exp').notEmpty().withMessage(_faSr.required.field),

    body('business_exp').notEmpty().withMessage(_faSr.required.field),

    body('know_asanServ_from').notEmpty().withMessage(_faSr.required.field),

    body('asanServ_products_knowledge').notEmpty().withMessage(_faSr.required.field),

    body('computer_saling_exp').notEmpty().withMessage(_faSr.required.field)
  ],
  checkValidations(validationResult),
  async (req, res) => {
    const { user_id } = req
    const representation_id = req.params?.representation_id
    if (!user_id || !representation_id) throw new Error('invalid user id')
    const {
      representation_type,
      full_name,
      birth_date,
      id_number,
      place_of_issue,
      national_code,
      fathers_name,
      education_level,
      military_status,
      certificates,
      store_name,
      province_name,
      province_id,
      city_name,
      city_id,
      postal_code,
      mobile_number,
      tel_number,
      fax_number,
      economic_code,
      email,
      address,
      business_license,
      ownership_type,
      total_area,
      repair_area,
      stock_area,
      customer_reference_floor,
      place_location,
      geo_location,
      banner_info,
      repair_technicians,
      repair_masters,
      office_workers,
      bike_deliveries,
      computer_repair_exp,
      multimedia_repair_exp,
      business_exp,
      know_asanServ_from,
      introducer_info,
      asanServ_products_knowledge,
      computer_saling_exp,
      computer_saling_description,
      other_representations,
      more_descriptions
    } = req.body
    const data = {
      user_id,
      representation_type,
      full_name,
      birth_date,
      id_number,
      place_of_issue,
      national_code,
      fathers_name,
      education_level,
      military_status,
      certificates,
      store_name,
      province_name,
      province_id,
      city_name,
      city_id,
      postal_code,
      mobile_number,
      tel_number,
      fax_number,
      economic_code,
      email,
      address,
      business_license,
      ownership_type,
      total_area,
      repair_area,
      stock_area,
      customer_reference_floor,
      place_location,
      geo_location,
      banner_info,
      repair_technicians,
      repair_masters,
      office_workers,
      bike_deliveries,
      computer_repair_exp,
      multimedia_repair_exp,
      business_exp,
      know_asanServ_from,
      introducer_info,
      asanServ_products_knowledge,
      computer_saling_exp,
      computer_saling_description,
      other_representations,
      more_descriptions
    }
    try {
      const checkAccess = await Representation.findById(representation_id)
      if (!checkAccess.editAccess) throw new Error('شما دسترسی ویرایش اطلاعات ندارید')
      await Representation.findByIdAndUpdate(representation_id, data)
      return res.json({ message: 'با موفقیت آپدیت شد' })
    } catch (e) {
      return res500(res, e)
    }
  }
]

module.exports.getAll = [
  (req, res) => {
    Representation.find({})
      .select(
        'user_id representation_code agent_code full_name national_code mobile_number province_name province_id city_name city_id status created_at representation_type'
      )
      .exec((err, data) => {
        if (err || !data) return res404(res, err)
        else return res.json(data)
      })
  }
]

module.exports.getOne = [
  async (req, res) => {
    try {
      const representation = await Representation.findById(req.params?.id)
        .populate('_updatedBy', 'username first_name last_name')
        .populate('_revokedBy', 'username first_name last_name')
      if (!representation) return res404(res, 'incorrect id')
      if (representation.status === 'registered') {
        representation.status = 'ongoing'
        await representation.save()
        const smsMsg = [
          ' متقاصی گرامی درخواست شما برای اخذ نمایندگی آسان سرویس به کد پیگیری ',
          representation.representation_code,
          ' مورخ ',
          SmsDateFormat(Date.now()),
          ' توسط کارشناسان آسان سرویس مشاهده و مورد بررسی قرار گرفت. ',
          '\n',
          phrases.signature
        ]
        SMS([representation.mobile_number], smsMsg.join(''))
        notifyAdmin('updateNewRepresentations')
        return res.json(representation)
      } else return res.json(representation)
    } catch (e) {
      return res500(res, e)
    }
  }
]

module.exports.getLastUserRep = [
  async (req, res) => {
    try {
      const repId = req.params?.id
      const isId = Mongoose.isValidObjectId(repId)
      const representation = await Representation.findOne({
        $or: [{ representation_code: repId }, { _id: isId ? repId : undefined }]
      })
      if (!representation) return res404(res, 'incorrect id')
      return res.json(representation)
    } catch (e) {
      console.log('🚀 ~ file: representationController.js:620 ~ e', e)
      return res500(res, e)
    }
  }
]

module.exports.change_form_status = [
  async (req, res) => {
    const status = req.body?.status
    // status prop validation check
    if (!status) return res500(res, 'status prop required')
    const availableStatuses = [
      'verification',
      'accepted',
      'rejected',
      'uploadOff',
      'uploadOn',
      'editAccessOn',
      'editAccessOff'
    ]
    if (!availableStatuses.includes(status)) return res500(res, 'invalid status')

    try {
      // find representation and user
      const representation = await Representation.findById(req.params.id)
      if (!representation) return res404(res, 'incorrect id')
      if (
        status !== 'uploadOn' &&
        status !== 'uploadOff' &&
        status !== 'editAccessOn' &&
        status !== 'editAccessOff' &&
        representation.archived
      ) {
        return res500(res, 'شما نمیتوانید وضعیت این فرم را تغییر دهید')
      }
      const user = await User.findById(representation.user_id)
      if (!user) throw new Error('incorrect user id')
      if (status === 'accepted' && user.isAgent) return res500(res, 'حساب این کاربر قبلا به حساب نماینده تبدیل شده')

      // change upload ability
      if (status === 'uploadOn') {
        representation.upload = true
        await representation.save()
        const smsMsg = [
          ' متقاصی گرامی دسرسی آپلود مدارک برای درخواست ',
          representation.representation_code,
          ' ایجاد شد، لطفا هرچه سریع تر نسبت به آپلود مدارک خود اقدام کنید. ',
          '\n',
          phrases.signature
        ]
        SMS([representation.mobile_number], smsMsg.join(''))
        return res.json({ message: 'وضعیت جدید در سیستم ثبت شد و پیامک اطلاع رسانی برای متقاضی ارسال شد' })
      }
      if (status === 'uploadOff') {
        representation.upload = false
        await representation.save()
        return res.json({ message: 'وضعیت جدید در سیستم ثبت شد' })
      }
      // change editAccess ability
      if (status === 'editAccessOn') {
        representation.editAccess = true
        await representation.save()
        const smsMsg = [
          ' نماینده گرامی دسرسی ویرایش اطلاعات نمایندگی برای شما ایجاد شد،  لطفا هرچه سریع تر نسبت به ویرایش اطلاعات خود اقدام کنید.',
          '\n',
          phrases.signature
        ]
        SMS([representation.mobile_number], smsMsg.join(''))
        return res.json({ message: 'وضعیت جدید در سیستم ثبت شد و پیامک اطلاع رسانی برای متقاضی ارسال شد' })
      }
      if (status === 'editAccessOff') {
        representation.editAccess = false
        await representation.save()
        return res.json({ message: 'وضعیت جدید در سیستم ثبت شد' })
      }
      // change representation and user data
      representation.status = status
      user.askedForRepresentation = true
      user.isAgent = false

      if (status === 'rejected') {
        user.askedForRepresentation = false
        representation.archived = true
        representation.upload = false
        representation.editAccess = false
      }
      if (status === 'accepted') {
        user.askedForRepresentation = false
        representation.archived = true
        representation.upload = false
        representation.editAccess = false
        user.isAgent = true
        user.representation_id = representation._id
        const agentsCount = await Representation.find({ status: 'accepted' })
        representation.agent_code = 'ASG' + agentsCount.length.toString().padStart(2, '0')
      }

      // save changes
      await representation.save()
      await user.save()

      // send sms for user
      function statusToPhrase() {
        if (status === 'verification') return '  در وضعیت احراز هویت و بررسی مدارک قرار گرفت.'
        else if (status === 'rejected') return ' رد شد. '
        else return ' مورد قبول قرار گرفت. برای ادامه ی فرایند از طرف شرکت با شما تماس گرفته خواهد شد. '
      }

      const smsMsg = [
        ' متقاصی گرامی درخواست شما برای اخذ نمایندگی آسان سرویس به کد پیگیری ',
        representation.representation_code,
        ' مورخ ',
        SmsDateFormat(Date.now()),
        statusToPhrase(),
        '\n',
        phrases.signature
      ]
      SMS([representation.mobile_number], smsMsg.join(''))
      return res.json({ message: 'وضعیت جدید در سیستم ثبت شد و پیامک اطلاع رسانی برای متقاضی ارسال شد' })
    } catch (e) {
      return res404(res, `there is an error here --- ${e}`)
    }
  }
]

module.exports.check_representation = [
  [
    body('representation_code')
      .notEmpty()
      .withMessage('کد پیگیری را وارد کنید')
      .bail()
      .isLength({ min: 13 })
      .withMessage('فرمت کدپیگیری صحیح نمیباشد')
  ],
  checkValidations(validationResult),
  (req, res) => {
    const { representation_code } = req.body
    const { user_id } = req
    if (!user_id) return res500(res, 'ابتدا وارد حساب کاربری خود شوید')
    Representation.findOne({ user_id, representation_code: representation_code.toUpperCase() })
      .select('_id status upload created_at')
      .exec((err, data) => {
        if (err || !data) return res404(res, 'درخواستی با این کد پیگیری ثبت نشده')
        else return res.json(data)
      })
  }
]

module.exports.upload_image_to_representation = [
  (req, res) => {
    const file = req.files?.file
    const fieldName = req.query?.name
    const userType = req.params?.userType
    const representation_code = req.params?.representation_code

    if (!file) return res500(res, 'هیچ فایلی برای آپلود انتخاب نکرده اید')
    if (!fieldName) return res500(res, 'هیچ دسته بندی ای انتخاب نکرده اید')
    if (file.mimetype !== 'image/jpeg') return res500(res, 'فقط فرمت jpg قابل قبول است')
    if (file.size / 1024 / 1024 > 2) return res500(res, 'حداکثر حجم مجاز آپلود 2 مگابایت میباشد')

    Representation.findOne({ representation_code }, (err, data) => {
      if (err || !data) return res500(res, 'invalid rep id')
      if ((!data.upload || data.status === 'rejected') && userType !== 'admin') {
        return res500(res, 'شما دسترسی آپلود ندارید')
      }
      const fileName = data.representation_code + '_' + Date.now() + Math.random() + fieldName + file.name
      data[fieldName].push({ name: fileName })
      data.markModified(fieldName)
      file.mv(`./static/uploads/representation_docs/${fileName}`, err => {
        if (err) console.log(err)
      })
      data.save((err, data) => {
        if (err) console.log(err)
        return res.json({ message: 'فایل مدارک در سیستم ذخیره شد' })
      })
    })
  }
]

module.exports.remove_image_from_representation = [
  (req, res) => {
    const representation_code = req.params?.representation_code
    const imgId = req.params?.imgId
    const fieldName = req.query?.name
    const userType = req.params?.userType

    if (!representation_code || !imgId || !fieldName) return res500(res, 'please provide all nessesory information')

    Representation.findOne({ representation_code }, (err, data) => {
      if (err || !data) return res500(res, 'invalid rep id')
      if ((!data.upload || data.status === 'rejected') && userType !== 'admin') {
        return res500(res, 'شما دسترسی آپلود ندارید')
      }
      try {
        const img = data[fieldName].id(imgId)
        img.remove(err => {
          if (err) console.log(err)
          fs.unlink(`./static/uploads/representation_docs/${img.name}`, err => {
            if (err) console.log(err)
          })
        })
        data.save((err, data) => {
          if (err) console.log(err)
          return res.json({ message: 'file removed successfully' })
        })
      } catch (err) {
        res500(res, 'error')
      }
    })
  }
]

module.exports.get_agents = [
  (req, res) => {
    Representation.find({ status: 'accepted', _revoked: false })
      .select(
        'full_name province_name province_id city_name city_id address postal_code tel_number fax_number mobile_number email store_name agent_code representation_type'
      )
      .exec((err, agents) => {
        if (err) return res404(res, err)
        return res.json(agents)
      })
  }
]

module.exports.get_revoked_agents_for_admin = [
  (req, res) => {
    Representation.find({ _revoked: true })
      .select(
        'full_name province_name province_id city_name city_id address postal_code tel_number fax_number mobile_number email store_name agent_code representation_type'
      )
      .exec((err, agents) => {
        if (err) return res404(res, err)
        return res.json(agents)
      })
  }
]

module.exports.update_representation_by_admin = [
  [
    body('representation_type')
      .notEmpty()
      .withMessage('نوع نمایندگی را مشخص کنید')
      .bail()
      .custom((value, { req }) => {
        const acceptedValues = ['verity', 'panatech', 'both']
        if (!acceptedValues.includes(value)) return Promise.reject(new Error('invalid value'))
        else return true
      }),

    body('full_name')
      .notEmpty()
      .withMessage(_faSr.required.name)
      .bail()
      .custom((value, { req }) => {
        if (!isPersian(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('birth_date').notEmpty().withMessage(_faSr.required.birthdate),

    body('id_number').notEmpty().withMessage(_faSr.required.field).isNumeric().withMessage(_faSr.format.number),

    body('place_of_issue')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersianWithDigits(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('national_code')
      .notEmpty()
      .withMessage(_faSr.required.national_code)
      .custom((value, { req }) => {
        if (!checkNationalCode(value)) return Promise.reject(_faSr.format.national_code)
        else return Promise.resolve()
      }),

    body('fathers_name')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersian(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('education_level').notEmpty().withMessage(_faSr.required.field),

    body('military_status')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersianWithDigits(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('store_name').notEmpty().withMessage(_faSr.required.field),

    body('province_name').notEmpty().withMessage(_faSr.required.field),

    body('province_id').notEmpty().withMessage(_faSr.required.field),

    body('city_name').notEmpty().withMessage(_faSr.required.field),

    body('city_id').notEmpty().withMessage(_faSr.required.field),

    body('postal_code').notEmpty().withMessage(_faSr.required.field).isNumeric().withMessage(_faSr.format.number),

    body('mobile_number')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .isNumeric()
      .withMessage(_faSr.format.number)
      .custom((value, { req }) => {
        if (!checkMobileNumber(value)) return Promise.reject(new Error('فرمت شماره موبایل درست نمیباشد'))
        else return Promise.resolve()
      }),

    body('tel_number').notEmpty().withMessage(_faSr.required.field).isNumeric().withMessage(_faSr.format.number),

    body('email').notEmpty().withMessage(_faSr.required.field).bail().isEmail().withMessage(_faSr.format.email),

    body('address')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .custom((value, { req }) => {
        if (!isPersianWithDigits(value)) return Promise.reject(new Error('با حروف فارسی تایپ کنید'))
        else return Promise.resolve()
      }),

    body('business_license')
      .notEmpty()
      .withMessage(_faSr.required.field)
      .bail()
      .isBoolean()
      .withMessage(_faSr.format.boolean),

    body('ownership_type').notEmpty().withMessage(_faSr.required.field),

    body('total_area').notEmpty().withMessage(_faSr.required.field),

    body('repair_area').notEmpty().withMessage(_faSr.required.field),

    body('stock_area').notEmpty().withMessage(_faSr.required.field),

    body('customer_reference_floor').notEmpty().withMessage(_faSr.required.field),

    body('place_location').notEmpty().withMessage(_faSr.required.field),

    body('geo_location').notEmpty().withMessage(_faSr.required.field),

    body('banner_info').notEmpty().withMessage(_faSr.required.field),

    body('repair_technicians').notEmpty().withMessage(_faSr.required.field),

    body('repair_masters').notEmpty().withMessage(_faSr.required.field),

    body('office_workers').notEmpty().withMessage(_faSr.required.field),

    body('bike_deliveries').notEmpty().withMessage(_faSr.required.field),

    body('computer_repair_exp').notEmpty().withMessage(_faSr.required.field),

    body('multimedia_repair_exp').notEmpty().withMessage(_faSr.required.field),

    body('business_exp').notEmpty().withMessage(_faSr.required.field),

    body('know_asanServ_from').notEmpty().withMessage(_faSr.required.field),

    body('asanServ_products_knowledge').notEmpty().withMessage(_faSr.required.field),

    body('computer_saling_exp').notEmpty().withMessage(_faSr.required.field)
  ],
  checkValidations(validationResult),
  async (req, res) => {
    const { user_id } = req
    const representation_id = req.params?.id
    if (!user_id || !representation_id) throw new Error('invalid user id')
    const {
      representation_type,
      full_name,
      birth_date,
      id_number,
      place_of_issue,
      national_code,
      fathers_name,
      education_level,
      military_status,
      certificates,
      store_name,
      province_name,
      province_id,
      city_name,
      city_id,
      postal_code,
      mobile_number,
      tel_number,
      fax_number,
      economic_code,
      email,
      address,
      business_license,
      ownership_type,
      total_area,
      repair_area,
      stock_area,
      customer_reference_floor,
      place_location,
      geo_location,
      banner_info,
      repair_technicians,
      repair_masters,
      office_workers,
      bike_deliveries,
      computer_repair_exp,
      multimedia_repair_exp,
      business_exp,
      know_asanServ_from,
      introducer_info,
      asanServ_products_knowledge,
      computer_saling_exp,
      computer_saling_description,
      other_representations,
      more_descriptions
    } = req.body
    const data = {
      _updatedBy: user_id,
      representation_type,
      full_name,
      birth_date,
      id_number,
      place_of_issue,
      national_code,
      fathers_name,
      education_level,
      military_status,
      certificates,
      store_name,
      province_name,
      province_id,
      city_name,
      city_id,
      postal_code,
      mobile_number,
      tel_number,
      fax_number,
      economic_code,
      email,
      address,
      business_license,
      ownership_type,
      total_area,
      repair_area,
      stock_area,
      customer_reference_floor,
      place_location,
      geo_location,
      banner_info,
      repair_technicians,
      repair_masters,
      office_workers,
      bike_deliveries,
      computer_repair_exp,
      multimedia_repair_exp,
      business_exp,
      know_asanServ_from,
      introducer_info,
      asanServ_products_knowledge,
      computer_saling_exp,
      computer_saling_description,
      other_representations,
      more_descriptions
    }
    try {
      await Representation.findByIdAndUpdate(representation_id, data)
      return res.json({ message: 'با موفقیت آپدیت شد' })
    } catch (e) {
      return res500(res, e)
    }
  }
]

module.exports.revoke_representation_by_admin = [
  async (req, res) => {
    try {
      const { user_id } = req
      if (!user_id) return res406(res, 'invalid user id')
      const representation = await Representation.findByIdAndUpdate(req.params?.id)
      const agentAccount = await User.findById(representation.user_id)

      representation._revoked = true
      representation._revokedBy = user_id

      agentAccount.isAgent = false
      agentAccount.representation_id = undefined
      agentAccount.askedForRepresentation = false

      await representation.save()
      await agentAccount.save()

      return res.json({ message: 'امتیاز نمایندگی صلب شد' })
    } catch (e) {
      return res500(res, e)
    }
  }
]

module.exports.add_agent_by_admin = [
  async (req, res) => {
    const user_id = req.body.user
    if (!user_id) throw new Error('invalid user id')

    const data = {
      user_id,
      representation_type: 'both',
      full_name: '', // todo
      birth_date: '',
      id_number: '',
      place_of_issue: '',
      national_code: '', // todo
      fathers_name: '',
      education_level: '',
      military_status: '',
      certificates: '',
      store_name: '',
      province_name: '', // todo
      province_id: '', // todo
      city_name: '', // todo
      city_id: '', // todo
      postal_code: '',
      mobile_number: '', // todo
      tel_number: '',
      fax_number: '',
      economic_code: '',
      email: '', // todo
      address: '', // todo
      business_license: true,
      ownership_type: 'owner',
      total_area: '',
      repair_area: '',
      stock_area: '',
      customer_reference_floor: '',
      place_location: 'other',
      geo_location: 'inside_passage',
      banner_info: '',
      repair_technicians: '',
      repair_masters: '',
      office_workers: '',
      bike_deliveries: '',
      computer_repair_exp: '',
      multimedia_repair_exp: '',
      business_exp: '',
      know_asanServ_from: 'other',
      introducer_info: '',
      asanServ_products_knowledge: 4,
      computer_saling_exp: true,
      computer_saling_description: '',
      other_representations: [],
      more_descriptions: ''
    }

    try {
      const allRepresentations = await Representation.find()
      // generate rep code
      const representation_code =
        'ASAREP' +
        moment(Date.now()).format('jMMM').toUpperCase() +
        allRepresentations.length.toString().padStart(4, '0')

      // generate agent code
      const agentsCount = await Representation.find({ status: 'accepted' })
      data.agent_code = 'ASG' + agentsCount.length.toString().padStart(2, '0')

      data.representation_code = representation_code

      // find user and import information
      const user = await User.findById(user_id)
      if (user.isAgent) return res500(res, 'حساب کاربر از قبل نماینده است')
      user.askedForRepresentation = false
      user.isAgent = true
      user.representation_code = representation_code

      data.full_name = user.first_name + ' ' + user.last_name
      data.national_code = user.national_code
      data.province_name = user.province_name
      data.province_id = user.province_id
      data.city_name = user.city_name
      data.city_id = user.city_id
      data.mobile_number = user.mobile_number
      data.email = user.email
      data.address = user.address
      data.archived = true
      data.upload = true
      data.editAccess = true
      data.status = 'accepted'

      const representation = new Representation(data)
      await representation.save()
      user.representation_id = representation._id
      await user.save()

      return res.json({ representationId: representation.id })
    } catch (e) {
      return res500(res, e)
    }
  }
]
