const express = require('express');
const { body } = require('express-validator');
const { Op } = require('sequelize');

const {
  accountCreate,
  accountLogin,
  changePassword,
  deactivation,
  deleteAccount,
  editUserProfile,
  getLanguage,
  getUserById,
  requestPasswordReset,
  resendPasswordResetEmail,
  resetPassword,
  softDeleteAccount,
  updateLanguage,
} = require('../../../controllers/users/accounts');
const { deleteFile, jsonParser } = require('../../../helpers');
const { isAuth, validation } = require('../../../middlewares');
const { Users } = require('../../../models');

const router = express.Router();

router.post(
  '/login',
  [body('emailOrPhone').notEmpty(), body('password').notEmpty()],
  validation,
  accountLogin,
);

router.post(
  '/register',
  [
    body('emailAddress').notEmpty(),
    body('phoneNo').notEmpty(),
    body('firstname').notEmpty(),
    body('lastname').notEmpty(),
    body('password').notEmpty(),
    body('birthdate').optional(),
    body('addressCountry').isString().optional({
      values: 'falsy',
    }),
    body('addressStreet').isString().optional({
      values: 'falsy',
    }),
    body('addressApt').isString().optional({
      values: 'falsy',
    }),
    body('addressCity').isString().optional({
      values: 'falsy',
    }),
    body('addressState').isString().optional({
      values: 'falsy',
    }),
    body('addressZip').isString().optional({
      values: 'falsy',
    }),
  ],
  validation,
  accountCreate,
);

router.get('/me', isAuth, getUserById);

router.patch(
  '/update-profile',
  isAuth,
  jsonParser,
  [
    body('data.firstName').optional(),
    body('data.lastName').optional(),
    body('data.phoneNo').optional(),
    body('data.emailAddress')
      .optional()
      .isEmail()
      .custom(async (value, { req }) => {
        if (!value) return Promise.resolve();
        const user = await Users.findOne({
          where: {
            email_address: value,
            id: { [Op.ne]: req.userId },
          },
        });
        if (user) {
          if (req.files && req.files.profileImg) {
            return deleteFile(req.files.profileImg[0].filename, 'user-uploads');
          }
          return Promise.reject(new Error('Email Address already in use'));
        }
      }),
    body('data.data.birthdate').optional(),
    body('data.addressCountry').isString().trim().notEmpty().optional(),
    body('data.addressStreet').isString().trim().notEmpty().optional(),
    body('data.addressApt').isString().trim().notEmpty().optional({
      values: 'falsy',
    }),
    body('data.addressCity').isString().trim().notEmpty().optional(),
    body('data.addressState').isString().trim().notEmpty().optional(),
    body('data.addressZip').isString().trim().notEmpty().optional(),
    body('data.aboutMe').optional(),
    body('data.school').optional(),
    body('data.work').optional(),
    body('data.music').optional({
      values: 'null',
    }),
    body('data.livedIn').optional({
      values: 'null',
    }),
    body('data.languages').isArray().optional({
      values: 'falsy',
    }),
    body('data.pets').optional({
      values: 'null',
    }),
    body('data.hangouts').optional({
      values: 'null',
    }),
    body('data.birthYear').optional({
      values: 'null',
    }),
    body('data.likes').optional({
      values: 'null',
    }),
    body('data.dislikes').optional({
      values: 'null',
    }),
    body('data.interests').isArray().optional({
      values: 'null',
    }),
    body('data.showTravels').optional().isBoolean(),
  ],
  validation,
  async (req, res, next) => {
    try {
      const user = await Users.findByPk(req.userId);

      if (!user) {
        return res.status(404).json({ success: false, message: 'User not found' });
      }

      const previousProfileImage = user.image || null;

      await editUserProfile(req, res, next);

      if (req.files && req.files.profileImg && previousProfileImage) {
        return deleteFile(previousProfileImage, 'user-uploads');
      }
    } catch (error) {
      return next(error);
    }
  },
  editUserProfile,
);

router.patch('/deactivate-account', isAuth, deactivation);

router.post('/soft-delete', isAuth, softDeleteAccount);

router.patch(
  '/change-password',
  isAuth,
  [
    body('currentPass').notEmpty().isString(),
    body('newPass').notEmpty().isString(),
    body('confirmPass')
      .notEmpty()
      .isString()
      .custom((value, { req }) => {
        if (value !== req.body.newPass) {
          throw new Error('Passwords do not match!');
        }
        return true;
      }),
  ],
  validation,
  changePassword,
);

router.delete(
  '/delete-account',
  [body('reason').isString().trim().notEmpty()],
  validation,
  isAuth,
  deleteAccount,
);

router.get('/language', isAuth, getLanguage);

router.patch(
  '/language',
  isAuth,
  [body('language').isString().trim().notEmpty()],
  validation,
  updateLanguage,
);

router.post('/password-reset', [body('email').notEmpty()], validation, requestPasswordReset);

router.patch(
  '/password-reset',
  [body('newPass').notEmpty(), body('confirmPass').notEmpty()],
  validation,
  resetPassword,
);

router.post(
  '/password-reset/resend',
  [body('email').notEmpty()],
  validation,
  resendPasswordResetEmail,
);

module.exports = router;
