import { ServerlessMysql } from "serverless-mysql";

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

type Return<ReturnType = any> = ReturnType | null;

/**
 * # 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"]
): 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);
            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
                    );
                    resArray.push(JSON.parse(JSON.stringify(queryObjRes)));
                } catch (error: any) {
                    console.log(`connDbHandler Query Error: ${error.message}`);
                    resArray.push(null);
                }
            }

            return resArray as any;
        } else {
            return null;
        }
    } catch (error: any) {
        console.log(`connDbHandler Error: ${error.message}`);
        console.log(conn?.config());
        return null;
    } finally {
        conn?.end();
    }
}

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