// ======= ОБЩИЕ УТИЛИТЫ И КОНСТАНТЫ =======
const ETaxes = {
    // Константы
    PROGRESS_UPDATE_DELAY: 50,
    AUTH_POLL_INTERVAL: 6000,
    AUTH_MAX_ATTEMPTS: 20,
    
    // Глобальные переменные
    loadingDialog: null,
    cancelLoading: false,
    loadingErrors: [],
    
    // Кэш
    cache: {
        defaultLogin: null,
        cacheTime: null,
        cacheDuration: 300000 // 5 минут
    }
};

// ======= БАЗОВЫЕ УТИЛИТЫ =======
ETaxes.utils = {
    // Кэшированное получение настроек входа
    getDefaultLogin: function(callback, useCache = true) {
        const now = Date.now();
        
        if (useCache && ETaxes.cache.defaultLogin && ETaxes.cache.cacheTime && 
            (now - ETaxes.cache.cacheTime) < ETaxes.cache.cacheDuration) {
            callback(ETaxes.cache.defaultLogin);
            return;
        }
        
        frappe.call({
            method: 'invoice_az.auth.get_default_asan_login',
            callback: function(r) {
                if (r.message) {
                    ETaxes.cache.defaultLogin = r.message;
                    ETaxes.cache.cacheTime = now;
                }
                callback(r.message);
            },
            error: function() {
                callback({found: false, error: 'Network error'});
            }
        });
    },
    
    // Проверка валидности токена
    checkTokenValidity: function(callback) {
        frappe.call({
            method: 'invoice_az.auth.check_token_validity',
            callback: function(r) {
                callback(r.message && r.message.valid);
            },
            error: function() {
                callback(false);
            }
        });
    },
    
    // Форматирование валюты
    formatCurrency: function(amount) {
        return new Intl.NumberFormat('az-AZ', {
            style: 'currency',
            currency: 'AZN',
            minimumFractionDigits: 2
        }).format(amount || 0);
    },
    
    // Очистка кэша
    clearCache: function() {
        ETaxes.cache.defaultLogin = null;
        ETaxes.cache.cacheTime = null;
    }
};

// ======= ДИАЛОГИ ЗАГРУЗКИ =======
ETaxes.dialogs = {
    // Показать диалог загрузки
    showLoading: function(title, message, submessage) {
        if (ETaxes.loadingDialog) {
            this.updateLoading(title, message, submessage);
            return;
        }
        
        ETaxes.loadingDialog = new frappe.ui.Dialog({
            title: title,
            fields: [{
                fieldname: 'loading_html',
                fieldtype: 'HTML',
                options: this._getLoadingHTML(title, message, submessage)
            }],
            primary_action_label: __('Cancel'),
            primary_action: function() {
                ETaxes.cancelLoading = true;
                ETaxes.loadingDialog.$wrapper.find('.primary-action').prop('disabled', true);
                ETaxes.loadingDialog.$wrapper.find('.primary-action').html(__('Cancelling...'));
                $('#status_message p').text(__('Cancelling the operation.'));
            }
        });
        
        ETaxes.cancelLoading = false;
        ETaxes.loadingDialog.show();
        ETaxes.loadingDialog.$wrapper.find('.modal-dialog').css('max-width', '450px');
    },
    
    // Обновить сообщение в диалоге
    updateLoading: function(title, message, submessage) {
        if (!ETaxes.loadingDialog) return;
        
        if (title) $('#loading_title').text(title);
        if (message) $('#loading_message').text(message);
        if (submessage !== undefined) {
            $('#loading_submessage').text(submessage);
            $('#loading_submessage').toggle(!!submessage);
        }
    },
    
    // Показать код верификации
    showVerificationCode: function(code) {
        if (ETaxes.loadingDialog && code) {
            $('#verification_code').text(code);
            $('#verification_code_container').show();
        }
    },
    
    // Установить статус успеха
    setSuccess: function(message, submessage, callback, delay = 2000) {
        if (!ETaxes.loadingDialog) {
            if (callback) callback();
            return;
        }
        
        ETaxes.loadingDialog.$wrapper.find('.loading-animation').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>
        `);
        
        $('#loading_message').text(message);
        if (submessage !== undefined) {
            $('#loading_submessage').text(submessage);
            $('#loading_submessage').toggle(!!submessage);
        }
        
        $('#verification_code_container').hide();
        ETaxes.loadingDialog.set_primary_action(null);
        ETaxes.loadingDialog.set_secondary_action(null);
        
        setTimeout(() => {
            this.hide();
            if (callback) callback();
        }, delay);
    },
    
    // Установить статус ошибки
    setError: function(message, submessage, showCloseButton = true) {
        if (!ETaxes.loadingDialog) return;

        // Update dialog title
        ETaxes.loadingDialog.set_title(__('Error'));

        // Change animation to error icon
        ETaxes.loadingDialog.$wrapper.find('.loading-animation').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>
        `);

        // Clear all existing text elements
        ETaxes.loadingDialog.$wrapper.find('#loading_title').text('');
        ETaxes.loadingDialog.$wrapper.find('#loading_submessage').remove();

        // Set error message
        const $msgElement = ETaxes.loadingDialog.$wrapper.find('#loading_message');
        if ($msgElement.length) {
            $msgElement.css({
                'color': '#d9534f',
                'font-weight': '500',
                'font-size': '14px',
                'margin-top': '15px'
            });

            if (submessage) {
                $msgElement.html(submessage.replace(/\n/g, '<br>'));
            } else {
                $msgElement.text(message);
            }
        }

        $('#verification_code_container').hide();
        
        if (showCloseButton) {
            ETaxes.loadingDialog.set_primary_action(__('Close'), () => this.hide());
        }
    },
    
    // Скрыть диалог
    hide: function() {
        if (ETaxes.loadingDialog) {
            try {
                ETaxes.loadingDialog.hide();
            } catch (e) {
                console.error("Error hiding loading dialog:", e);
            }
            ETaxes.loadingDialog = null;
        }
        ETaxes.cancelLoading = false;
    },
    
    // Получить HTML для диалога загрузки
    _getLoadingHTML: function(title, message, submessage) {
        return `
            <div class="text-center">
                <div class="loading-animation" 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" id="status_message">
                    <h4 id="loading_title">${title || __('Please wait...')}</h4>
                    <p id="loading_message">${message || __('The operation may take some time')}</p>
                    <p id="loading_submessage" style="${submessage ? '' : 'display:none'}">${submessage || ''}</p>
                </div>
                <div id="verification_code_container" 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">----</span>
                    </div>
                    <p style="margin-top: 5px; font-size: 12px; color: #666;">Verification Code</p>
                </div>
            </div>
        `;
    }
};

// ======= МОДУЛЬ АУТЕНТИФИКАЦИИ =======
ETaxes.auth = {
    // Проверить токен и обработать аутентификацию при необходимости
    checkAndProcess: function(callback) {
        ETaxes.utils.checkTokenValidity(function(isValid) {
            if (isValid) {
                callback();
            } else {
                frappe.confirm(
                    __('Your E-Taxes session has expired or authentication is required. Would you like to authenticate now?'),
                    function() {
                        ETaxes.auth.startProcess(callback);
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Authentication canceled. Operation cannot be completed.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            }
        });
    },
    
    // Начать процесс аутентификации
    startProcess: function(callback) {
        ETaxes.dialogs.showLoading(
            __('Starting Authentication'),
            __('Getting Asan Login settings...'),
            __('Please wait')
        );
        
        ETaxes.utils.getDefaultLogin(function(loginData) {
            if (loginData && loginData.found) {
                const asanLoginName = loginData.name;
                ETaxes.dialogs.updateLoading(
                    null,
                    __('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': asanLoginName },
                    callback: function(r) {
                        if (r.message && r.message.success) {
                            const bearerToken = r.message.bearer_token;
                            
                            if (r.message.verification_code) {
                                ETaxes.dialogs.showVerificationCode(r.message.verification_code);
                            }
                            
                            ETaxes.dialogs.updateLoading(
                                null,
                                __('Waiting for confirmation on your phone'),
                                __('Please check your phone and confirm the authentication request')
                            );
                            
                            ETaxes.auth.pollStatus(asanLoginName, bearerToken, function(success) {
                                if (success) {
                                    ETaxes.auth.complete(asanLoginName, callback);
                                } else {
                                    ETaxes.dialogs.setError(
                                        __('Authentication Failed'),
                                        __('Could not authenticate with Asan Imza')
                                    );
                                }
                            });
                        } else {
                            ETaxes.dialogs.setError(
                                __('Authentication Error'),
                                r.message ? r.message.message : __('Authentication request failed')
                            );
                        }
                    }
                });
            } else {
                ETaxes.dialogs.setError(
                    __('No Asan Login Settings'),
                    __('Please configure Asan Login settings first')
                );
            }
        }, false); // Не использовать кэш для аутентификации
    },
    
    // Опрос статуса аутентификации
    pollStatus: function(asanLoginName, bearerToken, callback) {
        let attempts = 0;
        let stopPolling = false;
        
        function pollStatusStep() {
            if (attempts >= ETaxes.AUTH_MAX_ATTEMPTS || stopPolling) {
                if (attempts >= ETaxes.AUTH_MAX_ATTEMPTS) {
                    ETaxes.dialogs.setError(
                        __('Authentication Timeout'),
                        __('The authentication request has timed out. Please try again.')
                    );
                    callback(false);
                }
                return;
            }
            
            attempts++;
            
            ETaxes.dialogs.updateLoading(
                null,
                __('Waiting for confirmation on your phone'),
                __('Please check your phone and confirm the authentication request') + 
                ' (' + attempts + '/' + ETaxes.AUTH_MAX_ATTEMPTS + ')'
            );
            
            frappe.call({
                method: 'invoice_az.auth.poll_auth_status',
                args: {
                    'asan_login_name': asanLoginName,
                    'bearer_token': bearerToken
                },
                callback: function(r) {
                    if (r.message && r.message.success) {
                        if (r.message.authenticated) {
                            stopPolling = true;
                            ETaxes.dialogs.setSuccess(
                                __('Authentication Successful'),
                                __('You are now authenticated with Asan Imza'),
                                function() {
                                    callback(true);
                                }
                            );
                        } else {
                            setTimeout(pollStatusStep, ETaxes.AUTH_POLL_INTERVAL);
                        }
                    } else {
                        stopPolling = true;
                        ETaxes.dialogs.setError(
                            __('Authentication Error'),
                            r.message ? r.message.message : __('An unknown error occurred')
                        );
                        callback(false);
                    }
                },
                error: function(err) {
                    console.error('Error during status check:', err);
                    setTimeout(pollStatusStep, ETaxes.AUTH_POLL_INTERVAL);
                }
            });
        }
        
        pollStatusStep();
    },
    
    // Завершение аутентификации
    complete: function(asanLoginName, callback) {
        ETaxes.dialogs.showLoading(
            __('Completing Authentication'),
            __('Getting certificates...'),
            __('Please wait')
        );
        
        frappe.call({
            method: 'invoice_az.auth.get_auth_certificates',
            args: { 'asan_login_name': asanLoginName },
            callback: function(certR) {
                if (certR.message && certR.message.success) {
                    ETaxes.dialogs.updateLoading(
                        null,
                        __('Certificates retrieved'),
                        __('Selecting certificate and taxpayer')
                    );
                    
                    frappe.call({
                        method: 'frappe.client.get',
                        args: {
                            doctype: 'Asan Login',
                            name: asanLoginName
                        },
                        callback: function(r) {
                            if (r.message && r.message.selected_certificate_json) {
                                try {
                                    const certData = JSON.parse(r.message.selected_certificate_json);
                                    const certName = r.message.selected_certificate;
                                    
                                    ETaxes.dialogs.updateLoading(
                                        null,
                                        __('Selecting certificate'),
                                        certName
                                    );
                                    
                                    ETaxes.auth._selectCertificate(asanLoginName, certData, certName, callback);
                                } catch (e) {
                                    console.error('Error parsing certificate:', e);
                                    ETaxes.dialogs.hide();
                                    ETaxes.auth._showCertificateSelector(certR.message.certificates, asanLoginName, callback);
                                }
                            } else {
                                ETaxes.dialogs.hide();
                                ETaxes.auth._showCertificateSelector(certR.message.certificates, asanLoginName, callback);
                            }
                        }
                    });
                } else {
                    ETaxes.dialogs.setError(
                        __('Error'),
                        certR.message ? certR.message.message : __('Failed to get certificates')
                    );
                }
            }
        });
    },
    
    // Выбор сертификата
    _selectCertificate: function(asanLoginName, certData, certName, callback) {
        frappe.call({
            method: 'invoice_az.auth.select_certificate',
            args: {
                'asan_login_name': asanLoginName,
                'certificate_data': certData,
                'certificate_name': certName
            },
            callback: function(r) {
                if (r.message && r.message.success) {
                    ETaxes.dialogs.updateLoading(
                        null,
                        __('Selecting taxpayer'),
                        __('Using certificate: ') + certName
                    );
                    
                    frappe.call({
                        method: 'invoice_az.auth.select_taxpayer',
                        args: { 'asan_login_name': asanLoginName },
                        callback: function(r) {
                            if (r.message && r.message.success) {
                                ETaxes.utils.clearCache(); // Очищаем кэш после успешной аутентификации
                                ETaxes.dialogs.setSuccess(
                                    __('Authentication Complete'),
                                    __('You can now access E-Taxes services'),
                                    callback
                                );
                            } else {
                                ETaxes.dialogs.setError(
                                    __('Error'),
                                    r.message ? r.message.message : __('Failed to select taxpayer')
                                );
                            }
                        }
                    });
                } else {
                    ETaxes.dialogs.setError(
                        __('Error'),
                        r.message ? r.message.message : __('Failed to select certificate')
                    );
                }
            }
        });
    },
    
    // Показать селектор сертификатов
    _showCertificateSelector: function(certificates, asanLoginName, callback) {
        if (!certificates || !certificates.length) {
            frappe.msgprint(__('No certificates available'));
            return;
        }
        
        let certHtml = '<div style="max-height: 400px; overflow-y: auto;"><table class="table table-bordered">';
        certHtml += '<thead><tr><th>Type</th><th>Name</th><th>ID</th><th>Position</th><th>Status</th><th></th></tr></thead><tbody>';
        
        certificates.forEach(function(cert, index) {
            let name = '';
            let id = '';
            
            if (cert.taxpayerType === 'individual' && cert.individualInfo) {
                name = cert.individualInfo.name || '';
                id = cert.individualInfo.fin || '';
            } else if (cert.legalInfo) {
                name = cert.legalInfo.name || '';
                id = cert.legalInfo.tin || cert.legalInfo.voen || '';
            }
            
            certHtml += '<tr>' +
                '<td>' + (cert.taxpayerType || '') + '</td>' +
                '<td>' + name + '</td>' +
                '<td>' + id + '</td>' +
                '<td>' + (cert.position || '') + '</td>' +
                '<td>' + (cert.hasAccess ? 'Active' : 'Inactive') + (cert.liquidated ? ' (Liquidated)' : '') + '</td>' +
                '<td><button class="btn btn-xs btn-primary select-cert" data-index="' + index + '">Select</button></td>' +
                '</tr>';
        });
        
        certHtml += '</tbody></table></div>';
        
        const dialog = new frappe.ui.Dialog({
            title: __('Select Certificate'),
            fields: [{
                fieldtype: 'HTML',
                fieldname: 'certificates',
                options: certHtml
            }]
        });
        
        dialog.show();
        
        dialog.$wrapper.find('.select-cert').on('click', function() {
            const index = $(this).data('index');
            const cert = certificates[index];
            
            let certName = '';
            if (cert.taxpayerType === 'individual' && cert.individualInfo) {
                certName = `${cert.individualInfo.name} (${cert.individualInfo.fin})`;
            } else if (cert.legalInfo) {
                certName = `${cert.legalInfo.name} (${cert.legalInfo.voen || cert.legalInfo.tin})`;
            } else {
                certName = `Certificate ${index + 1}`;
            }
            
            dialog.hide();
            
            ETaxes.dialogs.showLoading(
                __('Selecting Certificate'),
                __('Processing your selection...'),
                certName
            );
            
            ETaxes.auth._selectCertificate(asanLoginName, cert, certName, callback);
        });
    }
};

// ======= УПРАВЛЕНИЕ ОШИБКАМИ =======
ETaxes.errors = {
    // Добавить ошибку в лог
    add: function(invoiceData, errorType, errorMessage, additionalData = {}) {
        const errorEntry = {
            invoice_id: invoiceData.id || 'Unknown',
            serial_number: invoiceData.serialNumber || 'Unknown',
            sender_name: invoiceData.sender ? invoiceData.sender.name : 'Unknown',
            creation_date: invoiceData.creationDate || invoiceData.createdAt || invoiceData.date || 'Unknown',
            error_type: errorType,
            error_message: errorMessage,
            timestamp: new Date().toISOString(),
            ...additionalData
        };
        
        ETaxes.loadingErrors.push(errorEntry);
        console.error('E-Taxes Import Error:', errorEntry);
    },
    
    // Очистить лог ошибок
    clear: function() {
        frappe.confirm(
            __('Are you sure you want to clear the error log?'),
            function() {
                ETaxes.loadingErrors = [];
                frappe.show_alert({
                    message: __('Error log cleared'),
                    indicator: 'green'
                }, 2);
            }
        );
    },
    
    // Показать детальный лог ошибок
    showDetails: function() {
        if (ETaxes.loadingErrors.length === 0) {
            frappe.msgprint(__('No errors to display'));
            return;
        }
        
        let errorsHtml = '<div class="error-log-container">';
        
        ETaxes.loadingErrors.forEach(function(error, index) {
            let documentDate = 'No date';
            if (error.creation_date && error.creation_date !== 'Unknown') {
                try {
                    documentDate = moment(error.creation_date).format('DD.MM.YYYY');
                } catch (e) {
                    documentDate = 'Invalid date';
                }
            }
            
            errorsHtml += '<div class="error-item" style="margin-bottom: 20px; padding: 15px; border: 1px solid var(--border-color); border-radius: 6px; background: var(--bg-color);">';
            
            // Заголовок ошибки
            errorsHtml += '<div class="error-header" style="margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border-color);">';
            errorsHtml += '<div style="display: flex; justify-content: space-between; align-items: center;">';
            errorsHtml += '<h5 style="margin: 0; color: var(--text-color);">' + 
                          '<strong>' + (error.serial_number || error.invoice_id) + '</strong></h5>';
            errorsHtml += '<span class="label label-danger">' + error.error_type + '</span>';
            errorsHtml += '</div>';
            errorsHtml += '<small style="color: var(--text-muted);">' + error.sender_name + '</small>';
            errorsHtml += '</div>';
            
            // Сообщение об ошибке
            errorsHtml += '<div class="error-message" style="margin-bottom: 10px;">';
            errorsHtml += '<strong style="color: var(--text-color);">' + error.error_message + '</strong>';
            errorsHtml += '</div>';
            
            // Детали ошибки
            if (error.unmatched_items && error.unmatched_items.length > 0) {
                errorsHtml += '<div class="error-details">';
                errorsHtml += '<div style="font-weight: 600; margin-bottom: 5px; color: var(--text-color);">' + __('Unmapped items:') + '</div>';
                errorsHtml += '<ul style="margin: 0; padding-left: 20px; color: var(--text-muted);">';
                error.unmatched_items.forEach(function(item, idx) {
                    errorsHtml += '<li><strong>Row ' + (idx + 1) + ':</strong> ' + item.name;
                    if (item.code) {
                        errorsHtml += ' <em>(Code: ' + item.code + ')</em>';
                    }
                    errorsHtml += '</li>';
                });
                errorsHtml += '</ul></div>';
            } else if (error.unmatched_parties && error.unmatched_parties.length > 0) {
                errorsHtml += '<div class="error-details">';
                errorsHtml += '<div style="font-weight: 600; margin-bottom: 5px; color: var(--text-color);">' + __('Unmapped parties:') + '</div>';
                errorsHtml += '<ul style="margin: 0; padding-left: 20px; color: var(--text-muted);">';
                error.unmatched_parties.forEach(function(party, idx) {
                    errorsHtml += '<li><strong>Party ' + (idx + 1) + ':</strong> ' + party.name;
                    if (party.tin) {
                        errorsHtml += ' <em>(TIN: ' + party.tin + ')</em>';
                    }
                    if (party.type) {
                        errorsHtml += ' <span class="label label-info" style="font-size: 10px;">' + party.type + '</span>';
                    }
                    errorsHtml += '</li>';
                });
                errorsHtml += '</ul></div>';
            } else if (error.unmatched_units && error.unmatched_units.length > 0) {
                errorsHtml += '<div class="error-details">';
                errorsHtml += '<div style="font-weight: 600; margin-bottom: 5px; color: var(--text-color);">' + __('Unmapped units:') + '</div>';
                errorsHtml += '<ul style="margin: 0; padding-left: 20px; color: var(--text-muted);">';
                error.unmatched_units.forEach(function(unit, idx) {
                    errorsHtml += '<li><strong>Unit ' + (idx + 1) + ':</strong> ' + unit.name + '</li>';
                });
                errorsHtml += '</ul></div>';
            }
            
            errorsHtml += '<div style="text-align: right; margin-top: 10px;">';
            errorsHtml += '<small style="color: var(--text-muted);"><em>' + documentDate + '</em></small>';
            errorsHtml += '</div>';
            
            errorsHtml += '</div>';
        });
        
        errorsHtml += '</div>';
        
        // Статистика
        const errorTypes = {};
        ETaxes.loadingErrors.forEach(function(error) {
            errorTypes[error.error_type] = (errorTypes[error.error_type] || 0) + 1;
        });
        
        let statsHtml = '<div style="margin-bottom: 20px; padding: 15px; background: var(--bg-light); border-radius: 6px; border: 1px solid var(--border-color);">';
        statsHtml += '<div style="display: flex; justify-content: space-between; align-items: center;">';
        statsHtml += '<div>';
        statsHtml += '<strong style="color: var(--text-color);">' + __('Total Errors:') + '</strong> ' + ETaxes.loadingErrors.length + '<br>';
        statsHtml += '<span style="color: var(--text-muted);">';
        Object.keys(errorTypes).forEach(function(type, index) {
            if (index > 0) statsHtml += ' • ';
            statsHtml += type + ': ' + errorTypes[type];
        });
        statsHtml += '</span>';
        statsHtml += '</div>';
        statsHtml += '<div>';
        statsHtml += '<button class="btn btn-default btn-sm" id="export-csv-dialog-btn" style="margin-right: 5px;">' +
                     '<i class="fa fa-download"></i> ' + __('Export CSV') + '</button>';
        statsHtml += '<button class="btn btn-warning btn-sm" id="clear-log-dialog-btn">' +
                     '<i class="fa fa-trash"></i> ' + __('Clear') + '</button>';
        statsHtml += '</div></div>';
        
        const d = new frappe.ui.Dialog({
            title: __('Error Details') + ' (' + ETaxes.loadingErrors.length + ')',
            size: 'large',
            fields: [
                {
                    fieldname: 'stats_html',
                    fieldtype: 'HTML',
                    options: statsHtml
                },
                {
                    fieldname: 'errors_html',
                    fieldtype: 'HTML',
                    options: '<div style="max-height: 500px; overflow-y: auto;">' + errorsHtml + '</div>'
                }
            ],
            primary_action_label: __('Close'),
            primary_action: function() {
                d.hide();
            }
        });
        
        d.show();
        
        // Добавляем обработчики событий
        setTimeout(function() {
            $('#export-csv-dialog-btn').off('click').on('click', function() {
                ETaxes.errors.exportCSV();
            });
            
            $('#clear-log-dialog-btn').off('click').on('click', function() {
                ETaxes.errors.clear();
                d.hide();
            });
        }, 200);
    },
    
    // Экспорт в CSV
    exportCSV: function() {
        if (ETaxes.loadingErrors.length === 0) {
            frappe.msgprint(__('No errors to export'));
            return;
        }
        
        try {
            let csvContent = "data:text/csv;charset=utf-8,";
            csvContent += "Invoice ID,Serial Number,Date,Supplier,Error Type,Error Message,Timestamp\n";
            
            ETaxes.loadingErrors.forEach(function(error) {
                const cleanMessage = error.error_message.replace(/"/g, '""').replace(/\n/g, ' ').replace(/\r/g, ' ');
                const cleanSender = error.sender_name.replace(/"/g, '""');
                
                const row = [
                    error.invoice_id,
                    error.serial_number,
                    error.creation_date,
                    cleanSender,
                    error.error_type,
                    cleanMessage,
                    moment(error.timestamp).format('DD.MM.YYYY HH:mm:ss')
                ].map(function(field) {
                    return '"' + (field || '') + '"';
                }).join(',');
                
                csvContent += row + "\n";
            });
            
            const encodedUri = encodeURI(csvContent);
            const link = document.createElement("a");
            link.setAttribute("href", encodedUri);
            link.setAttribute("download", "etaxes_import_errors_" + moment().format('YYYY-MM-DD_HH-mm-ss') + ".csv");
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            
            frappe.show_alert({
                message: __('Error log exported successfully'),
                indicator: 'green'
            }, 3);
        } catch (e) {
            console.error('Export error:', e);
            frappe.show_alert({
                message: __('Failed to export error log'),
                indicator: 'red'
            }, 3);
        }
    },
    
    // Показать сводку результатов
    showSummary: function(totalInvoices, processedCount, errorsCount) {
        let title = '';
        let indicator = '';
        let message = '';
        
        if (errorsCount === 0) {
            title = __('Import Completed Successfully');
            indicator = 'green';
            message = __('All ') + totalInvoices + __(' invoices were imported successfully.');
            
            frappe.msgprint({
                title: title,
                indicator: indicator,
                message: message
            });
        } else {
            title = errorsCount === totalInvoices ? __('Import Failed') : __('Import Completed with Errors');
            indicator = processedCount > 0 ? 'orange' : 'red';
            
            message = '<div style="margin-bottom: 15px;">';
            if (processedCount > 0) {
                message += __('Successfully imported: ') + '<strong>' + processedCount + '</strong>' + __(' invoices') + '<br>';
            }
            message += __('Failed: ') + '<strong>' + errorsCount + '</strong>' + __(' invoices');
            message += '</div>';
            
            message += '<div style="text-align: center;">' +
                      '<button class="btn btn-primary btn-sm" id="view-error-details-btn" style="margin-right: 10px;">' +
                      '<i class="fa fa-list"></i> ' + __('View Error Details') + '</button>' +
                      '<button class="btn btn-default btn-sm" id="export-error-log-btn">' +
                      '<i class="fa fa-download"></i> ' + __('Export CSV') + '</button>' +
                      '</div>';
            
            const summaryDialog = frappe.msgprint({
                title: title,
                indicator: indicator,
                message: message
            });
            
            // Добавляем обработчики событий
            setTimeout(function() {
                $('#view-error-details-btn').off('click').on('click', function() {
                    summaryDialog.hide();
                    ETaxes.errors.showDetails();
                });
                
                $('#export-error-log-btn').off('click').on('click', function() {
                    ETaxes.errors.exportCSV();
                });
            }, 200);
        }
    }
};

// ======= МОДУЛЬ ИМПОРТА ИНВОЙСОВ =======
ETaxes.import = {
    // Показать диалог импорта из E-Taxes
    showDialog: function() {
        ETaxes.auth.checkAndProcess(function() {
            const minDate = moment("2020-01-01", "YYYY-MM-DD");
            
            const d = new frappe.ui.Dialog({
                title: __('Import invoice from E-Taxes'),
                fields: [
                    {
                        fieldname: 'date_range_section',
                        fieldtype: 'Section Break',
                        label: __('Period')
                    },
                    {
                        fieldname: 'creationDateFrom',
                        fieldtype: 'Date',
                        label: __('Date from'),
                        default: moment().subtract(1, 'month').format('YYYY-MM-DD')
                    },
                    {
                        fieldname: 'creationDateTo',
                        fieldtype: 'Date',
                        label: __('Date to'),
                        default: moment().format('YYYY-MM-DD')
                    },
                    {
                        fieldname: 'settings_section',
                        fieldtype: 'Section Break',
                        label: __('Settings')
                    },
                    {
                        fieldname: 'warehouse',
                        fieldtype: 'Link',
                        label: __('Default warehouse'),
                        options: 'Warehouse',
                        reqd: true,
                        get_query: function() {
                            return {
                                filters: {
                                    'is_group': 0,
                                    'disabled': 0
                                }
                            };
                        }
                    }
                ],
                primary_action_label: __('Search'),
                primary_action: function() {
                    const values = d.get_values();
                    
                    // Validate date range
                    const fromDateMoment = moment(values.creationDateFrom, "YYYY-MM-DD");
                    const toDateMoment = moment(values.creationDateTo, "YYYY-MM-DD");
                    const todayMoment = moment();
                    
                    if (fromDateMoment.isBefore(minDate)) {
                        frappe.msgprint(__('From Date cannot be earlier than January 1, 2020'));
                        return;
                    }
                    
                    if (toDateMoment.isAfter(todayMoment)) {
                        frappe.msgprint(__('To Date cannot be later than today'));
                        return;
                    }
                    
                    if (!values.warehouse) {
                        frappe.msgprint({
                            title: __('Warning'),
                            indicator: 'orange',
                            message: __('Please select a default warehouse')
                        });
                        return;
                    }
                    
                    const fromDate = moment(values.creationDateFrom).format('DD-MM-YYYY 00:00');
                    const toDate = moment(values.creationDateTo).format('DD-MM-YYYY 23:59');
                    
                    d.hide();
                    ETaxes.import.loadInvoices(fromDate, toDate, values.warehouse);
                }
            });
            
            d.show();
        });
    },
    
    // Загрузить инвойсы с фильтрацией дубликатов
    loadInvoices: function(fromDate, toDate, warehouse, accumulatedInvoices = [], offset = 0) {
        ETaxes.cancelLoading = false;
        $(document).off('progress-cancel.etaxes_import');
        
        if (offset === 0) {
            frappe.show_alert({
                message: __('Fetching E-Taxes invoices...'),
                indicator: 'blue'
            }, 3);
        }
        
        ETaxes.utils.getDefaultLogin(function(loginResponse) {
            if (ETaxes.cancelLoading) return;
            
            if (loginResponse && loginResponse.found) {
                const mainToken = loginResponse.main_token;
                
                if (!mainToken) {
                    frappe.msgprint({
                        title: __('Authentication Error'),
                        indicator: 'red',
                        message: __('Authentication token not found. Please complete the authentication process in E-Taxes settings.')
                    });
                    return;
                }
                
                const maxCount = 200;
                
                frappe.call({
                    method: 'invoice_az.api.get_invoices',
                    args: {
                        'token': mainToken,
                        'filters': JSON.stringify({
                            "creationDateFrom": fromDate,
                            "creationDateTo": toDate,
                            "maxCount": maxCount,
                            "offset": offset
                        })
                    },
                    callback: function(r) {
                        if (ETaxes.cancelLoading) return;
                        
                        if (r.message && !r.message.error) {
                            const currentInvoices = r.message.data || r.message.invoices || [];
                            const hasMore = r.message.hasMore || false;
                            const allInvoices = accumulatedInvoices.concat(currentInvoices);
                            
                            if (hasMore && currentInvoices.length > 0) {
                                const newOffset = offset + currentInvoices.length;
                                ETaxes.import.loadInvoices(fromDate, toDate, warehouse, allInvoices, newOffset);
                            } else {
                                if (allInvoices.length > 0) {
                                    frappe.show_alert({
                                        message: __('Processing ') + allInvoices.length + __(' invoices...'),
                                        indicator: 'blue'
                                    }, 3);
                                    
                                    ETaxes.import.filterDuplicates(allInvoices, mainToken, warehouse);
                                } else {
                                    frappe.msgprint({
                                        title: __('Information'),
                                        indicator: 'blue',
                                        message: __('No invoices found for the specified period')
                                    });
                                }
                            }
                        } else if (r.message && r.message.error === 'unauthorized') {
                            frappe.confirm(
                                __('Your E-Taxes session has expired. Would you like to authenticate now?'),
                                function() {
                                    ETaxes.auth.startProcess(function() {
                                        ETaxes.import.loadInvoices(fromDate, toDate, warehouse);
                                    });
                                },
                                function() {
                                    frappe.show_alert({
                                        message: __('Authentication canceled. Operation cannot be completed.'),
                                        indicator: 'red'
                                    }, 5);
                                }
                            );
                        } else {
                            frappe.msgprint({
                                title: __('Error'),
                                indicator: 'red',
                                message: r.message ? r.message.message : __('Error loading invoices')
                            });
                        }
                    },
                    error: function(xhr, status, error) {
                        console.error("Error fetching invoices:", error);
                        frappe.msgprint({
                            title: __('Network Error'),
                            indicator: 'red',
                            message: __('Error fetching data from server: ') + (error || 'Unknown error')
                        });
                    }
                });
            } else {
                frappe.msgprint({
                    title: __('Error'),
                    indicator: 'red',
                    message: __('E-Taxes authentication settings not found')
                });
            }
        });
    },
    
    // Фильтрация дубликатов
    filterDuplicates: function(allInvoices, token, warehouse) {
        frappe.call({
            method: 'invoice_az.api.get_etaxes_purchases',
            callback: function(etaxesR) {
                try {
                    if (ETaxes.cancelLoading) return;
                    
                    const importedInvoices = {};
                    
                    if (etaxesR.message && etaxesR.message.success && etaxesR.message.purchases) {
                        etaxesR.message.purchases.forEach(function(purchase) {
                            if (purchase.etaxes_id) {
                                const normId = String(purchase.etaxes_id).trim();
                                importedInvoices[normId] = true;
                            }
                        });
                    }
                    
                    const filteredInvoices = [];
                    
                    for (let i = 0; i < allInvoices.length; i++) {
                        const invoice = allInvoices[i];
                        const invoiceId = String(invoice.id).trim();
                        
                        if (!importedInvoices.hasOwnProperty(invoiceId)) {
                            filteredInvoices.push(invoice);
                        }
                    }
                    
                    if (filteredInvoices.length > 0) {
                        ETaxes.import.showInvoiceSelection(filteredInvoices, token, warehouse);
                    } else {
                        frappe.msgprint({
                            title: __('Information'),
                            indicator: 'blue',
                            message: __('No new invoices found for the specified period (all ' + 
                                allInvoices.length + ' are already imported)')
                        });
                    }
                } catch (e) {
                    console.error("Error processing purchase data:", e);
                    frappe.msgprint({
                        title: __('Error'),
                        indicator: 'red',
                        message: __('An error occurred while processing data: ') + e.message
                    });
                }
            },
            error: function(err) {
                console.error("Error fetching purchases:", err);
                ETaxes.import.showInvoiceSelection(allInvoices, token, warehouse);
                frappe.show_alert({
                    message: __('Failed to check for duplicates. Showing all invoices.'),
                    indicator: 'orange'
                }, 5);
            }
        });
    },
    
    // Показать диалог выбора инвойсов
    showInvoiceSelection: function(invoices, token, warehouse) {
        let invoiceTable = '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered etaxes-invoices-table" style="width: 100%; table-layout: fixed;">';
        invoiceTable += '<thead><tr>' +
                    '<th style="width: 6%;"><input type="checkbox" class="select-all-invoices"></th>' +
                    '<th style="width: 24%;">' + __('Number') + '</th>' +
                    '<th style="width: 16%;">' + __('Date') + '</th>' +
                    '<th style="width: 38%;">' + __('Supplier') + '</th>' +
                    '<th style="width: 16%;">' + __('Amount') + '</th>' +
                    '</tr></thead><tbody>';
        
        invoices.forEach(function(invoice) {
            const serialNumber = invoice.serialNumber || '';
            
            let creationDate = '';
            if (invoice.createdAt) {
                creationDate = moment(invoice.createdAt).format('DD.MM.YYYY');
            } else if (invoice.creationDate) {
                creationDate = moment(invoice.creationDate).format('DD.MM.YYYY');
            }
            
            const senderName = invoice.sender ? invoice.sender.name : (invoice.senderName || '');
            const amount = invoice.totalAmount || invoice.amount || 0;
            
            invoiceTable += '<tr>' +
                        '<td><input type="checkbox" class="select-invoice" data-id="' + invoice.id + '"></td>' +
                        '<td style="word-break: break-word;">' + serialNumber + '</td>' +
                        '<td>' + creationDate + '</td>' +
                        '<td style="word-break: break-word;">' + senderName + '</td>' +
                        '<td style="text-align: right;">' + ETaxes.utils.formatCurrency(amount) + '</td>' +
                        '</tr>';
        });
        
        invoiceTable += '</tbody></table></div>';
        
        const infoMessage = '<div class="alert alert-info">' +
                           __('New invoices found: ') + invoices.length + 
                           '</div>';
        
        const d = new frappe.ui.Dialog({
            title: __('Select invoice'),
            size: 'large',
            fields: [
                {
                    fieldname: 'info_html',
                    fieldtype: 'HTML',
                    options: infoMessage
                },
                {
                    fieldname: 'invoices_html',
                    fieldtype: 'HTML',
                    options: invoiceTable
                },
                {
                    fieldname: 'warehouse_display',
                    fieldtype: 'HTML',
                    options: '<div class="row"><div class="col-xs-12"><div class="alert alert-info">' + 
                             __('Selected warehouse: ') + '<strong>' + warehouse + '</strong></div></div></div>'
                }
            ],
            primary_action_label: __('Load selected'),
            primary_action: function() {
                const selectedInvoiceIds = [];
                d.$wrapper.find('.select-invoice:checked').each(function() {
                    selectedInvoiceIds.push($(this).data('id'));
                });
                
                if (selectedInvoiceIds.length === 0) {
                    frappe.msgprint({
                        title: __('Warning'),
                        indicator: 'orange',
                        message: __('No invoices selected')
                    });
                    return;
                }
                
                d.hide();
                ETaxes.cancelLoading = false;
                ETaxes.import.loadSelectedInvoices(selectedInvoiceIds, token, warehouse);
            },
            secondary_action_label: __('Cancel'),
            secondary_action: function() {
                d.hide();
            }
        });
        
        d.$wrapper.find('.modal-dialog').css({
            'max-width': '80%',
            'width': '80%',
            'margin': '30px auto'
        });
        
        d.$wrapper.find('.modal-body').css({
            'padding': '15px'
        });
        
        d.show();
        
        // Обработчик для чекбокса "выбрать все"
        d.$wrapper.find('.select-all-invoices').on('change', function() {
            const isChecked = $(this).prop('checked');
            d.$wrapper.find('.select-invoice').prop('checked', isChecked);
        });
    },
    
    // Загрузка выбранных инвойсов
    loadSelectedInvoices: function(invoiceIds, token, warehouse, processedCount = 0, currentIndex = 0) {
        if (processedCount === 0 && currentIndex === 0) {
            ETaxes.loadingErrors = [];
            window.totalInvoicesToProcess = invoiceIds.length;
        }
        
        $(document).off('progress-cancel.loading_invoices');
        
        if (invoiceIds.length === 0) {
            frappe.hide_progress();
            
            const errorsCount = ETaxes.loadingErrors.length;
            const totalInvoices = window.totalInvoicesToProcess || processedCount;
            
            ETaxes.errors.showSummary(totalInvoices, processedCount, errorsCount);
            window.totalInvoicesToProcess = null;
            
            if (cur_list) {
                cur_list.refresh();
            }
            
            return;
        }
        
        if (ETaxes.cancelLoading) {
            invoiceIds = [];
            frappe.hide_progress();
            ETaxes.import.loadSelectedInvoices(invoiceIds, token, warehouse, processedCount, currentIndex);
            return;
        }
        
        const invoiceId = invoiceIds.shift();
        const isLastInvoice = invoiceIds.length === 0;
        const totalToProcess = window.totalInvoicesToProcess || (processedCount + invoiceIds.length + 1);
        
        currentIndex++;
        
        frappe.show_progress(__('Importing Invoices'), currentIndex - 1, totalToProcess, 
            __('Loading invoice ') + currentIndex + __(' of ') + totalToProcess, null, true);
        
        $(document).on('progress-cancel.loading_invoices', function() {
            ETaxes.cancelLoading = true;
            frappe.show_alert({
                message: __('Cancelling import... Finishing current invoice.'),
                indicator: 'orange'
            }, 3);
            frappe.hide_progress();
        });
        
        frappe.call({
            method: 'invoice_az.api.get_invoice_details',
            args: {
                'token': token,
                'invoice_id': invoiceId
            },
            callback: function(r) {
                if (r.message && !r.message.error) {
                    const creationDate = r.message.creationDate || r.message.date || frappe.datetime.nowdate();
                    const scheduleDate = moment(creationDate).format('YYYY-MM-DD');
                    const serialNumber = r.message.serialNumber || '';
                    const senderName = r.message.sender ? r.message.sender.name : '';
                    const total = r.message.totalAmount || r.message.amount || 0;
                    
                    frappe.show_progress(__('Importing Invoices'), currentIndex - 1, totalToProcess, 
                        __('Importing invoice: ') + serialNumber);
                    
                    frappe.call({
                        method: 'invoice_az.api.import_invoice_with_mapping',
                        args: {
                            'invoice_data': r.message,
                            'purchase_order_name': null,
                            'schedule_date': scheduleDate,
                            'warehouse': warehouse
                        },
                        callback: function(importR) {
                            ETaxes.import._handleImportResult(importR, r.message, invoiceId, scheduleDate, senderName, total, 
                                invoiceIds, token, warehouse, processedCount, currentIndex, isLastInvoice);
                        },
                        error: function(xhr, status, error) {
                            const errorMessage = 'Network error during import: ' + (error || 'Unknown network error');
                            ETaxes.errors.add(r.message, 'Network Error', errorMessage, {
                                invoice_items: r.message.items || [],
                                xhr_status: xhr.status,
                                xhr_response: xhr.responseText
                            });
                            
                            ETaxes.import._continueOrFinish(invoiceIds, token, warehouse, processedCount, currentIndex, isLastInvoice);
                        }
                    });
                } else if (r.message && r.message.error === 'unauthorized') {
                    frappe.hide_progress();
                    $(document).off('progress-cancel.loading_invoices');
                    
                    frappe.confirm(
                        __('Your E-Taxes session has expired. Would you like to authenticate now?'),
                        function() {
                            ETaxes.auth.startProcess(function() {
                                ETaxes.utils.getDefaultLogin(function(loginR) {
                                    if (loginR && loginR.found && loginR.main_token) {
                                        invoiceIds.unshift(invoiceId);
                                        ETaxes.import.loadSelectedInvoices(invoiceIds, loginR.main_token, warehouse, processedCount, currentIndex - 1);
                                    } else {
                                        ETaxes.errors.add({id: invoiceId}, 'Authentication Error', 
                                            'Failed to get token after authentication');
                                        
                                        const errorsCount = ETaxes.loadingErrors.length;
                                        ETaxes.errors.showSummary(totalToProcess, processedCount, errorsCount);
                                    }
                                }, false);
                            });
                        },
                        function() {
                            ETaxes.errors.add({id: invoiceId}, 'Authentication Cancelled', 
                                'User cancelled authentication process');
                            
                            const errorsCount = ETaxes.loadingErrors.length;
                            ETaxes.errors.showSummary(totalToProcess, processedCount, errorsCount);
                        }
                    );
                } else {
                    const errorMessage = r.message ? r.message.message : 'Failed to load invoice details';
                    ETaxes.errors.add({id: invoiceId}, 'Invoice Data Error', errorMessage, {
                        server_response: r.message
                    });
                    
                    ETaxes.import._continueOrFinish(invoiceIds, token, warehouse, processedCount, currentIndex, isLastInvoice);
                }
            },
            error: function(xhr, status, error) {
                const errorMessage = 'Network error loading invoice details: ' + (error || 'Unknown network error');
                ETaxes.errors.add({id: invoiceId}, 'Network Error', errorMessage, {
                    xhr_status: xhr.status,
                    xhr_response: xhr.responseText
                });
                
                ETaxes.import._continueOrFinish(invoiceIds, token, warehouse, processedCount, currentIndex, isLastInvoice);
            }
        });
    },
    
    // Обработка результата импорта
    _handleImportResult: function(importR, invoiceMessage, invoiceId, scheduleDate, senderName, total, 
                                 invoiceIds, token, warehouse, processedCount, currentIndex, isLastInvoice) {
        if (importR.message && importR.message.success) {
            frappe.show_alert({
                message: __('Invoice successfully imported: ') + (invoiceMessage.serialNumber || ''),
                indicator: 'green'
            }, 3);
            
            const purchaseOrderName = importR.message.purchase_order;
            
            frappe.call({
                method: 'invoice_az.api.create_etaxes_purchase',
                args: {
                    'etaxes_id': invoiceId,
                    'date': scheduleDate,
                    'party': senderName,
                    'total': total
                },
                callback: function(etaxesR) {
                    if (etaxesR.message && etaxesR.message.success) {
                        frappe.call({
                            method: 'invoice_az.api.link_purchase_order_to_etaxes',
                            args: {
                                'purchase_order': purchaseOrderName,
                                'etaxes_purchase': etaxesR.message.name
                            },
                            callback: function(linkR) {
                                processedCount++;
                                ETaxes.import._continueOrFinish(invoiceIds, token, warehouse, processedCount, currentIndex, isLastInvoice);
                            }
                        });
                    } else {
                        ETaxes.errors.add(invoiceMessage, 'E-Taxes Purchase Creation Error', 
                            etaxesR.message ? etaxesR.message.message : 'Failed to create E-Taxes Purchase record', {
                            server_response: etaxesR.message
                        });
                        
                        ETaxes.import._continueOrFinish(invoiceIds, token, warehouse, processedCount, currentIndex, isLastInvoice);
                    }
                }
            });
        } else if (importR.message && (importR.message.unmatched_items || importR.message.unmatched_parties || importR.message.unmatched_units)) {
            let errorType = '';
            const additionalData = { invoice_items: invoiceMessage.items || [] };
            
            if (importR.message.unmatched_items) {
                errorType = 'Unmapped Items';
                additionalData.unmatched_items = importR.message.unmatched_items;
            } else if (importR.message.unmatched_parties) {
                errorType = 'Unmapped Parties';
                additionalData.unmatched_parties = importR.message.unmatched_parties;
            } else if (importR.message.unmatched_units) {
                errorType = 'Unmapped Units';
                additionalData.unmatched_units = importR.message.unmatched_units;
            }
            
            additionalData.server_response = importR.message;
            ETaxes.errors.add(invoiceMessage, errorType, importR.message.message, additionalData);
            
            ETaxes.import._continueOrFinish(invoiceIds, token, warehouse, processedCount, currentIndex, isLastInvoice);
        } else {
            const errorMessage = importR.message ? importR.message.message : 'Unknown import error';
            const additionalData = {
                invoice_items: invoiceMessage.items || [],
                server_response: importR.message
            };
            
            if (importR.exc) {
                additionalData.stack_trace = importR.exc;
            }
            
            ETaxes.errors.add(invoiceMessage, 'Import Error', errorMessage, additionalData);
            ETaxes.import._continueOrFinish(invoiceIds, token, warehouse, processedCount, currentIndex, isLastInvoice);
        }
    },
    
    // Продолжить или завершить обработку
    _continueOrFinish: function(invoiceIds, token, warehouse, processedCount, currentIndex, isLastInvoice) {
        if (isLastInvoice) {
            frappe.hide_progress();
            $(document).off('progress-cancel.loading_invoices');
            
            const totalToProcess = window.totalInvoicesToProcess || processedCount;
            const errorsCount = ETaxes.loadingErrors.length;
            ETaxes.errors.showSummary(totalToProcess, processedCount, errorsCount);
            
            if (cur_list) {
                cur_list.refresh();
            }
            return;
        }
        
        setTimeout(function() {
            if (invoiceIds.length === 0) {
                frappe.hide_progress();
            }
            
            ETaxes.import.loadSelectedInvoices(invoiceIds, token, warehouse, processedCount, currentIndex);
        }, ETaxes.PROGRESS_UPDATE_DELAY);
    }
};


// ======= SALES INVOICE SPECIFIC CODE =======
/**
 * Sales Invoice Form and List Configuration
 * Uses ETaxes common module patterns for consistency
 */

frappe.ui.form.on('Sales Invoice', {
	refresh: function(frm) {
		// Check if is_taxes_doc flag is set
		if (frm.doc.is_taxes_doc) {
			// Make all fields read-only
			frm.set_read_only(true);

			// Add visual indicator
			frm.page.set_indicator(__('Tax Document'), 'blue');
		}

		// Add E-Taxes buttons only for submitted invoices
		if (frm.doc.docstatus === 1) {
			add_etaxes_buttons(frm);
		}

		// Add cancel button for cancelled invoices that were sent to E-Taxes
		if (frm.doc.docstatus === 2 && frm.doc.etaxes_invoice_id) {
			add_cancel_etaxes_button(frm);
		}
	},

	// Make is_taxes_doc field read-only when document loads
	onload: function(frm) {
		frm.set_df_property('is_taxes_doc', 'read_only', 1);
	}
});

/**
 * Add E-Taxes buttons based on current status
 */
function add_etaxes_buttons(frm) {
	// Add test buttons - always visible
	frm.add_custom_button(__('Test API - Services'), function() {
		test_product_groups_api(frm, 'service');
	}, __('E-Taxes'));

	frm.add_custom_button(__('Test API - Goods'), function() {
		test_product_groups_api(frm, 'good');
	}, __('E-Taxes'));

	// Status: Sent and Signed - show indicator and details button
	if (frm.doc.etaxes_send_status === 'Sent and Signed') {
		frm.page.set_indicator(__('Sent to E-Taxes'), 'green');

		// Add button to view details
		frm.add_custom_button(__('View E-Taxes Details'), function() {
			show_etaxes_details(frm);
		}, __('E-Taxes'));

		return;
	}

	// Status: Created, not signed - show warning and sign button
	if (frm.doc.etaxes_send_status === 'Created, not signed') {
		frm.page.set_indicator(__('Draft Created'), 'orange');

		// Add button to sign document
		frm.add_custom_button(__('Sign Document'), function() {
			sign_document(frm);
		}, __('E-Taxes'));

		// Add button to view details
		frm.add_custom_button(__('View Details'), function() {
			show_etaxes_details(frm);
		}, __('E-Taxes'));

		return;
	}

	// Status: Not sent - show send button
	frm.add_custom_button(__('Send to E-Taxes'), function() {
		send_to_etaxes(frm);
	}, __('E-Taxes'));
}

/**
 * Add cancel button for cancelled Sales Invoices that were sent to E-Taxes
 */
function add_cancel_etaxes_button(frm) {
	// Show indicator that invoice needs to be cancelled on E-Taxes
	frm.page.set_indicator(__('Cancelled - Remove from E-Taxes'), 'red');

	// Add button to cancel on E-Taxes
	frm.add_custom_button(__('Cancel on E-Taxes'), function() {
		cancel_invoice_on_etaxes(frm);
	}, __('E-Taxes'));
}

/**
 * Cancel invoice on E-Taxes system
 */
function cancel_invoice_on_etaxes(frm) {
	// Check authentication first
	ETaxes.auth.checkAndProcess(function() {
		// Show confirmation dialog
		frappe.confirm(
			__('Cancel this invoice on E-Taxes Government Portal?') + '<br><br>' +
			__('Invoice: {0}', [frm.doc.name]) + '<br>' +
			__('E-Taxes ID: {0}', [frm.doc.etaxes_invoice_id]) + '<br>' +
			__('Status: {0}', [frm.doc.etaxes_send_status]) + '<br><br>' +
			__('<strong>Warning:</strong> This will permanently remove the invoice from E-Taxes system.'),
			function() {
				// User confirmed - proceed with cancellation
				frappe.call({
					method: 'invoice_az.send_sales_api.cancel_invoice_on_etaxes',
					args: {
						sales_invoice_name: frm.doc.name
					},
					callback: function(r) {
						if (r.message && r.message.success) {
							// Success
							frappe.show_alert({
								message: __('Invoice successfully removed from E-Taxes'),
								indicator: 'green'
							}, 5);

							// Reload document to show updated status
							frm.reload_doc();
						} else {
							// Error
							const errorMsg = r.message ? r.message.message : __('Failed to cancel invoice on E-Taxes');
							frappe.msgprint({
								title: __('Error'),
								indicator: 'red',
								message: errorMsg
							});
						}
					},
					error: function(r) {
						frappe.msgprint({
							title: __('Error'),
							indicator: 'red',
							message: __('Failed to communicate with E-Taxes service.')
						});
					}
				});
			},
			function() {
				// User cancelled - do nothing
			}
		);
	});
}

/**
 * Main function to send invoice to E-Taxes (create draft)
 */
function send_to_etaxes(frm) {
	// Check authentication first
	ETaxes.auth.checkAndProcess(function() {
		// НОВОЕ: Сначала показываем диалог выбора объекта
		show_object_selection_dialog(frm);
	});
}

/**
 * Show object selection dialog for customer
 * This is the first step before sending to E-Taxes
 */
function show_object_selection_dialog(frm) {
	// Show loading
	ETaxes.dialogs.showLoading(
		__('Loading Customer Objects'),
		__('Fetching available objects from E-Taxes...'),
		__('Please wait')
	);

	// Call backend to get customer objects
	frappe.call({
		method: 'invoice_az.send_sales_api.get_customer_objects',
		args: {
			sales_invoice_name: frm.doc.name
		},
		callback: function(r) {
			// Add small delay to ensure loading dialog is fully rendered before hiding
			setTimeout(function() {
				// Hide loading dialog
				ETaxes.dialogs.hide();

				if (r.message && r.message.success) {
					const objects = r.message.objects || [];
					const customerName = r.message.customer_name || frm.doc.customer;
					const taxId = r.message.tax_id || '';

					if (objects.length === 0) {
						// No objects available
						frappe.msgprint({
							title: __('No Objects Available'),
							indicator: 'orange',
							message: __('Customer "{0}" (TIN: {1}) has no available objects in E-Taxes. Please contact the customer or E-Taxes support.', [customerName, taxId])
						});
						return;
					}

					// Show object selection dialog
					show_object_picker_dialog(frm, objects, customerName, taxId);
				} else {
					// Error getting objects
					const errorMsg = r.message ? r.message.message : __('Failed to load customer objects');
					frappe.msgprint({
						title: __('Error'),
						indicator: 'red',
						message: errorMsg
					});
				}
			}, 150); // Small delay to prevent race condition with fast API responses
		},
		error: function(r) {
			// Add small delay for error case too
			setTimeout(function() {
				ETaxes.dialogs.hide();

				let errorMsg = __('Failed to communicate with E-Taxes service.');

				// Try to extract actual error message
				if (r && r.responseText) {
					try {
						const errorData = JSON.parse(r.responseText);
						if (errorData.exc) {
							const excMatch = errorData.exc.match(/Exception: (.+)/);
							if (excMatch) {
								errorMsg = excMatch[1];
							}
						} else if (errorData.message) {
							errorMsg = errorData.message;
						}
					} catch (e) {
						// Ignore parsing errors
					}
				}

				frappe.msgprint({
					title: __('Error'),
					indicator: 'red',
					message: errorMsg
				});
			}, 150); // Small delay to prevent race condition
		}
	});
}

/**
 * Show dialog with object picker
 * User can select one object from the list
 */
function show_object_picker_dialog(frm, objects, customerName, taxId) {
	// Build objects table HTML
	let objectsHtml = '<div style="max-height: 400px; overflow-y: auto;">';
	objectsHtml += '<table class="table table-bordered">';
	objectsHtml += '<thead><tr>';
	objectsHtml += '<th style="width: 5%;"></th>';
	objectsHtml += '<th style="width: 35%;">' + __('Object Name') + '</th>';
	objectsHtml += '<th style="width: 20%;">' + __('Code') + '</th>';
	objectsHtml += '<th style="width: 40%;">' + __('Address') + '</th>';
	objectsHtml += '</tr></thead><tbody>';

	objects.forEach(function(obj, index) {
		const objectName = obj.name || '-';
		const objectCode = obj.code || '-';
		const objectAddress = obj.address || '-';

		objectsHtml += '<tr class="object-row" data-index="' + index + '" style="cursor: pointer;">';
		objectsHtml += '<td><input type="radio" name="object_selection" value="' + index + '" class="object-radio"></td>';
		objectsHtml += '<td>' + objectName + '</td>';
		objectsHtml += '<td>' + objectCode + '</td>';
		objectsHtml += '<td style="word-break: break-word;">' + objectAddress + '</td>';
		objectsHtml += '</tr>';
	});

	objectsHtml += '</tbody></table></div>';

	// Info message
	const infoHtml = '<div class="alert alert-info" style="margin-bottom: 15px;">' +
					'<strong>' + __('Customer:') + '</strong> ' + customerName + '<br>' +
					'<strong>' + __('TIN:') + '</strong> ' + taxId + '<br>' +
					'<strong>' + __('Available Objects:') + '</strong> ' + objects.length +
					'</div>';

	// Create dialog
	const d = new frappe.ui.Dialog({
		title: __('Select Customer Object'),
		size: 'large',
		fields: [
			{
				fieldname: 'info_html',
				fieldtype: 'HTML',
				options: infoHtml
			},
			{
				fieldname: 'objects_html',
				fieldtype: 'HTML',
				options: objectsHtml
			}
		],
		primary_action_label: __('Select and Continue'),
		primary_action: function() {
			// Get selected object
			const selectedIndex = d.$wrapper.find('input[name="object_selection"]:checked').val();

			if (selectedIndex === undefined) {
				frappe.msgprint({
					title: __('Warning'),
					indicator: 'orange',
					message: __('Please select an object')
				});
				return;
			}

			const selectedObject = objects[parseInt(selectedIndex)];

			// Hide dialog
			d.hide();

			// Save selected object code to customer_object_name
			// We use frappe.client.set_value to bypass read_only restriction
			frappe.call({
				method: 'frappe.client.set_value',
				args: {
					doctype: 'Sales Invoice',
					name: frm.doc.name,
					fieldname: 'customer_object_name',
					value: selectedObject.code
				},
				callback: function(r) {
					if (r.message) {
						// Make sure all dialogs are hidden
						ETaxes.dialogs.hide();

						// Refresh form to show updated value
						frm.reload_doc();

						// Wait for reload to complete before showing confirmation
						setTimeout(function() {
							// Show first confirmation dialog
							frappe.confirm(
								__('Send this Sales Invoice to Azerbaijan E-Taxes system?') + '<br><br>' +
								__('Invoice: {0}', [frm.doc.name]) + '<br>' +
								__('Customer: {0}', [frm.doc.customer]) + '<br>' +
								__('Object: {0}', [selectedObject.name]) + '<br>' +
								__('Total: {0}', [ETaxes.utils.formatCurrency(frm.doc.grand_total)]),
								function() {
									// First confirmation accepted - show second confirmation
									show_second_confirmation(frm);
								}
							);
						}, 300); // Small delay to ensure reload completes
					}
				}
			});
		},
		secondary_action_label: __('Cancel'),
		secondary_action: function() {
			d.hide();
		}
	});

	// Show dialog
	d.show();

	// Make dialog wider
	d.$wrapper.find('.modal-dialog').css({
		'max-width': '900px',
		'width': '90%'
	});

	// Add click handler for table rows
	d.$wrapper.find('.object-row').on('click', function() {
		const index = $(this).data('index');
		$(this).find('.object-radio').prop('checked', true);
	});

	// Automatically select first object
	d.$wrapper.find('.object-radio').first().prop('checked', true);
}

/**
 * Show second confirmation dialog
 */
function show_second_confirmation(frm) {
	frappe.confirm(
		__('Are you sure you want to send this invoice to E-Taxes?') + '<br><br>' +
		__('<strong>A draft will be created on E-Taxes system.</strong>') + '<br>' +
		__('You will need to sign it separately after creation.'),
		function() {
			// Second confirmation accepted - proceed with sending
			execute_send_to_etaxes(frm);
		}
	);
}

/**
 * Execute the actual sending to E-Taxes (create draft only)
 */
function execute_send_to_etaxes(frm) {
	// Show loading dialog using ETaxes common module
	ETaxes.dialogs.showLoading(
		__('Sending to E-Taxes'),
		__('Creating draft invoice...'),
		__('Please wait')
	);

	// Call backend API
	frappe.call({
		method: 'invoice_az.send_sales_api.send_sales_invoice_to_etaxes',
		args: {
			sales_invoice_name: frm.doc.name
		},
		callback: function(r) {
			if (r.message && r.message.success) {
				// Success
				const status = r.message.status;
				const serialNumber = r.message.serial_number;

				if (status === 'Sent and Signed') {
					// Fully completed (shouldn't happen with new workflow, but handle it)
					ETaxes.dialogs.setSuccess(
						__('Invoice Sent and Signed'),
						__('Serial: {0}', [serialNumber]),
						function() {
							frappe.show_alert({
								message: __('Successfully sent and signed!'),
								indicator: 'green'
							}, 5);
							frm.reload_doc();
						}
					);
				} else if (status === 'Created, not signed') {
					// Draft created successfully
					ETaxes.dialogs.setSuccess(
						__('Draft Created Successfully'),
						__('Serial: {0}', [serialNumber]),
						function() {
							frappe.msgprint({
								title: __('Draft Created'),
								indicator: 'blue',
								message: __('Invoice draft has been created on E-Taxes.') + '<br><br>' +
										 __('Serial Number: {0}', ['<strong>' + serialNumber + '</strong>']) + '<br><br>' +
										 __('Please use "Sign Document" button to complete the process.')
							});
							frm.reload_doc();
						}
					);
				} else {
					// Unknown status
					ETaxes.dialogs.hide();
					frappe.msgprint({
						title: __('Sent'),
						indicator: 'blue',
						message: r.message.message || __('Invoice sent to E-Taxes')
					});
					frm.reload_doc();
				}
			} else {
				// Error
				const errorMsg = r.message ? r.message.message : __('Unknown error occurred');
				ETaxes.dialogs.setError(
					__('Failed to Send'),
					errorMsg
				);
			}
		},
		error: function(r) {
			let errorMsg = __('Failed to communicate with E-Taxes service.');

			// Try to extract actual error message
			if (r && r.responseText) {
				try {
					const errorData = JSON.parse(r.responseText);
					if (errorData.exc) {
						// Extract error from exception
						const excMatch = errorData.exc.match(/Exception: (.+)/);
						if (excMatch) {
							errorMsg = excMatch[1];
						} else {
							// If no match, try to get last line
							const lines = errorData.exc.split('\n');
							errorMsg = lines[lines.length - 1] || errorData.exc.substring(0, 200);
						}
					} else if (errorData.message) {
						errorMsg = errorData.message;
					} else if (errorData._server_messages) {
						try {
							const messages = JSON.parse(errorData._server_messages);
							if (Array.isArray(messages) && messages.length > 0) {
								const msg = JSON.parse(messages[0]);
								errorMsg = msg.message || errorMsg;
							}
						} catch (e) {
							// Ignore parsing errors
						}
					}
				} catch (e) {
					// If parsing fails, use response text
					errorMsg = r.responseText.substring(0, 300);
				}
			} else if (r && r.statusText) {
				errorMsg = r.statusText;
			}

			ETaxes.dialogs.setError(
				__('Error'),
				errorMsg
			);
		}
	});
}

/**
 * Sign document on E-Taxes
 */
function sign_document(frm) {
	// Check authentication first
	ETaxes.auth.checkAndProcess(function() {
		frappe.confirm(
			__('Sign this invoice on E-Taxes?') + '<br><br>' +
			__('Serial: {0}', [frm.doc.etaxes_serial_number || '-']) + '<br><br>' +
			__('This will complete the sending process.'),
			function() {
				execute_signing(frm);
			}
		);
	});
}

/**
 * Execute the signing process
 */
function execute_signing(frm) {
	// Show loading dialog
	ETaxes.dialogs.showLoading(
		__('Signing Document'),
		__('Sending signature request...'),
		__('Please wait')
	);

	frappe.call({
		method: 'invoice_az.send_sales_api.retry_signing_invoice',
		args: {
			sales_invoice_name: frm.doc.name
		},
		callback: function(r) {
			if (r.message && r.message.success) {
				// Success
				const verificationCode = r.message.verification_code;

				ETaxes.dialogs.setSuccess(
					__('Document Signed Successfully'),
					__('Verification Code: {0}', [verificationCode || '-']),
					function() {
						frappe.show_alert({
							message: __('Invoice signed successfully!'),
							indicator: 'green'
						}, 5);
						frm.reload_doc();
					}
				);
			} else {
				// Error
				const errorMsg = r.message ? r.message.message : __('Signing failed');
				ETaxes.dialogs.setError(
					__('Signing Failed'),
					errorMsg
				);
			}
		},
		error: function(r) {
			let errorMsg = __('Failed to communicate with E-Taxes service.');

			// Try to extract actual error message
			if (r && r.responseText) {
				try {
					const errorData = JSON.parse(r.responseText);
					if (errorData.exc) {
						// Extract error from exception
						const excMatch = errorData.exc.match(/Exception: (.+)/);
						if (excMatch) {
							errorMsg = excMatch[1];
						} else {
							// If no match, try to get last line
							const lines = errorData.exc.split('\n');
							errorMsg = lines[lines.length - 1] || errorData.exc.substring(0, 200);
						}
					} else if (errorData.message) {
						errorMsg = errorData.message;
					} else if (errorData._server_messages) {
						try {
							const messages = JSON.parse(errorData._server_messages);
							if (Array.isArray(messages) && messages.length > 0) {
								const msg = JSON.parse(messages[0]);
								errorMsg = msg.message || errorMsg;
							}
						} catch (e) {
							// Ignore parsing errors
						}
					}
				} catch (e) {
					// If parsing fails, use response text
					errorMsg = r.responseText.substring(0, 300);
				}
			} else if (r && r.statusText) {
				errorMsg = r.statusText;
			}

			ETaxes.dialogs.setError(
				__('Error'),
				errorMsg
			);
		}
	});
}

/**
 * Show E-Taxes details for sent invoice
 * Hides technical information (invoice ID) from client
 */
function show_etaxes_details(frm) {
	let details_html = `
		<table class="table table-bordered">
			<tr>
				<th style="width: 40%;">${__('Serial Number')}</th>
				<td><strong>${frm.doc.etaxes_serial_number || '-'}</strong></td>
			</tr>
			<tr>
				<th>${__('Status')}</th>
				<td><strong>${frm.doc.etaxes_send_status || 'Not Sent'}</strong></td>
			</tr>
		</table>
		<div style="margin-top: 15px; padding: 10px; background-color: #f8f9fa; border-radius: 4px;">
			<p style="margin: 0; font-size: 12px; color: #6c757d;">
				${__('You can verify this invoice on the E-Taxes portal using the serial number above.')}
			</p>
		</div>
	`;

	frappe.msgprint({
		title: __('E-Taxes Details'),
		indicator: 'blue',
		message: details_html
	});
}

/**
 * Test Product Groups API function
 * @param {object} frm - The form object
 * @param {string} productType - Type of products to fetch ('service' or 'good')
 */
function test_product_groups_api(frm, productType) {
	productType = productType || 'service';
	const typeLabel = productType === 'service' ? __('Services') : __('Goods');

	// Show loading dialog
	ETaxes.dialogs.showLoading(
		__('Testing API'),
		__('Requesting {0} from E-Taxes...', [typeLabel]),
		__('Please wait')
	);

	// Call backend API
	frappe.call({
		method: 'invoice_az.api.test_product_groups_api',
		args: {
			product_type: productType
		},
		callback: function(r) {
			if (r.message && r.message.success) {
				// Success
				const count = r.message.count || 0;
				const data = r.message.data || [];

				ETaxes.dialogs.setSuccess(
					__('API Test Successful'),
					__('Received {0} product groups ({1})', [count, typeLabel]),
					function() {
						// Show detailed results
						let html = '<div style="max-height: 400px; overflow-y: auto;">';
						html += '<div style="margin-bottom: 10px; padding: 8px; background: #e8f5e9; border-radius: 4px;">';
						html += '<strong>Type:</strong> ' + typeLabel + ' | <strong>Count:</strong> ' + count;
						html += '</div>';

						if (Array.isArray(data) && data.length > 0) {
							html += '<table class="table table-bordered">';
							html += '<thead><tr><th>Code</th><th>Name</th><th>Type</th></tr></thead>';
							html += '<tbody>';

							data.slice(0, 10).forEach(function(item) {
								html += '<tr>';
								html += '<td>' + (item.code || '-') + '</td>';
								html += '<td>' + (item.name || '-') + '</td>';
								html += '<td>' + (item.type || '-') + '</td>';
								html += '</tr>';
							});

							html += '</tbody></table>';

							if (data.length > 10) {
								html += '<p style="text-align: center; color: #888;">Showing first 10 of ' + data.length + ' items</p>';
							}
						} else if (typeof data === 'object') {
							html += '<pre style="background: #f5f5f5; padding: 10px; border-radius: 4px;">';
							html += JSON.stringify(data, null, 2);
							html += '</pre>';
						} else {
							html += '<p>No data received</p>';
						}

						html += '</div>';

						frappe.msgprint({
							title: __('Product Groups Data - {0}', [typeLabel]),
							indicator: 'green',
							message: html
						});
					}
				);
			} else {
				// Error
				const errorMsg = r.message ? r.message.message : __('Unknown error occurred');
				ETaxes.dialogs.setError(
					__('API Test Failed'),
					errorMsg
				);
			}
		},
		error: function(r) {
			let errorMsg = __('Failed to communicate with E-Taxes service.');

			// Try to extract actual error message
			if (r && r.responseText) {
				try {
					const errorData = JSON.parse(r.responseText);
					if (errorData.exc) {
						const excMatch = errorData.exc.match(/Exception: (.+)/);
						if (excMatch) {
							errorMsg = excMatch[1];
						} else {
							const lines = errorData.exc.split('\n');
							errorMsg = lines[lines.length - 1] || errorData.exc.substring(0, 200);
						}
					} else if (errorData.message) {
						errorMsg = errorData.message;
					}
				} catch (e) {
					errorMsg = r.responseText.substring(0, 300);
				}
			} else if (r && r.statusText) {
				errorMsg = r.statusText;
			}

			ETaxes.dialogs.setError(
				__('Error'),
				errorMsg
			);
		}
	});
}

/**
 * List view settings
 */
frappe.listview_settings['Sales Invoice'] = {
	onload: function(listview) {
		// Add field as column (proper way)
		listview.columns.push({
			type: 'Check',
			df: {
				label: __('Tax Doc'),
				fieldname: 'is_taxes_doc'
			},
			width: 120
		});

		// Add E-Taxes status column
		listview.columns.push({
			type: 'Select',
			df: {
				label: __('E-Taxes Status'),
				fieldname: 'etaxes_send_status'
			},
			width: 150
		});

		// Force refresh list with new columns
		listview.refresh();
	},

	// Format is_taxes_doc field display
	formatters: {
		is_taxes_doc: function(value) {
			return value ?
				`<span class="indicator-pill green" title="${__('Tax Document')}"></span>` :
				`<span class="indicator-pill gray" title="${__('Regular Document')}"></span>`;
		},
		etaxes_send_status: function(value) {
			if (value === 'Sent and Signed') {
				return `<span class="indicator-pill green">${__('Sent and Signed')}</span>`;
			} else if (value === 'Created, not signed') {
				return `<span class="indicator-pill orange">${__('Draft Created')}</span>`;
			} else if (value === 'Not Sent') {
				return `<span class="indicator-pill gray">${__('Not Sent')}</span>`;
			}
			return value || '';
		}
	}
};
