"use strict";
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 = void 0;
const base_1 = require("@corejam/base");
const Client_1 = require("@corejam/base/dist/resolvers/db/fauna/Client");
const faunadb_1 = require("faunadb");
const User_1 = require("../../../../shared/types/User");
const Errors_1 = require("../../../Errors");
const Functions_1 = require("../../../Functions");
function allUsers() {
    return Client_1.FaunaClient()
        .query(faunadb_1.query.Map(faunadb_1.query.Paginate(faunadb_1.query.Match(faunadb_1.query.Index("allUsers"))), faunadb_1.query.Lambda("x", faunadb_1.query.Merge({ id: faunadb_1.query.Select(["ref", "id"], faunadb_1.query.Get(faunadb_1.query.Var("x"))) }, faunadb_1.query.Select("data", faunadb_1.query.Get(faunadb_1.query.Var("x")))))))
        .then((response) => {
        return response.data;
    });
}
exports.allUsers = allUsers;
function userCreate(userCreateInput) {
    return Client_1.FaunaClient()
        .query(faunadb_1.query.Create(faunadb_1.query.Collection("users"), {
        data: Object.assign({ email: userCreateInput.email, role: [User_1.roles.USER], active: true, status: User_1.STATUS.PENDING }, base_1.updateDates()),
        credentials: { password: userCreateInput.password },
    }))
        .then((response) => {
        return Object.assign({ id: response.ref.id }, response.data);
    });
}
exports.userCreate = userCreate;
function userEdit(id, userInput) {
    return Client_1.FaunaClient()
        .query(faunadb_1.query.Update(faunadb_1.query.Ref(faunadb_1.query.Collection("users"), id), {
        data: Object.assign({}, userInput),
    }))
        .then((response) => {
        return Object.assign({ id: response.ref.id }, response.data);
    });
}
exports.userEdit = userEdit;
function userById(id) {
    return Client_1.FaunaClient()
        .query(faunadb_1.query.Get(faunadb_1.query.Ref(faunadb_1.query.Collection("users"), id)))
        .then((response) => {
        return Object.assign({ id: response.ref.id }, response.data);
    });
}
exports.userById = userById;
function userByToken(token) {
    const decoded = Functions_1.decodeJWT(token);
    return userById(decoded.id);
}
exports.userByToken = userByToken;
function userByEmail(email) {
    return Client_1.FaunaClient()
        .query(faunadb_1.query.Get(faunadb_1.query.Match(faunadb_1.query.Index("userByEmail"), email)))
        .then((response) => {
        return Object.assign({ id: response.ref.id }, response.data);
    })
        .catch((e) => {
        if (e.message == "instance not found")
            return null;
        throw e;
    });
}
exports.userByEmail = userByEmail;
function userRegister(userInput, _id) {
    return __awaiter(this, void 0, void 0, function* () {
        return userCreate(userInput);
    });
}
exports.userRegister = userRegister;
function userAuthenticate(email, password) {
    return Client_1.FaunaClient()
        .query(faunadb_1.query.Merge(faunadb_1.query.Login(faunadb_1.query.Match("userByEmail", email), { password: password }), {
        user: faunadb_1.query.Select(["data"], faunadb_1.query.Get(faunadb_1.query.Match("userByEmail", email))),
    }))
        .then((response) => {
        if (!response.user.active) {
            throw new Errors_1.AuthenticationError();
        }
        const user = Object.assign(Object.assign({}, response.user), { id: response.instance.id });
        return Functions_1.generateTokensForUser(user, userEdit);
    })
        .catch((_e) => {
        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* () {
        return Client_1.FaunaClient()
            .query(faunadb_1.query.Update(faunadb_1.query.Ref(faunadb_1.query.Collection("users"), user.id), {
            credentials: { password: passwordInput.password },
        }))
            .then((_res) => {
            return true;
        });
    });
}
exports.userUpdatePassword = userUpdatePassword;
