import { User } from "../model/user";
import { jwtAuth } from "../services/jwtAuth";
import bcrypt from "bcrypt";

export class AuthController {
  async handleLogin(req, res) {
    const username = req.body.username;
    const password = req.body.password;

    User.findOne({ username }, (err, user) => {
      if (err) {
        res.sendStatus(500);
        return;
      }

      if (user) {
        bcrypt.compare(password, user.password, (err, successful) => {
          if (err) {
            res.status(500).send("Something went wrong");
            return;
          }

          if (successful) {
            const accessToken = jwtAuth.generateAccessToken({
              username: req.body.username,
            });
            const refreshToken = jwtAuth.generateRefreshToken({
              username: req.body.username,
            });

            if (accessToken && refreshToken) {
              const userObj = user.toObject();
              delete userObj.password;

              res.json({
                user: userObj,
                accessToken: accessToken,
                refreshToken: refreshToken,
              });
              return;
            }
          } else {
            res.sendStatus(403);
          }
        });
      } else {
        res.sendStatus(403);
      }
    });
  }

  handleAccount(req, res) {
    const refreshToken = req.body.token;

    if (refreshToken == null) {
      return res.sendStatus(401);
    }

    jwtAuth.verifyRefreshToken(refreshToken, (err, user) => {
      if (err) {
        return res.sendStatus(403);
      }

      User.findOne({ username: user.username }, (err, dbUser) => {
        if (user) {
          const userObj = dbUser.toObject();
          delete userObj.password;
          res.json(userObj);
        } else {
          res.sendStatus(500);
        }
      });
    });
  }

  handleToken(req, res) {
    const refreshToken = req.body.token;

    if (refreshToken == null) {
      return res.sendStatus(401);
    }

    jwtAuth.verifyRefreshToken(refreshToken, (err, user) => {
      if (err) {
        return res.sendStatus(403);
      }

      const accessToken = jwtAuth.generateAccessToken({
        username: user.username,
      });
      res.json({ accessToken: accessToken });
    });
  }

  handleRegister(req, res) {
    const SALT_ROUNDS = 10;

    const username: string = req.body.username;
    const password: string = req.body.password;

    bcrypt.hash(password, SALT_ROUNDS, (err, passwordHash) => {
      if (err) {
        return res.sendStatus(500);
      }

      if (username && passwordHash) {
        new User({
          username,
          password: passwordHash,
        }).save((err, result) => {
          if (err) {
            return res.sendStatus(500);
          }

          const userObj = result.toObject();
          delete userObj.password;

          res.json(userObj);
        });
      }
    });
  }

  handleLogout(req, res) {
    const refreshToken = req.body.token;

    jwtAuth.deleteRefreshToken(refreshToken, (err, count) => {
      if (err) {
        return res.sendStatus(500);
      }

      res.sendStatus(204);
    });
  }
}

export const authController = new AuthController();
