const express = require('express');
const { v4: uuidv4 } = require('uuid');
const crypto = require('crypto');

const {schemas} = require('../models/schemaMapper');
const {httpStatus} = require("../helpers/httpResponses");


const router = express.Router();

function validateBody(req, res, next) {
    let validationSchema = undefined;

    switch(req.path){
        case '/register':
            validationSchema = schemas.usersRegisterModelSchema;
            break;
        case '/login':
            validationSchema = schemas.usersLoginModelSchema;
            break;
        case '/validate_ceo_password':
            validationSchema = schemas.ceoPasswordModelSchema;
            break;
        case '/validate_email':
            validationSchema = schemas.emailVerificationSchema;
            break;
        case '/':
            if(req.method === 'PUT'){
                validationSchema = schemas.usersModifyModelSchema;
            }
            break;
        case '/change_department':
            validationSchema = schemas.userDepartmentPatchSchema;
            break;
        default:
            validationSchema = undefined;
    }

    if(validationSchema !== undefined){
        console.log(req.body);
        const {error} = validationSchema.validate(req.body);
        if(error){
            const errorMessage = error.details.map(detail => detail.message).join(', ');
            return res.status(httpStatus.BAD_REQUEST).json({ message: errorMessage });
        }
    }
    next();
}

router.post('/register', validateBody, (req, res) => {
    const usersDB = req.app.get('usersDB');
    const usersJson = usersDB.readFile();

    const { name, email, password, department } = req.body;
    const hashedPassword = crypto.createHash('sha256').update(password).digest('hex');

    const newUser = {
        id: uuidv4(),
        name: name,
        email: email,
        password: hashedPassword,
        department: department
    }

    usersJson.push(newUser);
    usersDB.writeFile(usersJson);

    return res.status(httpStatus.CREATED).json({message: "User successfully created.", data: newUser});
});

router.post('/login', validateBody, (req, res) => {
    const usersDB = req.app.get('usersDB');
    const { email, password } = req.body;
    const hashedPassword = crypto.createHash('sha256').update(password).digest('hex');

    if(usersDB.readFile().length === 0){
        return res.status(httpStatus.INTERNAL_SERVER_ERROR).json({message: 'Internal server error.'});
    }

    if(usersDB.findIndexByKeyValueInArray('email', email) !==
    usersDB.findIndexByKeyValueInArray('password', hashedPassword)){
        return res.status(httpStatus.UNAUTHORIZED).json({message: 'Invalid credentials.'});
    }

    const userIndex = usersDB.findIndexByKeyValueInArray('email', email);

    return res.status(httpStatus.OK).json({
        message: 'Logged in.',
        data: usersDB.readFile()[userIndex]
    });
});

router.post('/validate_ceo_password', validateBody, (req, res) => {
    const ceoDB = req.app.get('ceoDB');
    const { password } = req.body;

    const ceoJson = ceoDB.readFile();
    if(ceoJson.password !== password){
        return res.status(httpStatus.UNAUTHORIZED).json({message: 'Incorrect CEO password'});
    }

    return res.status(httpStatus.OK).json({message: 'Password verified.'})
})

router.post('/validate_email', validateBody, (req, res) => {
    const usersDB = req.app.get('usersDB');
    const { email } = req.body;

    if(usersDB.isKeyValue("email", email)){
        return res.status(httpStatus.CONFLICT).json({"message": "Email already in system."});
    }

    return res.status(httpStatus.OK).json({"message": "Email is valid."});
});

router.get('/', (req, res) => {
    const usersDB = req.app.get('usersDB');
    const ceoDB = req.app.get('ceoDB');

    const ceoJson = ceoDB.readFile();
    let usersJson = usersDB.readFile();
    usersJson.push(ceoJson);

    return res.status(httpStatus.OK).json({
        message: "Fetched users",
        data: usersJson
    })
});

router.get('/departments', (req, res) => {
    const departmentsDB = req.app.get('departmentsDB');
    return res.status(httpStatus.OK).json({
        message: 'Departments fetched.',
        data: departmentsDB.readFile()
    });
})

router.put('/', validateBody, (req, res) => {
    const usersDB = req.app.get('usersDB');
    let usersJson = usersDB.readFile();

    const { name, email, password } = req.body;
    const userIndex = usersDB.findIndexByKeyValueInArray('email', email);
    if(userIndex === -1){
        return res.status(httpStatus.NOT_FOUND).json({message: 'User not found.'});
    }

    const hashedPassword = crypto.createHash('sha256').update(password).digest('hex');
    let userInfo = usersJson[userIndex];
    userInfo = {
        id: userInfo.id,
        name: name,
        email: email,
        password: hashedPassword,
        department: userInfo.department
    }

    usersJson[userIndex] = userInfo;
    usersDB.writeFile(usersJson);

    return res.status(httpStatus.OK).json({message: 'Information modified'});
});

router.patch('/change_department', validateBody, (req, res) => {
    const usersDB = req.app.get('usersDB');
    const { id, department } = req.body;

    const userIndex = usersDB.findIndexByKeyValueInArray('id', id);
    if(userIndex === -1){
        return res.status(httpStatus.NOT_FOUND).json({message: "User not found."});
    }

    let usersJson = usersDB.readFile();
    let userInfo = usersJson[userIndex];

    userInfo = {
        id: userInfo.id,
        name: userInfo.name,
        email: userInfo.email,
        password: userInfo.password,
        department: department
    }

    usersJson[userIndex] = userInfo
    usersDB.writeFile(usersJson);

    return res.status(httpStatus.OK).json({message: "Department modified."});
});

router.get('/get_decrypt_keys', (req, res) => {
    const ceoDB = req.app.get('ceoDB');
    const departmentsDB = req.app.get('departmentsDB');
    const ceoPassword = req.headers['ceo_password'];
    const {password} = ceoDB.readFile()

    if(ceoPassword !== password){
        return res.status(httpStatus.UNAUTHORIZED).json({message: 'Invalid CEO password.'});
    }

    return res.status(httpStatus.OK).json({
        message: 'Departments fetched.',
        data: departmentsDB.readFile()
    });
});

router.use((req, res) => {
    return res.status(httpStatus.NOT_FOUND).json({message: "Endpoint not found"});
})

module.exports = router;
