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

const { sendResponse } = require('../helpers/responseHelper');
const {httpStatus, httpStatusMessages} = require('../helpers/httpResponses')
const {schemas} = require("../models/schemaMapper");
const InvalidKeyErrorException = require("../exceptions/invalidKeyErrorException");
const UserNotExistingError = require("../exceptions/userNotExistingError");

const router = express.Router();

router.get('/reset_key', (req, res) => {

    const adminKey= crypto.randomBytes(32).toString('hex');
    res.locals.adminKey = adminKey;
    sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK], adminKey);
});

router.get('/reset', (req, res) => {
    try {
        const requestAdminKey = req.headers['admin-key'];

        if (requestAdminKey !== res.locals.adminKey) {
            throw new InvalidKeyErrorException();
        }

        fs.writeFileSync(path.join(__dirname, '..', 'db', 'users.json'), '[]');
        fs.writeFileSync(path.join(__dirname, '..', 'db', 'departments.json'), '[]');
        fs.writeFileSync(path.join(__dirname, '..', 'db', 'security_levels.json'), '{}');
        fs.writeFileSync(path.join(__dirname, '..', 'db', 'backup_schemas.json'), '{}');
        fs.writeFileSync(path.join(__dirname, '..', 'db', 'config.json'), JSON.stringify({
            adminKey: ' ',
            ceoID: ' '
        }, null, 2));

        const adminPassword = crypto.randomBytes(16).toString('hex'); // Generating random password
        const ceoID = uuidv4();
        res.locals.ceoID = ceoID;
        const adminAccount = {
            id: ceoID,
            name: 'CEO',
            email: 'ceo@yourfirm.com',
            password: adminPassword
        };

        const usersData = [adminAccount];
        fs.writeFileSync(path.join(__dirname, '..', 'db', 'users.json'),
            JSON.stringify(usersData, null, 2));

        sendResponse(res, httpStatus.CREATED, httpStatusMessages[httpStatus.CREATED]);
    } catch (error) {
        console.log(error.message);
        if(error instanceof InvalidKeyErrorException){
            return sendResponse(res, httpStatus.UNAUTHORIZED, error.message);
        }

        sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
    }
});

const validateRegisterCeoBody = (req, res, next) => {
    const { error, value } = schemas.ceoRegisterModelSchema.validate(req.body);
    if (error) {
        return sendResponse(res, httpStatus.BAD_REQUEST, error.details[0].message);
    }
    req.jsonModel = value;
    next();
}

router.put('/change_admin_credentials', validateRegisterCeoBody, (req, res) => {
    try {
        const requestAdminKey = req.headers['admin-key'];
        if (requestAdminKey !== res.locals.adminKey) {
            throw new InvalidKeyErrorException();
        }

        const usersFilePath = path.join(__dirname, '..', 'db', 'users.json');
        const usersData = JSON.parse(fs.readFileSync(usersFilePath, 'utf8'));

        const adminIndex = usersData.findIndex(user => user.id === res.locals.ceoID);
        if (adminIndex === -1) {
            throw new UserNotExistingError();
        }

        const { name, email } = req.body; // Using req.body instead of req.jsonModel
        const newPassword = crypto.randomBytes(16).toString('hex'); // Generate new random password

        // Update the user data
        usersData[adminIndex] = {
            id: res.locals.ceoID,
            name: name,
            email: email,
            password: newPassword
        };

        // Write the updated user data back to the file
        fs.writeFileSync(usersFilePath, JSON.stringify(usersData, null, 2));

        sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK]);
    } catch (error) {
        console.log(error.message);
        if (error instanceof InvalidKeyErrorException) {
            return sendResponse(res, httpStatus.UNAUTHORIZED, error.message);
        }
        if (error instanceof UserNotExistingError) {
            return sendResponse(res, httpStatus.NOT_FOUND, error.message);
        }

        sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR])
    }
});

router.post('/validate_admin_password', (req, res) => {
    try {
        const requestAdminKey = req.headers['admin-key'];
        if (requestAdminKey !== res.locals.adminKey) {
            console.log(res.locals.adminKey);
            throw new InvalidKeyErrorException();
        }

        if(req.body.password === undefined){
            return sendResponse(res, httpStatus.BAD_REQUEST, httpStatusMessages[httpStatus.BAD_REQUEST]);
        }
        const password = req.body.password;

        const usersFilePath = path.join(__dirname, '..', 'db', 'users.json');
        const usersData = fs.readFileSync(usersFilePath, 'utf8');
        const usersJson = JSON.parse(usersData);

        const user = usersJson.find(user => user.id === res.locals.ceoID);
        if(user.password !== password){
            return sendResponse(res, httpStatus.UNAUTHORIZED, httpStatusMessages[httpStatus.UNAUTHORIZED]);
        }

        sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK]);
    } catch (error) {
        console.log(error.message);
        if(error instanceof InvalidKeyErrorException){
            return sendResponse(res, httpStatus.UNAUTHORIZED, error.message);
        }

        sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
    }
});

router.use((req, res) => {
    return sendResponse(res, httpStatus.NOT_FOUND, "Path not found");
});

module.exports = router;
