let transactionId = 0;

(function init() {

    if (currentLocationSplited[0] == "sell") {

        var ent_id = $("#sale_ent_id").val();

        localStorage.setItem("PosProductListLimit", 18);

        if (currentLocationSplited[1] == 'det' && Number(currentLocationSplited[2] > 0)) {

            transactionId = currentLocationSplited[2];
            storeSaleData(transactionId);
            $(".btnReloadNewOrder").removeClass("hide");

        } else {
            // console.log(`No id was found in url`);
            $("#inputLoadSaleById").focus();
            selectBranchToSell(ent_id);
            js_selectListTable();
            js_selectListFiscalReceipt(ent_id);
        }
    }
})();

// Remove options if user doesn't belong to the sale enterprise
window.addEventListener('load', function () {
    jsRemoveOptionsIfUserNotBelongToTheSaleEnterprise();
});


async function storeSaleData(transactionId) {

    // ── Helper: clear sale state and show a toast ─────────────────────────────
    function clearSaleData(message, icon = 'warning', duration = 2500) {
        localStorage.removeItem('sale_info');
        fnSweetToast(message, icon, duration);
    }

    // ── Guard: transactionId must be a valid positive integer ─────────────────
    if (Number(transactionId) < 1) {
        clearSaleData(translate.invalid_transaction_id, 'error', 3500);
        return;
    }

    try {
        const sale_info = await getSaleData(transactionId);

        if (sale_info.status === 'success') {

            // Verify the sale belongs to the current user's entity (ROOT sees all)
            const saleEntId = Number(sale_info.data.sale_ent_id);
            const sessionEntId = Number(sess_ent_id);
            const isAuthorized = sessionEntId === saleEntId || sess_user_profile === 'ROOT';

            if (isAuthorized) {
                const posInfo = await getBranchData(sale_info.data.sale_pos_id);
                jsStorePosInfo(posInfo);
                localStorage.setItem('sale_info', JSON.stringify(sale_info.data));
                jsShowSaleInfo();

            } else {
                clearSaleData(translate.sale_not_found);
            }

        } else if (sale_info.status === 'warning') {
            clearSaleData(translate.sale_not_found);

        } else {
            clearSaleData(
                translate.data_could_not_be_loaded_please_contact_the_system_vendor_for_technical_assistance,
                'error',
                3500
            );
        }

    } catch (error) {
        console.error('storeSaleData error:', error);
        clearSaleData(
            translate.data_could_not_be_loaded_please_contact_the_system_vendor_for_technical_assistance,
            'error',
            3500
        );
    }
}

/*================================================
HELPER: CHECK IF SALE IS ACTIVE AND NOT DISABLED
=================================================*/
async function jsCheckActiveSale(additionalMessage = "") {
    if (Number(transactionId) < 1) {
        return true; // No active transaction, skip validation
    }

    let sale_info = JSON.parse(localStorage.getItem("sale_info"));

    if (!sale_info) {
        location.reload();
        return false;
    }

    if (sale_info.sale_status === "Disabled") {
        swalInit.fire(translate.this_sale_has_been_canceled, additionalMessage, "error");
        return false;
    }

    return true; // Sale is active and enabled
}

/*================================================
FUNCTION TO SHOW ALL BRANCHES LIST
=================================================*/
async function selectBranchToSell(ent_id = "", pos_id = "") {

    try {

        const url = `ajax/branches.ajax.php?op=ajax_selectBranchesByUserPermission&ent_id=${ent_id}&pos_id=${pos_id}`;
        const response = await fetch(url);

        if (!response.ok) {
            throw new Error('Failed to get data from API');
        }

        const res = await response.json();

        const userPosAccess = JSON.parse(res.data);

        $("#sale_pos_id").html("");

        if (res.status == "success") {
            if (userPosAccess.length > 1) {

                if (pos_id == "") {
                    $("#sale_pos_id").append(`<option value="">-- ${translate.select} --</option>`);
                }

                userPosAccess.forEach(item => {
                    $("#sale_pos_id").append(`<option value='${item.pos_id}'>${item.pos_name}</option>`);
                });
            } else {
                $("#sale_pos_id").append(`<option value='${userPosAccess[0].pos_id}'>${userPosAccess[0].pos_name}</option>`);
            }

            $("#sale_pos_id").trigger("change");

            return true;

        } else if (res.status == "warning") {
            $("#sale_pos_id").append(`<option value="">-- ${translate.select} --</option>`);
            swalInit.fire(res.title, res.message, res.status).then(function (result) {
                // return false;
                window.location = "sell";
            });

        } else {
            $("#sale_pos_id").append(`<option value="">-- ${translate.select} --</option>`);
            console.log(res);
        }

    } catch (error) {
        console.log(error);
    }
}

// ON CHANGE BRANCH ID
$(document).on("change", "#sale_pos_id", function () {

    let pos_id = $(this).val();

    if (Number(pos_id) >= 1) {
        jsOnChangeBranchId(pos_id);
    }

});

async function jsOnChangeBranchId(pos_id) {

    var ent_id = $("#sale_ent_id").val();

    let posInfo = await getBranchData(pos_id);
    jsStorePosInfo(posInfo);

    // Get object from localStorage
    let pos_info = JSON.parse(localStorage.getItem("pos_info"));

    if (Number(transactionId) <= 0) {
        fnSelectCustomersList();
        js_SelectSaleType(pos_id);

        if (pos_info.pos_status == "Disabled") {
            swalInit.fire(translate.this_point_of_sale_is_closed, translate.please_contact_the_system_provider, "warning");
            selectBranchToSell(ent_id);
            return false;
        }
    }

    $(".pos_description").text($("#sale_pos_id option:selected").text());
    $(".divBranchSelect").hide();
    $(".divBranchDescription").show();

    js_SelectPaymentType(ent_id, pos_id);

    $("#pos_cash_back_percentage").val(pos_info.pos_cash_back_percentage);
    $("#pos_cash_back_status").val(pos_info.pos_cash_back_status);

    if (pos_info.pos_cash_back_status == "On") {
        $(".trCashBackinfo").show();
    }
};

async function js_SelectPaymentType(ent_id, pos_id) {

    if (Number(pos_id) <= 0) {
        $("#cbo_payment_type").html("");
        $("#cbo_payment_type").append(`<option value="">-- ${translate.select} --</option>`);
        return;
    }

    try {

        const url = `ajax/payment-types.ajax.php?op=ajaxSelectPaymentType&ent_id=${ent_id}&pos_id=${pos_id}&section=sell`;
        const response = await fetch(url);

        if (!response.ok) {
            throw new Error('Failed to get data from API');
        }

        const res = await response.json();
        // console.log(res);

        $("#cbo_payment_type").html("");

        if (res.status == "success") {
            res.data.forEach(item => {
                let payTypeName = item.pay_type_name;
                if (payTypeName.toUpperCase() == "CASH") payTypeName = translate.cash;
                if (payTypeName.toUpperCase() == "CREDIT CARD") payTypeName = translate.credit_card;
                if (payTypeName.toUpperCase() == "DEBIT CARD") payTypeName = translate.debit_card;
                if (payTypeName.toUpperCase() == "BANK DEPOSIT") payTypeName = translate.bank_deposit;

                payTypeName = payTypeName.toLowerCase().replace(/\b\w/, char => char.toUpperCase());

                $("#cbo_payment_type").append(`<option value='${item.pay_type_name}'>${payTypeName}</option>`);
            });
        }

    } catch (error) {
        console.log(error);
    }
}

/*================================================
FUNCTION TO SHOW ALL CLIENTS LIST
=================================================*/
async function fnSelectCustomersList(ent_id = "", cus_id = "") {
    try {

        const url = `ajax/customers.ajax.php?op=ajaxSelectCustomer&ent_id=${ent_id}&cus_id=${cus_id}`;
        const response = await fetch(url);

        if (!response.ok) {
            throw new Error('Failed to get data from API');
        }

        const res = await response.json();

        $("#sale_cus_id").html("");

        if (cus_id == "") {
            $("#sale_cus_id").append(`<option value="">-- ${translate.select} --</option>`);
        }

        if (res.status == "success") {
            res.data.forEach(item => {
                $("#sale_cus_id").append(`<option value='${item.cus_id}'>${item.cus_full_name}</option>`);
            });

            // if (cus_id > 0) {
            $("#sale_cus_id").trigger("change");
            // }
        }

    } catch (error) {
        console.log(error);
    }
}


// GET CUSTOMER DEBT ON CHANGE
$(document).on("change", "#sale_cus_id", async function () {

    var ent_id = $("#sale_ent_id").val();
    var cus_id = $(this).val();

    var parameters = {
        ent_id: ent_id,
        cus_id: cus_id,
    }

    if (Number(cus_id) > 0) {

        try {

            // Get object from localStorage
            let pos_info = JSON.parse(localStorage.getItem("pos_info"));

            let cusInfo = await getCustomerDataById(cus_id)
            $("#sale_cus_fiscal_number").val(cusInfo.data.cus_fiscal_number);

            let customerCashBack = await getCustomerCashBack(cus_id);
            $("#customerCashBack").val(customerCashBack.data.available_cashback);
            $("#span_available_cash_back").text(showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, customerCashBack.data.available_cashback));

            const response = await $.ajax({
                type: "GET",
                url: "ajax/customers.ajax.php?op=ajaxShowCustomerDebt",
                data: parameters,
            });

            // Handle the response
            if (Number(response) > 0) {

                var total_client_debt = showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, response);

                swalInit.fire({
                    title: `${translate.this_customer_has_a_debt_of} ${total_client_debt}`,
                    text: translate.make_sure_you_collect_the_debt,
                    icon: "warning",
                    confirmButtonText: `<i class="ph-arrow-right me-1"></i> ${translate.continue}`,
                    buttonsStyling: false,
                    customClass: {
                        confirmButton: 'btn btn-indigo',
                    }
                });
            }

        } catch (error) {
            // Handle any errors that might occur during the request
            console.error(error);
        }
    }
});

/*================================================
FUNCTION TO SHOW ALL SALES TYPE LIST
=================================================*/
async function js_SelectSaleType(pos_id = "", sale_type_name = "") {

    let pos_info = JSON.parse(localStorage.getItem("pos_info"));

    if (Number(pos_id) <= 0) {
        $("#sale_type").html("");
        $("#sale_type").append(`<option value="">-- ${translate.select} --</option>`);
        return;
    }

    try {

        const url = `ajax/sale-types.ajax.php?op=ajaxSelectSaleType&pos_id=${pos_id}&sale_type_name=${sale_type_name}`;
        const response = await fetch(url);

        if (!response.ok) {
            throw new Error('Failed to get data from API');
        }

        const res = await response.json();

        $("#sale_type").html("");

        if (res.status == "success") {
            res.data.forEach(item => {
                let saleTypeName = item.sale_type_name;
                if (saleTypeName == "Local" && pos_info.pos_business_category == "Restaurant") saleTypeName = translate.local_sale_type;
                if (saleTypeName == "Delivery") saleTypeName = translate.delivery;
                if (saleTypeName == "Take Away") saleTypeName = translate.takeaway;
                if (saleTypeName == "Without Taxes") saleTypeName = translate.without_taxes;
                $("#sale_type").append(`<option value='${item.sale_type_name}'>${saleTypeName}</option>`);
            });

            $("#sale_type").trigger("change");
        }

    } catch (error) {
        console.log(error);
    }
}

$(document).on("change", "#sale_type", async function () {
    let sale_type = $(this).val();
    jsOnchangeSaleType(sale_type);
});

async function jsOnchangeSaleType(sale_type) {

    // ── Helper: apply DOM state for "Without Taxes" ───────────────────────────
    function applyWithoutTaxes() {
        $('.divTableSelect, .divTax, .divCostDelivery, .divLegalTipping, .divTotalDelivery').hide();
        $('.spanTaxPercent').text('(0%)');
        $('#sale_tax_percent, #sale_tax_value').val(0);
        $('#sale_cost_delivery').val(0);
        $('#sale_tax_law_percent, #sale_tax_law_value').val(0);
    }

    // ── Helper: apply shared tax + no-delivery DOM state ─────────────────────
    function applyTaxVisible(taxPercent) {
        $('.divTax').show();
        $('.spanTaxPercent').text(`(${taxPercent}%)`);
        $('#sale_tax_percent').val(taxPercent);
        $('.divCostDelivery').hide();
        $('#sale_cost_delivery').val(0);
        $('.divTotalDelivery').hide();
    }

    // ── Read pos_info ─────────────────────────────────────────────────────────
    const pos_info = JSON.parse(localStorage.getItem('pos_info'));

    let saleTaxPercent = pos_info.pos_tax;
    let saleTaxTippingPercent = pos_info.pos_legal_tipping;

    // ── Override tax rates from saved sale when editing ───────────────────────
    if (Number(transactionId) > 0) {
        const sale_info = JSON.parse(localStorage.getItem('sale_info'));

        if (!sale_info) {
            location.reload();
            return;
        }

        saleTaxPercent = sale_info.sale_tax_percent;
        saleTaxTippingPercent = sale_info.sale_tax_law_percent;

    } else {
        localStorage.removeItem('sale_info');
        localStorage.removeItem('ticketInfos');
    }

    const isRestaurantOrNightclub = pos_info.pos_business_category === 'Restaurant'
        || pos_info.pos_business_category === 'Nightclub';

    // ── Delivery — always applies regardless of business category ─────────────
    if (sale_type === 'Delivery') {

        applyTaxVisible(saleTaxPercent);
        $('.divTableSelect, .divLegalTipping').hide();
        $('.divCostDelivery, .divTotalDelivery').show();
        $('#sale_tax_law_percent, #sale_tax_law_value').val(0);

        // ── Without Taxes — requires password for non-privileged users ────────────
    } else if (sale_type === 'Without Taxes') {

        const isPrivileged = sess_user_profile === 'ROOT' || sess_user_profile === 'Owner';

        if (isPrivileged) {
            applyWithoutTaxes();

        } else {
            // Fetch enterprise data lazily — only needed for password prompt
            const entInfo = await jsGetEnterpriseData();

            const result = await swalInit.fire({
                title: translate.discount_password,
                input: 'password',
                inputPlaceholder: '**********',
                showCancelButton: true,
                inputAttributes: { autocapitalize: 'off', autocorrect: 'off', autocomplete: 'off' },
                allowOutsideClick: false,
                allowEscapeKey: false,
                stopKeydownPropagation: false,
                preConfirm(value) {
                    if (!value) {
                        swalInit.showValidationMessage(translate.you_must_enter_the_password);
                        return false;
                    }
                    if (value !== entInfo.ent_discount_password) {
                        swalInit.showValidationMessage(translate.incorrect_password_please_try_again);
                        return false;
                    }
                    return value;
                }
            });

            if (result.isConfirmed) {
                applyWithoutTaxes();

                // Regenerate password immediately after single use
                $.post('ajax/enterprises.ajax.php?op=ajaxGenerateNewDiscountPassword',
                    { entId: entInfo.ent_id, csrf_token });

            } else {
                // User cancelled — restore the previous sale type selection
                js_SelectSaleType(pos_info.pos_id);
            }
        }

        // ── Restaurant / Nightclub sale types ─────────────────────────────────────
    } else if (isRestaurantOrNightclub) {

        // Apply legal tipping if configured
        if (Number(pos_info.pos_legal_tipping) > 0) {
            $('#sale_tax_law_percent, #pos_legal_tipping').val(saleTaxTippingPercent);
            $('.spanLawPercent').text(`(${saleTaxTippingPercent}%)`);
        }

        const deliveryTypes = ['Take Away', 'Pedidos Ya', 'Uber Eats', 'Didi Food'];

        if (deliveryTypes.includes(sale_type)) {
            applyTaxVisible(saleTaxPercent);
            $('.divTableSelect, .divLegalTipping').hide();
            $('#sale_tax_law_percent, #sale_tax_law_value').val(0);

        } else if (sale_type === 'Local') {
            applyTaxVisible(saleTaxPercent);
            $('#sale_tax_law_percent').val(saleTaxTippingPercent);
            $('.divTableSelect, .divLegalTipping').show();
        }

        // ── All other business categories ─────────────────────────────────────────
    } else {

        $('#pos_legal_tipping, #sale_tax_law_percent, #sale_tax_law_value').val(0);
        $('.divTableSelect, .divLegalTipping').hide();
        $('.spanLawPercent').text('(0%)');

        if (sale_type === 'Local') {
            applyTaxVisible(saleTaxPercent);
        }
    }

    // ── Recalculate totals — awaited swal above means this always runs last ───
    showAmount();
}

/*================================================
FUNCTION TO SHOW ALL TABLES LIST
=================================================*/
async function js_selectListTable(table_id = "") {
    try {
        const url = `ajax/tables.ajax.php?op=ajax_selectTable&table_id=${table_id}`;
        const response = await fetch(url);

        if (!response.ok) {
            throw new Error('Failed to get data from API');
        }

        const res = await response.json();

        $("#sale_table_id").html("");

        if (res.status == "success") {
            res.data.forEach(item => {
                $("#sale_table_id").append(`<option value='${item.table_id}'>${translate.table} ${item.table_id}</option>`);
            });
        }

    } catch (error) {
        console.log(error);
    }
}

// Add New Customer
function jsAddCustomer() {

    $(".span-modal-title").text(translate.add_customer);

    $(".btnSaveCustomer").show();
    $(".btnEditCustomer").hide();

    document.getElementById("frmAddEditCustomer").reset();

    $("#cus_id").val("");
    $("#cus_ent_id").val($("#sale_ent_id").val());
    $("#cus_pos_id").val($("#sale_pos_id").val());

    $('#customer-modal').modal('show');
}

async function jsEditCustomer() {

    $(".btnSaveCustomer").hide();
    $(".btnEditCustomer").show();

    $(".span-modal-title").text(translate.edit_customer);
    document.getElementById("frmAddEditCustomer").reset();

    let cus_id = $("#sale_cus_id").val();

    if (cus_id != "") {
        let cusInfo = await getCustomerDataById(cus_id);

        if (cusInfo.status == "success") {

            let data = cusInfo.data;

            $("#cus_id").val(data.cus_id);
            $("#cus_ent_id").val(data.cus_ent_id);
            $("#cus_pos_id").val(data.cus_pos_id);
            $("#cus_full_name").val(data.cus_full_name);
            $("#cus_phone").val(data.cus_phone);
            $("#cus_email").val(data.cus_email);
            $("#cus_address").val(data.cus_address);
            $("#cus_fiscal_number").val(data.cus_fiscal_number);

            $("#customer-modal").modal("show");
        }
    } else {
        fnSweetToast(translate.select_a_customer, "warning", 2000);
    }
}

$(".btnSaveCustomer").click(function () {
    if (validateCustomerForm("save") == false) {
        return false;
    } else {
        fnSaveUpdateCustomer();
    }
});


$(".btnEditCustomer").click(function () {
    if (validateCustomerForm("edit") == false) {
        return false;
    } else {
        fnSaveUpdateCustomer();
    }
});

/*=============================================
VALIDATE INPUT FORM
=============================================*/
function validateCustomerForm(type) {

    if (type == "edit") {

        var cus_id = $("#cus_id").val();

        if ((cus_id || '').trim() == "" && Number(cus_id <= 0)) {
            fnSweetToast(translate.no_data_was_selected_for_updating, "error", 3500);
            return false;
        }
    }

    var cus_full_name = $("#cus_full_name").val();
    var cus_email = $("#cus_email").val();

    if ((cus_full_name || '').trim() == "") {
        $("#cus_full_name").css("border", "1px solid red ");
        fnSweetToast(translate.you_must_enter_the_customer_name, "error", 3500);
        return false;
    } else {
        $("#cus_full_name").css("border", `1px solid ${borderColorValidated}`);
    }

    if ($(".intelli-shared-phone").val() != "") {
        if (!intlPhoneFormatShared.isValidNumber()) {
            fnSweetToast(translate.invalid_phone_number_please_try_again, "error", 3500);
            $(".intelli-shared-phone").css("border", "1px solid red");
            return false;
        } else {
            $(".intelli-shared-phone").css("border", `1px solid ${borderColorValidated}`);
        }
    }

    if (cus_email != "") {
        if (validateEmail(cus_email.trim()) == false) {
            $("#cus_email").css("border", "1px solid red ");
            fnSweetToast(translate.invalid_email_address, "error", 3500);
            return false;
        } else {
            $("#cus_email").css("border", `1px solid ${borderColorValidated}`);
        }
    }
}

/*=============================================
FUNCTION TO SAVE OR UPDATE DATA
=============================================*/
async function fnSaveUpdateCustomer() {

    const formPostData = new FormData($("#frmAddEditCustomer")[0]);
    const apiUrl = 'ajax/customers.ajax.php?op=ajaxSaveUpdate';

    try {
        const response = await fetch(apiUrl, {
            method: 'POST',
            body: formPostData,
        });

        const data = await response.json();
        // console.log(data);

        if (data.status == "success") {

            let cus_id = $("#cus_id").val();
            let cus_ent_id = $("#cus_ent_id").val();

            fnSweetAlert(data.message, "", data.status, 1500);
            $("#customer-modal").modal("hide");

            if (Number(cus_id) >= 1) {
                fnSelectCustomersList(cus_ent_id, cus_id);
            } else {
                fnSelectCustomersList();
            }

            document.getElementById("frmAddEditCustomer").reset();

        } else {
            console.log(data);
            swalInit.fire(translate.data_could_not_be_saved, "", data.status).then(function (result) {
                $("#customer-modal").modal("hide");
                document.getElementById("frmAddEditCustomer").reset();
            });
        }

    } catch (error) {
        console.error('Error:', error);
        swalInit.fire(translate.data_could_not_be_saved, "", "error").then(function (result) {
            $("#customer-modal").modal("hide");
            document.getElementById("frmAddEditCustomer").reset();
        });
    }
}


$(document).on("change", "#sale_cost_delivery", function () {

    if ($(this).val() === '' || isNaN($(this).val()) || Number($(this).val()) < 0) {
        $(this).val(0);
    }

    showAmount();
});


// ── Debounce helper — prevents double-fire on rapid barcode scanner input ─────
let _searchDebounceTimer = null;

$(document).on('keydown', '#inputProductSearch', async function (e) {
    if (e.which !== 13) return;

    e.preventDefault();

    const $input = $(this);
    const productNameOrBarcode = $input.val().trim();
    const sale_pos_id = $('#sale_pos_id').val();

    // ── Guard: input must not be empty ────────────────────────────────────────
    if (!productNameOrBarcode) {
        $input.css('border', '1px solid red');
        fnSweetToast(translate.scan_or_type_the_product_name, 'warning', 1500);
        return false;
    }

    $input.css('border', `1px solid ${borderColorValidated}`);

    // ── Guard: only allow alphanumeric + space + dash + underscore ────────────
    // Covers: barcodes, product names with spaces/dashes/underscores
    if (/[^a-zA-Z0-9_\s-]/.test(productNameOrBarcode)) {
        fnSweetToast(translate.please_enter_only_alphanumeric_characters, 'warning', 2500);
        return false;
    }

    // ── Guard: sale must not be cancelled ─────────────────────────────────────
    if ($('#sale_status').val() === 'Disabled') {
        fnSweetToast(translate.this_sale_has_been_canceled, 'error');
        return false;
    }

    // ── Detect input type:
    //    Barcode scanners fire with no spaces and typically ≤ 20 chars.
    //    Typed product names contain spaces, dashes, or underscores.
    const looksLikeBarcode = !/[\s_-]/.test(productNameOrBarcode);

    $input.val('').focus();

    // ── Debounce: barcode scanners can fire Enter twice on some devices ────────
    clearTimeout(_searchDebounceTimer);
    _searchDebounceTimer = setTimeout(async () => {

        if (looksLikeBarcode) {
            // ── Path 1: barcode lookup ────────────────────────────────────────
            try {
                const response = await fetch('ajax/products.ajax.php?op=ajax_addProductWithBarCode', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    body: new URLSearchParams({
                        pro_code: productNameOrBarcode,
                        sale_pos_id,
                        csrf_token,
                    }),
                });

                if (!response.ok) {
                    throw new Error(`HTTP error — status: ${response.status}`);
                }

                const data = await response.json();

                if (data.status === 'success') {
                    jsAddProductToCart(data);

                } else if (data.status === 'warning') {
                    // Barcode not found — fall through to product name search
                    const sale_ent_id = $('#sale_ent_id').val();
                    await jsShowProductList(sale_ent_id, sale_pos_id, productNameOrBarcode);

                } else {
                    fnSweetToast(data.message || translate.code_not_found_or_invalid, 'warning');
                }

            } catch (error) {
                console.error('inputProductSearch barcode error:', error);
                fnSweetToast(translate.data_could_not_be_loaded_please_contact_the_system_vendor_for_technical_assistance, 'error');
            }

        } else {
            // ── Path 2: product name search (has spaces / dashes / underscores) ─
            const sale_ent_id = $('#sale_ent_id').val();
            await jsShowProductList(sale_ent_id, sale_pos_id, productNameOrBarcode);
        }

    }, 80); // 80ms debounce — absorbs duplicate Enter from scanner hardware
});


let productSearchTimeId = null;

$(document).on('keyup', '#inputProductSearch', function () {

    const sale_ent_id = $('#sale_ent_id').val();
    const sale_pos_id = $('#sale_pos_id').val();
    const productNameOrBarcode = $('#inputProductSearch').val().trim();

    // Clear any pending search
    clearTimeout(productSearchTimeId);

    productSearchTimeId = setTimeout(() => {

        // Allow alphanumeric + space + dash + underscore (same as keydown handler)
        if (/[^a-zA-Z0-9_\s-]/.test(productNameOrBarcode)) {
            fnSweetToast(translate.please_enter_only_alphanumeric_characters, 'warning', 2500);
            return false;
        }

        $('#inputProductSearch').css('border', `1px solid ${borderColorValidated}`);
        jsShowProductList(sale_ent_id, sale_pos_id, productNameOrBarcode, '');

    }, 300);
});


// ONCLICK GENERAR NUEVO CODIGO DE PEDIDO
$(document).on("click", ".btnShowNewProductOrder", function () {

    let sale_ent_id = $("#sale_ent_id");
    let sale_pos_id = $("#sale_pos_id");

    if (sale_pos_id.val().trim() === "") {
        sale_pos_id.focus();
        sale_pos_id.next(".select2").css("border", "1px solid red");
        swalInit.fire(translate.please_select_a_branch, "", "warning");
        return false;
    } else {
        sale_pos_id.next(".select2").css("border", "none");
    }

    $("#inputProductSearch").prop('disabled', false);
    // $(".btnSearchProduct").prop('disabled', false);
    $("#inputProductSearch").val("");
    // $("#inputProductSearch").focus();

    $.ajax({
        url: "ajax/sales.ajax.php?op=ajax_newOrderCode",
        success: function (response) {
            $("#txt_ord_det_code").val(response);
        },
    });

    jsShowProductList(sale_ent_id.val(), sale_pos_id.val(), "", 18);
    $(".btnReloadNewOrder").removeClass("hide");

});

async function getProductsListToSale(props) {
    try {

        const url = `ajax/products.ajax.php?op=ajaxShowProductListToSale&ent_id=${props.ent_id}&pos_id=${props.pos_id}&productNameOrBarcode=${props.productNameOrBarcode}&PosProductListLimit=${props.PosProductListLimit}`;
        const response = await fetch(url);

        if (!response.ok) {
            throw new Error('Failed to get data from API');
        }

        const data = await response.json();
        return data;

    } catch (error) {
        console.log(error);
        $(".posProductListContainer, .posProductLoadingStatus").show();
        $(".posProductLoadingStatus").html(`${translate.no_products_found}`);

        $(".btnNewProductOrder").prop("disabled", false);
        $(".btnNewProductOrder").html(`<i class="ph-circles-four me-2"></i> ${translate.show_products}`);
        $(".btnNewProductOrder").addClass("btnShowNewProductOrder");

        // $("#inputProductSearch").focus();
        return false;
    }
}

/*=============================================
SHOW PRODUCTS LIST
=============================================*/
async function jsShowProductList(sale_ent_id, sale_pos_id, productNameOrBarcode = '', PosProductListLimit = '') {

    // ── Helper: reset the "load more" button to its default ready state ───────
    function resetLoadMoreButton() {
        $('.btnLoadMoreProducts')
            .prop('disabled', false)
            .css('cursor', 'pointer')
            .html(`<i class="ph-arrows-clockwise me-1"></i> ${translate.show_more_products}`);
    }

    // ── Helper: reset the "new order" button to its default ready state ───────
    function resetNewOrderButton() {
        $('.btnNewProductOrder')
            .prop('disabled', false)
            .html(`<i class="ph-circles-four me-2"></i> ${translate.show_products}`)
            .addClass('btnShowNewProductOrder');
    }

    // ── Helper: resolve stock indicator colour class ───────────────────────────
    function stockColourClass(stock) {
        const n = Number(stock);
        if (n <= 10) return 'bg-danger text-danger';
        if (n <= 20) return 'bg-warning text-warning';
        return 'bg-success text-success';
    }

    // ── Lock UI while loading ─────────────────────────────────────────────────
    $('.posProductListContainer').show();
    $('.posProductLoadingStatus').html(translate.loading_icon_text);

    $('.btnNewProductOrder')
        .prop('disabled', true)
        .html(translate.loading_icon_text);

    $('.btnLoadMoreProducts')
        .prop('disabled', true)
        .css('cursor', 'not-allowed')
        .html(translate.loading_icon_text);

    const props = {
        ent_id: sale_ent_id,
        pos_id: sale_pos_id,
        productNameOrBarcode,
        PosProductListLimit,
    };

    const pos_info = JSON.parse(localStorage.getItem('pos_info'));

    let productsHtml = "";
    $(".product-grid-container").html("");

    try {
        const res = await getProductsListToSale(props);

        if (res.status === 'success') {

            // ── Restore chrome ────────────────────────────────────────────────
            $('.btnNewProductOrder')
                .prop('disabled', true)
                .html(`<i class="ph-circles-four me-2"></i> ${translate.show_products}`)
                .removeClass('btnShowNewProductOrder')
                .hide();

            $('.posProductLoadingStatus').hide();
            $('.product-grid-container').show();
            $('.btnLoadMoreProducts').show();
            resetLoadMoreButton();

            // ── Build product cards ───────────────────────────────────────────
            if (res.data.length > 0) {

                productsHtml = res.data.map(item => {

                    const rawPrice = pos_info.pos_festive_mode === 'On'
                        ? item.pro_price_party
                        : item.pro_price;

                    const pro_price = showCurrencyFormat(
                        pos_info.pos_currency,
                        pos_info.pos_country_code,
                        rawPrice
                    );

                    const pro_image = `
                        <img src="${item.pro_image || 'assets/images/no-image.png'}"
                             alt="Product"
                             class="rounded-full object-cover w-[100px] h-[100px]"
                             onerror="this.onerror=null;this.src='assets/images/no-image.png';">`;

                    return `
                        <div class="product-card rounded-lg cursor-pointer transition w-[140px] text-center"
                             onclick='jsAddProductToCart(${JSON.stringify(item)})'>
                            <div class="stock-info top-left bg-opacity-10 ${stockColourClass(item.pro_current_stock)}">
                                ${item.pro_current_stock}
                            </div>
                            <div class="aspect-w-1 aspect-h-1 flex justify-center mt-2">
                                ${pro_image}
                            </div>
                            <div class="mt-2">
                                <p class="text-sm">${item.pro_description}</p>
                                <p class="text-blue-400 text-[13px] font-semibold">${pro_price}</p>
                            </div>
                        </div>`;

                }).join('');

                $('.product-grid-container').html(productsHtml);

            } else {
                $('.product-grid-container').html(`<div class="text-center">${translate.no_results_found}</div>`);
            }

        } else if (res.status === 'warning') {

            $('.product-grid-container, .posProductListContainer, .posProductLoadingStatus').show();
            $('.posProductLoadingStatus').html(translate.no_products_found);
            $('.btnLoadMoreProducts').hide();
            resetLoadMoreButton();
            resetNewOrderButton();

        } else {

            await swalInit.fire(
                translate.data_could_not_be_loaded_please_contact_the_system_vendor_for_technical_assistance,
                '',
                'error'
            );

            $('.posProductListContainer, .posProductLoadingStatus').show();
            $('.posProductLoadingStatus').html(translate.no_products_found);
            resetLoadMoreButton();
            resetNewOrderButton();
        }

    } catch (error) {
        console.error('jsShowProductList error:', error);
        await swalInit.fire(
            translate.data_could_not_be_loaded_please_contact_the_system_vendor_for_technical_assistance,
            '',
            'error'
        );
        resetLoadMoreButton();
        resetNewOrderButton();
    }
}

// $(document).on("click", ".btnSearchProduct", function () {

//     var sale_ent_id = $("#sale_ent_id").val();
//     var sale_pos_id = $("#sale_pos_id").val();
//     var productNameOrBarcode = $("#inputProductSearch").val();

//     if (productNameOrBarcode == "" || productNameOrBarcode.trim() == "") {
//         $("#inputProductSearch").focus();
//         $("#inputProductSearch").css("border", "1px solid red");
//         fnSweetToast(translate.scan_or_type_the_product_name, "warning", 1500);
//         return false;
//     } else {
//         if (/[^a-zA-Z0-9]/.test(productNameOrBarcode)) {
//             fnSweetToast(translate.please_enter_only_alphanumeric_characters, "warning", 2500);
//             return false;
//         } else {
//             // Valid input: contains only alphanumeric characters
//             jsShowProductList(sale_ent_id, sale_pos_id, productNameOrBarcode, "");
//             $("#inputProductSearch").css("border", `1px solid ${borderColorValidated}`);
//         }
//     }
// });

function refreshProductListToShowRealStock() {
    var sale_ent_id = $("#sale_ent_id").val();
    var sale_pos_id = $("#sale_pos_id").val();
    jsShowProductList(sale_ent_id, sale_pos_id, "", 18);
}

$(document).on("click", ".btnLoadMoreProducts", function () {
    $("#inputProductSearch").val("");
    var sale_ent_id = $("#sale_ent_id").val();
    var sale_pos_id = $("#sale_pos_id").val();
    var getLimit = localStorage.getItem("PosProductListLimit");
    var newlimitValue = Number(getLimit) + 18;
    localStorage.setItem("PosProductListLimit", newlimitValue);
    jsShowProductList(sale_ent_id, sale_pos_id, "", newlimitValue);

});

const currentProductStock = async function (pro_id) {
    try {

        const url = `ajax/products.ajax.php?op=ajaxGetCurrentProductStockById&pro_id=${pro_id}`;
        const response = await fetch(url);

        if (!response.ok) {
            throw new Error('Failed to get data from API');
        }

        const res = await response.json();

        if (res.status == "success") {
            pro_current_stock = res.data.pro_current_stock;
            return pro_current_stock;
        } else {
            return false;
        }


    } catch (error) {
        console.log(error);
        return false;
    }
}

function buildQtyControls(mode, item, ord_det_code, pos_info) {

    const id = `product_${item.pro_id}${ord_det_code}`;
    const qty = item.sale_det_pro_qty ?? 1;
    const stock = item.current_stock ?? '';

    switch (mode) {

        // New order — fully editable stepper
        case 'new':
            return `
                <div class="input-group productQty">
                    <button type="button" class="btn btn-light btn-icon btnMinus">
                        <i class="ph-minus ph-sm"></i>
                    </button>
                    <input  type="number"
                            min="1"
                            step="1.00"
                            class="form-control form-control-number text-center sale_det_pro_qty"
                            name="sale_det_pro_qty[]"
                            id="${id}"
                            data-stock="${stock}"
                            value="${qty}">
                    <button type="button" class="btn btn-light btn-icon btnPlus">
                        <i class="ph-plus ph-sm"></i>
                    </button>
                </div>`;

        case 'edit-no-payment':
            return `
                <div class="input-group productQty">
                    <button type="button" class="btn btn-light btn-icon btnMinus">
                        <i class="ph-minus ph-sm"></i>
                    </button>

                    <input  type="hidden"
                            readonly
                            min="1"
                            step="1.00"
                            class="form-control form-control-number text-center sale_det_pro_qty"
                            name="sale_det_pro_qty[]"
                            id="${id}"
                            data-stock="${stock}"
                            data-committed="${qty}"
                            value="${qty}">
                    
                    <input  type="number"
                            readonly
                            class="form-control form-control-number text-center sale_det_pro_quantity"
                            value="${qty}">
                            
                    <button type="button" class="btn btn-light btn-icon btnPlus">
                        <i class="ph-plus ph-sm"></i>
                    </button>
                </div>`;

        // Edit WITH payment — display only, no quantity changes allowed
        case 'edit-paid':
            return `
                <div class="input-group productQty" data-mode="edit-paid">
                    <span>${qty} x ${showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, item.sale_det_pro_price)}</span>
                    <input  type="hidden"
                            class="sale_det_pro_qty"
                            name="sale_det_pro_qty[]"
                            id="${id}"
                            data-stock="${stock}"
                            value="${qty}">
                </div>`;
    }
}

/*=============================================
ADD NEW PRODUCT ROW
=============================================*/
async function jsAddProductToCart(data = "") {

    if (data == "") return false;

    $("#productSearch").focus();

    if (!(await jsCheckActiveSale(translate.cannot_add_more_products))) {
        return false;
    }

    // Get object from localStorage
    let pos_info = JSON.parse(localStorage.getItem("pos_info"));

    let currentStock = await currentProductStock(data.pro_id);
    if (!currentStock) return false;

    /*=================================================
    Do not allow to add more than current stock
    ==================================================*/
    if (currentStock != 'FULL' && Number(currentStock) <= 0) {
        fnSweetToast(translate.not_enough_stock_available, "error", 1500);
        return false;
    }

    let ord_det_code = $("#txt_ord_det_code").val();
    let product = document.getElementById(`product_${data.pro_id}${ord_det_code}`);

    if (product) {

        const currentQty = parseFloat(product.value) + 1;

        if (Number(currentQty) > currentStock) {
            fnSweetToast(`${translate.there_are_only} ${currentStock} ${translate.units_available}`, "warning", 2500);
            $("#inputProductSearch").focus();
            return false;
        } else {
            product.value = Number(currentQty).toFixed(2);
            fnSweetToast(translate.quantity_increased, "success", 800);
            $("#inputProductSearch").focus();
        }

    } else {

        let pro_price = data.pro_price;
        if (pos_info.pos_festive_mode == "On") pro_price = data.pro_price_party;

        let saleDetProPrice = `<div>
            <input type="hidden" class="sale_det_pro_price" name="sale_det_pro_price[]" value="${pro_price}"/>
            ${showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, pro_price)}</div>`;

        if (pro_price == 0) saleDetProPrice = `<div class="col-4">
            <input type="text" class="form-control form-control-lg sale_det_pro_price" name="sale_det_pro_price[]" step="0.01" value="${pro_price}" />
            </div>`;

        let pro_image = `<img src="${data.pro_image || 'assets/images/no-image.png'}" class="w-40px h-40px rounded-pill mt-1" alt="product-image" onerror="this.onerror=null;this.src='assets/images/no-image.png';" />`;

        let productNameFormated = data.pro_description.toLowerCase().replace(/\b\w/g, char => char.toUpperCase());

        // 1 — New order — fully editable stepper
        $(".products-cart-list").prepend(`
            
            <div class="product-item" data-pro-id="${data.pro_id}" data-mode="new">

                <input type="hidden" name="sale_det_ord_det_code[]"  value="${ord_det_code}">
                <input type="hidden" name="sale_det_pro_id[]"   class="sale_det_pro_id"   value="${data.pro_id}">

                ${pro_image}

                <div class="product-details">
                    <span class="product-cart-name mt-1">${productNameFormated}</span>
                    <div class="quantity-controls">
                        ${buildQtyControls('new', data, ord_det_code, pos_info)}
                        ${saleDetProPrice}
                    </div>
                </div>

            </div>
        `);

        fnSweetToast(translate.product_added, "success", 800);

        $("#inputProductSearch").focus();
    }

    showAmount();
}


// DECREASE PRODUCT QUANTITY
$(document).on("click", ".btnMinus", async function () {

    const thisMinusBtn = $(this);
    const inputSaleQty = thisMinusBtn.closest('.productQty').find('.sale_det_pro_qty');
    const inputSaleQtyAfterSaved = thisMinusBtn.closest('.productQty').find('.sale_det_pro_quantity');
    const productItem = thisMinusBtn.closest('.product-item');

    const currentSaleQty = Number(inputSaleQty.val()) || 1;
    const newQty = currentSaleQty - 1;
    const alreadyCommitted = Number(inputSaleQty.data('committed') || 0);

    // ── Shared helpers ───────────────────────────────────────────────────────

    // Applies the decrement or asks for removal confirmation when qty hits 0
    function applyDecrement() {
        if (newQty <= 0) {
            swalInit.fire({
                title: translate.are_you_sure,
                text: translate.Confirm_that_you_want_to_remove_this_product,
                icon: 'question',
                showCancelButton: true,
                confirmButtonText: translate.yes,
                cancelButtonText: translate.no,
                buttonsStyling: false,
                customClass: {
                    confirmButton: 'btn btn-success',
                    cancelButton: 'btn btn-danger'
                }
            }).then(function (result) {
                if (result.value) {
                    productItem.remove();
                } else {
                    inputSaleQty.val((1).toFixed(2));
                    inputSaleQtyAfterSaved.val((1).toFixed(2));
                }
                showAmount();
            });
            return;
        }

        inputSaleQty.val(newQty.toFixed(2));
        inputSaleQtyAfterSaved.val(newQty.toFixed(2));
        showAmount();
    }

    // Prompts for the cancellation password, regenerates it on success,
    // then runs applyDecrement() if confirmed
    async function promptCancelPassword() {
        const entInfo = await jsGetEnterpriseData();

        swalInit.fire({
            title: translate.cancellation_code,
            input: 'password',
            inputPlaceholder: '*****',
            showCancelButton: true,
            inputAttributes: { autocapitalize: 'off', autocorrect: 'off' },
            allowOutsideClick: false,
            allowEscapeKey: false,
            stopKeydownPropagation: false,
            preConfirm(value) {
                if (!value) {
                    swalInit.showValidationMessage(translate.you_must_enter_the_password);
                    return false;
                }
                if (value !== entInfo.ent_cancel_password) {
                    swalInit.showValidationMessage(translate.incorrect_password_please_try_again);
                    return false;
                }
                return value;
            }
        }).then(result => {
            if (!result.isConfirmed) return;

            // Regenerate cancel password immediately after use
            $.post('ajax/enterprises.ajax.php?op=ajaxGenerateNewCancelPassword',
                { entId: sess_ent_id, csrf_token });

            applyDecrement();
        });
    }

    // ── Main logic ───────────────────────────────────────────────────────────

    // Committed rows (edit mode) require authorisation for non-privileged users
    const needsPassword = alreadyCommitted > 0
        && sess_user_profile !== 'ROOT'
        && sess_user_profile !== 'Owner';

    if (needsPassword) {
        await promptCancelPassword();
    } else {
        applyDecrement();
    }
});


$(document).on("change", ".sale_det_pro_price", function () {
    showAmount();
});


$(document).on("keydown", ".sale_det_pro_qty", function (e) {
    if (e.which === 13) {
        e.preventDefault(); // Prevent the form from submitting
    }
});

// CHANGE PRODUCT QUANTITY
$(document).on('change', '.sale_det_pro_qty', async function () {

    const thisInputQty = $(this);
    const productItem = thisInputQty.closest('.product-item');
    const inputSaleQty = thisInputQty.closest('.productQty').find('.sale_det_pro_qty');
    const proId = productItem.find('.sale_det_pro_id').val();

    const newQty = Number(thisInputQty.val());

    // ── Guard: NaN or negative — treat as removal attempt ────────────────────
    const safeQty = isNaN(newQty) ? 1 : newQty;

    // Units already committed to DB for this sale row (edit mode only)
    const alreadyCommitted = Number(inputSaleQty.data('committed') || 0);

    // ── Fetch live stock ──────────────────────────────────────────────────────
    const currentStock = await currentProductStock(proId);

    // ── Stock check ───────────────────────────────────────────────────────────
    if (currentStock !== 'FULL') {
        const effectiveStock = Number(currentStock) + alreadyCommitted;

        if (safeQty > effectiveStock) {

            // Revert to effective stock ceiling — do not let the value stay invalid
            inputSaleQty.val(effectiveStock.toFixed(2));

            fnSweetToast(
                `${translate.there_are_only} ${effectiveStock} ${translate.units_available}`,
                'warning',
                2500
            );

            refreshProductListToShowRealStock();

            showAmount();
            return;
        }
    }

    // ── Removal confirmation when qty hits 0 or below ─────────────────────────
    if (safeQty <= 0) {
        const result = await swalInit.fire({
            title: translate.are_you_sure,
            text: translate.Confirm_that_you_want_to_remove_this_product,
            icon: 'question',
            showCancelButton: true,
            confirmButtonText: translate.yes,
            cancelButtonText: translate.no,
            buttonsStyling: false,
            customClass: {
                confirmButton: 'btn btn-success',
                cancelButton: 'btn btn-danger',
            },
        });

        if (result.value) {
            productItem.remove();
        } else {
            // Restore to minimum valid qty
            inputSaleQty.val((1).toFixed(2));
        }

        showAmount();
        return;
    }

    showAmount();
});


// INCREASE PRODUCT QUANTITY
$(document).on("click", ".btnPlus", async function () {

    const thisPlusBtn = $(this);
    const productItem = thisPlusBtn.closest('.product-item');
    const productId = productItem.find('.sale_det_pro_id').val();
    const inputSaleQty = thisPlusBtn.closest('.productQty').find('.sale_det_pro_qty');
    const inputSaleQtyAfterSaved = thisPlusBtn.closest('.productQty').find('.sale_det_pro_quantity');

    const currentSaleQty = Number(inputSaleQty.val()) || 1; // cart qty before increment
    const newQty = currentSaleQty + 1; // what we want to set

    // Units already saved in DB for this sale (edit-no-payment only).
    // New orders have nothing committed yet → defaults to 0.
    const alreadyCommitted = Number(inputSaleQty.data('committed') || 0);

    // Fetch live stock AFTER reading all local values (async)
    const currentStock = await currentProductStock(productId);

    // Effective stock = DB free units + units this sale already holds in DB.
    // getProductStockById() counts this sale's rows as consumed, so we add
    // them back to get the true ceiling for this cart.
    // 'FULL' = Service product, no limit → use Infinity so checks always pass.
    const effectiveStock = currentStock === 'FULL'
        ? Infinity
        : Number(currentStock) + alreadyCommitted;

    //  If there are units already committed, check if new qty exceeds them and don't allow it
    if (alreadyCommitted > 0) {
        if (currentStock !== 'FULL' && newQty > alreadyCommitted) {

            await swalInit.fire({
                title: translate.to_increase_the_quantity_please_add_the_product_again_with_the_desired_quantity,
                icon: "warning",
            }).then(function (result) {
                refreshProductListToShowRealStock();
            });


            return;
        }
    }

    // If there are no units already committed, check if new qty exceeds stock
    if (currentStock !== 'FULL' && newQty > effectiveStock) {

        // Revert to effective stock ceiling — do not let the value stay invalid
        inputSaleQty.val(effectiveStock.toFixed(2));

        fnSweetToast(
            `${translate.there_are_only} ${effectiveStock} ${translate.units_available}`,
            "warning",
            2500
        );

        refreshProductListToShowRealStock();

        return;
    }

    inputSaleQty.val(newQty.toFixed(2));
    inputSaleQtyAfterSaved.val(newQty.toFixed(2));
    showAmount();
});

// ── Updated showAmount — no discount validation inside ────────────────────────
async function showAmount() {

    const pos_info = JSON.parse(localStorage.getItem('pos_info'));

    // ── 1. Cart totals ────────────────────────────────────────────────────────
    const qtyInputs = [...document.getElementsByName('sale_det_pro_qty[]')];
    const priceInputs = [...document.getElementsByName('sale_det_pro_price[]')];

    const totalQuantity = qtyInputs.reduce((sum, el) => sum + Number(el.value), 0);
    const subTotalSale = qtyInputs.reduce((sum, el, i) =>
        sum + Number(el.value) * Number(priceInputs[i].value), 0);

    $('#orderSumQty').val(totalQuantity);

    // ── 2. Payment totals ─────────────────────────────────────────────────────
    const sumInputs = selector => [...$(selector)].reduce((sum, el) => sum + Number($(el).val()), 0);
    const totalPaid = sumInputs('.currentTotalPaid');
    const totalIncome = sumInputs('.currentTotalIncome');
    const totalPayDetChange = sumInputs('.currentPayDetChange');

    const txtCurrentDebtChange = $('#txtCurrentDebtChange');
    if (Number(txtCurrentDebtChange.val()) <= 0) {
        txtCurrentDebtChange.val(totalPayDetChange);
    }

    // ── 3. Read already-validated discount from DOM ───────────────────────────
    // Discount was validated and written by validateAndApplyDiscount() — read it directly
    const discountValue = Number($('#sale_discount_value').val() || 0);

    // ── 4. Tax & final totals ─────────────────────────────────────────────────
    const subTotalAfterDiscount = subTotalSale - discountValue;

    let sale_tax_percent = Number($('#sale_tax_percent').val());
    let sale_tax_law_percent = Number($('#sale_tax_law_percent').val());

    if (Number(transactionId) >= 1) {
        const sale_info = JSON.parse(localStorage.getItem('sale_info'));

        if (!sale_info) {
            location.reload();
            return;
        }

        sale_tax_percent = Number(sale_info.sale_tax_percent);
        sale_tax_law_percent = Number(sale_info.sale_tax_law_percent);
    }

    const saleTaxValue = sale_tax_percent > 0 ? roundedDecimal((sale_tax_percent / 100) * subTotalAfterDiscount, 2) : 0;
    const saleLegalTippingValue = sale_tax_law_percent > 0 ? roundedDecimal((sale_tax_law_percent / 100) * subTotalAfterDiscount, 2) : 0;
    const saleCostDelivery = roundedDecimal($('#sale_cost_delivery').val(), 2);
    const saleTotalFinal = roundedDecimal(subTotalAfterDiscount + saleTaxValue + saleLegalTippingValue + saleCostDelivery, 2);

    // ── 5. Render all display values ──────────────────────────────────────────
    const fmt = val => showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, val);

    $('.saleSubTotal').text(fmt(subTotalSale));
    $('.saleSubTotalFinal').text(fmt(subTotalAfterDiscount));
    $('.spanTaxValue').text(fmt(saleTaxValue));
    $('.spanLegalTippingValue').text(fmt(saleLegalTippingValue));
    $('.saleCostDelivery').text(fmt(saleCostDelivery));
    $('.saleTotalFinal').text(fmt(saleTotalFinal));
    $('#orderAmount').text(fmt(saleTotalFinal));
    $('#span_modal_final_total').text(fmt(saleTotalFinal));
    $('#spanModalTotalPaid').text(fmt(totalPaid));
    $('#spanModalTotalIncome').text(fmt(totalIncome));

    // ── 6. Write totals to hidden inputs ──────────────────────────────────────
    $('#sale_sub_total').val(subTotalSale);
    $('#sale_tax_value').val(saleTaxValue);
    $('#sale_tax_law_value').val(saleLegalTippingValue);
    $('#sale_amount_final').val(saleTotalFinal);

    // ── 7. Debt vs change row ─────────────────────────────────────────────────
    const valDebtChange = roundedDecimal(saleTotalFinal - totalIncome, 2);

    if (valDebtChange > 0) {
        $('#sale_debt').val(valDebtChange);
        $('.thDebtChangeRow').removeClass('bg-warning').addClass('bg-danger');
        $('#spanDebtChangeText').text(translate.debt);
        $('#spanDebtChangeValue').text(fmt(valDebtChange));
        $('#inp_paid_value').val('').prop('disabled', false).css('cursor', 'pointer').focus();
        $('.divGroupAddPayment').show();

    } else {
        $('#sale_debt').val(0.00);
        $('.thDebtChangeRow').removeClass('bg-danger').addClass('bg-warning');
        $('#spanDebtChangeText').text(translate.change);
        $('#spanDebtChangeValue').text(fmt(txtCurrentDebtChange.val()));
        $('#inp_paid_value').val(0.00).prop('disabled', true).css('cursor', 'not-allowed');
        $('.divGroupAddPayment').hide();
    }

    jsRemoveOptionsIfUserNotBelongToTheSaleEnterprise();
}


/*=============================================
SHOW SALES INFORMATIONS
=============================================*/
async function jsShowSaleInfo() {

    document.getElementById("frmSubmitOrder").reset();

    // Get object from localStorage
    let sale_info = JSON.parse(localStorage.getItem("sale_info"));

    $("#sale_id").val(sale_info.sale_id);
    $("#sale_ent_id").val(sale_info.sale_ent_id);

    let posResult = await selectBranchToSell(sale_info.sale_ent_id, sale_info.sale_pos_id);

    if (posResult) {

        // $("#sale_type").val(sale_info.sale_type).trigger('change');
        js_SelectSaleType(sale_info.sale_pos_id, sale_info.sale_type);
        fnSelectCustomersList(sale_info.sale_ent_id, sale_info.sale_cus_id);
        js_selectListFiscalReceipt(sale_info.sale_ent_id, sale_info.sale_ncf_type);
        js_selectListTable(sale_info.sale_table_id);

        $("#sale_id").val(sale_info.sale_id);
        $("#sale_ent_id").val(sale_info.sale_ent_id);
        $("#sale_sub_total").val(sale_info.sale_sub_total);
        $("#sale_tax_percent").val(sale_info.sale_tax_percent);
        $("#sale_tax_value").val(sale_info.sale_tax_value);
        $("#sale_tax_law_percent").val(sale_info.sale_tax_law_percent);
        $("#sale_tax_law_value").val(sale_info.sale_tax_law_value);
        $("#sale_discount_percent").val(sale_info.sale_discount_percent);
        $("#sale_discount_value").val(sale_info.sale_discount_value);
        $("#sale_debt").val(sale_info.sale_debt);
        $("#sale_cost_delivery").val(sale_info.sale_cost_delivery);
        $("#sale_amount_final").val(sale_info.sale_amount_final);
        $("#prevDiscountPercent").val(sale_info.sale_discount_percent);
        $("#prevDiscountValue").val(sale_info.sale_discount_value);
        $("#prevCurrentDebt").val(sale_info.sale_debt);
        $("#discountFormat").val("Amount");
        $("#sale_discount_enter_percent_value").val(sale_info.sale_discount_value);

        $(".spanDiscountPercent").text(`(-${sale_info.sale_discount_percent}%)`);
        $('.saleDiscount').text(`${sale_info.sale_discount_value}`);
        $(".spanTaxPercent").text(`(${sale_info.sale_tax_percent}%)`);
        $(".spanLawPercent").text(`(${sale_info.sale_tax_law_percent}%)`);
        $(".saleCostDelivery").text(sale_info.sale_cost_delivery);

        $("#sale_status").val(sale_info.sale_status);

        js_showSaleDetails(sale_info.sale_id);
        js_showDetailsPayments(sale_info.sale_id);
    }

}


/*=============================================
SHOW SALES PRODUCTS DETAILS
=============================================*/
async function js_showSaleDetails(sale_id) {

    try {

        const url = `ajax/sales.ajax.php?op=ajax_showSaleDetails&sale_id=${sale_id}`;
        const response = await fetch(url);

        if (!response.ok) {
            throw new Error('Failed to get data from API');
        }

        const res = await response.json();
        const parsedData = JSON.parse(res.data);

        let productsHtml = "";
        $(".products-cart-list").html("");

        if (res.status === "success") {

            let pos_info = JSON.parse(localStorage.getItem("pos_info"));

            // Edit WITH payment — display only, no quantity changes allowed
            if (Number(res.hasPayment) >= 1) {

                parsedData.forEach(item => {

                    let pro_image = `<img src="${item.pro_image || 'assets/images/no-image.png'}" class="w-40px h-40px rounded-pill" alt="product-image" onerror="this.onerror=null;this.src='assets/images/no-image.png';" />`;

                    let productNameFormated = item.pro_description.toLowerCase().replace(/\b\w/g, char => char.toUpperCase());

                    productsHtml += `
                    <div class="product-item" data-pro-id="${item.pro_id}" data-mode="edit-paid">

                        <input type="hidden" name="sale_id_editing[]" value="${sale_id}">
                        <input type="hidden" name="sale_det_ord_det_code[]"  value="${item.sale_det_ord_det_code}">
                        <input type="hidden" name="sale_det_pro_id[]"   class="sale_det_pro_id"   value="${item.pro_id}">
                        <input type="hidden" name="sale_det_pro_price[]" class="sale_det_pro_price" value="${item.sale_det_pro_price}">

                        ${pro_image}

                        <div class="product-details">
                            <span class="product-cart-name mt-1">${productNameFormated}</span>
                            <div class="quantity-controls">
                                ${buildQtyControls('edit-paid', item, item.sale_det_ord_det_code, pos_info)}
                            </div>
                        </div>
                    </div>`
                });

                $(".products-cart-list").prepend(productsHtml);

            } else {

                // Edit, NO payment yet — still fully editable, same stepper as new
                parsedData.forEach(item => {

                    let topBorderDanger = item.pro_type === "Product" ? "border-top-danger" : "";

                    let pro_image = `<img src="${item.pro_image || 'assets/images/no-image.png'}" class="w-40px h-40px rounded-pill mt-1" alt="product-image" onerror="this.onerror=null;this.src='assets/images/no-image.png';" />`;

                    let productNameFormated = item.pro_description.toLowerCase().replace(/\b\w/g, char => char.toUpperCase());

                    productsHtml += `
                    <div class="product-item ${topBorderDanger}" data-pro-id="${item.pro_id}" data-mode="edit-no-payment">

                        <input type="hidden" name="sale_id_editing[]" value="${sale_id}">
                        <input type="hidden" name="sale_det_ord_det_code[]"  value="${item.sale_det_ord_det_code}">
                        <input type="hidden" name="sale_det_pro_id[]"   class="sale_det_pro_id"   value="${item.pro_id}">
                        <input type="hidden" name="sale_det_pro_price[]" class="sale_det_pro_price" value="${item.sale_det_pro_price}">

                        ${pro_image}

                        <div class="product-details">
                            <span class="product-cart-name mt-1">${productNameFormated}</span>
                            <div class="quantity-controls">
                                ${buildQtyControls('edit-no-payment', item, item.sale_det_ord_det_code, pos_info)}
                                <div>${showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, item.sale_det_pro_price)}</div>
                            </div>
                        </div>
                    </div>`
                });

                $(".products-cart-list").prepend(productsHtml);
            }

            showAmount();
        }

    } catch (error) {
        console.log(error);
    }
}

async function js_showDetailsPayments(sale_id) {
    try {

        const url = `ajax/payments.ajax.php?op=ajax_showPaymentsDetails&sale_id=${sale_id}`;
        const response = await fetch(url);

        if (!response.ok) {
            throw new Error('Failed to get data from API');
        }

        const res = await response.json();

        let paymentsHtml = "";

        if (res.status === "success") {

            let pos_info = JSON.parse(localStorage.getItem("pos_info"));

            res.data.forEach(item => {

                let cashBackRowStatus = "Yes";
                if (item.pay_det_payment_type == 'CASHBACK') cashBackRowStatus = "No";

                let cashierName = item.cashier_full_name ? formatName(item.cashier_full_name) : "--";

                paymentsHtml += `<tr class="text-center">
                    <td class="dataRow">
                    <span>${cashierName}</span>
                    <input type="hidden" name="pay_det_date[]" readonly value="${item.pay_det_date}">
                    <input type="hidden" name="pay_det_payment_type[]" readonly value="${item.pay_det_payment_type}">
                    <input type="hidden" class="currentTotalPaid " name="pay_det_value[]" value="${item.pay_det_value}">
                    <input type="hidden" class="currentTotalIncome" name="pay_det_income[]" readonly value="${item.pay_det_income}">
                    <input type="hidden" name="pay_det_created_by[]" value="${item.pay_det_created_by}">
                    <input type="hidden" name="pay_det_note[]" value="${item.pay_det_note}">
                    <input type="hidden" name="pay_det_previous_debt[]" value="${item.pay_det_previous_debt}">
                    <input type="hidden" class="currentPayDetChange" name="pay_det_change[]" value="${item.pay_det_change}"></input>
                    <input type="hidden" class="currentPayDetCashBack" cashbackatt="${cashBackRowStatus}" name="pay_det_cashback[]" value="${item.pay_det_cashback}">
                    <input type="hidden" name="pay_det_cashback_status[]" value="${item.pay_det_cashback_status}">
                    </td>
                    <td><span>${item.pay_det_date_formatted}</span></td>
                    <td><span>${item.pay_det_payment_type}</span></td>
                    <td><span>${showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, item.pay_det_value)}</span></td>
                    <td><span>${showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, item.pay_det_income)}</span></td>
                    <td><span>${showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, item.pay_det_change)}</span ></td >
                    <td><span>${item.pay_det_note}</span></td>
                    </tr>`
            });

            $(".payment_entry_details").prepend(paymentsHtml);

            showAmount();
        }

    } catch (error) {
        console.log(error);
    }
}


function jsRemoveOptionsIfUserNotBelongToTheSaleEnterprise() {

    var sale_ent_id = $("#sale_ent_id").val();

    if (Number(sess_ent_id) !== Number(sale_ent_id)) {

        $(".btnShowNewProductOrder, .btnSaveOrder, .btnDiscount, .divAddPayment, .btnConfirmPayment, .divGroupAddPayment").remove();
        $(".divGroupAddPayment").hide();
    }

}

async function validateToSaveOrder(option = "") {

    if (!(await jsCheckActiveSale())) {
        return false;
    }

    let sale_pos_id = $("#sale_pos_id");
    let sale_cus_id = $("#sale_cus_id");
    let sale_type = ($("#sale_type").val() || '').trim();
    let sale_table_id = ($("#sale_table_id").val() || '').trim();
    let sale_cost_delivery = ($("#sale_cost_delivery").val() || '').trim();
    let orderSumQty = ($("#orderSumQty").val() || '').trim();

    if ((sale_pos_id.val() || '').trim() === "") {
        sale_pos_id.next(".select2").css("border", "1px solid red");
        swalInit.fire(translate.please_select_a_branch, "", "warning");
        return false;
    } else {
        sale_pos_id.next(".select2").css("border", "none");
    }

    if ((sale_cus_id.val() || '').trim() === "") {
        sale_cus_id.next(".select2").css("border", "1px solid red");
        swalInit.fire(translate.select_a_customer, "", "warning");
        return false;
    } else {
        sale_cus_id.next(".select2").css("border", "none");
    }

    if (sale_type === "Local") {

        if (sale_table_id === '' || isNaN(sale_table_id) || Number(sale_table_id) <= 0) {
            swalInit.fire(translate.select_a_table, "warning", 1000);
            return false;
        }
    }

    if (sale_cost_delivery === '' || isNaN(sale_cost_delivery) || Number(sale_cost_delivery) < 0) {
        $("#sale_cost_delivery").val(0);
    }

    if (orderSumQty === '' || isNaN(orderSumQty) || Number(orderSumQty) <= 0) {
        swalInit.fire(translate.no_products_have_been_added, translate.please_add_a_product_to_continue, "error");
        return false;
    }
}

$(document).on("click", ".btnSaveOrder", async function () {

    // Await the result of validateToSaveOrder before continuing
    if (await validateToSaveOrder("save") === false) return false;

    fnSaveUpdate();

});


$(document).on('click', '.btnDiscount', async function () {

    // Bail out early if order is not in a valid state for discounting
    if (await validateToSaveOrder('discount') === false) return;

    // ── UI defaults ───────────────────────────────────────────────────────────
    $('.btnDiscPercent').removeClass('btn-warning').addClass('btn-light');
    $('.btnDiscAmount').removeClass('btn-light').addClass('btn-warning');
    $('#discountFormat').val('Amount');

    // ── Guard: sale is fully paid — no discount allowed ───────────────────────
    const currentDebt = Number($('#sale_debt').val());
    const totalPaid = [...$('.currentTotalPaid')]
        .reduce((sum, el) => sum + Number($(el).val()), 0);

    if (currentDebt <= 0 && totalPaid > 0) {

        await swalInit.fire(`${translate.no_discount_can_be_applied}. \n ${translate.payment_for_this_sale_has_been_completed}`,
            '',
            'warning'
        );

        return;
    }

    if (totalPaid > 0) {
        await swalInit.fire(
            translate.no_discount_can_be_applied_to_this_sale_because_payment_has_already_been_made,
            "",
            'warning'
        );
        return;
    }

    // ── Shared: open the discount modal cleanly ───────────────────────────────
    function openDiscountModal() {
        $('#myModalDiscount').modal('show');
        $('#sale_discount_enter_percent_value').val('').focus();
    }

    // ── ROOT / Owner: no password required ───────────────────────────────────
    if (sess_user_profile === 'ROOT' || sess_user_profile === 'Owner') {
        openDiscountModal();
        return;
    }

    // ── All other profiles: require discount password ─────────────────────────
    const entInfo = await jsGetEnterpriseData();

    const result = await swalInit.fire({
        title: translate.discount_password,
        input: 'password',
        inputPlaceholder: '**********',
        showCancelButton: true,
        inputAttributes: { autocapitalize: 'off', autocorrect: 'off' },
        allowOutsideClick: false,
        allowEscapeKey: false,
        stopKeydownPropagation: false,
        preConfirm(value) {
            if (!value) {
                swalInit.showValidationMessage(translate.you_must_enter_the_password);
                return false;
            }
            if (value !== entInfo.ent_discount_password) {
                swalInit.showValidationMessage(translate.incorrect_password_please_try_again);
                return false;
            }
            return value;
        }
    });

    if (!result.isConfirmed) return;

    openDiscountModal();

    // Regenerate discount password immediately after single use
    $.post('ajax/enterprises.ajax.php?op=ajaxGenerateNewDiscountPassword',
        { entId: entInfo.ent_id, csrf_token });
});

// ── Discount modal triggers ───────────────────────────────────────────────────
$(document).on('click', '.btnDiscAmount', function () {
    $('.btnDiscPercent').removeClass('btn-warning').addClass('btn-light');
    $(this).removeClass('btn-light').addClass('btn-warning');
    $('#sale_discount_enter_percent_value').focus();
    $('#discountFormat').val('Amount');
});

$(document).on('click', '.btnDiscPercent', function () {
    $('.btnDiscAmount').removeClass('btn-warning').addClass('btn-light');
    $(this).removeClass('btn-light').addClass('btn-warning');
    $('#sale_discount_enter_percent_value').focus();
    $('#discountFormat').val('Percentage');
});

// ── Confirm discount — Enter key ──────────────────────────────────────────────
$(document).on('keydown', '#sale_discount_enter_percent_value', async function (e) {
    if (e.which !== 13) return;
    const valid = await validateAndApplyDiscount();
    if (valid) {
        showAmount();
        $('#myModalDiscount').modal('hide');
    }
});

// ── Confirm discount — button click ──────────────────────────────────────────
$(document).on('click', '.btnConfirmDiscount', async function () {
    const valid = await validateAndApplyDiscount();
    if (valid) {
        showAmount();
        $('#myModalDiscount').modal('hide');
    }
});


// ── Standalone discount validator — called ONLY when user confirms a discount ─
async function validateAndApplyDiscount() {

    const pos_info = JSON.parse(localStorage.getItem('pos_info'));
    const fmt = val => showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, val);

    // Read live cart totals needed for validation
    const qtyInputs = [...document.getElementsByName('sale_det_pro_qty[]')];
    const priceInputs = [...document.getElementsByName('sale_det_pro_price[]')];
    const subTotalSale = qtyInputs.reduce((sum, el, i) =>
        sum + Number(el.value) * Number(priceInputs[i].value), 0);

    const sumInputs = selector => [...$(selector)].reduce((sum, el) => sum + Number($(el).val()), 0);
    const totalIncome = sumInputs('.currentTotalIncome');

    const prevDiscountPercent = Number($('#prevDiscountPercent').val() || 0);
    const prevDiscountValue = Number($('#prevDiscountValue').val() || 0);
    const prevCurrentDebt = Number($('#prevCurrentDebt').val() || 0);
    const discountFormat = $('#discountFormat').val();
    const discountInput = Number($('#sale_discount_enter_percent_value').val());

    let percentageValue = prevDiscountPercent;
    let discountValue = prevDiscountValue;

    const focusDiscountInput = () => $('#sale_discount_enter_percent_value').focus();

    const alertError = async msg => {
        await swalInit.fire(msg, '', 'error');
        focusDiscountInput();
    };

    const alertWarning = async (title, text) => {
        await swalInit.fire(title, text, 'warning');
        focusDiscountInput();
    };

    const resetToZero = () => {
        $('#sale_discount_enter_percent_value').val(0);
    };

    // ── Guard 1: sale already fully paid ──────────────────────────────────────
    if (totalIncome >= subTotalSale && discountInput > 0) {
        await alertError(translate.no_discount_can_be_applied_to_this_sale_because_payment_has_already_been_made);
        return false;

        // ── Guard 2: discount would reduce total below collected payments ─────────
    } else if (totalIncome > 0 && (subTotalSale - discountInput) < totalIncome && discountInput > 0) {
        await alertError(
            translate.the_discount_cannot_be_greater_than_the_debt_of_the_sale +
            ` ${fmt(subTotalSale - totalIncome)}`
        );
        return false;

        // ── Guard 3: negative discount ────────────────────────────────────────────
    } else if (discountInput < 0) {
        await alertError(translate.error_the_percentage_of_the_discount_cannot_be_less_than_0);
        return false;

        // ── Normal discount logic ─────────────────────────────────────────────────
    } else if (discountInput > 0) {

        if (discountFormat === 'Percentage') {

            if (discountInput > 100) {
                await alertError(translate.the_discount_amount_or_percentage_cannot_be_greater_than_or_equal_to_the_subtotal);
                return false;

            } else if (discountInput === 100
                && sess_user_profile !== 'ROOT'
                && sess_user_profile !== 'Owner') {
                await alertError(translate.the_discount_amount_or_percentage_cannot_be_greater_than_or_equal_to_the_subtotal);
                return false;

            } else if (discountInput === 100 && totalIncome > 0) {
                await alertError(translate.a_100_discount_cannot_be_applied_to_this_sale_because_payments_have_already_been_made);
                return false;

            } else {
                const computed = roundedDecimal((subTotalSale * discountInput) / 100, 2);

                if (prevCurrentDebt > 0 && computed > prevCurrentDebt && totalIncome > 0 && prevDiscountValue <= 0) {
                    await alertWarning(
                        translate.the_discount_cannot_be_greater_than_the_debt_of_the_sale,
                        `${translate.this_sale_only_has_a_debt_of}: ${fmt(prevCurrentDebt)}`
                    );
                    resetToZero();
                    return false;
                }

                percentageValue = discountInput;
                discountValue = computed;
            }

        } else {
            // Amount format
            if (discountInput > subTotalSale) {
                await alertError(translate.the_discount_amount_or_percentage_cannot_be_greater_than_or_equal_to_the_subtotal);
                return false;

            } else if (discountInput === subTotalSale && totalIncome > 0) {
                await alertError(translate.a_100_discount_cannot_be_applied_to_this_sale_because_payments_have_already_been_made);
                return false;

            } else {
                if (prevCurrentDebt > 0 && discountInput > prevCurrentDebt && totalIncome > 0) {
                    await alertWarning(
                        translate.the_discount_cannot_be_greater_than_the_debt_of_the_sale,
                        `${translate.this_sale_only_has_a_debt_of}: ${fmt(prevCurrentDebt)}`
                    );
                    resetToZero();
                    return false;
                }

                discountValue = discountInput;
                percentageValue = roundedDecimal((discountValue / subTotalSale) * 100, 2);
            }
        }
    }
    // discountInput === 0 → percentageValue / discountValue stay at previous values

    // ── Write validated discount to DOM ───────────────────────────────────────
    $('#sale_discount_percent').val(percentageValue);
    $('#sale_discount_value').val(discountValue);
    $('.spanDiscountPercent').text(`(-${percentageValue}%)`);
    $('.saleDiscount').text(fmt(discountValue));

    return true;
}


$(document).on("click", ".btnShowPayment", async function () {

    if (await validateToSaveOrder("show_payment") === false) return false;

    $("#myModalPayment").modal("show");
    $("#inp_paid_value").focus();
    showAmount();

});

function paiment_validation() {

    // var cbo_payment_type = $(".cbo_payment_type").val();
    // var pay_det_confirmation_number = $("#pay_det_confirmation_number").val();
    // var nameOnCard = $("#nameOnCard").val();

    // if (cbo_payment_type == "CREDIT CARD" || cbo_payment_type == "BANK DEPOSIT" || cbo_payment_type == "MONCASH" || cbo_payment_type == "ZELLE" || cbo_payment_type == "CASH APP" && (pay_det_confirmation_number || '').trim() === '') {
    //     fnSweetToast(translate.please_enter_the_payment_confirmation_number, "error")
    //     $("#pay_det_confirmation_number").css("border", "1px solid red");
    //     $("#pay_det_confirmation_number").focus();
    //     return false;
    // } else {
    //     $("#pay_det_confirmation_number").css("border", `1px solid ${borderColorValidated}`);
    // }

    var inp_paid_value = $("#inp_paid_value").val();

    if (inp_paid_value === '' || inp_paid_value <= 0) {
        fnSweetToast(translate.enter_the_amount_to_pay, "error")
        $("#inp_paid_value").css("border", "1px solid red");
        $("#inp_paid_value").focus();
        return false;
    } else {
        $("#inp_paid_value").css("border", `1px solid ${borderColorValidated}`);
    }

}


$("#inp_paid_value").keydown(async function (e) {
    if (e.which === 13) {
        e.preventDefault(); // Prevent the form from submitting
        if (await validateToSaveOrder("add_payment") === false || paiment_validation() == false) return false;

        js_addPaymentData();
    }
});


$("#pay_det_note").keydown(async function (e) {
    if (e.which === 13) {
        e.preventDefault(); // Prevent the form from submitting
        if (await validateToSaveOrder("add_payment") === false || paiment_validation() == false) return false;

        js_addPaymentData();
    }
});

/*=============================================
PAYMENT BUTTON FUNCTION TO ADD NEW PAYMENT ROW
=============================================*/
$(document).on("click", ".btnAddPayment", async function () {

    if (await validateToSaveOrder("add_payment") === false || paiment_validation() == false) return false;

    js_addPaymentData();
})

async function js_addPaymentData() {

    if (!(await jsCheckActiveSale(translate.cannot_add_more_payments))) {
        return false;
    }

    // Get object from localStorage
    let pos_info = JSON.parse(localStorage.getItem("pos_info"));

    $.get("ajax/sales.ajax.php?op=ajaxCurrentDateTime", function (response, status) {
        $("#txtCurrentDateTime").val(response);
    });

    let CurrentDateTime = $("#txtCurrentDateTime").val();

    let payment_type = $("#cbo_payment_type").val();
    let currentPaid = roundedDecimal($("#inp_paid_value").val(), 2);
    let pay_det_note = $("#pay_det_note").val();

    let pay_det_income = 0;
    let newTotalToPaid = 0;
    let pay_det_change = 0;
    let pay_det_previous_debt = $("#sale_debt").val();

    //GET TAXE PERCENT TO CALCULATE VAL TO PAID
    let totalToPaid = roundedDecimal($("#sale_amount_final").val(), 2);

    //GET TOTAL PAID
    let currentTotalIncome = $(".currentTotalIncome");
    let arraySumaQuantity = [];
    for (var i = 0; i < currentTotalIncome.length; i++) {
        arraySumaQuantity.push(Number($(currentTotalIncome[i]).val()));
    }

    // Providing an initial value of 0 if totalPaid is empty
    let previousPaid = roundedDecimal(arraySumaQuantity.reduce((previousValue, currentValue) => previousValue + currentValue, 0), 2);

    // console.log("totalToPaid: " + totalToPaid);
    // console.log("previousPaid: " + previousPaid);
    // console.log("currentPaid: " + currentPaid);

    newTotalToPaid = roundedDecimal(totalToPaid - previousPaid, 2);
    pay_det_income = roundedDecimal(currentPaid - newTotalToPaid, 2);

    if (pay_det_income >= 0) {
        pay_det_income = newTotalToPaid;
    } else {
        pay_det_income = currentPaid;
    }

    pay_det_change = roundedDecimal(currentPaid - pay_det_income, 2);

    // START CALCULATE NEW CASHBACK
    let totalCashBack = $("#totalCashBack").val();
    let currentCashBack = 0;
    let pos_cash_back_percentage = $("#pos_cash_back_percentage").val();
    let totalCustomerCashBack = $("#customerCashBack").val();
    let cashBackRowStatus = "Yes";
    let pay_det_cashback_status = "Pending";

    if (payment_type == "CASHBACK") {

        if (Number(totalCustomerCashBack) <= 0) {
            fnSweetToast(`${translate.you_do_not_have_available_cashback}`, "error", 2500);
            return;
        } else if (Number(totalCustomerCashBack) < Number(currentPaid)) {
            fnSweetToast(`${translate.you_do_not_have_enough_cashback_you_just_have}: ${totalCustomerCashBack} ${translate.available_cash_back}`, "info", 4500);
            return;
        }

        pay_det_change = 0;
        cashBackRowStatus = "No";
        pay_det_cashback_status = "Used";
        currentCashBack = pay_det_income;
        currentPaid = pay_det_income;

        let leftCashBack = roundedDecimal(Number(totalCustomerCashBack) - Number(pay_det_income), 2);
        $("#customerCashBack").val(leftCashBack);
        $("#span_available_cash_back").text(showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, leftCashBack));

    } else {

        currentCashBack = roundedDecimal((pay_det_income * pos_cash_back_percentage) / 100, 2);
        totalCashBack = roundedDecimal(Number(totalCashBack) + Number(currentCashBack), 2);
        $("#totalCashBack").val(roundedDecimal(totalCashBack, 2));
        $("#span_modal_new_cash_back").text(showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, totalCashBack));
    }

    $("#txtCurrentDebtChange").val(pay_det_change);
    // console.log(`totalCashBack = ${totalCashBack}`)
    // console.log(`leftCashBack = ${leftCashBack}`)
    // console.log(`pay_det_change = ${pay_det_change}`)
    // console.log(`currentCashBack = ${currentCashBack}`)

    $(".payment_entry_details tbody").prepend(`
        <tr class="text-center">
        <td class="dataRow">
        <button type="button" class="btn btn-sm btn-icon rounded-pill btn-danger removeRow_payment"><i class="mi-close" style="text-align: center;"></i></button>
        <input type="hidden" name="pay_det_date[]" readonly value="${CurrentDateTime}">
        <input type="hidden" name="pay_det_payment_type[]" readonly value="${payment_type}">
        <input type="hidden" class="currentTotalPaid " name="pay_det_value[]" value="${currentPaid}">
        <input type="hidden" class="currentTotalIncome" name="pay_det_income[]" readonly value="${pay_det_income}">
        <input type="hidden" name="pay_det_created_by[]" value="${sess_user_id}">
        <input type="hidden" name="pay_det_note[]" readonly value="${pay_det_note}">
        <input type="hidden" name="pay_det_previous_debt[]" value="${pay_det_previous_debt}">
        <input type="hidden" class="currentPayDetChange" name="pay_det_change[]" value="${pay_det_change}"></input>
        <input type="hidden" class="currentPayDetCashBack" cashbackatt="${cashBackRowStatus}" name="pay_det_cashback[]" value="${currentCashBack}">
        <input type="hidden" name="pay_det_cashback_status[]" value="${pay_det_cashback_status}">
        </td>
        <td><span>${CurrentDateTime}</span></td>
        <td><span>${payment_type}</span></td>
        <td><span>${showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, currentPaid)}</span></td>
        <td><span>${showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, pay_det_income)}</span></td>
        <td><span>${showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, pay_det_change)}</span ></td >
        <td><span>${pay_det_note}</span></td>

        </tr >
    `);

    $("#inp_paid_value").val(0);
    showAmount();
}


/*=============================================
FUNCTION TO REMOVE ROW FROM PAYMENT
=============================================*/
$(document).on("click", ".removeRow_payment", function () {

    let pos_info = JSON.parse(localStorage.getItem("pos_info"));

    let currentButton = $(this);

    $(this).parent().parent().remove();

    // RECALCULATE NEW CASHBACK ON REMOVE PAYMENT ROW
    let totalCashBack = $("#totalCashBack").val();
    let totalCustomerCashBack = $("#customerCashBack").val();
    let cashBackAtt = currentButton.closest('.dataRow').find('.currentPayDetCashBack').attr("cashbackatt");
    let currentCashBack = currentButton.closest('.dataRow').find('.currentPayDetCashBack');

    currentCashBack = Number(currentCashBack.val());

    // IF THE PAYMENT TYPE WAS DIFFERENT TO CASHBACK (MEANS THERE WAS NEW CASHBACK ASSIGNED TO THE CUSTOMER AND MUST BE REMOVED)
    if (cashBackAtt == "Yes") {

        let newCashBackAmount = totalCashBack - currentCashBack
        $("#totalCashBack").val(newCashBackAmount);
        $("#span_modal_new_cash_back").text(showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, newCashBackAmount));

    } else {

        let leftCashBack = roundedDecimal(Number(totalCustomerCashBack) + Number(currentCashBack), 2);
        $("#customerCashBack").val(leftCashBack);
        $("#span_available_cash_back").text(showCurrencyFormat(pos_info.pos_currency, pos_info.pos_country_code, leftCashBack));
    }

    fnSweetToast(translate.row_removed, "success", 1500);
    showAmount();

});

/*=============================================
CONFIMR PAYMENT CLICK ACTION
=============================================*/
$(document).on("change", "#sale_ncf_type", function () {

    let sale_ncf_type = $(this).val();
    let sale_cus_fiscal_number = $("#sale_cus_fiscal_number").val();

    if (!sale_cus_fiscal_number.trim() && sale_ncf_type == 'B01') {
        fnSweetToast(translate.please_confirm_the_customer_fiscal_number, "warning", 4000);
        jsEditCustomer();
        $("#myModalPayment").modal("hide");
        return false;
    }
});

/*=============================================
CONFIMR PAYMENT CLICK ACTION
=============================================*/
$(document).on("click", ".btnConfirmPayment", async function () {

    let tableListPaiement = $('.payment_entry_details tbody tr').length;

    if (tableListPaiement <= 0) {
        swalInit.fire(translate.no_payment_has_been_added, translate.please_add_a_payment_to_continue, "error");
        return;
    }

    let sale_ncf_type = ($("#sale_ncf_type").val() || '').trim();
    let sale_cus_fiscal_number = ($("#sale_cus_fiscal_number").val() || '').trim();

    if (!(await jsCheckActiveSale(translate.cannot_add_more_payments))) return false;

    if (await validateToSaveOrder("save_payment") === false) return false;

    if (!sale_cus_fiscal_number && sale_ncf_type == 'B01') {
        fnSweetToast(translate.please_confirm_the_customer_fiscal_number, "warning", 3000);
        jsEditCustomer();
        return false;
    } else {
        showAmount();
        fnSaveUpdate();
    }
});

// SAVE UPDATE SALE
async function fnSaveUpdate() {

    if (await validateToSaveOrder('save') === false) return;

    // ── Helper: set all action buttons to a given state ───────────────────────
    function setButtonStatus(state) {
        if (state === 'loading') {
            $('.btnSaveOrder, .btnConfirmPayment')
                .prop('disabled', true)
                .css('cursor', 'not-allowed')
                .html(translate.waiting_icon_text);
            return;
        }
        if (state === 'ready') {
            $('.btnSaveOrder')
                .prop('disabled', false)
                .css('cursor', 'pointer')
                .html(`<i class="ph-floppy-disk me-1"></i> ${translate.save}`);

            $('.btnConfirmPayment')
                .prop('disabled', false)
                .css('cursor', 'pointer')
                .html(`<i class="ph-check-circle me-1"></i> ${translate.confirm_payment}`);
        }
    }

    // ── Helper: fire swal with newline → <br> support ─────────────────────────
    function fireAlert(title, message = "", icon) {
        return swalInit.fire({
            icon,
            title: title,
            html: String(message).replace(/\n/g, '<br>'),
        });
    }

    setButtonStatus('loading');

    const formPostData = $(
        '#frmSubmitOrder, #frmSubmitOrderDetail, #frmSubmitPaymentDetail'
    ).serialize();

    try {
        const response = await fetch('ajax/sales.ajax.php?op=ajaxSaveUpdate', {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            body: formPostData,
        });

        const res = await response.json();

        if (res.status === 'success') {

            showAmount();
            setButtonStatus('ready');

            await fireAlert(res.message, "", res.status)

            $('.divBtnOrderControl').remove();

            jsShowTicket({
                sale_id: res.sale_id,
                sale_cus_id: res.sale_cus_id,
                sale_ent_id: res.sale_ent_id,
                sale_pos_id: res.sale_pos_id,
            });

        } else if (res.status === 'warning') {

            // console.error('Save failed:', res);
            setButtonStatus('ready');

            // Stock errors are recoverable — show all failures, let user fix and retry
            await fireAlert(res.title, res.message, res.status);

            refreshProductListToShowRealStock();

        } else {
            // Unexpected status — treat as unrecoverable
            console.error('Save unexpected response:', res);
            setButtonStatus('ready');
            await fireAlert(translate.data_could_not_be_saved, "", 'error');

            // Only redirect if the server explicitly signals an unrecoverable state
            if (res.redirect === true) {
                window.location.href = 'sell';
            }
        }

    } catch (error) {
        console.error('fnSaveUpdate error:', error);
        setButtonStatus('ready');
        await fireAlert(translate.data_could_not_be_saved, "", 'error');
        window.location.href = 'sell';
    }
}


$(document).on("click", ".btnClosePrintTicket", function () {
    if (currentLocationSplited[0] == "sell") {
        window.location = "sell";
    }
});

function js_selectListFiscalReceipt(ent_id, sale_ncf_type = "") {

    let parameters = {
        ent_id: ent_id,
        sale_ncf_type: sale_ncf_type,
        csrf_token: csrf_token
    }
    $.post("ajax/tax-receipt.ajax.php?op=ajax_selectFiscalList", parameters,
        function (response) {
            // console.log(response);
            $("#sale_ncf_type").html(response);
            $("#sale_ncf_type").trigger("change");
        }
    );
}

$("#inputLoadSaleById").keydown(function (e) {
    if (e.which === 13) {

        let sale_id = $("#inputLoadSaleById").val();

        if (Number(sale_id) >= 1) {

            if ((sale_id || '').trim() == "") {
                $("#inputLoadSaleById").focus();
                fnSweetToast(translate.enter_order_code, "warning", 1500);
                return false;
            } else {
                window.location = `sell-det-${sale_id}`;
            }

        } else {
            fnSweetToast(translate.invalide_code, "error", 1500);
        }
    }
});

$(document).on("click", ".btnSearchOrder", function () {

    let sale_id = $("#inputLoadSaleById").val();

    if (Number(sale_id) >= 1) {

        if ((sale_id || '').trim() == "") {
            $("#inputLoadSaleById").focus();
            fnSweetToast(translate.enter_order_code, "warning", 1500);
            return false;
        } else {
            window.location = `sell-det-${sale_id}`;
        }

    } else {
        fnSweetToast(translate.invalide_code, "error", 1500);
    }

});