import * as express from 'express';
import { Request, Response } from 'express';
import { User } from '../model/user.model';
import { Role } from '../model/role.model';
import { authenticateUser, authorizeUser } from './middleware/authMiddleware';
import { AuthController } from '../controller/authController';
import { InvalidEmailError, InvalidIdError, InvalidPasswordError, InvalidRoleError, IsEmptyOrNullError, IsNullError } from '../controller/customErrors';


export const authRouter = express.Router();
const userController = new AuthController();

authRouter.post('/register', authenticateUser, authorizeUser([Role.ADMIN]), async (req: Request, res: Response) => {
    let newUser = new User();
    try {
        newUser = await userController.registerUser(req.body);
    } catch (error) {
        if (error instanceof IsEmptyOrNullError) {
            return res.status(400).json({error: 'The field email or username may not be empty.'});
        } else if (error instanceof IsNullError) {
            return res.status(400).json({error: `Role must be on of the following: ${Object.values(Role)}`});
        } else if (error instanceof InvalidRoleError) {
            return res.status(400).json({error: `Role must be on of the following: ${Object.values(Role)}`});
        } else if (error instanceof InvalidEmailError) {
            return res.status(400).json({error: 'The email is invalid. Must use a valid OCCOA email address.'});
        } else if (error instanceof InvalidPasswordError) {
            return res.status(400).json({error: 'The password is invalid. Password must be at least 8 characters long and include each of the following: lowercase character, uppercase character, digit, special character.'});
        } else {
            console.log(error);
            return res.status(500).json({error: 'Could not register user. The email address might be already registered or the schema is invalid.'});
        }
    }
    newUser.password = ''; //do not send back hashed password
    return res.status(201).json(newUser);
});

authRouter.post('/login', async (req: Request, res: Response) => {
    let jwtToken: string;
    try {
        jwtToken = await userController.loginUser(req.body);
    } catch (error) {
        if (error instanceof InvalidIdError) {
            return res.status(401).json({ error: 'Invalid email or password.' });
        } else if (error instanceof InvalidPasswordError) {
            return res.status(401).json({ error: 'Invalid email or password.' });
        } else {
            console.log(error);
            return res.status(500).json({ error: 'Login failed.' });
        }
    }
    return res.status(200).send(jwtToken);
});