import _ from "lodash";
import serverError from "../../backend/serverError";
import runQuery, { DbContextsArray } from "../../backend/db/runQuery";
import {
    ApiGetQueryObject,
    DSQL_TableSchemaType,
    GetReturn,
} from "../../../types";
import apiGetGrabQueryAndValues from "../../../utils/grab-query-and-values";

type Param<T extends { [key: string]: any } = { [key: string]: any }> = {
    query: string | ApiGetQueryObject<T>;
    queryValues?: (string | number)[];
    dbFullName: string;
    tableName?: string;
    dbSchema?: import("../../../types").DSQL_DatabaseSchemaType;
    debug?: boolean;
    dbContext?: (typeof DbContextsArray)[number];
    forceLocal?: boolean;
};

/**
 * # Get Function FOr API
 */
export default async function apiGet<
    T extends { [key: string]: any } = { [key: string]: any }
>({
    query,
    dbFullName,
    queryValues,
    tableName,
    dbSchema,
    debug,
    dbContext,
    forceLocal,
}: Param<T>): Promise<import("../../../types").GetReturn> {
    const queryAndValues = apiGetGrabQueryAndValues({
        query,
        values: queryValues,
    });

    if (typeof query == "string" && query.match(/^alter|^delete|^create/i)) {
        return { success: false, msg: "Wrong Input." };
    }

    let results;

    try {
        let { result, error } = await runQuery({
            dbFullName: dbFullName,
            query: queryAndValues.query,
            queryValuesArray: queryAndValues.values,
            readOnly: true,
            dbSchema,
            tableName,
            dbContext,
            debug,
            forceLocal,
        });

        if (debug && global.DSQL_USE_LOCAL) {
            console.log("apiGet:result", result);
            console.log("apiGet:error", error);
        }

        let tableSchema: DSQL_TableSchemaType | undefined;

        if (dbSchema) {
            const targetTable = dbSchema.tables.find(
                (table) => table.tableName === tableName
            );

            if (targetTable) {
                const clonedTargetTable = _.cloneDeep(targetTable);
                delete clonedTargetTable.childTable;
                delete clonedTargetTable.childTableDbFullName;
                delete clonedTargetTable.childTableName;
                delete clonedTargetTable.childrenTables;
                delete clonedTargetTable.updateData;
                delete clonedTargetTable.tableNameOld;
                delete clonedTargetTable.indexes;
                tableSchema = clonedTargetTable;
            }
        }

        if (error) throw error;
        if (result.error) throw new Error(result.error);

        results = result;

        const resObject: GetReturn = {
            success: true,
            payload: results,
            schema: tableName && tableSchema ? tableSchema : undefined,
        };

        return resObject;
    } catch (error: any) {
        serverError({
            component: "/api/query/get/lines-85-94",
            message: error.message,
        });

        global.ERROR_CALLBACK?.(`API Get Error`, error as Error);

        if (debug && global.DSQL_USE_LOCAL) {
            console.log("apiGet:error", error.message);
            console.log("queryAndValues", queryAndValues);
        }

        return {
            success: false,
            payload: null,
            error: error.message,
        };
    }
}