import { toDeleteProp } from "@/base/fieldSettings";

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

window.app.modals.openCollectionChangesConfirmation = async function(
    oldCollection,
    newCollection,
    yesCallback,
    noCallback,
) {
    const data = store({
        isLoadingConflictingOIDCProviders: false,
        conflictingOIDCProviders: [],
        // ---
        get isCollectionRenamed() {
            return oldCollection?.name != newCollection?.name;
        },
        get isNewCollectionAuth() {
            return newCollection?.type === "auth";
        },
        get isNewCollectionView() {
            return newCollection?.type === "view";
        },
        get renamedFields() {
            if (data.isNewCollectionView) {
                return [];
            }

            return newCollection?.fields?.filter?.((f) => {
                let oldField;
                if (f.id && !f[toDeleteProp]) {
                    oldField = oldCollection.fields?.find?.((old) => old.id == f.id);
                }

                return oldField && oldField.name != f.name;
            }) || [];
        },
        get deletedFields() {
            if (data.isNewCollectionView) {
                return [];
            }

            return newCollection?.fields?.filter?.((f) => {
                return f.id && f[toDeleteProp];
            }) || [];
        },
        get multipleToSingleFields() {
            if (data.isNewCollectionView) {
                return [];
            }

            return newCollection?.fields?.filter?.((newField) => {
                const oldField = oldCollection?.fields?.find?.((f) => f.id == newField.id);
                if (!oldField || typeof oldField.maxSelect == "undefined") {
                    return false;
                }

                // normalize
                const oldMaxSelect = oldField.maxSelect || 1;
                const newMaxSelect = newField.maxSelect || 1;

                return oldMaxSelect > 1 && newMaxSelect == 1;
            }) || [];
        },
        get changedRules() {
            // for now enable only for "production"
            if (window.location.protocol != "https:") {
                return [];
            }

            const result = [];

            const ruleProps = ["listRule", "viewRule"];
            if (!data.isNewCollectionView) {
                ruleProps.push("createRule", "updateRule", "deleteRule");
            }
            if (data.isNewCollectionAuth) {
                ruleProps.push("manageRule", "authRule");
            }

            let oldRule, newRule;
            for (let prop of ruleProps) {
                oldRule = oldCollection?.[prop];
                newRule = newCollection?.[prop];
                if (oldRule === newRule) {
                    continue;
                }

                result.push({ prop, oldRule, newRule });
            }

            return result;
        },
        get needConfirmation() {
            return !app.utils.isEmpty(oldCollection?.id) && (
                data.isCollectionRenamed
                || data.renamedFields.length
                || data.deletedFields.length
                || data.multipleToSingleFields.length
                || data.changedRules.length
                || data.conflictingOIDCProviders.length
            );
        },
    });

    const knownOIDCProviders = ["oidc", "oidc2", "oidc3"];

    async function detectConflictingOIDCProviders() {
        if (app.utils.isEmpty(oldCollection?.id) || !data.isNewCollectionAuth) {
            return;
        }

        data.isLoadingConflictingOIDCProviders = true;

        try {
            data.conflictingOIDCProviders = [];

            for (const name of knownOIDCProviders) {
                const oldProvider = oldCollection?.oauth2?.providers?.find?.((p) => p.name == name);
                const newProvider = newCollection?.oauth2?.providers?.find?.((p) => p.name == name);

                if (!oldProvider || !newProvider) {
                    continue;
                }

                const oldHost = new URL(oldProvider.authURL).host;
                const newHost = new URL(newProvider.authURL).host;
                if (oldHost == newHost) {
                    continue;
                }

                // check if there are existing externalAuths
                const haveExternalAuths = await app.pb.collection("_externalAuths").getFirstListItem(
                    app.pb.filter("collectionRef={:collectionId} && provider={:provider}", {
                        collectionId: newCollection?.id,
                        provider: name,
                    }),
                    {
                        requestKey: null,
                    },
                );
                if (haveExternalAuths) {
                    data.conflictingOIDCProviders.push({ name, oldHost, newHost });
                }
            }

            data.isLoadingConflictingOIDCProviders = false;
        } catch (err) {
            if (!err?.isAbort) {
                data.isLoadingConflictingOIDCProviders = false;
                app.checkApiError(err);
            }
        }
    }

    await detectConflictingOIDCProviders();

    if (!data.needConfirmation) {
        return yesCallback();
    }

    app.modals.confirm(
        t.div(
            { className: "dangerous-collection-changes-list" },
            t.h5({ className: "block txt-center m-b-base" }, "Do you really want to save the collection changes?"),
            // general collection warning
            () => {
                if (!data.isCollectionRenamed && !data.deletedFields.length && !data.renamedFields.length) {
                    return;
                }

                return t.div(
                    { className: "alert warning m-b-base" },
                    t.p(
                        null,
                        "If the collection participate in another collection rule, filter or view query, you'll have to update it manually!",
                    ),
                    () => {
                        if (data.deletedFields.length) {
                            return t.p(
                                null,
                                "All data associated with the removed fields will be permanently deleted!",
                            );
                        }
                    },
                );
            },
            // renamed collection
            () => {
                if (!data.isCollectionRenamed) {
                    return;
                }

                return t.ul(
                    { className: "collection-changes-list changes-renamed-collection" },
                    t.li(
                        { className: "list-item" },
                        "Renamed collection ",
                        t.strong({ className: "label warning" }, oldCollection?.name),
                        t.i({ className: "ri-arrow-right-line txt-sm", ariaHidden: true }),
                        t.strong({ className: "label success" }, newCollection?.name || "N/A"),
                    ),
                );
            },
            // renamed fields
            () => {
                if (!data.renamedFields.length) {
                    return;
                }

                return t.ul(
                    { className: "collection-changes-list changes-renamed-fields" },
                    () => {
                        return data.renamedFields.map((newField) => {
                            const oldField = oldCollection?.fields?.find?.((f) => f.id == newField.id);
                            return t.li(
                                { className: "list-item" },
                                "Renamed field ",
                                t.strong({ className: "label warning" }, oldField?.name),
                                t.i({ className: "ri-arrow-right-line txt-sm", ariaHidden: true }),
                                t.strong({ className: "label success" }, newField.name || "N/A"),
                            );
                        });
                    },
                );
            },
            // deleted fields
            () => {
                if (!data.deletedFields.length) {
                    return;
                }

                return t.ul(
                    { className: "collection-changes-list changes-deleted-fields" },
                    () => {
                        return data.deletedFields.map((field) => {
                            return t.li(
                                { className: "list-item" },
                                "Deleted field ",
                                t.strong({ className: "label danger" }, field.name || "N/A"),
                            );
                        });
                    },
                );
            },
            // multiple->single fields
            () => {
                if (!data.multipleToSingleFields.length) {
                    return;
                }

                return t.ul(
                    { className: "collection-changes-list changes-multiple-to-single-fields" },
                    () => {
                        return data.multipleToSingleFields.map((field) => {
                            return t.li(
                                { className: "list-item" },
                                "Multiple to single value conversion of field ",
                                t.strong({ className: "label warning" }, field.name || field.id),
                                t.em({ className: "txt-sm" }, " (will keep only the last array item)"),
                            );
                        });
                    },
                );
            },
            // API rule changes
            () => {
                if (!data.changedRules.length) {
                    return;
                }

                return t.ul(
                    { className: "collection-changes-list changes-api-rules" },
                    () => {
                        return data.changedRules.map((ruleChange) => {
                            return t.li(
                                { className: "list-item" },
                                t.div(
                                    { className: "content" },
                                    t.span({ className: "txt" }, "Changed API rule for "),
                                    t.code(null, ruleChange.prop),
                                ),
                                t.small({ className: "txt-bold" }, "Old:"),
                                t.div(
                                    { className: "rule-content old-rule" },
                                    ruleChange.oldRule === null
                                        ? "null (superusers only)"
                                        : (ruleChange.oldRule || "\"\""),
                                ),
                                t.small({ className: "txt-bold" }, "New:"),
                                t.div(
                                    { className: "rule-content new-rule" },
                                    ruleChange.newRule === null
                                        ? "null (superusers only)"
                                        : (ruleChange.newRule || "\"\""),
                                ),
                            );
                        });
                    },
                );
            },
            // Conflicting OIDC changes
            () => {
                if (!data.conflictingOIDCProviders.length) {
                    return;
                }

                return t.ul(
                    { className: "collection-changes-list changes-api-rules" },
                    () => {
                        return data.conflictingOIDCProviders.map((oidc) => {
                            return t.li(
                                { className: "list-item" },
                                "Changed OIDC ",
                                oidc.name,
                                " host ",
                                t.strong({ className: "label warning" }, oidc.oldHost),
                                t.i({ className: "ri-arrow-right-line txt-sm", ariaHidden: true }),
                                t.strong({ className: "label success" }, oidc.newHost),
                                t.br(),
                                t.span(
                                    { className: "txt-hint" },
                                    "If the old and new OIDC configuration is not for the same provider consider deleting",
                                    " all old _externalAuths records associated to the current collection and provider,",
                                    " otherwise it may result in account linking errors.",
                                ),
                                " ",
                                t.a({
                                    rel: "noopenener noreferrer",
                                    target: "_blank",
                                    href: () => {
                                        return `#/collections?collection=_externalAuths&filter=collectionRef%3D%22${newCollection?.id}%22+%26%26+provider%3D%22${oidc.name}%22`;
                                    },
                                    textContent: "Review existing _externalAuths records",
                                }),
                            );
                        });
                    },
                );
            },
        ),
        yesCallback,
        noCallback,
        {
            className: "collection-changes-confirm-modal",
            yesButton: "Yes, save changes",
        },
    );
};
