"use strict";
// @ts-check
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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = apiCreateUser;
const addUsersTableToDb_1 = __importDefault(require("../../backend/addUsersTableToDb"));
const addDbEntry_1 = __importDefault(require("../../backend/db/addDbEntry"));
const updateUsersTableSchema_1 = __importDefault(require("../../backend/updateUsersTableSchema"));
const varDatabaseDbHandler_1 = __importDefault(require("../../backend/varDatabaseDbHandler"));
const hashPassword_1 = __importDefault(require("../../dsql/hashPassword"));
const validate_email_1 = __importDefault(require("../../email/fns/validate-email"));
/**
 * # API Create User
 */
function apiCreateUser(_a) {
    return __awaiter(this, arguments, void 0, function* ({ encryptionKey, payload, database, userId, }) {
        const dbFullName = database;
        const API_USER_ID = userId || process.env.DSQL_API_USER_ID;
        const finalEncryptionKey = encryptionKey || process.env.DSQL_ENCRYPTION_PASSWORD;
        if (!finalEncryptionKey) {
            return {
                success: false,
                msg: "No encryption key provided",
                payload: null,
            };
        }
        if (!(finalEncryptionKey === null || finalEncryptionKey === void 0 ? void 0 : finalEncryptionKey.match(/.{8,}/))) {
            return {
                success: false,
                msg: "Encryption key must be at least 8 characters long",
                payload: null,
            };
        }
        const hashedPassword = (0, hashPassword_1.default)({
            encryptionKey: finalEncryptionKey,
            password: String(payload.password),
        });
        payload.password = hashedPassword;
        const fieldsQuery = `SHOW COLUMNS FROM ${dbFullName}.users`;
        let fields = yield (0, varDatabaseDbHandler_1.default)({
            queryString: fieldsQuery,
            database: dbFullName,
        });
        if (!(fields === null || fields === void 0 ? void 0 : fields[0])) {
            const newTable = yield (0, addUsersTableToDb_1.default)({
                userId: Number(API_USER_ID),
                database: dbFullName,
                payload: payload,
            });
            fields = yield (0, varDatabaseDbHandler_1.default)({
                queryString: fieldsQuery,
                database: dbFullName,
            });
        }
        if (!(fields === null || fields === void 0 ? void 0 : fields[0])) {
            return {
                success: false,
                msg: "Could not create users table",
            };
        }
        const fieldsTitles = fields.map((fieldObject) => fieldObject.Field);
        let invalidField = null;
        for (let i = 0; i < Object.keys(payload).length; i++) {
            const key = Object.keys(payload)[i];
            if (!fieldsTitles.includes(key)) {
                yield (0, updateUsersTableSchema_1.default)({
                    userId: Number(API_USER_ID),
                    database: dbFullName,
                    newPayload: {
                        [key]: payload[key],
                    },
                });
            }
        }
        if (invalidField) {
            return {
                success: false,
                msg: `${invalidField} is not a valid field!`,
            };
        }
        const existingUserQuery = `SELECT * FROM ${dbFullName}.users WHERE email = ?${payload.username ? " OR username = ?" : ""}`;
        const existingUserValues = payload.username
            ? [payload.email, payload.username]
            : [payload.email];
        const existingUser = yield (0, varDatabaseDbHandler_1.default)({
            queryString: existingUserQuery,
            queryValuesArray: existingUserValues,
            database: dbFullName,
        });
        if (existingUser === null || existingUser === void 0 ? void 0 : existingUser[0]) {
            return {
                success: false,
                msg: "User Already Exists",
                payload: null,
            };
        }
        const isEmailValid = yield (0, validate_email_1.default)({ email: payload.email });
        if (!isEmailValid.isValid) {
            return {
                success: false,
                msg: isEmailValid.message,
                payload: null,
            };
        }
        const addUser = yield (0, addDbEntry_1.default)({
            dbFullName: dbFullName,
            tableName: "users",
            data: Object.assign(Object.assign({}, payload), { image: process.env.DSQL_DEFAULT_USER_IMAGE ||
                    "/images/user-preset.png", image_thumbnail: process.env.DSQL_DEFAULT_USER_IMAGE ||
                    "/images/user-preset-thumbnail.png" }),
        });
        if (addUser === null || addUser === void 0 ? void 0 : addUser.insertId) {
            const newlyAddedUserQuery = `SELECT id,first_name,last_name,email,username,phone,image,image_thumbnail,city,state,country,zip_code,address,verification_status,more_user_data FROM ${dbFullName}.users WHERE id='${addUser.insertId}'`;
            const newlyAddedUser = yield (0, varDatabaseDbHandler_1.default)({
                queryString: newlyAddedUserQuery,
                database: dbFullName,
            });
            return {
                success: true,
                payload: newlyAddedUser[0],
            };
        }
        else {
            return {
                success: false,
                msg: "Could not create user",
                sqlResult: addUser,
                payload: null,
            };
        }
    });
}