// @ts-check

const varDatabaseDbHandler = require("./varDatabaseDbHandler");
const generateColumnDescription = require("./generateColumnDescription");
const supplementTable = require("./supplementTable");
const dbHandler = require("./dbHandler");

/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */

/**
 *
 * @param {object} params
 * @param {string} params.dbFullName
 * @param {string} params.tableName
 * @param {any[]} params.tableInfoArray
 * @param {import("../../types").DSQL_DatabaseSchemaType[]} [params.dbSchema]
 * @param {import("../../types").DSQL_TableSchemaType} [params.tableSchema]
 * @param {any} [params.recordedDbEntry]
 * @param {boolean} [params.clone] - Is this a newly cloned table?
 * @returns
 */
module.exports = async function createTable({
    dbFullName,
    tableName,
    tableInfoArray,
    dbSchema,
    clone,
    tableSchema,
    recordedDbEntry,
}) {
    /**
     * Format tableInfoArray
     *
     * @description Format tableInfoArray
     */
    const finalTable = supplementTable({ tableInfoArray: tableInfoArray });

    /**
     * Grab Schema
     *
     * @description Grab Schema
     */
    const createTableQueryArray = [];

    createTableQueryArray.push(`CREATE TABLE IF NOT EXISTS \`${tableName}\` (`);

    ////////////////////////////////////////
    ////////////////////////////////////////
    ////////////////////////////////////////

    try {
        if (!recordedDbEntry) {
            throw new Error("Recorded Db entry not found!");
        }

        const existingTable = await varDatabaseDbHandler({
            database: "datasquirel",
            queryString: `SELECT * FROM user_database_tables WHERE db_id = ? AND table_slug = ?`,
            queryValuesArray: [recordedDbEntry.id, tableSchema?.tableName],
        });

        /** @type {import("../../types").MYSQL_user_database_tables_table_def} */
        const table = existingTable?.[0];

        if (!table?.id) {
            const newTableEntry = await dbHandler({
                query: `INSERT INTO user_database_tables SET ?`,
                values: {
                    user_id: recordedDbEntry.user_id,
                    db_id: recordedDbEntry.id,
                    db_slug: recordedDbEntry.db_slug,
                    table_name: tableSchema?.tableFullName,
                    table_slug: tableSchema?.tableName,
                    child_table: tableSchema?.childTable ? "1" : null,
                    child_table_parent_database:
                        tableSchema?.childTableDbFullName || null,
                    child_table_parent_table:
                        tableSchema?.childTableName || null,
                    date_created: Date(),
                    date_created_code: Date.now(),
                    date_updated: Date(),
                    date_updated_code: Date.now(),
                },
                database: "datasquirel",
            });
        }
    } catch (error) {}

    ////////////////////////////////////////
    ////////////////////////////////////////
    ////////////////////////////////////////

    let primaryKeySet = false;

    /** @type {import("../../types").DSQL_FieldSchemaType[]} */
    let foreignKeys = [];

    ////////////////////////////////////////

    for (let i = 0; i < finalTable.length; i++) {
        const column = finalTable[i];
        const {
            fieldName,
            dataType,
            nullValue,
            primaryKey,
            autoIncrement,
            defaultValue,
            defaultValueLiteral,
            foreignKey,
            updatedField,
            onUpdate,
            onUpdateLiteral,
            onDelete,
            onDeleteLiteral,
            defaultField,
            encrypted,
            json,
            newTempField,
            notNullValue,
            originName,
            plainText,
            pattern,
            patternFlags,
            richText,
        } = column;

        if (foreignKey) {
            foreignKeys.push({
                ...column,
            });
        }

        let { fieldEntryText, newPrimaryKeySet } = generateColumnDescription({
            columnData: column,
            primaryKeySet: primaryKeySet,
        });

        primaryKeySet = newPrimaryKeySet;

        ////////////////////////////////////////

        const comma = (() => {
            if (foreignKeys[0]) return ",";
            if (i === finalTable.length - 1) return "";
            return ",";
        })();

        createTableQueryArray.push("    " + fieldEntryText + comma);

        ////////////////////////////////////////
    }

    ////////////////////////////////////////
    ////////////////////////////////////////
    ////////////////////////////////////////

    if (foreignKeys[0]) {
        foreignKeys.forEach((foreighKey, index, array) => {
            const fieldName = foreighKey.fieldName;
            const destinationTableName =
                foreighKey.foreignKey?.destinationTableName;
            const destinationTableColumnName =
                foreighKey.foreignKey?.destinationTableColumnName;
            const cascadeDelete = foreighKey.foreignKey?.cascadeDelete;
            const cascadeUpdate = foreighKey.foreignKey?.cascadeUpdate;
            const foreignKeyName = foreighKey.foreignKey?.foreignKeyName;

            const comma = (() => {
                if (index === foreignKeys.length - 1) return "";
                return ",";
            })();

            createTableQueryArray.push(
                `    CONSTRAINT \`${foreignKeyName}\` FOREIGN KEY (\`${fieldName}\`) REFERENCES \`${destinationTableName}\`(${destinationTableColumnName})${
                    cascadeDelete ? " ON DELETE CASCADE" : ""
                }${cascadeUpdate ? " ON UPDATE CASCADE" : ""}${comma}`
            );
        });
    }

    ////////////////////////////////////////

    createTableQueryArray.push(
        `) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;`
    );

    const createTableQuery = createTableQueryArray.join("\n");

    ////////////////////////////////////////

    const newTable = await varDatabaseDbHandler({
        queryString: createTableQuery,
        database: dbFullName,
    });

    return newTable;

    ////////////////////////////////////////
    ////////////////////////////////////////
    ////////////////////////////////////////
};

/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */