"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.userUpdatePassword = exports.userTokenRefresh = exports.userAuthenticate = exports.userRegister = exports.userByEmail = exports.userByToken = exports.userById = exports.userEdit = exports.userCreate = exports.allUsers = exports.users = void 0;
const base_1 = require("@corejam/base");
const bcrypt = __importStar(require("bcryptjs"));
const faker_1 = require("faker");
const User_1 = require("../../../../shared/types/User");
const Errors_1 = require("../../../Errors");
const Functions_1 = require("../../../Functions");
const Generator_1 = require("./Generator");
exports.users = [];
try {
    const staticFile = require(process.cwd() + "/.corejam/faker.json");
    exports.users.push(...staticFile.users);
    console.log("Load from static data");
}
catch (e) {
    //Nothing for now
}
function allUsers() {
    return new Promise((res) => res(exports.users));
}
exports.allUsers = allUsers;
function userCreate(userCreateInput) {
    const user = Object.assign(Object.assign({ id: faker_1.random.uuid(), role: [User_1.roles.USER], status: User_1.STATUS.PENDING }, userCreateInput), base_1.updateDates());
    exports.users.push(user);
    return new Promise((res) => res(user));
}
exports.userCreate = userCreate;
function userEdit(id, userInput) {
    let user = exports.users.filter((user) => {
        return user.id === id;
    })[0];
    user = Object.assign(Object.assign({}, user), userInput);
    exports.users = exports.users.map((user) => {
        if (user.id === id) {
            user = Object.assign(Object.assign({}, user), userInput);
        }
        return user;
    });
    return new Promise((res) => res(user));
}
exports.userEdit = userEdit;
function userById(id) {
    const user = exports.users.filter((user) => user.id === id)[0];
    return new Promise((res) => res(user));
}
exports.userById = userById;
function userByToken(token) {
    return __awaiter(this, void 0, void 0, function* () {
        const payload = Functions_1.decodeJWT(token);
        return yield userById(payload.id);
    });
}
exports.userByToken = userByToken;
function userByEmail(email) {
    const user = exports.users.filter((user) => {
        if (user.email == email) {
            return user;
        }
        return;
    });
    return new Promise((res) => res(user[0]));
}
exports.userByEmail = userByEmail;
function userRegister(userInput) {
    return __awaiter(this, void 0, void 0, function* () {
        const userObj = Object.assign({ id: faker_1.random.uuid(), email: userInput.email ? userInput.email : "", password: yield Functions_1.hashPassword(userInput.password), active: true, status: User_1.STATUS.PENDING, role: [User_1.roles.USER] }, base_1.updateDates());
        exports.users.push(userObj);
        return userObj;
    });
}
exports.userRegister = userRegister;
function userAuthenticate(email, password) {
    const userFilter = exports.users.filter((user) => {
        if (user.email == email) {
            return user;
        }
        return;
    });
    const user = userFilter[0];
    //User isnt active or hasnt set a password yet
    if (!user.active || !user.password) {
        throw new Errors_1.AuthenticationError();
    }
    return bcrypt.compare(password, user.password).then((result) => __awaiter(this, void 0, void 0, function* () {
        if (result) {
            return yield Functions_1.generateTokensForUser(user, userEdit);
        }
        throw new Errors_1.AuthenticationError();
    }));
}
exports.userAuthenticate = userAuthenticate;
function userTokenRefresh(refreshToken) {
    return __awaiter(this, void 0, void 0, function* () {
        const decodedRefresh = Functions_1.decodeJWT(refreshToken);
        const user = yield userById(decodedRefresh.id);
        if (!user || !user.refreshToken) {
            throw new Errors_1.AuthenticationError();
        }
        return yield Functions_1.generateTokensForUser(user, userEdit);
    });
}
exports.userTokenRefresh = userTokenRefresh;
function userUpdatePassword(user, passwordInput) {
    return __awaiter(this, void 0, void 0, function* () {
        const hashedPass = yield Functions_1.hashPassword(passwordInput.password);
        exports.users = exports.users.map((userDb) => {
            if (user.id === userDb.id) {
                userDb = Object.assign(Object.assign({}, userDb), { password: hashedPass });
            }
            return userDb;
        });
        return new Promise((res) => res(typeof hashedPass === "string"));
    });
}
exports.userUpdatePassword = userUpdatePassword;
if (process.env.FAKER_MODULE === "auth") {
    if (exports.users.length === 0) {
        for (let index = 0; index < 10; index++) {
            const generated = Object.assign({ id: faker_1.random.uuid() }, Generator_1.generateUser());
            exports.users.push(generated);
        }
    }
    //We want a test account
    userRegister({
        email: "test@test.com",
        password: "valid123Password@",
        passwordConfirm: "valid123Password@",
    }).then((user) => {
        userEdit(user.id, { role: [User_1.roles.ADMIN] });
    });
}
