import { logUserIn } from '../authentication/userAuthentication.js';
import { User } from '../database/user.js';
import { hash } from '../authentication/passwordAuthentication.js';
import {
  getUsersValidation,
  groupGetValidation,
  groupValidation,
  registerAndLoginValidation,
  validate
} from './validation.js';
import { Router } from 'express';
import { Group } from '../database/group.js';
import * as groupRouter from './groupRouter.js';
import { getCurrentUser } from './util.js';
import { RouteError } from './routeError.js';

export const uncheckedJwtRoutes = [
  '/authenticated', '/login', '/register',
].map(path => '/api' + path);

export function setupRoutes(db) {
  const router = Router();

  router.get('/authenticated', (req, res) => {
    res.json({ isAuthenticated: typeof req.jwtData !== 'undefined' });
  });

  router.get('/user', async (req, res) => {
    res.json(await getCurrentUser(req, db));
  });

  router.get('/user/:name', async (req, res) => {
    res.json(await db.getUser(req.params.name));
  });

  router.get('/users', getUsersValidation(), validate, async (req, res) => {
    res.json(await db.getUsersStartingWith(req.query.startsWith, req.query.limit));
  });

  router.post('/register', registerAndLoginValidation(), validate, async (req, res) => {
    const username = req.body.username;
    const password = req.body.password;

    if (await db.getUser(username)) {
      throw new RouteError(400, 'User already exists');
    }

    await db.createUser(new User(username, await hash(password)));
    res.status(200).json({});
  });

  router.use('/group/:name', (req, res, next) => {
    req.groupName = req.params.name;
    next();
  }, groupRouter.routes(db));

  router.get('/groups', groupGetValidation(), validate, async (req, res) => {
    res.json(await db.getGroupsOfUser(await getCurrentUser(req, db), req.query.closed));
  });

  router.post('/group', groupValidation(), validate, async (req, res) => {
    if (await db.getGroup(req.body.name)) {
      throw new RouteError(400, 'Group already exists');
    }

    const group = new Group(req.body.name, req.body.currency, await getCurrentUser(req, db), req.body.description);
    await db.createGroup(group);
    res.status(200).end();
  });

  router.post('/login', registerAndLoginValidation(), validate, async (req, res) => {
    try {
      await logUserIn(req, res, db);
      res.status(200).json({});
    } catch (e) {
      console.error(e);
      throw new RouteError(401, 'Invalid username or password');
    }
  });

  return router;
}
