// ======= ОБЩИЕ УТИЛИТЫ И КОНСТАНТЫ =======
const VATETaxes = {
    // Константы
    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 минут
    }
};

// ======= БАЗОВЫЕ УТИЛИТЫ =======
VATETaxes.utils = {
    // Кэшированное получение настроек входа
    getDefaultLogin: function(callback, useCache = true) {
        const now = Date.now();

        if (useCache && VATETaxes.cache.defaultLogin && VATETaxes.cache.cacheTime &&
            (now - VATETaxes.cache.cacheTime) < VATETaxes.cache.cacheDuration) {
            callback(VATETaxes.cache.defaultLogin);
            return;
        }

        frappe.call({
            method: 'invoice_az.auth.get_default_asan_login',
            callback: function(r) {
                if (r.message) {
                    VATETaxes.cache.defaultLogin = r.message;
                    VATETaxes.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);
    },

    // Парсинг даты операции из формата "20250319154646"
    parseOperationDate: function(dateStr) {
        if (!dateStr || dateStr.length < 8) {
            return '';
        }
        const year = dateStr.substring(0, 4);
        const month = dateStr.substring(4, 6);
        const day = dateStr.substring(6, 8);
        return `${day}.${month}.${year}`;
    },

    // Гуманизация типа ошибки
    humanizeErrorType: function(errorType) {
        const errorTypeMap = {
            'customer_not_found': __('Customer Not Found'),
            'customer_creation_failed': __('Customer Creation Failed'),
            'account_not_found': __('Account Not Found'),
            'mapping_not_found': __('VAT Account Mapping Not Found'),
            'import_error': __('Import Error'),
            'network_error': __('Network Error'),
            'validation_error': __('Validation Error'),
            'duplicate': __('Duplicate'),
            'permission_error': __('Permission Error')
        };
        return errorTypeMap[errorType] || errorType;
    },

    // Очистка кэша
    clearCache: function() {
        VATETaxes.cache.defaultLogin = null;
        VATETaxes.cache.cacheTime = null;
    },

    // Получить красивое название типа операции
    getOperationTypeLabel: function(operationType) {
        return operationType || '-';
    }
};

// ======= ДИАЛОГИ ЗАГРУЗКИ =======
VATETaxes.dialogs = {
    // Показать диалог загрузки
    showLoading: function(title, message, submessage) {
        if (VATETaxes.loadingDialog) {
            this.updateLoading(title, message, submessage);
            return;
        }

        VATETaxes.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() {
                VATETaxes.cancelLoading = true;
                VATETaxes.loadingDialog.$wrapper.find('.primary-action').prop('disabled', true);
                VATETaxes.loadingDialog.$wrapper.find('.primary-action').html(__('Cancelling...'));
                $('#status_message p').text(__('Cancelling the operation.'));
            }
        });

        VATETaxes.cancelLoading = false;
        VATETaxes.loadingDialog.show();
        VATETaxes.loadingDialog.$wrapper.find('.modal-dialog').css('max-width', '450px');
    },

    // Обновить сообщение в диалоге
    updateLoading: function(title, message, submessage) {
        if (!VATETaxes.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 (VATETaxes.loadingDialog && code) {
            $('#verification_code').text(code);
            $('#verification_code_container').show();
        }
    },

    // Установить статус успеха
    setSuccess: function(message, submessage, callback, delay = 2000) {
        if (!VATETaxes.loadingDialog) {
            if (callback) callback();
            return;
        }

        VATETaxes.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();
        VATETaxes.loadingDialog.set_primary_action(null);
        VATETaxes.loadingDialog.set_secondary_action(null);

        setTimeout(() => {
            this.hide();
            if (callback) callback();
        }, delay);
    },

    // Установить статус ошибки
    setError: function(message, submessage, showCloseButton = true) {
        if (!VATETaxes.loadingDialog) return;

        VATETaxes.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>
        `);

        $('#loading_message').text(message);
        if (submessage !== undefined) {
            $('#loading_submessage').text(submessage);
            $('#loading_submessage').toggle(!!submessage);
        }

        $('#verification_code_container').hide();

        if (showCloseButton) {
            VATETaxes.loadingDialog.set_primary_action(__('Close'), () => this.hide());
        }
    },

    // Скрыть диалог
    hide: function() {
        if (VATETaxes.loadingDialog) {
            try {
                VATETaxes.loadingDialog.hide();
            } catch (e) {
                console.error("Error hiding loading dialog:", e);
            }
            VATETaxes.loadingDialog = null;
        }
        VATETaxes.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>
        `;
    }
};

// ======= МОДУЛЬ АУТЕНТИФИКАЦИИ =======
VATETaxes.auth = {
    // Проверить токен и обработать аутентификацию при необходимости
    checkAndProcess: function(callback) {
        VATETaxes.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() {
                        VATETaxes.auth.startProcess(callback);
                    },
                    function() {
                        frappe.show_alert({
                            message: __('Authentication canceled. Operation cannot be completed.'),
                            indicator: 'red'
                        }, 5);
                    }
                );
            }
        });
    },

    // Начать процесс аутентификации
    startProcess: function(callback) {
        VATETaxes.dialogs.showLoading(
            __('Starting Authentication'),
            __('Getting Asan Login settings...'),
            __('Please wait')
        );

        VATETaxes.utils.getDefaultLogin(function(loginData) {
            if (loginData && loginData.found) {
                const asanLoginName = loginData.name;
                VATETaxes.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) {
                                VATETaxes.dialogs.showVerificationCode(r.message.verification_code);
                            }

                            VATETaxes.dialogs.updateLoading(
                                null,
                                __('Waiting for confirmation on your phone'),
                                __('Please check your phone and confirm the authentication request')
                            );

                            VATETaxes.auth.pollStatus(asanLoginName, bearerToken, function(success) {
                                if (success) {
                                    VATETaxes.auth.complete(asanLoginName, callback);
                                } else {
                                    VATETaxes.dialogs.setError(
                                        __('Authentication Failed'),
                                        __('Could not authenticate with Asan Imza')
                                    );
                                }
                            });
                        } else {
                            VATETaxes.dialogs.setError(
                                __('Authentication Error'),
                                r.message ? r.message.message : __('Authentication request failed')
                            );
                        }
                    }
                });
            } else {
                VATETaxes.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 >= VATETaxes.AUTH_MAX_ATTEMPTS || stopPolling) {
                if (attempts >= VATETaxes.AUTH_MAX_ATTEMPTS) {
                    VATETaxes.dialogs.setError(
                        __('Authentication Timeout'),
                        __('The authentication request has timed out. Please try again.')
                    );
                    callback(false);
                }
                return;
            }

            attempts++;

            VATETaxes.dialogs.updateLoading(
                null,
                __('Waiting for confirmation on your phone'),
                __('Please check your phone and confirm the authentication request') +
                ' (' + attempts + '/' + VATETaxes.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;
                            VATETaxes.dialogs.setSuccess(
                                __('Authentication Successful'),
                                __('You are now authenticated with Asan Imza'),
                                function() {
                                    callback(true);
                                }
                            );
                        } else {
                            setTimeout(pollStatusStep, VATETaxes.AUTH_POLL_INTERVAL);
                        }
                    } else {
                        stopPolling = true;
                        VATETaxes.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, VATETaxes.AUTH_POLL_INTERVAL);
                }
            });
        }

        pollStatusStep();
    },

    // Завершение аутентификации
    complete: function(asanLoginName, callback) {
        VATETaxes.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) {
                    VATETaxes.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;

                                    VATETaxes.dialogs.updateLoading(
                                        null,
                                        __('Selecting certificate'),
                                        certName
                                    );

                                    VATETaxes.auth._selectCertificate(asanLoginName, certData, certName, callback);
                                } catch (e) {
                                    console.error('Error parsing certificate:', e);
                                    VATETaxes.dialogs.hide();
                                    VATETaxes.auth._showCertificateSelector(certR.message.certificates, asanLoginName, callback);
                                }
                            } else {
                                VATETaxes.dialogs.hide();
                                VATETaxes.auth._showCertificateSelector(certR.message.certificates, asanLoginName, callback);
                            }
                        }
                    });
                } else {
                    VATETaxes.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) {
                    VATETaxes.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) {
                                VATETaxes.utils.clearCache(); // Очищаем кэш после успешной аутентификации
                                VATETaxes.dialogs.setSuccess(
                                    __('Authentication Complete'),
                                    __('You can now access E-Taxes services'),
                                    callback
                                );
                            } else {
                                VATETaxes.dialogs.setError(
                                    __('Error'),
                                    r.message ? r.message.message : __('Failed to select taxpayer')
                                );
                            }
                        }
                    });
                } else {
                    VATETaxes.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();

            VATETaxes.dialogs.showLoading(
                __('Selecting Certificate'),
                __('Processing your selection...'),
                certName
            );

            VATETaxes.auth._selectCertificate(asanLoginName, cert, certName, callback);
        });
    }
};

// ======= УПРАВЛЕНИЕ ОШИБКАМИ =======
VATETaxes.errors = {
    // Добавить ошибку в лог
    add: function(operationData, errorType, errorMessage, additionalData = {}) {
        const errorEntry = {
            operation_id: operationData.id || 'Unknown',
            tin: operationData.tin || 'Unknown',
            name: operationData.name || 'Unknown',
            operation_date: operationData.operationDate || 'Unknown',
            error_type: errorType,
            error_message: errorMessage,
            timestamp: new Date().toISOString(),
            ...additionalData
        };

        VATETaxes.loadingErrors.push(errorEntry);
        console.error('VAT E-Taxes Import Error:', errorEntry);
    },

    // Очистить лог ошибок
    clear: function() {
        frappe.confirm(
            __('Are you sure you want to clear the error log?'),
            function() {
                VATETaxes.loadingErrors = [];
                frappe.show_alert({
                    message: __('Error log cleared'),
                    indicator: 'green'
                }, 2);
            }
        );
    },

    // Показать детальный лог ошибок
    showDetails: function() {
        if (VATETaxes.loadingErrors.length === 0) {
            frappe.msgprint(__('No errors to display'));
            return;
        }

        let errorsHtml = '<div class="error-log-container">';

        VATETaxes.loadingErrors.forEach(function(error, index) {
            let documentDate = 'No date';
            if (error.operation_date && error.operation_date !== 'Unknown') {
                try {
                    documentDate = VATETaxes.utils.parseOperationDate(error.operation_date);
                } 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 += '<span class="label label-danger">' + VATETaxes.utils.humanizeErrorType(error.error_type) + '</span>';
            errorsHtml += '</div>';
            errorsHtml += '<small style="color: var(--text-muted);">' + error.name + ' (TIN: ' + error.tin + ')</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.income || error.account_number || error.customer_name || error.operation_type) {
                errorsHtml += '<div class="error-details" style="margin-top: 10px; padding: 10px; background: var(--bg-light); border-radius: 4px; font-size: 0.9em;">';

                if (error.income) {
                    errorsHtml += '<div><strong>' + __('Amount:') + '</strong> ' + VATETaxes.utils.formatCurrency(error.income) + '</div>';
                }

                if (error.customer_name) {
                    errorsHtml += '<div><strong>' + __('Customer Name:') + '</strong> ' + error.customer_name + '</div>';
                }

                if (error.account_number) {
                    errorsHtml += '<div><strong>' + __('Missing Account:') + '</strong> ' + error.account_number + '</div>';
                }

                if (error.operation_type) {
                    let opTypeDisplay = error.operation_type;
                    if (error.expense_income_type) {
                        opTypeDisplay += ' (' + error.expense_income_type.toLowerCase() + ')';
                    }
                    errorsHtml += '<div><strong>' + __('Operation Type:') + '</strong> ' + opTypeDisplay + '</div>';
                }

                if (error.classification_code) {
                    errorsHtml += '<div><strong>' + __('Classification Code:') + '</strong> ' + error.classification_code + '</div>';
                }

                if (error.missing_tin) {
                    errorsHtml += '<div><strong>' + __('Missing TIN:') + '</strong> ' + error.missing_tin + '</div>';
                }

                errorsHtml += '</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 = {};
        VATETaxes.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> ' + VATETaxes.loadingErrors.length + '<br>';
        statsHtml += '<span style="color: var(--text-muted);">';
        Object.keys(errorTypes).forEach(function(type, index) {
            if (index > 0) statsHtml += ' • ';
            statsHtml += VATETaxes.utils.humanizeErrorType(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') + ' (' + VATETaxes.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() {
                VATETaxes.errors.exportCSV();
            });

            $('#clear-log-dialog-btn').off('click').on('click', function() {
                VATETaxes.errors.clear();
                d.hide();
            });
        }, 200);
    },

    // Экспорт в CSV
    exportCSV: function() {
        if (VATETaxes.loadingErrors.length === 0) {
            frappe.msgprint(__('No errors to export'));
            return;
        }

        try {
            let csvContent = "data:text/csv;charset=utf-8,";
            csvContent += "Operation ID,Date,TIN,Name,Error Type,Error Message,Timestamp\n";

            VATETaxes.loadingErrors.forEach(function(error) {
                const cleanMessage = error.error_message.replace(/"/g, '""').replace(/\n/g, ' ').replace(/\r/g, ' ');
                const cleanName = error.name.replace(/"/g, '""');

                const row = [
                    error.operation_id,
                    error.operation_date,
                    error.tin,
                    cleanName,
                    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", "vat_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(totalOperations, processedCount, errorsCount, createAsDraft = 0) {
        let title = '';
        let indicator = '';
        let message = '';

        if (errorsCount === 0) {
            title = __('Import Completed Successfully');
            indicator = 'green';
            message = __('All ') + totalOperations + __(' VAT operations were imported successfully.');
            if (createAsDraft) {
                message += ' ' + __('(created as Draft)');
            }

            frappe.msgprint({
                title: title,
                indicator: indicator,
                message: message
            });
        } else {
            title = errorsCount === totalOperations ? __('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>' + __(' operations') + '<br>';
            }
            message += __('Failed: ') + '<strong>' + errorsCount + '</strong>' + __(' operations');
            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();
                    VATETaxes.errors.showDetails();
                });

                $('#export-error-log-btn').off('click').on('click', function() {
                    VATETaxes.errors.exportCSV();
                });
            }, 200);
        }
    }
};

// ======= МОДУЛЬ ИМПОРТА VAT ОПЕРАЦИЙ =======
VATETaxes.import = {
    // Показать диалог импорта из E-Taxes
    showDialog: function() {
        VATETaxes.auth.checkAndProcess(function() {
            const d = new frappe.ui.Dialog({
                title: __('Import VAT Operations 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: 'company',
                        fieldtype: 'Link',
                        label: __('Company'),
                        options: 'Company',
                        reqd: true,
                        default: frappe.defaults.get_user_default('Company')
                    }
                ],
                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 (toDateMoment.isAfter(todayMoment)) {
                        frappe.msgprint(__('To Date cannot be later than today'));
                        return;
                    }

                    if (fromDateMoment.isAfter(toDateMoment)) {
                        frappe.msgprint(__('From Date cannot be later than To Date'));
                        return;
                    }

                    if (!values.company) {
                        frappe.msgprint({
                            title: __('Warning'),
                            indicator: 'orange',
                            message: __('Please select a company')
                        });
                        return;
                    }

                    const fromDate = values.creationDateFrom;
                    const toDate = values.creationDateTo;
                    const createAsDraft = values.create_as_draft || 0;

                    d.hide();
                    VATETaxes.import.loadOperations(fromDate, toDate, values.company, [], 0, createAsDraft, 0);
                }
            });

            d.show();
        });
    },

    // Загрузить операции с фильтрацией дубликатов
    loadOperations: function(fromDate, toDate, company, accumulatedOperations = [], offset = 0, createAsDraft = 0, autoCreateCustomers = 0) {
        VATETaxes.cancelLoading = false;
        $(document).off('progress-cancel.vat_import');

        if (offset === 0) {
            frappe.show_alert({
                message: __('Fetching VAT operations from E-Taxes...'),
                indicator: 'blue'
            }, 3);
        }

        VATETaxes.utils.getDefaultLogin(function(loginResponse) {
            if (VATETaxes.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 = 50;

                frappe.call({
                    method: 'invoice_az.vat_api.get_vat_operations',
                    args: {
                        'token': mainToken,
                        'date_from': fromDate,
                        'date_to': toDate,
                        'max_count': maxCount,
                        'offset': offset
                    },
                    callback: function(r) {
                        if (VATETaxes.cancelLoading) return;

                        if (r.message && !r.message.error) {
                            const currentOperations = r.message.operations || [];
                            const hasMore = r.message.hasMore || false;
                            const allOperations = accumulatedOperations.concat(currentOperations);

                            if (hasMore && currentOperations.length > 0) {
                                const newOffset = offset + currentOperations.length;
                                VATETaxes.import.loadOperations(fromDate, toDate, company, allOperations, newOffset, createAsDraft, autoCreateCustomers);
                            } else {
                                if (allOperations.length > 0) {
                                    frappe.show_alert({
                                        message: __('Processing ') + allOperations.length + __(' VAT operations...'),
                                        indicator: 'blue'
                                    }, 3);

                                    VATETaxes.import.filterDuplicates(allOperations, mainToken, company, createAsDraft, autoCreateCustomers);
                                } else {
                                    frappe.msgprint({
                                        title: __('Information'),
                                        indicator: 'blue',
                                        message: __('No VAT operations 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() {
                                    VATETaxes.auth.startProcess(function() {
                                        VATETaxes.import.loadOperations(fromDate, toDate, company, [], 0, createAsDraft, autoCreateCustomers);
                                    });
                                },
                                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 VAT operations')
                            });
                        }
                    },
                    error: function(xhr, status, error) {
                        console.error("Error fetching VAT operations:", 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(allOperations, token, company, createAsDraft = 0, autoCreateCustomers = 0) {
        frappe.call({
            method: 'frappe.client.get_list',
            args: {
                doctype: 'E-Taxes VAT Operations',
                fields: ['operation_id'],
                limit_page_length: 0
            },
            callback: function(r) {
                try {
                    if (VATETaxes.cancelLoading) return;

                    const importedOperations = {};

                    if (r.message) {
                        r.message.forEach(function(op) {
                            if (op.operation_id) {
                                const normId = String(op.operation_id).trim();
                                importedOperations[normId] = true;
                            }
                        });
                    }

                    const filteredOperations = [];

                    for (let i = 0; i < allOperations.length; i++) {
                        const operation = allOperations[i];
                        const operationId = String(operation.id).trim();

                        if (!importedOperations.hasOwnProperty(operationId)) {
                            filteredOperations.push(operation);
                        }
                    }

                    if (filteredOperations.length > 0) {
                        VATETaxes.import.showOperationSelection(filteredOperations, token, company, createAsDraft, autoCreateCustomers);
                    } else {
                        frappe.msgprint({
                            title: __('Information'),
                            indicator: 'blue',
                            message: __('No new VAT operations found for the specified period (all ' +
                                allOperations.length + ' are already imported)')
                        });
                    }
                } catch (e) {
                    console.error("Error processing VAT operations data:", e);
                    frappe.msgprint({
                        title: __('Error'),
                        indicator: 'red',
                        message: __('An error occurred while processing data: ') + e.message
                    });
                }
            },
            error: function(err) {
                console.error("Error fetching VAT operations:", err);
                VATETaxes.import.showOperationSelection(allOperations, token, company, createAsDraft, autoCreateCustomers);
                frappe.show_alert({
                    message: __('Failed to check for duplicates. Showing all operations.'),
                    indicator: 'orange'
                }, 5);
            }
        });
    },

    // Показать диалог выбора операций
    showOperationSelection: function(operations, token, company, createAsDraft = 0) {
        let operationTable = '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered vat-operations-table" style="width: 100%; table-layout: fixed;">';
        operationTable += '<thead><tr>' +
                    '<th style="width: 3%;"><input type="checkbox" class="select-all-operations"></th>' +
                    '<th style="width: 9%;">' + __('Date') + '</th>' +
                    '<th style="width: 10%;">' + __('TIN') + '</th>' +
                    '<th style="width: 18%;">' + __('Name') + '</th>' +
                    '<th style="width: 18%;">' + __('Operation Type') + '</th>' +
                    '<th style="width: 11%;">' + __('Classification Code') + '</th>' +
                    '<th style="width: 13%;">' + __('Income') + '</th>' +
                    '<th style="width: 13%;">' + __('Expense') + '</th>' +
                    '</tr></thead><tbody>';

        operations.forEach(function(operation) {
            const operationDate = VATETaxes.utils.parseOperationDate(operation.operationDate);
            const tin = operation.tin || '';
            const name = operation.name || '';
            // Разделяем income и expense
            const income = operation.income || 0;
            const expense = operation.expense || 0;
            const operationType = VATETaxes.utils.getOperationTypeLabel(operation.operationType);

            // Извлекаем classification code из taxCodeInfo
            let classificationCode = '-';
            if (operation.taxCodeInfo && operation.taxCodeInfo.code) {
                classificationCode = operation.taxCodeInfo.code;
            }

            operationTable += '<tr>' +
                        '<td><input type="checkbox" class="select-operation" data-id="' + operation.id + '"></td>' +
                        '<td>' + operationDate + '</td>' +
                        '<td style="word-break: break-word;">' + tin + '</td>' +
                        '<td style="word-break: break-word;">' + name + '</td>' +
                        '<td style="word-break: break-word;">' + operationType + '</td>' +
                        '<td style="text-align: center;">' + classificationCode + '</td>' +
                        '<td style="text-align: right;">' + VATETaxes.utils.formatCurrency(income) + '</td>' +
                        '<td style="text-align: right;">' + VATETaxes.utils.formatCurrency(expense) + '</td>' +
                        '</tr>';
        });

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

        const infoMessage = '<div class="alert alert-info">' +
                           __('New VAT operations found: ') + operations.length +
                           '</div>';

        const d = new frappe.ui.Dialog({
            title: __('Select VAT Operations'),
            size: 'large',
            fields: [
                {
                    fieldname: 'info_html',
                    fieldtype: 'HTML',
                    options: infoMessage
                },
                {
                    fieldname: 'settings_section',
                    fieldtype: 'Section Break',
                    label: __('Import Settings')
                },
                {
                    fieldname: 'create_as_draft',
                    fieldtype: 'Check',
                    label: __('Create as Draft'),
                    default: createAsDraft,
                    description: __('If checked, Journal Entries will be created in Draft status instead of being submitted automatically')
                },
                {
                    fieldname: 'auto_create_customers',
                    fieldtype: 'Check',
                    label: __('Auto-create missing customers'),
                    default: 0,
                    description: __('If checked, will automatically create Customer records and mappings for TINs not found in the system')
                },
                {
                    fieldname: 'operations_section',
                    fieldtype: 'Section Break',
                    label: __('Operations')
                },
                {
                    fieldname: 'operations_html',
                    fieldtype: 'HTML',
                    options: operationTable
                },
                {
                    fieldname: 'company_display',
                    fieldtype: 'HTML',
                    options: '<div class="row"><div class="col-xs-12"><div class="alert alert-info">' +
                             __('Selected company: ') + '<strong>' + company + '</strong></div></div></div>'
                }
            ],
            primary_action_label: __('Load Selected'),
            primary_action: function() {
                const selectedOperationIds = [];
                d.$wrapper.find('.select-operation:checked').each(function() {
                    selectedOperationIds.push($(this).data('id'));
                });

                if (selectedOperationIds.length === 0) {
                    frappe.msgprint({
                        title: __('Warning'),
                        indicator: 'orange',
                        message: __('No operations selected')
                    });
                    return;
                }

                // Получить значения настроек из диалога
                const values = d.get_values();
                const createAsDraftValue = values.create_as_draft || 0;
                const autoCreateCustomers = values.auto_create_customers || 0;

                // Найти полные данные операций
                const selectedOperations = [];
                selectedOperationIds.forEach(function(id) {
                    const operation = operations.find(op => op.id === id);
                    if (operation) {
                        selectedOperations.push(operation);
                    }
                });

                d.hide();
                VATETaxes.cancelLoading = false;
                VATETaxes.import.loadSelectedOperations(selectedOperations, token, company, 0, 0, createAsDraftValue, autoCreateCustomers);
            },
            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-operations').on('change', function() {
            const isChecked = $(this).prop('checked');
            d.$wrapper.find('.select-operation').prop('checked', isChecked);
        });
    },

    // Загрузка выбранных операций
    loadSelectedOperations: function(operations, token, company, processedCount = 0, currentIndex = 0, createAsDraft = 0, autoCreateCustomers = 0) {
        if (processedCount === 0 && currentIndex === 0) {
            VATETaxes.loadingErrors = [];
            window.totalOperationsToProcess = operations.length;
        }

        $(document).off('progress-cancel.loading_operations');

        if (operations.length === 0) {
            const errorsCount = VATETaxes.loadingErrors.length;
            const totalOperations = window.totalOperationsToProcess || processedCount;

            // Искусственная задержка перед показом summary, чтобы прогресс-бар успел закрыться
            setTimeout(function() {
                // Закрываем прогресс-бар прямо перед показом summary
                frappe.hide_progress();

                // Дополнительная микрозадержка для гарантии
                setTimeout(function() {
                    VATETaxes.errors.showSummary(totalOperations, processedCount, errorsCount, createAsDraft);
                    window.totalOperationsToProcess = null;

                    if (cur_list) {
                        cur_list.refresh();
                    }
                }, 100);
            }, 500);

            return;
        }

        if (VATETaxes.cancelLoading) {
            operations = [];
            frappe.hide_progress();
            VATETaxes.import.loadSelectedOperations(operations, token, company, processedCount, currentIndex, createAsDraft, autoCreateCustomers);
            return;
        }

        const operation = operations.shift();
        const isLastOperation = operations.length === 0;
        const totalToProcess = window.totalOperationsToProcess || (processedCount + operations.length + 1);

        currentIndex++;

        frappe.show_progress(__('Importing VAT Operations'), currentIndex, totalToProcess,
            __('Processing operation ') + currentIndex + __(' of ') + totalToProcess, null, true);

        $(document).on('progress-cancel.loading_operations', function() {
            VATETaxes.cancelLoading = true;
            frappe.show_alert({
                message: __('Cancelling import... Finishing current operation.'),
                indicator: 'orange'
            }, 3);
            frappe.hide_progress();
        });

        // Импорт одной операции
        frappe.call({
            method: 'invoice_az.vat_api.import_vat_operations',
            args: {
                'operations_data': JSON.stringify([operation]),
                'company': company,
                'create_as_draft': createAsDraft,
                'auto_create_customers': autoCreateCustomers
            },
            callback: function(r) {
                VATETaxes.import._handleImportResult(r, operation,
                    operations, token, company, processedCount, currentIndex, isLastOperation, createAsDraft, autoCreateCustomers);
            },
            error: function(xhr, status, error) {
                const errorMessage = 'Network error during import: ' + (error || 'Unknown network error');
                VATETaxes.errors.add(operation, 'Network Error', errorMessage, {
                    xhr_status: xhr.status,
                    xhr_response: xhr.responseText
                });

                VATETaxes.import._continueOrFinish(operations, token, company, processedCount, currentIndex, isLastOperation, createAsDraft, autoCreateCustomers);
            }
        });
    },

    // Обработка результата импорта
    _handleImportResult: function(importR, operation, operations, token, company, processedCount, currentIndex, isLastOperation, createAsDraft = 0, autoCreateCustomers = 0) {
        if (importR.message && importR.message.success) {
            if (importR.message.imported > 0) {
                // НЕ показываем индивидуальные алерты во время массового импорта
                // Только счетчик в прогресс-баре
                processedCount++;
            } else if (importR.message.failed > 0 && importR.message.errors && importR.message.errors.length > 0) {
                const error = importR.message.errors[0];
                // Передаем ВСЕ данные ошибки включая tin, customer_name, income, account_number
                VATETaxes.errors.add(operation, error.error_type || 'Import Error', error.message, error);
            }

            VATETaxes.import._continueOrFinish(operations, token, company, processedCount, currentIndex, isLastOperation, createAsDraft, autoCreateCustomers);
        } else {
            const errorMessage = importR.message ? importR.message.message : 'Unknown import error';
            VATETaxes.errors.add(operation, 'Import Error', errorMessage, {
                server_response: importR.message
            });

            VATETaxes.import._continueOrFinish(operations, token, company, processedCount, currentIndex, isLastOperation, createAsDraft, autoCreateCustomers);
        }
    },

    // Продолжить или завершить обработку
    _continueOrFinish: function(operations, token, company, processedCount, currentIndex, isLastOperation, createAsDraft = 0, autoCreateCustomers = 0) {
        if (isLastOperation) {
            $(document).off('progress-cancel.loading_operations');

            const totalToProcess = window.totalOperationsToProcess || processedCount;
            const errorsCount = VATETaxes.loadingErrors.length;

            // Искусственная задержка перед показом summary, чтобы прогресс-бар успел закрыться
            setTimeout(function() {
                // Закрываем прогресс-бар прямо перед показом summary
                frappe.hide_progress();

                // Дополнительная микрозадержка для гарантии
                setTimeout(function() {
                    VATETaxes.errors.showSummary(totalToProcess, processedCount, errorsCount, createAsDraft);

                    if (cur_list) {
                        cur_list.refresh();
                    }
                }, 100);
            }, 500);

            return;
        }

        setTimeout(function() {
            if (operations.length === 0) {
                frappe.hide_progress();
            }

            VATETaxes.import.loadSelectedOperations(operations, token, company, processedCount, currentIndex, createAsDraft, autoCreateCustomers);
        }, VATETaxes.PROGRESS_UPDATE_DELAY);
    }
};

// ======= ОСНОВНЫЕ ОБРАБОТЧИКИ СПИСКОВ =======

// Journal Entry List
frappe.listview_settings['Journal Entry'] = {
    add_fields: ['posting_date', 'voucher_type', 'total_debit', 'total_credit', 'docstatus', 'expense_income_type'],

    get_indicator: function(doc) {
        if (doc.docstatus == 1) {
            return [__('Submitted'), 'blue', 'docstatus,=,1'];
        } else if (doc.docstatus == 0) {
            return [__('Draft'), 'red', 'docstatus,=,0'];
        } else if (doc.docstatus == 2) {
            return [__('Cancelled'), 'grey', 'docstatus,=,2'];
        }
    },

    formatters: {
        expense_income_type: function(value) {
            if (value === 'Income') {
                return '<span class="indicator-pill green">' + value + '</span>';
            } else if (value === 'Expense') {
                return '<span class="indicator-pill red">' + value + '</span>';
            }
            return value || '';
        }
    },

    onload: function(listview) {
        listview.page.add_menu_item(__('Import VAT Operations from E-Taxes'), function() {
            VATETaxes.import.showDialog();
        });

        listview.refresh();
    }
};
