jQuery(function ($) {
    const hideElement = (name) => $(`#${name}`).addClass("tbk-hide");
    const showElement = (name) => $(`#${name}`).removeClass("tbk-hide");
    const post = (action, data, fnOk, fnError) => {
        $.post(
            ajax_object.ajax_url,
            { action, nonce: ajax_object.nonce, ...data },
            function (resp) {
                fnOk(resp);
            },
        ).fail(function (error) {
            fnError(error);
        });
    };

    const blockButton = (e, btnName, msg) => {
        if ($(`.${btnName}`).data("sending") === true) {
            return false;
        }
        const btn = $(`.${btnName}`);
        btn.data("sending", true).html(
            `${msg} <i class="fa fa-spinner fa-spin"></i>`,
        );

        e.preventDefault();
        return true;
    };

    const releaseButton = (btnName, msg) => {
        $(`.${btnName}`).data("sending", false).html(msg);
    };

    $(".check_conn").on("click", function (e) {
        if (!blockButton(e, "check_conn", "Verificando ...")) {
            return;
        }
        showElement("tbk_response_status");
        hideElement("div_status_error");
        hideElement("div_status_ok");
        post("check_connection", {}, (resp) => {
            if (resp.status.string == "OK") {
                $("#response_url_text").text(resp.response.url);
                $("#response_token_text").html(
                    "<pre>" + resp.response.token + "</pre>",
                );
                showElement("div_status_ok");
            } else {
                $("#error_response_text").text(resp.response.error);
                $("#error_detail_response_text").html(
                    '<code style="display: block; padding: 10px">' +
                        resp.response.detail +
                        "</code>",
                );
                showElement("div_status_error");
            }
            releaseButton("check_conn", "Verificar Conexión");
        });
    });

    $(".get-transaction-status").on("click", function (e) {
        e.preventDefault();
        if (!blockButton(e, "get-transaction-status", "Consultando estado")) {
            return;
        }

        const container = document.getElementById("transaction_status_admin");
        container.innerHTML = "";

        const separator = document.createElement("div");
        separator.className = "tbk-separator";
        separator.style.display = "none";
        container.appendChild(separator);

        post(
            "get_transaction_status",
            {
                order_id: $(".get-transaction-status").data("order-id"),
                buy_order: $(".get-transaction-status").data("buy-order"),
                token: $(".get-transaction-status").data("token")
            },
            (resp) => {
                for (const [key, value] of Object.entries(resp)) {
                    const fieldName = document.createElement("span");
                    fieldName.className = "tbk-field-name";
                    fieldName.textContent = getFieldName(key);

                    const fieldValue = document.createElement("span");
                    fieldValue.className = "tbk-field-value";
                    fieldValue.textContent = value;

                    if (key == "status") {
                        fieldValue.classList.add(
                            "tbk-badge",
                            getBadgeColorFromStatus(value),
                        );
                    }

                    if (key == "cardNumber") {
                        fieldValue.style.width = "100%";
                    }

                    const field = document.createElement("div");
                    field.className = "tbk-field";
                    field.appendChild(fieldName);
                    field.appendChild(fieldValue);

                    container.appendChild(field);
                }
                separator.style.removeProperty("display");

                releaseButton("get-transaction-status", "Consultar Estado");
            },
            (error) => {
                const errorContainer = createErrorContainer(
                    error.responseJSON.message,
                );
                container.appendChild(errorContainer);
                separator.style.removeProperty("display");

                releaseButton("get-transaction-status", "Consultar Estado");
            },
        );
    });

    function getBadgeColorFromStatus(status) {
        const statusColorsDictionary = {
            Inicializada: "tbk-badge-warning",
            Capturada: "tbk-badge-success",
            Autorizada: "tbk-badge-success",
            Fallida: "tbk-badge-error",
            Anulada: "tbk-badge-info",
            Reversada: "tbk-badge-info",
            "Parcialmente anulada": "tbk-badge-info"
        };

        return statusColorsDictionary[status] ?? "tbk-badge-default";
    }

    function getFieldName(fieldKey) {
        const fieldNameDictionary = {
            vci: "VCI",
            status: "Estado",
            responseCode: "Código de respuesta",
            amount: "Monto",
            authorizationCode: "Código de autorización",
            accountingDate: "Fecha contable",
            paymentType: "Tipo de pago",
            installmentType: "Tipo de cuota",
            installmentNumber: "Número de cuotas",
            installmentAmount: "Monto cuota",
            sessionId: "ID de sesión",
            buyOrder: "Orden de compra",
            buyOrderMall: "Orden de compra mall",
            buyOrderStore: "Orden de compra tienda",
            cardNumber: "Número de tarjeta",
            transactionDate: "Fecha transacción",
            transactionTime: "Hora transacción",
            balance: "Balance"
        };

        return fieldNameDictionary[fieldKey] ?? fieldKey;
    }

    $("#mainform").on("click", ".notice-dismiss", function () {
        let noticeId = $(this).closest(".notice").attr("id");

        post("dismiss_notice", {
            notice_id: noticeId
        });
    });

    function checkPermission(fileToDownload) {
        return $.ajax({
            url: ajax_object.ajax_url,
            type: "POST",
            data: {
                action: "check_can_download_file",
                file: fileToDownload,
                nonce: ajax_object.nonce
            }
        })
            .then(function (response) {
                return response;
            })
            .catch(function (error) {
                return {
                    success: false,
                    data: {
                        error:
                            error.message ||
                            "Error en la solicitud de descarga"
                    }
                };
            });
    }

    function showNotice(title, message, type = "success") {
        const notice = $("<div>")
            .addClass(`is-dismissible notice notice-${type}`)
            .prepend(`<p><strong>${title}</strong><br>${message}</p>`);

        const dismissButton = $("<button>").addClass("notice-dismiss");

        notice.append(dismissButton);

        notice.find(".notice-dismiss").on("click", function () {
            notice.fadeOut(300, function () {
                notice.remove();
            });
        });

        $("#logs-container").prepend(notice);
    }

    $("#btnDownload").on("click", function (e) {
        e.preventDefault();
        const logFileSelected = $("#log_file").val();

        if (!logFileSelected) {
            showNotice(
                "Error en la descarga",
                "Debes seleccionar un archivo",
                "error",
            );
            return;
        }

        checkPermission(logFileSelected).then(function (checkResponse) {
            if (checkResponse.success) {
                window.location.href = checkResponse.data.downloadUrl;
                return;
            }
            showNotice(
                "Error en la descarga",
                checkResponse.data.error,
                "error",
            );
        });
    });
});

const createErrorContainer = (errorMessage) => {
    const errorContainer = document.createElement("div");
    errorContainer.classList.add("tbk-status", "tbk-status-error");
    const icon = document.createElement("i");
    icon.classList.add("fa", "fa-times");
    const paragraph = document.createElement("p");
    paragraph.textContent = errorMessage;

    errorContainer.appendChild(icon);
    errorContainer.appendChild(paragraph);
    return errorContainer;
};

const generateRandomString = (length = 6) => {
    const characters =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    const charactersLength = characters.length;
    let result = "";
    const randomValues = new Uint8Array(length);
    crypto.getRandomValues(randomValues);
    for (let i = 0; i < length; i++) {
        result += characters.charAt(randomValues[i] % charactersLength);
    }
    return result;
};

const generateBuyOrderPreview = (format) => {
    const array = new Uint16Array(1);
    crypto.getRandomValues(array);
    const orderId = 10000 + (array[0] % 90000);
    return format
        .replaceAll(/\{orderId\}/gi, orderId.toString())
        .replaceAll(/\{random(?:, length=\d+)?\}/gi, (_, length) =>
            generateRandomString(length ? Number.parseInt(length, 10) : 6),
        );
};

const isValidFormat = (format) => {
    const allowedCharsRegex = /^[A-Za-z0-9-_:]*$/;
    const formatWithoutPlaceholders = format
        .replaceAll(/\{orderId\}/gi, "")
        .replaceAll(/\{random(?:, length=\d+)?\}/gi, "");
    if (!allowedCharsRegex.test(formatWithoutPlaceholders)) {
        return false;
    }
    return /\{orderId\}/i.test(format);
};

const createHelpTextBuyOrderFormat = (isOneclick) => {
    const helpText = document.createElement("div");
    helpText.className = "tbk-buy-order-format-help-text";
    helpText.innerHTML = `
        <br/><br/>
        <p><strong>ℹ️ Información: </strong></p>
        <p><strong>Componentes disponibles:</strong></p>
        <p>•<code>{orderId}</code> Número de orden de compra en Woocommerce (obligatorio).</p>
        <p>•<code>{random}</code> Texto aleatorio con longitud de 8 caracteres (opcional).</p>
        <p>•<code>{random, length=12}</code> Texto aleatorio con longitud especifica (opcional).</p>
        <p><strong>Ejemplo:</strong> <code>cualquierTexto-{random, length=12}-{orderId}</code></p>
        <p><strong>Notas:</strong></p>
        <p>•Solo se permiten caracteres alfanuméricos, guiones (<code>-</code>), guiones bajos (<code>_</code>)
            o dos puntos (<code>:</code>). No se permiten espacios. </p>
        <p>•El valor generado no puede exceder los 26 caracteres.</p>
        ${
            isOneclick
                ? `<p>•El formato de orden de compra hija debe ser distinto al formato de orden de compra principal.</p>`
                : ""
        }
    `;
    return helpText;
};

const attachBuyOrderFormatComponent = (
    inputId,
    defaultFormat,
    isOneclick,
    otherInputId,
    addHelpText,
) => {
    const input = document.getElementById(inputId);
    if (!input) {
        return;
    }

    const wrapper = document.createElement("div");
    wrapper.className = "tbk-buy-order-format-container";

    input.parentNode.insertBefore(wrapper, input);
    wrapper.appendChild(input);

    const valueDisplay = document.createElement("div");
    valueDisplay.className = "tbk-buy-order-format-value-display";

    const errorDisplay = document.createElement("div");
    errorDisplay.className = "tbk-buy-order-format-error-display";

    const btn1 = document.createElement("button");
    btn1.textContent = "Refrescar";
    btn1.className = "button button-primary tbk-button-primary";
    btn1.addEventListener("click", (event) => {
        event.preventDefault();
        validateAndDisplay(inputId);
    });

    const btn2 = document.createElement("button");
    btn2.textContent = "Restablecer";
    btn2.className = "button button-secondary tbk-button-secondary";
    btn2.addEventListener("click", (event) => {
        event.preventDefault();
        input.value = defaultFormat;
        validateAndDisplay(inputId);
    });

    wrapper.appendChild(btn1);
    wrapper.appendChild(btn2);
    wrapper.parentNode.insertBefore(valueDisplay, wrapper.nextSibling);
    wrapper.parentNode.insertBefore(errorDisplay, valueDisplay.nextSibling);

    if (addHelpText) {
        const helpText = createHelpTextBuyOrderFormat(isOneclick);
        wrapper.parentNode.insertBefore(helpText, errorDisplay.nextSibling);
    }

    input._errorDisplay = errorDisplay;
    input._valueDisplay = valueDisplay;
    input._otherInputId = otherInputId;

    const setDisplay = (inputId, message, error) => {
        const input = document.getElementById(inputId);
        if (error) {
            input._errorDisplay.style.display = "block";
            input._errorDisplay.textContent = error;
            input._valueDisplay.textContent = "";
            input.classList.remove("tbk-input-valid");
            input.classList.add("tbk-input-error");
        } else {
            input._errorDisplay.style.display = "none";
            input._valueDisplay.textContent = message;
            input.classList.remove("tbk-input-error");
            input.classList.add("tbk-input-valid");
        }
    };

    const validateAndDisplay = (inputId, isRecursive) => {
        const input = document.getElementById(inputId);
        if (!input?._valueDisplay) {
            return;
        }
        const value = input.value;
        if (isValidFormat(value)) {
            const preview = generateBuyOrderPreview(value);
            setDisplay(
                inputId,
                `✅ Vista previa: ${preview} (${preview.length} caracteres)`,
                null,
            );
        } else {
            setDisplay(
                inputId,
                null,
                `❌ Formato inválido. Asegúrate de que contenga solo caracteres alfanuméricos,
                guiones (-), guiones bajos (_) o dos puntos (:), sin espacios, y que contenga {orderId}.`,
            );
            return;
        }
        if (isOneclick) {
            const otherInput = document.getElementById(input._otherInputId);
            if (!otherInput) {
                return;
            }
            const otherFormat = otherInput.value;
            if (
                otherFormat &&
                value &&
                otherFormat.toUpperCase() === value.toUpperCase()
            ) {
                setDisplay(
                    inputId,
                    null,
                    `❌ El formato de orden de compra hija no puede ser igual
                    al formato de orden de compra principal.`,
                );
            }
            if (!isRecursive) {
                validateAndDisplay(input._otherInputId, true);
            }
        }
    };

    input.addEventListener("input", (event) => {
        validateAndDisplay(inputId);
    });

    validateAndDisplay(inputId);
};

document.addEventListener("DOMContentLoaded", function () {
    attachBuyOrderFormatComponent(
        "woocommerce_transbank_webpay_plus_rest_buy_order_format",
        "wc-{random, length=8}-{orderId}",
        false,
        null,
        true,
    );
    attachBuyOrderFormatComponent(
        "woocommerce_transbank_oneclick_mall_rest_buy_order_format",
        "wc-{random, length=8}-{orderId}",
        true,
        "woocommerce_transbank_oneclick_mall_rest_child_buy_order_format",
        false,
    );
    attachBuyOrderFormatComponent(
        "woocommerce_transbank_oneclick_mall_rest_child_buy_order_format",
        "wc-child-{random, length=8}-{orderId}",
        true,
        "woocommerce_transbank_oneclick_mall_rest_buy_order_format",
        true,
    );
});

(function () {
    document.addEventListener(
        "click",
        function (e) {
            const el = e.target.closest(".tbk-js-delete-inscription");
            if (!el) return;

            e.preventDefault();

            const href = el.getAttribute("href");
            if (!href) return;

            if (typeof swal !== "function") {
                globalThis.location.href = href;
                return;
            }

            swal({
                title: "Eliminar inscripción",
                text: "Esta acción no se puede deshacer. ¿Deseas continuar?",
                icon: "warning",
                buttons: {
                    cancel: {
                        text: "Cancelar",
                        visible: true,
                        closeModal: true
                    },
                    confirm: {
                        text: "Eliminar",
                        value: true,
                        closeModal: true
                    }
                },
                dangerMode: true
            }).then(function (ok) {
                if (ok) globalThis.location.href = href;
            });
        },
        true,
    );
})();
