// @ts-check

import updateDbEntry from "../../backend/db/updateDbEntry";
import encrypt from "../../dsql/encrypt";
import hashPassword from "../../dsql/hashPassword";
import varDatabaseDbHandler from "../../backend/varDatabaseDbHandler";

type Param = {
    payload: { [s: string]: any };
    dbFullName: string;
    updatedUserId: string | number;
    useLocal?: boolean;
    dbSchema?: import("../../../types").DSQL_DatabaseSchemaType;
};

type Return = { success: boolean; payload?: any; msg?: string };

/**
 * # Update API User Function
 */
export default async function apiUpdateUser({
    payload,
    dbFullName,
    updatedUserId,
    useLocal,
    dbSchema,
}: Param): Promise<Return> {
    const existingUserQuery = `SELECT * FROM ${dbFullName}.users WHERE id = ?`;
    const existingUserValues = [updatedUserId];

    const existingUser = await varDatabaseDbHandler({
        queryString: existingUserQuery,
        queryValuesArray: existingUserValues,
        database: dbFullName,
        useLocal,
    });

    if (!existingUser?.[0]) {
        return {
            success: false,
            msg: "User not found",
        };
    }

    const data = (() => {
        const reqBodyKeys = Object.keys(payload);

        const targetTableSchema = (() => {
            try {
                const targetDatabaseSchema = dbSchema?.tables?.find(
                    (tbl) => tbl.tableName == "users"
                );
                return targetDatabaseSchema;
            } catch (error) {
                return undefined;
            }
        })();

        /** @type {any} */
        const finalData: any = {};

        reqBodyKeys.forEach((key) => {
            const targetFieldSchema = targetTableSchema?.fields?.find(
                (field) => field.fieldName == key
            );

            if (key?.match(/^date_|^id$|^uuid$/)) return;
            let value = payload[key];

            if (targetFieldSchema?.encrypted) {
                value = encrypt({ data: value });
            }

            finalData[key] = value;
        });

        if (finalData.password && typeof finalData.password == "string") {
            finalData.password = hashPassword({ password: finalData.password });
        }

        return finalData;
    })();

    const updateUser = await updateDbEntry({
        dbContext: "Dsql User",
        paradigm: "Full Access",
        dbFullName,
        tableName: "users",
        identifierColumnName: "id",
        identifierValue: updatedUserId,
        data: data,
        useLocal,
    });

    return {
        success: true,
        payload: updateUser,
    };
}