const express = require('express');
const passport = require('passport');

const config = require('../config');
const AuthService = require('../services/auth');
const ForbiddenError = require('../services/notifications/errors/forbidden');
const EmailSender = require('../services/email');
const wrapAsync = require('../helpers').wrapAsync;

const router = express.Router();

/**
 *  @swagger
 *  components:
 *    schemas:
 *      Auth:
 *        type: object
 *        required:
 *          - email
 *          - password
 *        properties:
 *          email:
 *            type: string
 *            default: admin@flatlogic.com
 *            description: User email
 *          password:
 *            type: string
 *            default: password
 *            description: User password
 */

/**
 * @swagger
 * tags:
 *   name: Auth
 *   description: Authorization operations
 */

/**
 * @swagger
 *  /api/auth/signin/local:
 *    post:
 *      tags: [Auth]
 *      summary: Logs user into the system
 *      description: Logs user into the system
 *      requestBody:
 *        description: Set valid user email and password
 *        content:
 *          application/json:
 *            schema:
 *              $ref: "#/components/schemas/Auth"
 *      responses:
 *        200:
 *          description: Successful login
 *        400:
 *          description: Invalid username/password supplied
 *      x-codegen-request-body-name: body
 */

router.post('/signin/local', wrapAsync(async (req, res) => {
  const payload = await AuthService.signin(req.body.email, req.body.password, req,);
  res.status(200).send(payload);
}));

/**
 * @swagger
 *  /api/auth/me:
 *    get:
 *      security:
 *        - bearerAuth: []
 *      tags: [Auth]
 *      summary: Get current authorized user info
 *      description: Get current authorized user info
 *      responses:
 *        200:
 *          description: Successful retrieval of current authorized user data
 *        400:
 *          description: Invalid username/password supplied
 *      x-codegen-request-body-name: body
 */

router.get('/me', passport.authenticate('jwt', {session: false}), (req, res) => {
  if (!req.currentUser || !req.currentUser.id) {
    throw new ForbiddenError();
  }

  const payload = req.currentUser;
  delete payload.password;
  res.status(200).send(payload);
});

router.put('/password-reset', wrapAsync(async (req, res) => {
  const payload = await AuthService.passwordReset(req.body.token, req.body.password, req,);
  res.status(200).send(payload);
}));

router.put('/password-update', passport.authenticate('jwt', {session: false}), wrapAsync(async (req, res) => {
  const payload = await AuthService.passwordUpdate(req.body.currentPassword, req.body.newPassword, req);
  res.status(200).send(payload);
}));

router.post('/send-email-address-verification-email', passport.authenticate('jwt', {session: false}), wrapAsync(async (req, res) => {
  if (!req.currentUser) {
    throw new ForbiddenError();
  }

  await AuthService.sendEmailAddressVerificationEmail(req.currentUser.email);
  const payload = true;
  res.status(200).send(payload);
}));

router.post('/send-password-reset-email', wrapAsync(async (req, res) => {
  const link = new URL(req.headers.referer);
  await AuthService.sendPasswordResetEmail(req.body.email, 'register', link.host,);
  const payload = true;
  res.status(200).send(payload);
}));

/**
 * @swagger
 *  /api/auth/signup:
 *    post:
 *      tags: [Auth]
 *      summary: Register new user into the system
 *      description: Register new user into the system
 *      requestBody:
 *        description: Set valid user email and password
 *        content:
 *          application/json:
 *            schema:
 *              $ref: "#/components/schemas/Auth"
 *      responses:
 *        200:
 *          description: New user successfully signed up
 *        400:
 *          description: Invalid username/password supplied
 *        500:
 *          description: Some server error
 *      x-codegen-request-body-name: body
 */

router.post('/signup', wrapAsync(async (req, res) => {
  const link = new URL(req.headers.referer);
  const payload = await AuthService.signup(
      req.body.email,
      req.body.password,
      
      req,
      link.host,
    )
  res.status(200).send(payload);
}));

router.put('/profile', passport.authenticate('jwt', {session: false}), wrapAsync(async (req, res) => {
  if (!req.currentUser || !req.currentUser.id) {
    throw new ForbiddenError();
  }

  await AuthService.updateProfile(req.body.profile, req.currentUser);
  const payload = true;
  res.status(200).send(payload);
}));

router.put('/verify-email', wrapAsync(async (req, res) => {
  const payload = await AuthService.verifyEmail(req.body.token, req, req.headers.referer)
  res.status(200).send(payload);
}));

router.get('/email-configured', (req, res) => {
  const payload = EmailSender.isConfigured;
  res.status(200).send(payload);
});

router.get('/signin/google', (req, res, next) => {
  passport.authenticate("google", {scope: ["profile", "email"], state: req.query.app})(req, res, next);
});

router.get('/signin/google/callback', passport.authenticate("google", {failureRedirect: "/login", session: false}),

  function (req, res) {
    socialRedirect(res, req.query.state, req.user.token, config);
  }
);

router.get('/signin/microsoft', (req, res, next) => {
  passport.authenticate("microsoft", {
    scope: ["https://graph.microsoft.com/user.read openid"],
    state: req.query.app
  })(req, res, next);
});

router.get('/signin/microsoft/callback', passport.authenticate("microsoft", {
    failureRedirect: "/login",
    session: false
  }),
  function (req, res) {
    socialRedirect(res, req.query.state, req.user.token, config);
  }
);

router.use('/', require('../helpers').commonErrorHandler);

function socialRedirect(res, state, token, config) {
  res.redirect(config.uiUrl + "/login?token=" + token);
}

module.exports = router;
