frappe.form.link_formatters['E-Taxes Item'] = function(value, doc) { 
    return doc.etaxes_item_name || value; 
};

frappe.form.link_formatters['E-Taxes Unit'] = function(value, doc) { 
    return doc.etaxes_unit_name || value; 
};

frappe.ui.form.on('E-Taxes Settings', {
    after_save: function(frm) {
        // After save operations can be added here if needed
    },
    
    refresh: function(frm) {
        // Main Load All Data button
        frm.add_custom_button(__('Load All Data'), function() {
            show_load_all_data_dialog(frm);
        }, __('Data Loading'));
        
        // Load reference data lists for tabs if document exists
        if (frm.doc.name) {
            load_reference_data_tabs(frm);
        }
        
        // Add bulk edit buttons for mapping tables
        frm.fields_dict['item_mappings'].grid.add_custom_button(__('Bulk Edit'), function() {
            bulk_edit_table(frm, 'item_mappings');
        });
        
        frm.fields_dict['unit_mappings'].grid.add_custom_button(__('Bulk Edit'), function() {
            bulk_edit_table(frm, 'unit_mappings');
        });
        
        // Items section buttons
        frm.add_custom_button(__('Match items by similar name'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            match_similar_items();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                match_similar_items();
            }
            
            function match_similar_items() {
                frappe.confirm(
                    __('This operation will automatically match unmapped items with similar names. Continue?'),
                    function() {
                        frappe.show_alert({
                            message: __('Matching items...'),
                            indicator: 'blue'
                        });
                        
                        frappe.call({
                            method: 'invoice_az.api.match_similar_items',
                            callback: function(r) {
                                if (r.message && r.message.success) {
                                    frappe.show_alert({
                                        message: __('Matched {0} of {1} items', 
                                            [r.message.matched_count, r.message.total_processed]),
                                        indicator: 'green'
                                    }, 5);
                                    frm.reload_doc();
                                } else {
                                    frappe.msgprint({
                                        title: __('Error'),
                                        indicator: 'red',
                                        message: r.message ? r.message.message : __('Error matching items')
                                    });
                                }
                            }
                        });
                    }
                );
            }
        }, __('Items'));
        
        frm.add_custom_button(__('Create matching items'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            create_unmapped_items();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                create_unmapped_items();
            }
            
            function create_unmapped_items() {
                frappe.confirm(
                    __('<div style="color: red; font-weight: bold;">WARNING! This action will create new items in the system for all unmapped elements!</div><p>This action is irreversible. Are you sure?</p>'),
                    function() {
                        frappe.confirm(
                            __('Are you really sure you want to create new items? This cannot be undone.'),
                            function() {
                                frappe.call({
                                    method: 'invoice_az.api.create_unmapped_items',
                                    args: {
                                        'settings_name': frm.doc.name
                                    },
                                    callback: function(r) {
                                        if (r.message && r.message.success) {
                                            frappe.show_alert({
                                                message: __('Created {0} new items', [r.message.created_count]),
                                                indicator: 'green'
                                            }, 5);
                                            frm.reload_doc();
                                        } else {
                                            frappe.msgprint({
                                                title: __('Error'),
                                                indicator: 'red',
                                                message: r.message ? r.message.message : __('Error creating items')
                                            });
                                        }
                                    }
                                });
                            }
                        );
                    }
                );
            }
        }, __('Items'));
        
        frm.add_custom_button(__('Add unmapped items'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            add_unmapped_items();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                add_unmapped_items();
            }
            
            function add_unmapped_items() {
                frappe.call({
                    method: 'invoice_az.api.get_unmapped_items',
                    callback: function(r) {
                        if (r.message && r.message.success) {
                            if (r.message.items && r.message.items.length > 0) {
                                r.message.items.forEach(function(item) {
                                    let row = frm.add_child('item_mappings');
                                    
                                    row.etaxes_item_name = item.name;
                                    
                                    if (item.item_group) row.item_group = item.item_group;
                                    if (item.uom) row.uom = item.uom;
                                    if (item.is_stock_item !== undefined) row.is_stock_item = item.is_stock_item;
                                    if (item.is_purchase_item !== undefined) row.is_purchase_item = item.is_purchase_item;
                                    if (item.is_sales_item !== undefined) row.is_sales_item = item.is_sales_item;
                                    if (item.item_tax_template) row.item_tax_template = item.item_tax_template;
                                    
                                    row.mapping_type = 'Manual';
                                });
                                
                                frm.refresh_field('item_mappings');
                                
                                frm.save().then(function() {
                                    frappe.call({
                                        method: 'invoice_az.api.refresh_item_mappings_display',
                                        args: {
                                            'settings_name': frm.doc.name
                                        },
                                        callback: function(refresh_r) {
                                            if (refresh_r.message && refresh_r.message.success && refresh_r.message.updated_mappings) {
                                                refresh_r.message.updated_mappings.forEach(function(mapping) {
                                                    let grid_row = frm.fields_dict['item_mappings'].grid.grid_rows.find(
                                                        row => row.doc.name === mapping.name
                                                    );
                                                    
                                                    if (grid_row && grid_row.columns.etaxes_item_name) {
                                                        let link_field = grid_row.columns.etaxes_item_name;
                                                        if (link_field.$input) {
                                                            link_field.$input.val(mapping.etaxes_item_name_display);
                                                            link_field.set_value(mapping.etaxes_item_name_id);
                                                        }
                                                    }
                                                });
                                            }
                                            
                                            showFinalMessage(r.message.items);
                                        }
                                    });
                                });
                                
                            } else {
                                frappe.show_alert({
                                    message: __('No unmapped items'),
                                    indicator: 'blue'
                                }, 5);
                            }
                        } else {
                            frappe.msgprint({
                                title: __('Error'),
                                indicator: 'red',
                                message: r.message ? r.message.message : __('Error retrieving items')
                            });
                        }
                    }
                });
                
                function showFinalMessage(items) {
                    let services_count = items.filter(item => item.is_service_item).length;
                    let goods_count = items.length - services_count;
                    let purchase_count = items.filter(item => item.is_from_purchase).length;
                    let sales_count = items.filter(item => item.is_from_sales).length;
                    let both_count = items.filter(item => item.is_from_purchase && item.is_from_sales).length;
                    
                    let message = __('Added {0} unmapped items', [items.length]);
                    
                    let details = [];
                    if (services_count > 0 && goods_count > 0) {
                        details.push(`${goods_count} goods, ${services_count} services`);
                    } else if (services_count > 0) {
                        details.push(`${services_count} services`);
                    } else {
                        details.push(`${goods_count} goods`);
                    }
                    
                    if (both_count > 0) {
                        details.push(`${both_count} from both purchase & sales`);
                    } else {
                        if (purchase_count > 0) details.push(`${purchase_count} from purchases`);
                        if (sales_count > 0) details.push(`${sales_count} from sales`);
                    }
                    
                    if (details.length > 0) {
                        message += ` (${details.join(', ')})`;
                    }
                    
                    frappe.show_alert({
                        message: message,
                        indicator: 'green'
                    }, 6);
                }
            }
        
        }, __('Items'));
        
        // =================================================================
        // КНОПКИ ДЛЯ CUSTOMERS
        // =================================================================

        frm.add_custom_button(__('Match customers by similar name'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            match_similar_customers();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                match_similar_customers();
            }
            
            function match_similar_customers() {
                frappe.confirm(
                    __('This operation will automatically match unmapped customers with similar names. Continue?'),
                    function() {
                        frappe.show_alert({
                            message: __('Matching customers...'),
                            indicator: 'blue'
                        });
                        
                        frappe.call({
                            method: 'invoice_az.api.match_similar_customers',
                            callback: function(r) {
                                if (r.message && r.message.success) {
                                    frappe.show_alert({
                                        message: __('Matched {0} of {1} customers', 
                                            [r.message.matched_count, r.message.total_processed]),
                                        indicator: 'green'
                                    }, 5);
                                    frm.reload_doc();
                                } else {
                                    frappe.msgprint({
                                        title: __('Error'),
                                        indicator: 'red',
                                        message: r.message ? r.message.message : __('Error matching customers')
                                    });
                                }
                            }
                        });
                    }
                );
            }
        }, __('Customers'));

        frm.add_custom_button(__('Create matching customers'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            create_unmapped_customers();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                create_unmapped_customers();
            }
            
            function create_unmapped_customers() {
                frappe.confirm(
                    __('<div style="color: red; font-weight: bold;">WARNING! This action will create new customers in the system for all unmapped elements!</div><p>This action is irreversible. Are you sure?</p>'),
                    function() {
                        frappe.confirm(
                            __('Are you really sure you want to create new customers? This cannot be undone.'),
                            function() {
                                frappe.call({
                                    method: 'invoice_az.api.create_unmapped_customers',
                                    args: {
                                        'settings_name': frm.doc.name
                                    },
                                    callback: function(r) {
                                        if (r.message && r.message.success) {
                                            frappe.show_alert({
                                                message: __('Created {0} new customers', [r.message.created_count]),
                                                indicator: 'green'
                                            }, 5);
                                            frm.reload_doc();
                                        } else {
                                            frappe.msgprint({
                                                title: __('Error'),
                                                indicator: 'red',
                                                message: r.message ? r.message.message : __('Error creating customers')
                                            });
                                        }
                                    }
                                });
                            }
                        );
                    }
                );
            }
        }, __('Customers'));

        frm.add_custom_button(__('Add unmapped customers'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            add_unmapped_customers();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                add_unmapped_customers();
            }
            
            function add_unmapped_customers() {
                frappe.call({
                    method: 'invoice_az.api.get_unmapped_customers',
                    callback: function(r) {
                        if (r.message && r.message.success) {
                            if (r.message.customers && r.message.customers.length > 0) {
                                r.message.customers.forEach(function(customer) {
                                    let row = frm.add_child('customer_mappings');
                                    
                                    row.etaxes_customer_name = customer.etaxes_party_name;
                                    row.etaxes_tax_id = customer.etaxes_tax_id;
                                    
                                    if (customer.customer_group) 
                                        row.customer_group = customer.customer_group;
                                    
                                    if (customer.territory) 
                                        row.territory = customer.territory;
                                    
                                    if (customer.payment_terms) 
                                        row.payment_terms = customer.payment_terms;
                                    
                                    row.mapping_type = 'Manual';
                                });
                                
                                frm.refresh_field('customer_mappings');
                                
                                frm.save().then(function() {
                                    frappe.show_alert({
                                        message: __('Added {0} unmapped customers', [r.message.customers.length]),
                                        indicator: 'green'
                                    }, 5);
                                });
                                
                            } else {
                                frappe.show_alert({
                                    message: __('No unmapped customers'),
                                    indicator: 'blue'
                                }, 5);
                            }
                        } else {
                            frappe.msgprint({
                                title: __('Error'),
                                indicator: 'red',
                                message: r.message ? r.message.message : __('Error retrieving customers')
                            });
                        }
                    }
                });
            }

        }, __('Customers'));

        // =================================================================
        // КНОПКИ ДЛЯ SUPPLIERS
        // =================================================================

        frm.add_custom_button(__('Match suppliers by similar name'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            match_similar_suppliers();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                match_similar_suppliers();
            }
            
            function match_similar_suppliers() {
                frappe.confirm(
                    __('This operation will automatically match unmapped suppliers with similar names. Continue?'),
                    function() {
                        frappe.show_alert({
                            message: __('Matching suppliers...'),
                            indicator: 'blue'
                        });
                        
                        frappe.call({
                            method: 'invoice_az.api.match_similar_suppliers',
                            callback: function(r) {
                                if (r.message && r.message.success) {
                                    frappe.show_alert({
                                        message: __('Matched {0} of {1} suppliers', 
                                            [r.message.matched_count, r.message.total_processed]),
                                        indicator: 'green'
                                    }, 5);
                                    frm.reload_doc();
                                } else {
                                    frappe.msgprint({
                                        title: __('Error'),
                                        indicator: 'red',
                                        message: r.message ? r.message.message : __('Error matching suppliers')
                                    });
                                }
                            }
                        });
                    }
                );
            }
        }, __('Suppliers'));

        frm.add_custom_button(__('Create matching suppliers'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            create_unmapped_suppliers();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                create_unmapped_suppliers();
            }
            
            function create_unmapped_suppliers() {
                frappe.confirm(
                    __('<div style="color: red; font-weight: bold;">WARNING! This action will create new suppliers in the system for all unmapped elements!</div><p>This action is irreversible. Are you sure?</p>'),
                    function() {
                        frappe.confirm(
                            __('Are you really sure you want to create new suppliers? This cannot be undone.'),
                            function() {
                                frappe.call({
                                    method: 'invoice_az.api.create_unmapped_suppliers',
                                    args: {
                                        'settings_name': frm.doc.name
                                    },
                                    callback: function(r) {
                                        if (r.message && r.message.success) {
                                            frappe.show_alert({
                                                message: __('Created {0} new suppliers', [r.message.created_count]),
                                                indicator: 'green'
                                            }, 5);
                                            frm.reload_doc();
                                        } else {
                                            frappe.msgprint({
                                                title: __('Error'),
                                                indicator: 'red',
                                                message: r.message ? r.message.message : __('Error creating suppliers')
                                            });
                                        }
                                    }
                                });
                            }
                        );
                    }
                );
            }
        }, __('Suppliers'));

        frm.add_custom_button(__('Add unmapped suppliers'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            add_unmapped_suppliers();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                add_unmapped_suppliers();
            }
            
            function add_unmapped_suppliers() {
                frappe.call({
                    method: 'invoice_az.api.get_unmapped_suppliers',
                    callback: function(r) {
                        if (r.message && r.message.success) {
                            if (r.message.suppliers && r.message.suppliers.length > 0) {
                                r.message.suppliers.forEach(function(supplier) {
                                    let row = frm.add_child('supplier_mappings');
                                    
                                    row.etaxes_supplier_name = supplier.etaxes_party_name;
                                    row.etaxes_tax_id = supplier.etaxes_tax_id;
                                    
                                    if (supplier.supplier_group) 
                                        row.supplier_group = supplier.supplier_group;
                                    
                                    if (supplier.payment_terms) 
                                        row.payment_terms = supplier.payment_terms;
                                    
                                    row.mapping_type = 'Manual';
                                });
                                
                                frm.refresh_field('supplier_mappings');
                                
                                frm.save().then(function() {
                                    frappe.show_alert({
                                        message: __('Added {0} unmapped suppliers', [r.message.suppliers.length]),
                                        indicator: 'green'
                                    }, 5);
                                });
                                
                            } else {
                                frappe.show_alert({
                                    message: __('No unmapped suppliers'),
                                    indicator: 'blue'
                                }, 5);
                            }
                        } else {
                            frappe.msgprint({
                                title: __('Error'),
                                indicator: 'red',
                                message: r.message ? r.message.message : __('Error retrieving suppliers')
                            });
                        }
                    }
                });
            }

        }, __('Suppliers'));

        // Кнопки для единиц измерения
        frm.add_custom_button(__('Match units by similar name'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            match_similar_units();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                match_similar_units();
            }
            
            function match_similar_units() {
                frappe.confirm(
                    __('This operation will automatically match unmapped units with similar names. Continue?'),
                    function() {
                        frappe.show_alert({
                            message: __('Matching units...'),
                            indicator: 'blue'
                        });
                        
                        frappe.call({
                            method: 'invoice_az.api.match_similar_units',
                            callback: function(r) {
                                if (r.message && r.message.success) {
                                    frappe.show_alert({
                                        message: __('Matched {0} of {1} units', 
                                            [r.message.matched_count, r.message.total_processed]),
                                        indicator: 'green'
                                    }, 5);
                                    frm.reload_doc();
                                } else {
                                    frappe.msgprint({
                                        title: __('Error'),
                                        indicator: 'red',
                                        message: r.message ? r.message.message : __('Error matching units')
                                    });
                                }
                            }
                        });
                    }
                );
            }
        }, __('Units'));
        
        frm.add_custom_button(__('Create matching units'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            create_unmapped_units();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                create_unmapped_units();
            }
            
            function create_unmapped_units() {
                frappe.confirm(
                    __('<div style="color: red; font-weight: bold;">WARNING! This action will create new UOM units in the system for all unmapped elements!</div><p>This action is irreversible. Are you sure?</p>'),
                    function() {
                        frappe.confirm(
                            __('Are you really sure you want to create new UOM units? This cannot be undone.'),
                            function() {
                                frappe.call({
                                    method: 'invoice_az.api.create_unmapped_units',
                                    args: {
                                        'settings_name': frm.doc.name
                                    },
                                    callback: function(r) {
                                        if (r.message && r.message.success) {
                                            frappe.show_alert({
                                                message: __('Created {0} new UOM units', [r.message.created_count]),
                                                indicator: 'green'
                                            }, 5);
                                            frm.reload_doc();
                                        } else {
                                            frappe.msgprint({
                                                title: __('Error'),
                                                indicator: 'red',
                                                message: r.message ? r.message.message : __('Error creating UOM units')
                                            });
                                        }
                                    }
                                });
                            }
                        );
                    }
                );
            }
        }, __('Units'));
        
        frm.add_custom_button(__('Add unmapped units'), function() {
            if(frm.is_dirty()) {
                frappe.confirm(
                    __('Document contains unsaved changes. Save before performing the operation?'),
                    function() {
                        frm.save().then(function() {
                            add_unmapped_units();
                        });
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Operation canceled. Please save the document first.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            } else {
                add_unmapped_units();
            }
            
        function add_unmapped_units() {
            frappe.call({
                method: 'invoice_az.api.get_unmapped_units',
                callback: function(r) {
                    if (r.message && r.message.success) {
                        if (r.message.units && r.message.units.length > 0) {
                            r.message.units.forEach(function(unit) {
                                let row = frm.add_child('unit_mappings');
                                
                                frappe.model.set_value(row.doctype, row.name, 'etaxes_unit_name', unit.value);
                                row.mapping_type = 'Manual';
                            });
                            
                            frm.refresh_field('unit_mappings');
                            
                            frm.save().then(function() {
                                frappe.show_alert({
                                    message: __('Added {0} unmapped units', [r.message.units.length]),
                                    indicator: 'green'
                                }, 5);
                            });
                            
                        } else {
                            frappe.show_alert({
                                message: __('No unmapped units'),
                                indicator: 'blue'
                            }, 5);
                        }
                    } else {
                        frappe.msgprint({
                            title: __('Error'),
                            indicator: 'red',
                            message: r.message ? r.message.message : __('Error retrieving units')
                        });
                    }
                }
            });
        }

        }, __('Units'));
    }
});
// =================================================================
// NEW FUNCTIONS FOR LOAD ALL DATA FUNCTIONALITY
// =================================================================

function show_load_all_data_dialog(frm) {
    // Check authentication first
    check_and_process_token_settings(function() {
        open_load_dialog(frm);
    });
}

function open_load_dialog(frm) {
    // Get current data summary
    frappe.call({
        method: 'invoice_az.api.get_reference_data_summary',
        callback: function(r) {
            if (r.message && r.message.success) {
                show_load_dialog_with_summary(frm, r.message.summary);
            } else {
                show_load_dialog_with_summary(frm, {});
            }
        }
    });
}

function show_load_dialog_with_summary(frm, summary) {
    const today = frappe.datetime.get_today();
    const first_day_of_month = frappe.datetime.add_months(frappe.datetime.month_start(today), 0);
    const last_day_of_month = frappe.datetime.add_months(frappe.datetime.month_end(today), 0);
    
    // Build summary HTML
    let summary_html = '<div class="reference-data-summary" style="background: #f8f9fa; padding: 15px; border-radius: 6px; margin-bottom: 15px;">';
    summary_html += '<h5 style="margin-bottom: 15px;">Current Reference Data</h5>';
    summary_html += '<div class="row">';
    
    const data_types = [
        {key: 'items', label: 'Items'},
        {key: 'customers', label: 'Customers'},
        {key: 'suppliers', label: 'Suppliers'},
        {key: 'units', label: 'Units'}
    ];
    
    data_types.forEach(function(type) {
        const data = summary[type.key] || {total: 0, mapped: 0};
        const mapped_percent = data.total > 0 ? Math.round((data.mapped / data.total) * 100) : 0;
        const unmapped = data.total - data.mapped;
        
        summary_html += `<div class="col-sm-3">
            <div class="text-center" style="border: 1px solid #ddd; padding: 10px; border-radius: 4px; background: white;">
                <h6 style="margin-bottom: 8px; color: #333;">${type.label}</h6>
                <div style="margin-bottom: 4px;"><strong>${data.total}</strong> total</div>
                <div style="margin-bottom: 4px; color: #28a745;"><strong>${data.mapped}</strong> mapped</div>
                <div style="color: #dc3545;"><strong>${unmapped}</strong> unmapped</div>
                <div style="font-size: 11px; color: #666; margin-top: 4px;">${mapped_percent}% mapped</div>
            </div>
        </div>`;
    });
    
    summary_html += '</div></div>';
    
    const d = new frappe.ui.Dialog({
        title: __('Load All Reference Data'),
        fields: [
            {
                fieldname: 'summary_section',
                fieldtype: 'HTML',
                options: summary_html
            },
            {
                fieldname: 'period_section',
                fieldtype: 'Section Break',
                label: __('Period')
            },
            {
                fieldname: 'date_from',
                fieldtype: 'Date',
                label: __('Date From'),
                default: first_day_of_month,
                reqd: 1
            },
            {
                fieldname: 'col_break_1',
                fieldtype: 'Column Break'
            },
            {
                fieldname: 'date_to',
                fieldtype: 'Date', 
                label: __('Date To'),
                default: last_day_of_month,
                reqd: 1
            },
            {
                fieldname: 'data_types_section',
                fieldtype: 'Section Break',
                label: __('Data Types to Load')
            },
            {
                fieldname: 'load_items',
                fieldtype: 'Check',
                label: __('Load Items'),
                default: 1,
                description: __('Load items from invoices (includes service/product classification)')
            },
            {
                fieldname: 'col_break_2',
                fieldtype: 'Column Break'
            },
            {
                fieldname: 'load_units',
                fieldtype: 'Check',
                label: __('Load Units'),
                default: 1,
                description: __('Load units of measurement from invoices')
            },
            {
                fieldname: 'col_break_3',
                fieldtype: 'Column Break'
            },
            {
                fieldname: 'load_customers',
                fieldtype: 'Check',
                label: __('Load Customers'),
                default: 1,
                description: __('Load customers from invoice receivers')
            },
            {
                fieldname: 'col_break_4',
                fieldtype: 'Column Break'
            },
            {
                fieldname: 'load_suppliers',
                fieldtype: 'Check',
                label: __('Load Suppliers'),
                default: 1,
                description: __('Load suppliers from invoice senders')
            }
        ],
        size: 'large',
        primary_action_label: __('Load Data'),
        primary_action: function() {
            const values = d.get_values();
            
            // Validate selections
            if (!values.load_items && !values.load_customers && !values.load_suppliers && !values.load_units) {
                frappe.msgprint(__('Please select at least one data type to load.'));
                return;
            }
            
            if (values.date_from > values.date_to) {
                frappe.msgprint(__('Date From cannot be later than Date To.'));
                return;
            }
            
            // Show confirmation with selected types
            const selected_types = [];
            if (values.load_items) selected_types.push(__('Items'));
            if (values.load_customers) selected_types.push(__('Customers'));
            if (values.load_suppliers) selected_types.push(__('Suppliers'));
            if (values.load_units) selected_types.push(__('Units'));
            
            // УЛУЧШЕНО: Более подробное сообщение о процессе
            frappe.confirm(
                __('This will load {0} from E-Taxes for the period {1} to {2}.<br><br>' +
                '<strong>Process:</strong><br>' +
                '1. First, all invoices will be fetched (may take 1-2 minutes)<br>' +
                '2. Then each invoice will be processed for reference data<br><br>' +
                '<strong>This operation may take several minutes depending on the number of invoices.</strong><br><br>' +
                'Continue?', 
                    [selected_types.join(', '), values.date_from, values.date_to]),
                function() {
                    d.hide();
                    start_reference_data_loading(frm, values);
                }
            );
        }
    });
    
    d.show();
}

function start_reference_data_loading(frm, values) {
    // ИЗМЕНЕНО: Теперь используем поэтапную загрузку вместо одного большого запроса
    start_staged_invoice_loading(frm, values);
}

function process_invoices_for_reference_data(invoices, token, accumulated_data, current_index = 0, frm) {
    // Инициализация при первом вызове
    if (current_index === 0) {
        window.cancelReferenceLoading = false;
        
        // Показываем прогресс-бар для обработки инвойсов
        frappe.show_progress(__('Processing Reference Data'), 0, invoices.length, 
            __('Processing {0} invoices...', [invoices.length]), null, true);
    }
    
    // Проверка отмены
    if (window.cancelReferenceLoading) {
        frappe.hide_progress();
        frappe.show_alert({
            message: __('Reference data loading cancelled'),
            indicator: 'red'
        }, 3);
        return;
    }
    
    // Если все инвойсы обработаны
    if (current_index >= invoices.length) {
        frappe.hide_progress();
        
        const msg = [];
        if (accumulated_data.items_created > 0) {
            msg.push(`${accumulated_data.items_created} items`);
        }
        if (accumulated_data.units_created > 0) {
            msg.push(`${accumulated_data.units_created} units`);
        }
        if (accumulated_data.customers_created > 0) {
            msg.push(`${accumulated_data.customers_created} customers`);
        }
        if (accumulated_data.suppliers_created > 0) {
            msg.push(`${accumulated_data.suppliers_created} suppliers`);
        }
        
        frappe.show_alert({
            message: __('Created: ') + msg.join(', ') + '. Use "Add unmapped" buttons to add them to mappings.',
            indicator: 'green'
        }, 10);
        
        frm.reload_doc();
        return;
    }
    
    const invoice = invoices[current_index];
    const invoice_id = invoice.id;
    const serial_number = invoice.serialNumber || invoice_id;
    const source = invoice._source || 'inbox';
    const source_type = source === 'outbox' ? 'sales' : 'purchase';
    
    // Обновляем прогресс
    frappe.show_progress(
        __('Processing Reference Data'), 
        current_index, 
        invoices.length, 
        __('Processing invoice {0} of {1}: {2}', [current_index + 1, invoices.length, serial_number])
    );
    
    // Обрабатываем текущий инвойс
    frappe.call({
        method: 'invoice_az.api.process_single_invoice_for_reference_data',
        args: {
            'token': token,
            'invoice_id': invoice_id,
            'source_type': source_type
        },
        callback: function(r) {
            if (r.message) {
                // Проверяем, есть ли новый токен в ответе
                if (r.message.new_token) {
                    // Обновляем токен для последующих запросов
                    token = r.message.new_token;
                }
                
                // Если ошибка unauthorized и нет нового токена - пробуем обновить токен
                if (r.message.error === 'unauthorized' && !r.message.new_token) {
                    // Получаем новый токен из Asan Login
                    frappe.call({
                        method: 'invoice_az.api.refresh_token_from_asan_login',
                        callback: function(token_r) {
                            if (token_r.message && token_r.message.success) {
                                // Обновляем токен и повторяем текущий инвойс
                                token = token_r.message.token;
                                setTimeout(function() {
                                    if (!window.cancelReferenceLoading) {
                                        process_invoices_for_reference_data(invoices, token, accumulated_data, current_index, frm);
                                    }
                                }, 100);
                            } else {
                                // Не удалось обновить токен - останавливаем обработку
                                frappe.hide_progress();
                                frappe.msgprint(__('Authentication expired. Please re-authenticate and try again.'));
                            }
                        }
                    });
                    return; // Выходим, чтобы не продолжать со старым токеном
                }
                
                // Обработка успешного результата
                if (r.message.success && r.message.stats) {
                    const stats = r.message.stats;
                    accumulated_data.items_created += stats.items_created || 0;
                    accumulated_data.items_skipped += stats.items_skipped || 0;
                    accumulated_data.units_created += stats.units_created || 0;
                    accumulated_data.units_skipped += stats.units_skipped || 0;
                    accumulated_data.customers_created += stats.customers_created || 0;
                    accumulated_data.customers_skipped += stats.customers_skipped || 0;
                    accumulated_data.suppliers_created += stats.suppliers_created || 0;
                    accumulated_data.suppliers_skipped += stats.suppliers_skipped || 0;
                }
            }
            
            // Переходим к следующему инвойсу
            setTimeout(function() {
                if (!window.cancelReferenceLoading) {
                    process_invoices_for_reference_data(invoices, token, accumulated_data, current_index + 1, frm);
                }
            }, 50);
            
        },
        error: function(xhr, status, error) {
            // При ошибке сети пробуем обновить токен
            if (xhr.status === 401) {
                frappe.call({
                    method: 'invoice_az.api.refresh_token_from_asan_login',
                    callback: function(token_r) {
                        if (token_r.message && token_r.message.success) {
                            // Обновляем токен и повторяем текущий инвойс
                            token = token_r.message.token;
                            setTimeout(function() {
                                if (!window.cancelReferenceLoading) {
                                    process_invoices_for_reference_data(invoices, token, accumulated_data, current_index, frm);
                                }
                            }, 100);
                        } else {
                            // Переходим к следующему инвойсу
                            setTimeout(function() {
                                if (!window.cancelReferenceLoading) {
                                    process_invoices_for_reference_data(invoices, token, accumulated_data, current_index + 1, frm);
                                }
                            }, 100);
                        }
                    }
                });
            } else {
                // При других ошибках переходим к следующему инвойсу
                setTimeout(function() {
                    if (!window.cancelReferenceLoading) {
                        process_invoices_for_reference_data(invoices, token, accumulated_data, current_index + 1, frm);
                    }
                }, 100);
            }
        }
    });
}

function show_loading_results(stats, selected_types) {
    let details = [];
    
    if (stats.items_created !== undefined || stats.items_updated !== undefined) {
        const created = stats.items_created || 0;
        const updated = stats.items_updated || 0;
        const skipped = stats.items_skipped || 0;
        details.push(__('Items: {0} created, {1} updated, {2} skipped', [created, updated, skipped]));
    }
    if (stats.customers_created !== undefined) {
        details.push(__('Customers: {0} created, {1} skipped', 
            [stats.customers_created, stats.customers_skipped || 0]));
    }
    if (stats.suppliers_created !== undefined) {
        details.push(__('Suppliers: {0} created, {1} skipped', 
            [stats.suppliers_created, stats.suppliers_skipped || 0]));
    }
    if (stats.units_created !== undefined) {
        details.push(__('Units: {0} created, {1} skipped', 
            [stats.units_created, stats.units_skipped || 0]));
    }
    
    const message = details.length > 0 ? details.join('<br>') : __('No new data loaded');
    
    let additional_info = '';
    if (stats.invoices_processed && stats.invoices_failed) {
        const total_processed = stats.invoices_processed + stats.invoices_failed;
        additional_info = `<br><br><small>Processed ${stats.invoices_processed} of ${total_processed} invoices successfully.</small>`;
    }
    
    frappe.msgprint({
        title: __('Data Loading Complete'),
        indicator: 'green',
        message: message + additional_info
    });
}

function load_reference_data_tabs(frm) {
    // Load data for each tab
    load_items_tab();
    load_customers_tab();
    load_suppliers_tab();
    load_units_tab();
}

function load_items_tab() {
    console.log('Loading items tab...');
    frappe.call({
        method: 'invoice_az.api.get_reference_data_lists',
        args: {'data_type': 'items', 'limit': 50, 'offset': 0},
        callback: function(r) {
            console.log('Items response:', r);
            if (r.message && r.message.success) {
                render_items_list(r.message.data, r.message.total_count);
            } else {
                const error_msg = r.message ? r.message.message : 'Unknown error';
                console.error('Items loading error:', error_msg);
                $('#items-list-container').html(`<div class="form-section card-section">
                    <div class="section-body">
                        <div class="alert alert-warning">
                            <p>Error loading items: ${error_msg}</p>
                            <p>This usually means there are no items to display or a field is missing.</p>
                            <button class="btn btn-sm btn-default retry-items-btn">Try Again</button>
                        </div>
                    </div>
                </div>`);
                
                // Add retry handler
                $('#items-list-container').off('click', '.retry-items-btn').on('click', '.retry-items-btn', function() {
                    load_items_tab();
                });
            }
        },
        error: function(xhr, status, error) {
            console.error('Items network error:', xhr, status, error);
            $('#items-list-container').html(`<div class="form-section card-section">
                <div class="section-body">
                    <div class="alert alert-danger">
                        <p>Network error loading items: ${error}</p>
                        <button class="btn btn-sm btn-default retry-items-btn">Try Again</button>
                    </div>
                </div>
            </div>`);
            
            // Add retry handler
            $('#items-list-container').off('click', '.retry-items-btn').on('click', '.retry-items-btn', function() {
                load_items_tab();
            });
        }
    });
}

function render_items_list(items, total_count) {
    let html = `<div class="frappe-control" style="margin-bottom: 15px;">
        <div class="clearfix">
            <div class="pull-left">
                <h6 class="text-muted">Items (${total_count} total)</h6>
            </div>
            <div class="pull-right">
                <button class="btn btn-xs btn-default refresh-items-btn">
                    <i class="octicon octicon-sync"></i> Refresh
                </button>
            </div>
        </div>
    </div>`;
    
    if (items && items.length > 0) {
        html += '<div class="form-section card-section">';
        html += '<div class="section-body">';
        html += '<table class="table table-bordered">';
        html += '<thead><tr><th>Name</th><th>Code</th><th>Status</th><th>Mapped To</th><th>Type</th><th>Created</th></tr></thead>';
        html += '<tbody>';
        
        items.forEach(function(item) {
            const status = item.status || 'New';
            const status_indicator = status === 'Mapped' ? 'green' : 'red';
            const item_type = item.is_service_item ? 'Service' : 'Product';
            const mapped_to = item.mapped_item ? `<a href="/app/item/${item.mapped_item}">${item.mapped_item}</a>` : '-';
            const created = item.creation ? frappe.datetime.str_to_user(item.creation) : '-';
            const item_name = item.etaxes_item_name || 'Unknown';
            const item_code = item.etaxes_item_code || '-';
            
            html += `<tr>
                <td><a href="/app/e-taxes-item/${item.name}">${item_name}</a></td>
                <td>${item_code}</td>
                <td><span class="indicator-pill ${status_indicator}">${status}</span></td>
                <td>${mapped_to}</td>
                <td>${item_type}</td>
                <td>${created}</td>
            </tr>`;
        });
        
        html += '</tbody></table>';
        html += '</div>'; // section-body
        html += '</div>'; // form-section
        
        if (total_count > items.length) {
            html += `<div class="text-center" style="margin-top: 10px;">
                <p class="text-muted small">Showing ${items.length} of ${total_count} items</p>
                <a href="/app/e-taxes-item" class="btn btn-default btn-xs">View All Items</a>
            </div>`;
        }
    } else {
        html += '<div class="form-section card-section">';
        html += '<div class="section-body">';
        html += '<div class="empty-state">';
        html += '<p class="text-muted">No items found. Use "Load All Data" to import items from E-Taxes.</p>';
        html += '</div>';
        html += '</div>';
        html += '</div>';
    }
    
    $('#items-list-container').html(html);
    
    // Add event handler for refresh button
    $('#items-list-container').off('click', '.refresh-items-btn').on('click', '.refresh-items-btn', function() {
        $('#items-list-container').html('<div class="text-center" style="padding: 20px;"><i class="fa fa-spinner fa-spin"></i> Loading...</div>');
        load_items_tab();
    });
}

function load_customers_tab() {
    console.log('Loading customers tab...');
    frappe.call({
        method: 'invoice_az.api.get_reference_data_lists',
        args: {'data_type': 'customers', 'limit': 50, 'offset': 0},
        callback: function(r) {
            console.log('Customers response:', r);
            if (r.message && r.message.success) {
                render_customers_list(r.message.data, r.message.total_count);
            } else {
                const error_msg = r.message ? r.message.message : 'Unknown error';
                console.error('Customers loading error:', error_msg);
                $('#customers-list-container').html(`<div class="form-section card-section">
                    <div class="section-body">
                        <div class="alert alert-warning">
                            <p>Error loading customers: ${error_msg}</p>
                            <p>This usually means there are no customers to display or a field is missing.</p>
                            <button class="btn btn-sm btn-default retry-customers-btn">Try Again</button>
                        </div>
                    </div>
                </div>`);
                
                // Add retry handler
                $('#customers-list-container').off('click', '.retry-customers-btn').on('click', '.retry-customers-btn', function() {
                    load_customers_tab();
                });
            }
        },
        error: function(xhr, status, error) {
            console.error('Customers network error:', xhr, status, error);
            $('#customers-list-container').html(`<div class="form-section card-section">
                <div class="section-body">
                    <div class="alert alert-danger">
                        <p>Network error loading customers: ${error}</p>
                        <button class="btn btn-sm btn-default retry-customers-btn">Try Again</button>
                    </div>
                </div>
            </div>`);
            
            // Add retry handler
            $('#customers-list-container').off('click', '.retry-customers-btn').on('click', '.retry-customers-btn', function() {
                load_customers_tab();
            });
        }
    });
}

function render_customers_list(customers, total_count) {
    let html = `<div class="frappe-control" style="margin-bottom: 15px;">
        <div class="clearfix">
            <div class="pull-left">
                <h6 class="text-muted">Customers (${total_count} total)</h6>
            </div>
            <div class="pull-right">
                <button class="btn btn-xs btn-default refresh-customers-btn">
                    <i class="octicon octicon-sync"></i> Refresh
                </button>
            </div>
        </div>
    </div>`;
    
    if (customers && customers.length > 0) {
        html += '<div class="form-section card-section">';
        html += '<div class="section-body">';
        html += '<table class="table table-bordered">';
        html += '<thead><tr><th>Name</th><th>Tax ID</th><th>Status</th><th>Mapped To</th><th>Created</th></tr></thead>';
        html += '<tbody>';
        
        customers.forEach(function(customer) {
            const status = customer.status || 'New';
            const status_indicator = status === 'Mapped' ? 'green' : 'red';
            const mapped_to = customer.mapped_customer ? `<a href="/app/customer/${customer.mapped_customer}">${customer.mapped_customer}</a>` : '-';
            const created = customer.creation ? frappe.datetime.str_to_user(customer.creation) : '-';
            const party_name = customer.etaxes_party_name || 'Unknown';
            const tax_id = customer.etaxes_tax_id || '-';
            
            html += `<tr>
                <td><a href="/app/e-taxes-customers/${customer.name}">${party_name}</a></td>
                <td>${tax_id}</td>
                <td><span class="indicator-pill ${status_indicator}">${status}</span></td>
                <td>${mapped_to}</td>
                <td>${created}</td>
            </tr>`;
        });
        
        html += '</tbody></table>';
        html += '</div>'; // section-body
        html += '</div>'; // form-section
        
        if (total_count > customers.length) {
            html += `<div class="text-center" style="margin-top: 10px;">
                <p class="text-muted small">Showing ${customers.length} of ${total_count} customers</p>
                <a href="/app/e-taxes-customers" class="btn btn-default btn-xs">View All Customers</a>
            </div>`;
        }
    } else {
        html += '<div class="form-section card-section">';
        html += '<div class="section-body">';
        html += '<div class="empty-state">';
        html += '<p class="text-muted">No customers found. Use "Load All Data" to import customers from E-Taxes.</p>';
        html += '</div>';
        html += '</div>';
        html += '</div>';
    }
    
    $('#customers-list-container').html(html);
    
    // Add event handler for refresh button
    $('#customers-list-container').off('click', '.refresh-customers-btn').on('click', '.refresh-customers-btn', function() {
        $('#customers-list-container').html('<div class="text-center" style="padding: 20px;"><i class="fa fa-spinner fa-spin"></i> Loading...</div>');
        load_customers_tab();
    });
}

function load_suppliers_tab() {
    console.log('Loading suppliers tab...');
    frappe.call({
        method: 'invoice_az.api.get_reference_data_lists',
        args: {'data_type': 'suppliers', 'limit': 50, 'offset': 0},
        callback: function(r) {
            console.log('Suppliers response:', r);
            if (r.message && r.message.success) {
                render_suppliers_list(r.message.data, r.message.total_count);
            } else {
                const error_msg = r.message ? r.message.message : 'Unknown error';
                console.error('Suppliers loading error:', error_msg);
                $('#suppliers-list-container').html(`<div class="form-section card-section">
                    <div class="section-body">
                        <div class="alert alert-warning">
                            <p>Error loading suppliers: ${error_msg}</p>
                            <p>This usually means there are no suppliers to display or a field is missing.</p>
                            <button class="btn btn-sm btn-default retry-suppliers-btn">Try Again</button>
                        </div>
                    </div>
                </div>`);
                
                // Add retry handler
                $('#suppliers-list-container').off('click', '.retry-suppliers-btn').on('click', '.retry-suppliers-btn', function() {
                    load_suppliers_tab();
                });
            }
        },
        error: function(xhr, status, error) {
            console.error('Suppliers network error:', xhr, status, error);
            $('#suppliers-list-container').html(`<div class="form-section card-section">
                <div class="section-body">
                    <div class="alert alert-danger">
                        <p>Network error loading suppliers: ${error}</p>
                        <button class="btn btn-sm btn-default retry-suppliers-btn">Try Again</button>
                    </div>
                </div>
            </div>`);
            
            // Add retry handler
            $('#suppliers-list-container').off('click', '.retry-suppliers-btn').on('click', '.retry-suppliers-btn', function() {
                load_suppliers_tab();
            });
        }
    });
}

function render_suppliers_list(suppliers, total_count) {
    let html = `<div class="frappe-control" style="margin-bottom: 15px;">
        <div class="clearfix">
            <div class="pull-left">
                <h6 class="text-muted">Suppliers (${total_count} total)</h6>
            </div>
            <div class="pull-right">
                <button class="btn btn-xs btn-default refresh-suppliers-btn">
                    <i class="octicon octicon-sync"></i> Refresh
                </button>
            </div>
        </div>
    </div>`;
    
    if (suppliers && suppliers.length > 0) {
        html += '<div class="form-section card-section">';
        html += '<div class="section-body">';
        html += '<table class="table table-bordered">';
        html += '<thead><tr><th>Name</th><th>Tax ID</th><th>Status</th><th>Mapped To</th><th>Created</th></tr></thead>';
        html += '<tbody>';
        
        suppliers.forEach(function(supplier) {
            const status = supplier.status || 'New';
            const status_indicator = status === 'Mapped' ? 'green' : 'red';
            const mapped_to = supplier.mapped_supplier ? `<a href="/app/supplier/${supplier.mapped_supplier}">${supplier.mapped_supplier}</a>` : '-';
            const created = supplier.creation ? frappe.datetime.str_to_user(supplier.creation) : '-';
            const party_name = supplier.etaxes_party_name || 'Unknown';
            const tax_id = supplier.etaxes_tax_id || '-';
            
            html += `<tr>
                <td><a href="/app/e-taxes-suppliers/${supplier.name}">${party_name}</a></td>
                <td>${tax_id}</td>
                <td><span class="indicator-pill ${status_indicator}">${status}</span></td>
                <td>${mapped_to}</td>
                <td>${created}</td>
            </tr>`;
        });
        
        html += '</tbody></table>';
        html += '</div>'; // section-body
        html += '</div>'; // form-section
        
        if (total_count > suppliers.length) {
            html += `<div class="text-center" style="margin-top: 10px;">
                <p class="text-muted small">Showing ${suppliers.length} of ${total_count} suppliers</p>
                <a href="/app/e-taxes-suppliers" class="btn btn-default btn-xs">View All Suppliers</a>
            </div>`;
        }
    } else {
        html += '<div class="form-section card-section">';
        html += '<div class="section-body">';
        html += '<div class="empty-state">';
        html += '<p class="text-muted">No suppliers found. Use "Load All Data" to import suppliers from E-Taxes.</p>';
        html += '</div>';
        html += '</div>';
        html += '</div>';
    }
    
    $('#suppliers-list-container').html(html);
    
    // Add event handler for refresh button
    $('#suppliers-list-container').off('click', '.refresh-suppliers-btn').on('click', '.refresh-suppliers-btn', function() {
        $('#suppliers-list-container').html('<div class="text-center" style="padding: 20px;"><i class="fa fa-spinner fa-spin"></i> Loading...</div>');
        load_suppliers_tab();
    });
}

function load_units_tab() {
    console.log('Loading units tab...');
    frappe.call({
        method: 'invoice_az.api.get_reference_data_lists',
        args: {'data_type': 'units', 'limit': 50, 'offset': 0},
        callback: function(r) {
            console.log('Units response:', r);
            if (r.message && r.message.success) {
                render_units_list(r.message.data, r.message.total_count);
            } else {
                const error_msg = r.message ? r.message.message : 'Unknown error';
                console.error('Units loading error:', error_msg);
                $('#units-list-container').html(`<div class="form-section card-section">
                    <div class="section-body">
                        <div class="alert alert-warning">
                            <p>Error loading units: ${error_msg}</p>
                            <p>This usually means there are no units to display or a field is missing.</p>
                            <button class="btn btn-sm btn-default retry-units-btn">Try Again</button>
                        </div>
                    </div>
                </div>`);
                
                // Add retry handler
                $('#units-list-container').off('click', '.retry-units-btn').on('click', '.retry-units-btn', function() {
                    load_units_tab();
                });
            }
        },
        error: function(xhr, status, error) {
            console.error('Units network error:', xhr, status, error);
            $('#units-list-container').html(`<div class="form-section card-section">
                <div class="section-body">
                    <div class="alert alert-danger">
                        <p>Network error loading units: ${error}</p>
                        <button class="btn btn-sm btn-default retry-units-btn">Try Again</button>
                    </div>
                </div>
            </div>`);
            
            // Add retry handler
            $('#units-list-container').off('click', '.retry-units-btn').on('click', '.retry-units-btn', function() {
                load_units_tab();
            });
        }
    });
}

function render_units_list(units, total_count) {
    let html = `<div class="frappe-control" style="margin-bottom: 15px;">
        <div class="clearfix">
            <div class="pull-left">
                <h6 class="text-muted">Units (${total_count} total)</h6>
            </div>
            <div class="pull-right">
                <button class="btn btn-xs btn-default refresh-units-btn">
                    <i class="octicon octicon-sync"></i> Refresh
                </button>
            </div>
        </div>
    </div>`;
    
    if (units && units.length > 0) {
        html += '<div class="form-section card-section">';
        html += '<div class="section-body">';
        html += '<table class="table table-bordered">';
        html += '<thead><tr><th>Name</th><th>Status</th><th>Mapped To</th><th>Created</th></tr></thead>';
        html += '<tbody>';
        
        units.forEach(function(unit) {
            const status = unit.status || 'New';
            const status_indicator = status === 'Mapped' ? 'green' : 'red';
            const mapped_to = unit.mapped_unit ? `<a href="/app/uom/${unit.mapped_unit}">${unit.mapped_unit}</a>` : '-';
            const created = unit.creation ? frappe.datetime.str_to_user(unit.creation) : '-';
            const unit_name = unit.etaxes_unit_name || 'Unknown';
            
            html += `<tr>
                <td><a href="/app/e-taxes-unit/${unit.name}">${unit_name}</a></td>
                <td><span class="indicator-pill ${status_indicator}">${status}</span></td>
                <td>${mapped_to}</td>
                <td>${created}</td>
            </tr>`;
        });
        
        html += '</tbody></table>';
        html += '</div>'; // section-body
        html += '</div>'; // form-section
        
        if (total_count > units.length) {
            html += `<div class="text-center" style="margin-top: 10px;">
                <p class="text-muted small">Showing ${units.length} of ${total_count} units</p>
                <a href="/app/e-taxes-unit" class="btn btn-default btn-xs">View All Units</a>
            </div>`;
        }
    } else {
        html += '<div class="form-section card-section">';
        html += '<div class="section-body">';
        html += '<div class="empty-state">';
        html += '<p class="text-muted">No units found. Use "Load All Data" to import units from E-Taxes.</p>';
        html += '</div>';
        html += '</div>';
        html += '</div>';
    }
    
    $('#units-list-container').html(html);
    
    // Add event handler for refresh button
    $('#units-list-container').off('click', '.refresh-units-btn').on('click', '.refresh-units-btn', function() {
        $('#units-list-container').html('<div class="text-center" style="padding: 20px;"><i class="fa fa-spinner fa-spin"></i> Loading...</div>');
        load_units_tab();
    });
}

// =================================================================
// EXISTING UTILITY FUNCTIONS
// =================================================================

function bulk_edit_table(frm, table_field) {
    // Получаем выбранные строки
    const selected_rows = frm.fields_dict[table_field].grid.get_selected_children();
    
    if (selected_rows.length === 0) {
        frappe.msgprint(__("No rows selected. Please select rows to edit."));
        return;
    }
    
    // Получаем метаданные дочернего doctype
    const child_doctype = selected_rows[0].doctype;
    const meta = frappe.get_meta(child_doctype);
    
    // Формируем список полей для редактирования
    const field_options = [];
    const field_map = {};
    
    meta.fields.forEach(df => {
        // Исключаем служебные поля и поля только для чтения
        if (!['Section Break', 'Column Break', 'Tab Break', 'HTML', 'Table', 'Button'].includes(df.fieldtype) && 
            !df.read_only && !df.hidden) {
            field_options.push({
                label: __(df.label || frappe.model.unscrub(df.fieldname)),
                value: df.fieldname
            });
            field_map[df.fieldname] = df;
        }
    });
    
    // Создаем диалог
    const d = new frappe.ui.Dialog({
        title: __("Bulk Edit Selected Rows"),
        fields: [
            {
                label: __("Field to Edit"),
                fieldname: "field_to_edit",
                fieldtype: "Select",
                options: field_options,
                reqd: 1
            },
            {
                fieldname: "value_section",
                fieldtype: "Section Break",
                label: __("New Value"),
                collapsible: 0,
                hidden: 1
            },
            {
                fieldname: "value_container",
                fieldtype: "HTML",
                options: '<div id="value_field_container"></div>'
            }
        ],
        primary_action_label: __("Apply"),
        primary_action: function() {
            // Получаем выбранное поле и значение
            const field_name = d.get_value("field_to_edit");
            
            // Если не выбрано поле
            if (!field_name || !d.new_value_field) {
                frappe.msgprint(__("Please select a field and enter a value."));
                return;
            }
            
            // Получаем новое значение из динамического поля
            const new_value = d.new_value_field.get_value();
            
            // Проверяем, что значение введено
            if (new_value === undefined || new_value === null || new_value === "") {
                frappe.msgprint(__("Please enter a new value."));
                return;
            }
            
            // Применяем изменения
            frappe.show_alert({
                message: __("Updating rows..."),
                indicator: 'blue'
            });
            
            let count = 0;
            const total = selected_rows.length;
            const promises = [];
            
            selected_rows.forEach(row => {
                promises.push(
                    frappe.model.set_value(row.doctype, row.name, field_name, new_value)
                        .then(() => {
                            count++;
                        })
                );
            });
            
            Promise.all(promises).then(() => {
                frm.refresh_field(table_field);
                frappe.show_alert({
                    message: __("Updated {0} rows", [count]),
                    indicator: 'green'
                }, 5);
                
                d.hide();
            });
        }
    });
    
    // Обработчик изменения поля
    d.fields_dict.field_to_edit.$input.on('change', function() {
        const field_name = d.get_value("field_to_edit");
        const field_def = field_map[field_name];
        
        if (!field_def) return;
        
        // Показываем секцию для нового значения
        d.set_df_property("value_section", "hidden", 0);
        
        // Удаляем предыдущее поле, если оно было
        if (d.new_value_field) {
            d.new_value_field.$wrapper.remove();
            delete d.new_value_field;
        }
        
        // Создаем новое поле нужного типа
        const value_container = d.fields_dict.value_container.$wrapper.find("#value_field_container");
        
        d.new_value_field = frappe.ui.form.make_control({
            df: {
                label: __("New Value for {0}", [__(field_def.label || frappe.model.unscrub(field_def.fieldname))]),
                fieldname: "new_value",
                fieldtype: field_def.fieldtype,
                options: field_def.options || "",
                reqd: 1
            },
            parent: value_container,
            render_input: true
        });
        
        d.new_value_field.refresh();
    });
    
    d.show();
}

// Authentication functions for Load All Data
function check_and_process_token_settings(callback) {
    // Проверяем, доступен ли новый модуль ETaxes
    if (typeof ETaxes !== 'undefined' && ETaxes.auth) {
        ETaxes.auth.checkAndProcess(callback);
        return;
    }
    
    // Fallback на старый код
    frappe.call({
        method: 'invoice_az.auth.check_token_validity',
        callback: function(r) {
            if (r.message && r.message.valid) {
                callback();
            } else {
                frappe.confirm(
                    __('Your E-Taxes session has expired or authentication is required. Would you like to authenticate now?'),
                    function() {
                        start_authentication_process_settings(callback);
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Authentication canceled. Operation cannot be completed.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            }
        },
        error: function() {
            frappe.msgprint({
                title: __('Error'),
                indicator: 'red',
                message: __('Failed to check authentication status')
            });
        }
    });
}

function start_authentication_process_settings(callback) {
    show_loading_dialog_settings(
        __('Starting Authentication'),
        __('Getting Asan Login settings...'),
        __('Please wait')
    );
    
    frappe.call({
        method: 'invoice_az.auth.get_default_asan_login',
        callback: function(r) {
            if (r.message && r.message.found) {
                var asan_login_name = r.message.name;
                update_loading_message_settings(
                    __('Sending authentication request...'),
                    __('This will send a request to your Asan Imza mobile app')
                );
                
                frappe.call({
                    method: 'invoice_az.auth.handle_authentication',
                    args: {
                        'asan_login_name': asan_login_name
                    },
                    callback: function(r) {
                        if (r.message && r.message.success) {
                            const bearer_token = r.message.bearer_token;
                            
                            if (r.message.verification_code) {
                                show_verification_code_settings(r.message.verification_code);
                            }
                            
                            update_loading_message_settings(
                                __('Waiting for confirmation on your phone'),
                                __('Please check your phone and confirm the authentication request')
                            );
                            
                            poll_authentication_status_settings(asan_login_name, bearer_token, function(success) {
                                if (success) {
                                    complete_authentication_settings(asan_login_name, callback);
                                } else {
                                    set_loading_error_settings(
                                        __('Authentication Failed'),
                                        __('Could not authenticate with Asan Imza')
                                    );
                                }
                            });
                        } else {
                            set_loading_error_settings(
                                __('Authentication Error'),
                                r.message ? r.message.message : __('Authentication request failed')
                            );
                        }
                    }
                });
            } else {
                set_loading_error_settings(
                    __('No Asan Login Settings'),
                    __('Please configure Asan Login settings first')
                );
            }
        }
    });
}

// Простые функции диалогов для settings
var loading_dialog_settings = null;

function show_loading_dialog_settings(title, message, submessage) {
    if (loading_dialog_settings) {
        $('#loading_title_settings').text(title);
        $('#loading_message_settings').text(message);
        if (submessage) {
            $('#loading_submessage_settings').text(submessage).show();
        } else {
            $('#loading_submessage_settings').hide();
        }
        return;
    }
    
    loading_dialog_settings = new frappe.ui.Dialog({
        title: title,
        fields: [{
            fieldname: 'loading_html',
            fieldtype: 'HTML',
            options: `
                <div class="text-center">
                    <div class="lds-dual-ring" style="display: inline-block; width: 64px; height: 64px;">
                        <div style="width: 64px; height: 64px; border: 6px solid #4e73df; border-radius: 50%; border-color: #4e73df transparent #4e73df transparent; animation: lds-dual-ring 1.2s linear infinite;"></div>
                    </div>
                    <style>
                        @keyframes lds-dual-ring {
                            0% { transform: rotate(0deg); }
                            100% { transform: rotate(360deg); }
                        }
                    </style>
                    <div class="mt-3">
                        <h4 id="loading_title_settings">${title}</h4>
                        <p id="loading_message_settings">${message}</p>
                        <p id="loading_submessage_settings" style="${submessage ? '' : 'display:none'}">${submessage || ''}</p>
                        <div id="verification_code_container_settings" style="display:none; margin-top: 15px;">
                            <div style="background: #f8f9fa; padding: 10px; display: inline-block; border-radius: 5px; font-size: 24px; font-weight: bold; letter-spacing: 2px; color: #333; border: 1px solid #ddd;">
                                <span id="verification_code_settings">----</span>
                            </div>
                            <p style="margin-top: 5px; font-size: 12px; color: #666;">Verification Code</p>
                        </div>
                    </div>
                </div>
            `
        }]
    });
    
    loading_dialog_settings.show();
    loading_dialog_settings.$wrapper.find('.modal-dialog').css('max-width', '450px');
}

function update_loading_message_settings(message, submessage) {
    if (loading_dialog_settings) {
        $('#loading_message_settings').text(message);
        if (submessage !== undefined) {
            $('#loading_submessage_settings').text(submessage);
            $('#loading_submessage_settings').toggle(!!submessage);
        }
    }
}

function show_verification_code_settings(code) {
    if (loading_dialog_settings && code) {
        $('#verification_code_settings').text(code);
        $('#verification_code_container_settings').show();
    }
}

function set_loading_error_settings(message, submessage) {
    if (loading_dialog_settings) {
        loading_dialog_settings.$wrapper.find('.lds-dual-ring').html(`
            <div style="width: 64px; height: 64px; display: flex; align-items: center; justify-content: center;">
                <i class="fa fa-times" style="font-size: 48px; color: #d9534f;"></i>
            </div>
        `);
        
        $('#loading_message_settings').text(message);
        if (submessage !== undefined) {
            $('#loading_submessage_settings').text(submessage);
            $('#loading_submessage_settings').toggle(!!submessage);
        }
        
        $('#verification_code_container_settings').hide();
        
        loading_dialog_settings.set_primary_action(__('Close'), function() {
            hide_loading_dialog_settings();
        });
    }
}

function hide_loading_dialog_settings() {
    if (loading_dialog_settings) {
        try {
            loading_dialog_settings.hide();
        } catch (e) {
            console.error('Error hiding loading dialog:', e);
        }
        loading_dialog_settings = null;
    }
}

function poll_authentication_status_settings(asan_login_name, bearer_token, callback) {
    let attempts = 0;
    const maxAttempts = 20;
    let stopPolling = false;
    
    function pollStatus() {
        if (attempts >= maxAttempts || stopPolling) {
            if (attempts >= maxAttempts) {
                set_loading_error_settings(
                    __('Authentication Timeout'),
                    __('The authentication request has timed out. Please try again.')
                );
                callback(false);
            }
            return;
        }
        
        attempts++;
        
        frappe.call({
            method: 'invoice_az.auth.poll_auth_status',
            args: {
                'asan_login_name': asan_login_name,
                'bearer_token': bearer_token
            },
            callback: function(r) {
                if (r.message && r.message.success) {
                    if (r.message.authenticated) {
                        stopPolling = true;
                        loading_dialog_settings.$wrapper.find('.lds-dual-ring').html(`
                            <div style="width: 64px; height: 64px; display: flex; align-items: center; justify-content: center;">
                                <i class="fa fa-check" style="font-size: 48px; color: #5cb85c;"></i>
                            </div>
                        `);
                        update_loading_message_settings(
                            __('Authentication Successful'),
                            __('You are now authenticated with Asan Imza')
                        );
                        setTimeout(function() {
                            hide_loading_dialog_settings();
                            callback(true);
                        }, 1500);
                    } else {
                        update_loading_message_settings(
                            __('Waiting for confirmation on your phone'),
                            __('Please check your phone and confirm the authentication request') + 
                            ' (' + attempts + '/' + maxAttempts + ')'
                        );
                        setTimeout(pollStatus, 6000);
                    }
                } else {
                    stopPolling = true;
                    set_loading_error_settings(
                        __('Authentication Error'),
                        r.message ? r.message.message : __('An unknown error occurred')
                    );
                    callback(false);
                }
            },
            error: function(err) {
                console.error('Error during status check:', err);
                setTimeout(pollStatus, 6000);
            }
        });
    }
    
    pollStatus();
}

function complete_authentication_settings(asan_login_name, callback) {
    show_loading_dialog_settings(
        __('Completing Authentication'),
        __('Getting certificates...'),
        __('Please wait')
    );
    
    frappe.call({
        method: 'invoice_az.auth.get_auth_certificates',
        args: {
            'asan_login_name': asan_login_name
        },
        callback: function(cert_r) {
            if (cert_r.message && cert_r.message.success) {
                update_loading_message_settings(
                    __('Certificates retrieved'),
                    __('Selecting certificate and taxpayer')
                );
                
                frappe.call({
                    method: 'frappe.client.get',
                    args: {
                        doctype: 'Asan Login',
                        name: asan_login_name
                    },
                    callback: function(r) {
                        if (r.message && r.message.selected_certificate_json) {
                            try {
                                const cert_data = JSON.parse(r.message.selected_certificate_json);
                                const cert_name = r.message.selected_certificate;
                                
                                frappe.call({
                                    method: 'invoice_az.auth.select_certificate',
                                    args: {
                                        'asan_login_name': asan_login_name,
                                        'certificate_data': cert_data,
                                        'certificate_name': cert_name
                                    },
                                    callback: function(select_r) {
                                        if (select_r.message && select_r.message.success) {
                                            frappe.call({
                                                method: 'invoice_az.auth.select_taxpayer',
                                                args: {
                                                    'asan_login_name': asan_login_name
                                                },
                                                callback: function(tax_r) {
                                                    if (tax_r.message && tax_r.message.success) {
                                                        loading_dialog_settings.$wrapper.find('.lds-dual-ring').html(`
                                                            <div style="width: 64px; height: 64px; display: flex; align-items: center; justify-content: center;">
                                                                <i class="fa fa-check" style="font-size: 48px; color: #5cb85c;"></i>
                                                            </div>
                                                        `);
                                                        update_loading_message_settings(
                                                            __('Authentication Complete'),
                                                            __('You can now access E-Taxes services')
                                                        );
                                                        setTimeout(function() {
                                                            hide_loading_dialog_settings();
                                                            callback();
                                                        }, 2000);
                                                    } else {
                                                        set_loading_error_settings(
                                                            __('Error'),
                                                            tax_r.message ? tax_r.message.message : __('Failed to select taxpayer')
                                                        );
                                                    }
                                                }
                                            });
                                        } else {
                                            set_loading_error_settings(
                                                __('Error'),
                                                select_r.message ? select_r.message.message : __('Failed to select certificate')
                                            );
                                        }
                                    }
                                });
                            } catch (e) {
                                set_loading_error_settings(
                                    __('Error'),
                                    __('Error parsing certificate data')
                                );
                            }
                        } else {
                            set_loading_error_settings(
                                __('Error'),
                                __('No certificate configuration found')
                            );
                        }
                    }
                });
            } else {
                set_loading_error_settings(
                    __('Error'),
                    cert_r.message ? cert_r.message.message : __('Failed to get certificates')
                );
            }
        }
    });
}

// ===== НОВЫЕ JAVASCRIPT ФУНКЦИИ =====

// НОВАЯ ФУНКЦИЯ: Поэтапная загрузка инвойсов
function start_staged_invoice_loading(frm, values) {
    // Инициализируем данные для поэтапной загрузки
    const loading_state = {
        date_from: moment(values.date_from).format("DD-MM-YYYY 00:00"),
        date_to: moment(values.date_to).format("DD-MM-YYYY 23:59"),
        all_invoices: [],
        current_offset: 0,
        total_loaded: 0,
        inbox_completed: false,
        outbox_completed: false,
        token: null,
        last_update_count: 0  // Для отслеживания когда показывать обновление
    };
    
    window.cancelReferenceLoading = false;
    
    // ВОЗВРАЩАЕМ: Модальное окно в центре экрана
    const loading_dialog = frappe.msgprint({
        title: __('Loading Data'),
        message: __('Fetching invoices from E-Taxes, please wait...'),
        indicator: 'blue'
    });
    
    // Сохраняем ссылку на диалог в состоянии
    loading_state.loading_dialog = loading_dialog;
    
    // Начинаем загрузку inbox
    load_invoice_batch(loading_state, 'inbox', frm);
}

// НОВАЯ ФУНКЦИЯ: Загрузка одной порции инвойсов
function load_invoice_batch(loading_state, source, frm) {
    if (window.cancelReferenceLoading) {
        // Закрываем диалог при отмене
        if (loading_state.loading_dialog && loading_state.loading_dialog.hide) {
            loading_state.loading_dialog.hide();
        }
        frappe.show_alert({
            message: __('Loading cancelled'),
            indicator: 'red'
        }, 3);
        return;
    }
    
    const method = source === 'inbox' ? 
        'invoice_az.api.load_single_invoice_batch' : 
        'invoice_az.api.load_single_sales_invoice_batch';
    
    frappe.call({
        method: method,
        args: {
            date_from: loading_state.date_from,
            date_to: loading_state.date_to,
            offset: loading_state.current_offset
        },
        callback: function(r) {
            if (!r.message || !r.message.success) {
                if (source === 'inbox') {
                    // Если inbox не удался - закрываем диалог и показываем ошибку
                    if (loading_state.loading_dialog && loading_state.loading_dialog.hide) {
                        loading_state.loading_dialog.hide();
                    }
                    frappe.msgprint(__('Failed to load invoices: ') + (r.message?.message || 'Unknown error'));
                    return;
                } else {
                    // Если outbox не удался - продолжаем без него
                    loading_state.outbox_completed = true;
                    check_loading_completion(loading_state, frm);
                    return;
                }
            }
            
            const batch_invoices = r.message.invoices || [];
            const token = r.message.token;
            const hasMore = r.message.hasMore || false;
            
            // Сохраняем токен при первом запросе
            if (!loading_state.token) {
                loading_state.token = token;
            }
            
            // Помечаем источник для каждого инвойса
            batch_invoices.forEach(invoice => {
                invoice._source = source;
            });
            
            // Добавляем к общему списку
            loading_state.all_invoices = loading_state.all_invoices.concat(batch_invoices);
            loading_state.total_loaded += batch_invoices.length;
            
            // ИЗМЕНЕНО: Обновляем сообщение каждые 200 инвойсов или при смене источника
            const should_update = (
                Math.floor(loading_state.total_loaded / 200) > Math.floor(loading_state.last_update_count / 200) ||
                (source === 'outbox' && loading_state.last_update_count === 0) // Первое сообщение для outbox
            );
            
            if (should_update && loading_state.loading_dialog && loading_state.loading_dialog.$wrapper) {
                const progress_text = source === 'inbox' ? 
                    __('Finding purchase invoices: {0} found...', [loading_state.total_loaded]) :
                    __('Finding sales invoices: {0} total found...', [loading_state.total_loaded]);
                
                // Пробуем обновить текст в модальном окне
                try {
                    const $wrapper = loading_state.loading_dialog.$wrapper;
                    const $modal_body = $wrapper.find('.modal-body');
                    if ($modal_body.length > 0) {
                        $modal_body.html(`<p>${progress_text}</p>`);
                    }
                } catch (e) {
                    console.log('Could not update modal text:', e);
                }
                
                loading_state.last_update_count = loading_state.total_loaded;
            }
            
            if (hasMore && batch_invoices.length > 0) {
                // Есть еще данные - загружаем следующую порцию
                loading_state.current_offset += 200;
                setTimeout(() => load_invoice_batch(loading_state, source, frm), 100);
            } else {
                // Завершили загрузку из этого источника
                if (source === 'inbox') {
                    loading_state.inbox_completed = true;
                    // Начинаем загрузку outbox
                    loading_state.current_offset = 0;
                    loading_state.last_update_count = 0; // Сбрасываем счетчик для outbox
                    setTimeout(() => load_invoice_batch(loading_state, 'outbox', frm), 100);
                } else {
                    loading_state.outbox_completed = true;
                    check_loading_completion(loading_state, frm);
                }
            }
        },
        error: function(r) {
            if (source === 'inbox') {
                // Закрываем диалог при ошибке
                if (loading_state.loading_dialog && loading_state.loading_dialog.hide) {
                    loading_state.loading_dialog.hide();
                }
                frappe.msgprint(__('Error loading invoices: ') + (r.message || 'Network error'));
            } else {
                // Ошибка outbox - продолжаем без него
                loading_state.outbox_completed = true;
                check_loading_completion(loading_state, frm);
            }
        }
    });
}


// НОВАЯ ФУНКЦИЯ: Проверка завершения загрузки
function check_loading_completion(loading_state, frm) {
    if (loading_state.inbox_completed && loading_state.outbox_completed) {
        // ИСПРАВЛЕНО: Закрываем диалог загрузки
        if (loading_state.loading_dialog && loading_state.loading_dialog.hide) {
            loading_state.loading_dialog.hide();
        }
        
        if (loading_state.all_invoices.length === 0) {
            frappe.msgprint(__('No invoices found for the selected period.'));
            return;
        }
        
        // ИЗМЕНЕНО: Показываем результат загрузки
        frappe.show_alert({
            message: __('Found {0} invoices. Starting processing...', [loading_state.all_invoices.length]),
            indicator: 'green'
        }, 3); // Показываем на 3 секунды
        
        // Небольшая задержка и начинаем обработку
        setTimeout(() => {
            process_invoices_for_reference_data(loading_state.all_invoices, loading_state.token, {
                items_created: 0,
                items_skipped: 0,
                units_created: 0,
                units_skipped: 0,
                customers_created: 0,
                customers_skipped: 0,
                suppliers_created: 0,
                suppliers_skipped: 0,
                total_invoices: loading_state.all_invoices.length
            }, 0, frm);
        }, 2000);
    }
}
