import varDatabaseDbHandler from "./varDatabaseDbHandler";
import generateColumnDescription from "./generateColumnDescription";
import supplementTable from "./supplementTable";
import dbHandler from "./dbHandler";
import { DSQL_DatabaseSchemaType, DSQL_TableSchemaType } from "../../types";

type Param = {
    dbFullName: string;
    tableName: string;
    tableInfoArray: any[];
    tableSchema?: DSQL_TableSchemaType;
    recordedDbEntry?: any;
};

/**
 * # Create Table Functions
 */
export default async function createTable({
    dbFullName,
    tableName,
    tableInfoArray,
    tableSchema,
    recordedDbEntry,
}: Param) {
    /**
     * Format tableInfoArray
     *
     * @description Format tableInfoArray
     */
    const finalTable = supplementTable({ tableInfoArray: tableInfoArray });

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

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

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

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

        const existingTable = await varDatabaseDbHandler({
            queryString: `SELECT * FROM datasquirel.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: import("../../types").MYSQL_user_database_tables_table_def =
            existingTable?.[0];

        if (!table?.id) {
            const newTableEntry = await dbHandler({
                query: `INSERT INTO datasquirel.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(),
                },
            });
        }
    } catch (error) {}

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

    let primaryKeySet = false;

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

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

    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,
    });

    return newTable;
}
