"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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = runQuery;
const fullAccessDbHandler_1 = __importDefault(require("../fullAccessDbHandler"));
const varReadOnlyDatabaseDbHandler_1 = __importDefault(require("../varReadOnlyDatabaseDbHandler"));
const serverError_1 = __importDefault(require("../serverError"));
const addDbEntry_1 = __importDefault(require("./addDbEntry"));
const updateDbEntry_1 = __importDefault(require("./updateDbEntry"));
const deleteDbEntry_1 = __importDefault(require("./deleteDbEntry"));
const trim_sql_1 = __importDefault(require("../../../utils/trim-sql"));
/**
 * # Run DSQL users queries
 */
function runQuery(_a) {
    return __awaiter(this, arguments, void 0, function* ({ dbFullName, query, readOnly, dbSchema, queryValuesArray, tableName, local, }) {
        /**
         * Declare variables
         *
         * @description Declare "results" variable
         */
        let result;
        let error;
        let tableSchema;
        if (dbSchema) {
            try {
                const table = tableName
                    ? tableName
                    : typeof query == "string"
                        ? null
                        : query
                            ? query === null || query === void 0 ? void 0 : query.table
                            : null;
                if (!table)
                    throw new Error("No table name provided");
                tableSchema = dbSchema.tables.filter((tb) => (tb === null || tb === void 0 ? void 0 : tb.tableName) === table)[0];
            }
            catch (_err) {
                // console.log("ERROR getting tableSchema: ", _err.message);
            }
        }
        /**
         * Declare variables
         *
         * @description Declare "results" variable
         */
        try {
            if (typeof query === "string") {
                const formattedQuery = (0, trim_sql_1.default)(query);
                /**
                 * Input Validation
                 *
                 * @description Input Validation
                 */
                if (readOnly &&
                    formattedQuery.match(/^alter|^delete|information_schema|^create/i)) {
                    throw new Error("Wrong Input!");
                }
                if (readOnly) {
                    result = yield (0, varReadOnlyDatabaseDbHandler_1.default)({
                        queryString: formattedQuery,
                        queryValuesArray: queryValuesArray === null || queryValuesArray === void 0 ? void 0 : queryValuesArray.map((vl) => String(vl)),
                        tableSchema,
                        useLocal: local,
                    });
                }
                else {
                    result = yield (0, fullAccessDbHandler_1.default)({
                        queryString: formattedQuery,
                        queryValuesArray: queryValuesArray === null || queryValuesArray === void 0 ? void 0 : queryValuesArray.map((vl) => String(vl)),
                        tableSchema,
                        local,
                    });
                }
            }
            else if (typeof query === "object") {
                /**
                 * Declare variables
                 *
                 * @description Declare "results" variable
                 */
                const { data, action, table, identifierColumnName, identifierValue, update, duplicateColumnName, duplicateColumnValue, } = query;
                switch (action.toLowerCase()) {
                    case "insert":
                        result = yield (0, addDbEntry_1.default)({
                            dbContext: local ? "Master" : "Dsql User",
                            paradigm: "Full Access",
                            dbFullName: dbFullName,
                            tableName: table,
                            data: data,
                            update,
                            duplicateColumnName,
                            duplicateColumnValue,
                            tableSchema,
                            useLocal: local,
                        });
                        if (!(result === null || result === void 0 ? void 0 : result.insertId)) {
                            error = new Error("Couldn't insert data");
                        }
                        break;
                    case "update":
                        result = yield (0, updateDbEntry_1.default)({
                            dbContext: local ? "Master" : "Dsql User",
                            paradigm: "Full Access",
                            dbFullName: dbFullName,
                            tableName: table,
                            data: data,
                            identifierColumnName,
                            identifierValue,
                            tableSchema,
                            useLocal: local,
                        });
                        break;
                    case "delete":
                        result = yield (0, deleteDbEntry_1.default)({
                            dbContext: local ? "Master" : "Dsql User",
                            paradigm: "Full Access",
                            dbFullName: dbFullName,
                            tableName: table,
                            identifierColumnName,
                            identifierValue,
                            tableSchema,
                            useLocal: local,
                        });
                        break;
                    default:
                        result = null;
                        break;
                }
            }
        }
        catch ( /** @type {any} */error) {
            (0, serverError_1.default)({
                component: "functions/backend/runQuery",
                message: error.message,
            });
            result = null;
            error = error.message;
        }
        return { result, error };
    });
}