window.app = window.app || {};
window.app.modals = window.app.modals || {};

window.app.modals.openIndexUpsert = function(
    collection,
    index = "",
    settings = {
        onsave: () => {},
        ondelete: () => {},
    },
) {
    const modal = indexUpsertModal(collection, index, settings);
    if (!modal) {
        return;
    }

    document.body.appendChild(modal);
    app.modals.open(modal);
};

function indexUpsertModal(collection, index = "", settings = {}) {
    if (!collection) {
        console.warn("[indexUpsertModal] missing required collection argument");
        return;
    }

    let modal;

    const uniqueId = app.utils.randomString();

    const data = store({
        originalIndex: "",
        index: "",
        get isNew() {
            return data.originalIndex == "";
        },
        get indexParts() {
            return app.utils.parseIndex(data.index);
        },
        get lowerCasedIndexColumnNames() {
            return data.indexParts.columns.map((c) => c.name.toLowerCase());
        },
        get canSave() {
            return data.lowerCasedIndexColumnNames.length > 0;
        },
    });

    const presetColumns = collection?.fields?.filter((f) => !f["@toDelete"] && f.name != "id")?.map((f) => f.name)
        || [];

    function loadIndex(index) {
        data.originalIndex = index || "";

        if (!index) {
            const parsed = app.utils.parseIndex("");
            parsed.tableName = collection?.name || "";
            index = app.utils.buildIndex(parsed);
        }

        data.index = index;
    }

    function saveIndex() {
        if (!collection || !data.canSave) {
            console.warn("[saveIndex] no collection or invalid save state:", collection, data.canSave);
            return;
        }

        collection.indexes = collection.indexes || [];

        // search for existing
        const pos = collection.indexes.findIndex((index) => index == data.originalIndex);
        if (pos >= 0) {
            // replace
            collection.indexes[pos] = data.index;
            app.utils.deleteByPath(app.store.errors, "indexes." + pos);
        } else {
            // push missing
            collection.indexes.push(data.index);
        }

        if (typeof settings?.onsave == "function") {
            settings.onsave({
                collection: collection,
                index: data.index,
                oldIndex: data.originalIndex,
            });
        }

        clearIndexError();

        app.modals.close(modal);
    }

    function deleteIndex() {
        if (!collection || !data.originalIndex) {
            console.warn("[deleteIndex] no collection or index:", collection, data.originalIndex);
            return;
        }

        const pos = collection.indexes?.findIndex((index) => index == data.originalIndex);
        if (pos == -1) {
            console.warn("[deleteIndex] missing index:", data.originalIndex);
            return;
        }

        collection.indexes.splice(pos, 1);
        app.utils.deleteByPath(app.store.errors, "indexes." + pos);

        if (typeof settings?.ondelete == "function") {
            settings.ondelete({
                collection: collection,
                position: pos,
                index: data.originalIndex,
            });
        }

        clearIndexError();

        app.modals.close(modal);
    }

    function toggleColumn(column) {
        const clone = JSON.parse(JSON.stringify(data.indexParts));
        clone.tableName = collection?.name || "";

        const colLowerCased = column.toLowerCase();

        const i = clone.columns.findIndex((c) => c.name.toLowerCase() == colLowerCased);
        if (i >= 0) {
            clone.columns.splice(i, 1);
        } else {
            app.utils.pushUnique(clone.columns, { name: column });
        }

        data.index = app.utils.buildIndex(clone);

        clearIndexError();
    }

    function clearIndexError() {
        if (app.store.errors?.indexes) {
            const pos = collection.indexes.findIndex((idx) => idx == data.originalIndex);
            app.utils.deleteByPath(app.store.errors, "indexes." + pos);
        }
    }

    modal = t.div(
        {
            className: "modal popup index-upsert-modal",
            onbeforeopen: () => {
                loadIndex(index);
            },
            onafteropen: () => {
                // retrigger indexes error (if any)
                if (app.store.errors?.indexes) {
                    app.store.errors.indexes = JSON.parse(JSON.stringify(app.store.errors.indexes));
                }
            },
            onafterclose: (el) => {
                el?.remove();
            },
        },
        t.header(
            { className: "modal-header" },
            t.h6(
                { className: "modal-title" },
                t.span({ className: "txt" }, () => (data.isNew ? "Create index" : "Update index")),
            ),
        ),
        t.div(
            { className: "modal-content" },
            t.form(
                {
                    id: uniqueId + "form",
                    className: "grid sm index-upsert-form",
                    onsubmit: (e) => {
                        e.preventDefault();
                        saveIndex();
                    },
                },
                t.div(
                    { className: "col-12" },
                    t.div(
                        { className: "field" },
                        t.input({
                            type: "checkbox",
                            className: "switch",
                            id: uniqueId + "checkbox_unique",
                            checked: () => data.indexParts.unique,
                            onchange: (e) => {
                                const newIndexParts = JSON.parse(JSON.stringify(data.indexParts));
                                newIndexParts.unique = e.target.checked;
                                newIndexParts.tableName = newIndexParts.tableName || collection?.name || "";
                                data.index = app.utils.buildIndex(newIndexParts);
                            },
                        }),
                        t.label({ htmlFor: uniqueId + "checkbox_unique" }, "Unique"),
                    ),
                ),
                t.div(
                    { className: "col-12" },
                    t.div(
                        { className: "field" },
                        app.components.codeEditor({
                            required: true,
                            className: "collection-index-input pre-wrap",
                            name: () => "indexes." + collection.indexes?.findIndex((idx) => idx == data.originalIndex),
                            placeholder: () => `e.g. CREATE INDEX idx_test on ${collection?.name || "X"} (created)`,
                            value: () => data.index,
                            oninput: (val) => (data.index = val),
                        }),
                    ),
                    t.div(
                        { hidden: () => !presetColumns.length, className: "field-help m-t-sm" },
                        t.div(
                            { className: "flex flex-wrap gap-5" },
                            t.span({ className: "txt", textContent: "Presets:" }),
                            () => {
                                return presetColumns?.map((col) => {
                                    const isSelected = data.lowerCasedIndexColumnNames.includes(col.toLowerCase());
                                    return t.button({
                                        type: "button",
                                        textContent: col,
                                        className: () => `label handle ${isSelected ? "success" : ""}`,
                                        onclick: () => toggleColumn(col),
                                    });
                                });
                            },
                        ),
                    ),
                ),
            ),
        ),
        t.footer(
            { className: "modal-footer gap-base" },
            t.button(
                {
                    type: "button",
                    className: "btn transparent m-r-auto",
                    onclick: () => app.modals.close(modal),
                },
                t.span({ className: "txt" }, "Close"),
            ),
            t.button(
                {
                    hidden: () => data.isNew,
                    type: "button",
                    className: () => "btn sm circle transparent secondary",
                    ariaLabel: app.attrs.tooltip("Delete index", "left"),
                    onclick: () => {
                        app.modals.confirm(
                            "Do you really want to remove the selected index from the collection?",
                            deleteIndex,
                        );
                    },
                },
                t.i({ className: "ri-delete-bin-7-line", ariaHidden: true }),
            ),
            t.button(
                {
                    "type": "submit",
                    "html-form": uniqueId + "form",
                    "disabled": () => !data.canSave,
                    "className": () => "btn expanded",
                },
                t.span({ className: "txt" }, "Set index"),
            ),
        ),
    );

    return modal;
}
