/*
 * ChurchCRM JavaScript Object Model Initialization Script
 */

/**
 * Escape HTML special characters to prevent XSS when inserting user data into DOM
 * GHSA-8r36-fvxj-26qv: Used to sanitize property values before rendering
 * @param {string} text - The text to escape
 * @returns {string} - HTML-escaped text safe for DOM insertion
 */
window.CRM.escapeHtml = function (text) {
    if (text === null || text === undefined) {
        return "";
    }
    var div = document.createElement("div");
    div.textContent = text;
    return div.innerHTML;
};

window.CRM.APIRequest = function (options) {
    if (!options.method) {
        options.method = "GET";
    }
    options.dataType = "json";
    options.url = window.CRM.root + "/api/" + options.path;
    options.contentType = "application/json";
    options.beforeSend = function (jqXHR, settings) {
        jqXHR.url = settings.url;
    };
    options.error = function (jqXHR, textStatus, errorThrown) {
        window.CRM.system.handlejQAJAXError(jqXHR, textStatus, errorThrown, options.suppressErrorDialog);
    };
    return $.ajax(options);
};

/**
 * Admin-only API Request wrapper
 * Used for endpoints in /admin/api/* - does NOT add /api prefix
 * Endpoint paths should be like "upgrade/download-latest-release" which becomes "/admin/api/upgrade/download-latest-release"
 */
window.CRM.AdminAPIRequest = function (options) {
    if (!options.method) {
        options.method = "GET";
    }
    options.dataType = "json";
    options.url = window.CRM.root + "/admin/api/" + options.path;
    options.contentType = "application/json";
    options.beforeSend = function (jqXHR, settings) {
        jqXHR.url = settings.url;
    };
    options.error = function (jqXHR, textStatus, errorThrown) {
        window.CRM.system.handlejQAJAXError(jqXHR, textStatus, errorThrown, options.suppressErrorDialog);
    };
    return $.ajax(options);
};

window.CRM.DisplayErrorMessage = function (endpoint, error) {
    // Handle different error response formats (message, error, msg)
    var errorText =
        error && (error.message || error.error || error.msg)
            ? error.message || error.error || error.msg
            : i18next.t("Unknown error");

    var message =
        "<p>" +
        i18next.t("Error making API Call to") +
        ": " +
        endpoint +
        "</p>" +
        "<p>" +
        i18next.t("Error text") +
        ": " +
        errorText +
        "</p>";

    // Never include server side traces in the UI
    bootbox.alert({
        title: i18next.t("ERROR"),
        message: message,
    });
};

window.CRM.VerifyThenLoadAPIContent = function (url) {
    var error = i18next.t("There was a problem retrieving the requested object");

    // Helper function to fetch error message from JSON response
    function fetchErrorMessage(targetUrl, fallbackError, callback) {
        try {
            $.ajax({
                method: "GET",
                url: targetUrl,
                async: false,
                dataType: "json",
                success: function (data) {
                    var msg = data && data.message ? data.message : fallbackError;
                    callback(msg);
                },
                error: function () {
                    callback(fallbackError);
                },
            });
        } catch (e) {
            callback(fallbackError);
        }
    }

    $.ajax({
        method: "HEAD",
        url: url,
        async: false,
        statusCode: {
            200: function () {
                window.open(url);
            },
            404: function () {
                fetchErrorMessage(url, error, function (msg) {
                    window.CRM.DisplayErrorMessage(url, { message: msg });
                });
            },
            500: function () {
                fetchErrorMessage(url, error, function (msg) {
                    window.CRM.DisplayErrorMessage(url, { message: msg });
                });
            },
        },
    });
};

window.CRM.kiosks = {
    assignmentTypes: {
        1: "Event Attendance",
        2: "Self Registration",
        3: "Self Checkin",
        4: "General Attendance",
    },
    reload: function (id) {
        window.CRM.APIRequest({
            path: "kiosks/" + id + "/reloadKiosk",
            method: "POST",
        }).done(function (data) {});
    },
    enableRegistration: function () {
        return window.CRM.APIRequest({
            path: "kiosks/allowRegistration",
            method: "POST",
        });
    },
    accept: function (id) {
        window.CRM.APIRequest({
            path: "kiosks/" + id + "/acceptKiosk",
            method: "POST",
        }).done(function (data) {
            window.CRM.kioskDataTable.ajax.reload();
        });
    },
    identify: function (id) {
        window.CRM.APIRequest({
            path: "kiosks/" + id + "/identifyKiosk",
            method: "POST",
        }).done(function (data) {
            //do nothing...
        });
    },
    setAssignment: function (id, assignmentId) {
        let assignmentSplit = assignmentId.split("-");
        let assignmentType, eventId;
        if (assignmentSplit.length > 0) {
            assignmentType = assignmentSplit[0];
            eventId = assignmentSplit[1];
        } else {
            assignmentType = assignmentId;
        }

        window.CRM.APIRequest({
            path: "kiosks/" + id + "/setAssignment",
            method: "POST",
            data: JSON.stringify({
                assignmentType: assignmentType,
                eventId: eventId,
            }),
        }).done(function (data) {});
    },
};

window.CRM.groups = {
    get: function () {
        return window.CRM.APIRequest({
            path: "groups/",
            method: "GET",
        });
    },
    getRoles: function (GroupID) {
        return window.CRM.APIRequest({
            path: "groups/" + GroupID + "/roles",
            method: "GET",
        });
    },
    selectTypes: {
        Group: 1,
        Role: 2,
    },
    promptSelection: function (selectOptions, selectionCallback) {
        var options = {
            message:
                '<div class="modal-body">\
                  <input type="hidden" id="targetGroupAction">',
            buttons: {
                confirm: {
                    label: i18next.t("OK"),
                    className: "btn-success",
                },
                cancel: {
                    label: i18next.t("Cancel"),
                    className: "btn-danger",
                },
            },
        };
        let initFunction = function () {};

        if (selectOptions.Type & window.CRM.groups.selectTypes.Group) {
            options.title = i18next.t("Select Group");
            options.message +=
                '<span style="color: red">' +
                i18next.t("Please select target group for members") +
                ':</span>\
                  <select name="targetGroupSelection" id="targetGroupSelection" class="form-control"></select>';
            options.buttons.confirm.callback = function () {
                selectionCallback({
                    GroupID: $("#targetGroupSelection option:selected").val(),
                });
            };
        }
        if (selectOptions.Type & window.CRM.groups.selectTypes.Role) {
            options.title = i18next.t("Select Role");
            options.message +=
                '<span style="color: red">' +
                i18next.t("Please select target Role for members") +
                ':</span>\
                  <select name="targetRoleSelection" id="targetRoleSelection" class="form-control"></select>';
            options.buttons.confirm.callback = function () {
                selectionCallback({
                    RoleID: $("#targetRoleSelection option:selected").val(),
                });
            };
        }

        if (selectOptions.Type === window.CRM.groups.selectTypes.Role) {
            if (!selectOptions.GroupID) {
                throw i18next.t("GroupID required for role selection prompt");
            }
            initFunction = function () {
                window.CRM.groups.getRoles(selectOptions.GroupID).done(function (rdata) {
                    let rolesList = rdata.map(function (item) {
                        return {
                            // i18next-disable-next-line
                            text: i18next.t(item.OptionName), // to translate the Teacher and Student in localize text
                            id: item.OptionId,
                        };
                    });
                    $("#targetRoleSelection").select2({
                        data: rolesList,
                        dropdownParent: $(".bootbox"),
                    });
                });
            };
        }
        if (selectOptions.Type === (window.CRM.groups.selectTypes.Group | window.CRM.groups.selectTypes.Role)) {
            options.title = i18next.t("Select Group and Role");
            options.buttons.confirm.callback = function () {
                selection = {
                    RoleID: $("#targetRoleSelection option:selected").val(),
                    GroupID: $("#targetGroupSelection option:selected").val(),
                };
                selectionCallback(selection);
            };
        }
        options.message += "</div>";
        bootbox.dialog(options).init(initFunction).show();

        window.CRM.groups.get().done(function (rdata) {
            groupsList = rdata.map(function (item) {
                return {
                    text: item.Name,
                    id: item.Id,
                };
            });
            $("#targetGroupSelection").parents(".bootbox").removeAttr("tabindex");
            $groupSelect2 = $("#targetGroupSelection").select2({
                data: groupsList,
                dropdownParent: $(".bootbox"),
            });

            $groupSelect2.on("select2:select", function (e) {
                var targetGroupId = $("#targetGroupSelection option:selected").val();
                $parent = $("#targetRoleSelection").parent();
                $("#targetRoleSelection").empty();
                window.CRM.groups.getRoles(targetGroupId).done(function (rdata) {
                    rolesList = rdata.map(function (item) {
                        return {
                            // i18next-disable-next-line
                            text: i18next.t(item.OptionName), // this is for the Teacher and Student role
                            id: item.OptionId,
                        };
                    });
                    $("#targetRoleSelection").select2({
                        data: rolesList,
                        dropdownParent: $(".bootbox"),
                    });
                });
            });
        });
    },
    addPerson: function (GroupID, PersonID, RoleID) {
        params = {
            method: "POST", // define the type of HTTP verb we want to use (POST for our form)
            path: "groups/" + GroupID + "/addperson/" + PersonID,
        };
        if (RoleID) {
            params.data = JSON.stringify({
                RoleID: RoleID,
            });
        }
        return window.CRM.APIRequest(params);
    },
    removePerson: function (GroupID, PersonID) {
        return window.CRM.APIRequest({
            method: "DELETE", // define the type of HTTP verb we want to use (POST for our form)
            path: "groups/" + GroupID + "/removeperson/" + PersonID,
        });
    },
    addGroup: function (callbackM) {
        bootbox.prompt({
            title: i18next.t("Add A Group Name"),
            value: i18next.t("Default Name Group"),
            onEscape: true,
            closeButton: true,
            buttons: {
                confirm: {
                    label: i18next.t("Yes"),
                    className: "btn-success",
                },
                cancel: {
                    label: i18next.t("No"),
                    className: "btn-danger",
                },
            },
            callback: function (result) {
                if (result) {
                    var newGroup = { groupName: result };

                    $.ajax({
                        method: "POST",
                        url: window.CRM.root + "/api/groups/", //call the groups api handler located at window.CRM.root
                        data: JSON.stringify(newGroup), // stringify the object we created earlier, and add it to the data payload
                        contentType: "application/json; charset=utf-8",
                        dataType: "json",
                    }).done(function (data) {
                        //yippie, we got something good back from the server
                        window.CRM.cartManager.refreshCartCount();
                        if (callbackM) {
                            callbackM(data);
                        }
                    });
                }
            },
        });
    },
};

window.CRM.system = {
    runTimerJobs: function () {
        window.CRM.APIRequest({
            method: "POST",
            path: "background/timerjobs",
            suppressErrorDialog: true,
        });
    },
    handlejQAJAXError: function (jqXHR, textStatus, errorThrown, suppressErrorDialog) {
        if (jqXHR.status === 401) {
            window.location = window.CRM.root + "/session/begin?location=" + window.location.pathname;
        }
        try {
            var CRMResponse = JSON.parse(jqXHR.responseText);
        } catch (err) {
            var errortext = textStatus + " " + errorThrown;
        }

        if (!(textStatus === "abort" || suppressErrorDialog)) {
            if (CRMResponse) {
                window.CRM.DisplayErrorMessage(jqXHR.url, CRMResponse);
            } else {
                window.CRM.DisplayErrorMessage(jqXHR.url, {
                    message: errortext,
                });
            }
        }
    },
};

window.CRM.dashboard = {
    /**
     * Load event counters once on page load (birthdays, anniversaries, events today)
     */
    loadEventCounters: function () {
        window.CRM.APIRequest({
            method: "GET",
            path: "calendar/events-counters",
            suppressErrorDialog: true,
        }).done(function (data) {
            document.getElementById("BirthdateNumber").innerText = data.Birthdays;
            document.getElementById("AnniversaryNumber").innerText = data.Anniversaries;
            document.getElementById("EventsNumber").innerText = data.Events;
        });
    },
};

function LimitTextSize(theTextArea, size) {
    if (theTextArea.value.length > size) {
        theTextArea.value = theTextArea.value.substr(0, size);
    }
}

function popUp(URL) {
    window.open(
        URL,
        "popup-window",
        "toolbar=0,scrollbars=yes,location=0,statusbar=0,menubar=0,resizable=yes,width=600,height=400,left=100,top=50,noopener,noreferrer",
    );
}
