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());
    });
};
import { updateDates } from "@corejam/base";
import * as bcrypt from "bcryptjs";
import { random } from "faker";
import { roles, STATUS, } from "../../../../shared/types/User";
import { AuthenticationError } from "../../../Errors";
import { decodeJWT, generateTokensForUser, hashPassword } from "../../../Functions";
import { generateUser } from "./Generator";
export let users = [];
try {
    const staticFile = require(process.cwd() + "/.corejam/faker.json");
    users.push(...staticFile.users);
    console.log("Load from static data");
}
catch (e) {
    //Nothing for now
}
export function allUsers() {
    return new Promise((res) => res(users));
}
export function userCreate(userCreateInput) {
    const user = Object.assign(Object.assign({ id: random.uuid(), role: [roles.USER], status: STATUS.PENDING }, userCreateInput), updateDates());
    users.push(user);
    return new Promise((res) => res(user));
}
export function userEdit(id, userInput) {
    let user = users.filter((user) => {
        return user.id === id;
    })[0];
    user = Object.assign(Object.assign({}, user), userInput);
    users = users.map((user) => {
        if (user.id === id) {
            user = Object.assign(Object.assign({}, user), userInput);
        }
        return user;
    });
    return new Promise((res) => res(user));
}
export function userById(id) {
    const user = users.filter((user) => user.id === id)[0];
    return new Promise((res) => res(user));
}
export function userByToken(token) {
    return __awaiter(this, void 0, void 0, function* () {
        const payload = decodeJWT(token);
        return yield userById(payload.id);
    });
}
export function userByEmail(email) {
    const user = users.filter((user) => {
        if (user.email == email) {
            return user;
        }
        return;
    });
    return new Promise((res) => res(user[0]));
}
export function userRegister(userInput) {
    return __awaiter(this, void 0, void 0, function* () {
        const userObj = Object.assign({ id: random.uuid(), email: userInput.email ? userInput.email : "", password: yield hashPassword(userInput.password), active: true, status: STATUS.PENDING, role: [roles.USER] }, updateDates());
        users.push(userObj);
        return userObj;
    });
}
export function userAuthenticate(email, password) {
    const userFilter = 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 AuthenticationError();
    }
    return bcrypt.compare(password, user.password).then((result) => __awaiter(this, void 0, void 0, function* () {
        if (result) {
            return yield generateTokensForUser(user, userEdit);
        }
        throw new AuthenticationError();
    }));
}
export function userTokenRefresh(refreshToken) {
    return __awaiter(this, void 0, void 0, function* () {
        const decodedRefresh = decodeJWT(refreshToken);
        const user = yield userById(decodedRefresh.id);
        if (!user || !user.refreshToken) {
            throw new AuthenticationError();
        }
        return yield generateTokensForUser(user, userEdit);
    });
}
export function userUpdatePassword(user, passwordInput) {
    return __awaiter(this, void 0, void 0, function* () {
        const hashedPass = yield hashPassword(passwordInput.password);
        users = 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"));
    });
}
if (process.env.FAKER_MODULE === "auth") {
    if (users.length === 0) {
        for (let index = 0; index < 10; index++) {
            const generated = Object.assign({ id: random.uuid() }, generateUser());
            users.push(generated);
        }
    }
    //We want a test account
    userRegister({
        email: "test@test.com",
        password: "valid123Password@",
        passwordConfirm: "valid123Password@",
    }).then((user) => {
        userEdit(user.id, { role: [roles.ADMIN] });
    });
}
