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

/**
 * Opens a record preview modal.
 *
 * @example
 *
 * ```js
 * // full record model
 * app.modals.openRecordPreview(record)
 *
 * // or partial record
 * app.modals.openRecordPreview({ id: "rId", collectionId: "cId"})
 * ```
 *
 * @param {Object} record
 */
window.app.modals.openRecordPreview = function(record, modalSettings = {
    onbeforeopen: null,
    onafteropen: null,
    onbeforeclose: null,
    onafterclose: null,
}) {
    const modal = recordPreviewModal(record, modalSettings);
    if (!modal) {
        return;
    }

    document.body.appendChild(modal);

    app.modals.open(modal);
};

function downloadJSON(record) {
    // clear expand if any
    if (record.expand) {
        record = Object.assign({}, record);
        delete record.expand;
    }

    app.utils.downloadJSON(record, record.collectionName + "_" + record.id + ".json");
}

function copyJSON(record) {
    // clear expand if any
    if (record.expand) {
        record = Object.assign({}, record);
        delete record.expand;
    }

    app.utils.copyToClipboard(JSON.stringify(record, null, 2));
    app.toasts.success("Record copied to clipboard!");
}

function recordPreviewModal(rawRecord, modalSettings) {
    if (!rawRecord?.id) {
        app.toasts.error("Failed to load record.");
        console.warn("[recordPreviewModal] missing required record id field:", rawRecord);
        return;
    }

    if (!rawRecord.collectionId && !rawRecord.collectionName) {
        app.toasts.error("Failed to load record.");
        console.warn("[recordPreviewModal] missing required collectionId or collectionName field:", rawRecord);
        return;
    }

    let modal;

    const uniqueId = app.utils.randomString();

    const data = store({
        isLoading: false,
        record: null,
        get collection() {
            return app.store.collections.find((c) => {
                return c.id == rawRecord.collectionId || c.name == rawRecord.collectionName;
            });
        },
    });

    async function loadRecord() {
        data.isLoading = true;

        try {
            // preload to minimize content jumps
            data.record = JSON.parse(JSON.stringify(rawRecord));

            // eagerly expand first level relations (if any and the collections are loaded)
            let relExpands = [];
            const presentableRelationFields = data.collection?.fields?.filter(
                (f) => !f.hidden && f.type == "relation",
            ) || [];
            for (let field of presentableRelationFields) {
                relExpands.push(field.name);
            }

            const record = await app.pb
                .collection(rawRecord.collectionName || rawRecord.collectionId)
                .getOne(rawRecord.id, {
                    requestKey: "record_preview_" + rawRecord.id,
                    expand: relExpands.join(",") || undefined,
                });

            // populate with an up-to-date fields
            Object.assign(data.record, record);

            data.isLoading = false;
        } catch (err) {
            if (!err?.isAbort) {
                data.isLoading = false;
                app.checkApiError(err);
                setTimeout(() => app.modals.close(modal), 0);
            }
        }
    }

    modal = t.div(
        {
            pbEvent: "recordPreviewModal",
            className: "modal record-preview-modal",
            onbeforeopen: (el) => {
                loadRecord();
                return modalSettings.onbeforeopen?.(el);
            },
            onafteropen: (el) => {
                modalSettings.onafteropen?.(el);
            },
            onbeforeclose: (el) => {
                return modalSettings.onbeforeclose?.(el);
            },
            onafterclose: (el) => {
                modalSettings.onafterclose?.(el);
                el?.remove();
            },
        },
        t.header(
            { className: "modal-header" },
            t.h6(
                null,
                t.strong(null, () => rawRecord?.collectionName || data.collection?.name),
                " record preview",
            ),
            t.button(
                {
                    title: "More options",
                    className: () => `btn sm circle transparent m-l-auto ${data.isLoading ? "loading" : ""}`,
                    disabled: () => data.isLoading,
                    "html-popovertarget": uniqueId + "preview-dropdown",
                },
                t.i({ className: "ri-more-line", ariaHidden: true }),
            ),
            t.div(
                { id: uniqueId + "preview-dropdown", className: "dropdown", popover: "auto" },
                (el) => {
                    return t.button(
                        {
                            className: "dropdown-item",
                            onclick: () => {
                                copyJSON(data.record);
                                el.hidePopover();
                            },
                        },
                        t.i({ className: "ri-braces-line", ariaHidden: true }),
                        t.span({ className: "txt" }, "Copy JSON"),
                    );
                },
            ),
        ),
        t.div(
            { className: "modal-content" },
            t.table(
                {
                    pbEvent: "recordPreviewTable",
                    className: "record-preview-table responsive-table",
                },
                t.tbody(null, () => {
                    const fields = data.collection?.fields?.filter((f) => f.type != "password") || [];

                    return fields.map((f) => {
                        return t.tr(
                            null,
                            t.th(
                                { className: () => `min-width p-r-0 col-field-name-${f.name}` },
                                f.name,
                            ),
                            t.td(
                                { className: () => `col-field-name-${f.name}` },
                                () => {
                                    if (app.fieldTypes[f.type]?.view) {
                                        return app.fieldTypes[f.type].view({
                                            short: false,
                                            get record() {
                                                return data.record;
                                            },
                                            get field() {
                                                return f;
                                            },
                                        });
                                    }

                                    return app.utils.displayValue(data.record[f.name], 1000);
                                },
                            ),
                        );
                    });
                }),
            ),
        ),
        t.footer(
            { className: "modal-footer" },
            t.button(
                {
                    type: "button",
                    className: "btn transparent m-r-auto",
                    onclick: () => app.modals.close(modal),
                },
                t.span({ className: "txt" }, "Close"),
            ),
            t.button(
                {
                    type: "button",
                    className: () => `btn ${data.isLoading ? "loading" : ""}`,
                    disabled: () => data.isLoading,
                    onclick: () => downloadJSON(data.record),
                },
                t.i({ className: "ri-download-line", ariaHidden: true }),
                t.span({ className: "txt" }, "Download JSON"),
            ),
        ),
    );

    return modal;
}
