import { ServerlessMysql } from "serverless-mysql";
import debugLog from "../logging/debug-log";

type QueryObject = {
    query: string;
    values?: (string | number | undefined)[];
};

type Return<ReturnType = any> = ReturnType | null | { error: string };

/**
 * # Run Query From MySQL Connection
 * @description Run a query from a pre-existing MySQL/Mariadb Connection
 * setup with `serverless-mysql` npm module
 */
export default async function connDbHandler<ReturnType = any>(
    /**
     * ServerlessMySQL Connection Object
     */
    conn?: ServerlessMysql,
    /**
     * String Or `QueryObject` Array
     */
    query?: QueryObject["query"] | QueryObject[],
    /**
     * Array of Values to Sanitize and Inject
     */
    values?: QueryObject["values"],
    debug?: boolean
): Promise<Return<ReturnType>> {
    try {
        if (!conn) throw new Error("No Connection Found!");
        if (!query) throw new Error("Query String Required!");

        if (typeof query == "string") {
            const res = await conn.query(trimQuery(query), values);

            if (debug) {
                debugLog({
                    log: res,
                    addTime: true,
                    label: "res",
                });
            }

            return JSON.parse(JSON.stringify(res));
        } else if (typeof query == "object") {
            const resArray = [];

            for (let i = 0; i < query.length; i++) {
                try {
                    const queryObj = query[i];
                    const queryObjRes = await conn.query(
                        trimQuery(queryObj.query),
                        queryObj.values
                    );

                    if (debug) {
                        debugLog({
                            log: queryObjRes,
                            addTime: true,
                            label: "queryObjRes",
                        });
                    }

                    resArray.push(JSON.parse(JSON.stringify(queryObjRes)));
                } catch (error: any) {
                    global.ERROR_CALLBACK?.(
                        `Connection DB Handler Query Error`,
                        error as Error
                    );
                    resArray.push(null);
                }
            }

            if (debug) {
                debugLog({
                    log: resArray,
                    addTime: true,
                    label: "resArray",
                });
            }

            return resArray as any;
        } else {
            return null;
        }
    } catch (error: any) {
        global.ERROR_CALLBACK?.(`Connection DB Handler Error`, error as Error);

        if (debug) {
            debugLog({
                log: `Connection DB Handler Error: ${error.message}`,
                addTime: true,
                label: "Error",
            });
        }

        return {
            error: `Connection DB Handler Error: ${error.message}`,
        };
    } finally {
        conn?.end();
    }
}

function trimQuery(query: string) {
    return query.replace(/\n/gm, "").replace(/ {2,}/g, "").trim();
}