// ======= ОБЩИЕ УТИЛИТЫ И КОНСТАНТЫ =======
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() {
                // Флаг ставим ПЕРЕД закрытием: hide() его больше не сбрасывает,
                // поэтому in-flight callback'и пагинации увидят отмену и выйдут.
                ETaxes.cancelLoading = true;
                ETaxes.dialogs.hide();
            }
        });

        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;

        ETaxes.loadingDialog.set_title(__('Error'));

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

        ETaxes.loadingDialog.$wrapper.find('#loading_title').text('');
        ETaxes.loadingDialog.$wrapper.find('#loading_submessage').remove();

        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() {
        // Мягкий loadingDialog.hide() в jey_theme/Bootstrap НЕ всегда убирает модал
        // (он зависает и следующий диалог накладывается сверху). Принудительно:
        // modal('hide') + remove() + чистка осиротевшего backdrop.
        // cancelLoading здесь НЕ сбрасываем — иначе отмена потеряется для in-flight
        // callback'ов; флаг сбрасывается в начале операции / при создании диалога.
        if (ETaxes.loadingDialog) {
            try {
                ETaxes.loadingDialog.$wrapper.modal('hide');
                ETaxes.loadingDialog.$wrapper.remove();
            } catch (e) {
                console.error("Error hiding loading dialog:", e);
            }
            ETaxes.loadingDialog = null;
        }
        if ($('.modal:visible').length === 0) {
            $('.modal-backdrop').remove();
            $('body').removeClass('modal-open');
        }
    },

    // Получить 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);
        });
    }
};
// ======= END ETaxes MODULE =======


// ======= COMPANY FORM: DATA LOADING =======
frappe.ui.form.on('Company', {
    refresh: function(frm) {
        if (frm.is_new()) return;
        frm.add_custom_button(__('Data Loading'), function() {
            show_data_loading_dialog(frm);
        }, __('E-Taxes'));
        render_all_reference_sections(frm);
    }
});

// ======= REFERENCE LIST SECTIONS (Tax Policy tab) =======

const REFERENCE_SECTIONS = [
    {
        doctype: 'E-Taxes Object',
        html_fieldname: 'objects_list_html',
        list_route: '/app/e-taxes-object',
        columns: [
            { label: 'Object Code', field: 'object_code', link_to_item: true },
            { label: 'Name',        field: 'object_name' },
            { label: 'Status',      field: 'object_status',
              indicator: { active: 'green', liquidated: 'red' } }
        ]
    },
    {
        doctype: 'E-Taxes Cash Register',
        html_fieldname: 'cash_registers_list_html',
        list_route: '/app/e-taxes-cash-register',
        columns: [
            { label: 'Serial Number', field: 'number', link_to_item: true },
            { label: 'Model',         field: 'model' },
            { label: 'E-Cash Status', field: 'ecash_status',
              indicator: { ACTIVE: 'green', ELIMINATED: 'red' } },
            { label: 'Object',        field: 'object',
              link_to: (v) => '/app/e-taxes-object/' + encodeURIComponent(v) },
            { label: 'Installed At',  field: 'installed_at', format: 'date' }
        ]
    },
    {
        doctype: 'E-Taxes POS Terminal',
        html_fieldname: 'pos_terminals_list_html',
        list_route: '/app/e-taxes-pos-terminal',
        columns: [
            { label: 'Registration Number', field: 'registration_number', link_to_item: true },
            { label: 'Serial Number',       field: 'serial_number' },
            { label: 'Status',              field: 'status',
              indicator: { A: 'green', C: 'red' } },
            { label: 'Registration Date',   field: 'registration_date', format: 'date' }
        ]
    },
    {
        doctype: 'E-Taxes Bank Account',
        html_fieldname: 'bank_accounts_list_html',
        list_route: '/app/e-taxes-bank-account',
        columns: [
            { label: 'Account Number', field: 'number', link_to_item: true },
            { label: 'Currency',       field: 'currency' },
            { label: 'Status',         field: 'status',
              indicator: { A: 'green', C: 'red' } },
            { label: 'Bank Name',      field: 'bank_name' }
        ]
    },
    {
        doctype: 'E-Taxes Presented Certificate',
        html_fieldname: 'presented_certificates_list_html',
        list_route: '/app/e-taxes-presented-certificate',
        columns: [
            { label: 'Cert No',   field: 'cert_no', link_to_item: true },
            { label: 'Taxpayer',  field: 'taxpayer_full_name' },
            { label: 'Category',  field: 'cert_category',
              indicator: { ACCEPTED: 'green', PRESENTED: 'blue', REJECTED: 'red', PENDING: 'orange' } }
        ]
    }
];

function render_all_reference_sections(frm) {
    // Defer to next tick so HTML fields are mounted in DOM.
    setTimeout(function() {
        REFERENCE_SECTIONS.forEach(function(section) {
            load_reference_section(frm, section);
        });
    }, 100);
}

function section_container(frm, section) {
    const field = frm.get_field(section.html_fieldname);
    return (field && field.$wrapper) ? field.$wrapper : null;
}

function load_reference_section(frm, section) {
    const $c = section_container(frm, section);
    if (!$c) return;

    frappe.call({
        method: 'invoice_az.company_api.get_company_reference_list',
        args: { doctype: section.doctype, company: frm.doc.name, limit: 50 },
        callback: function(r) {
            if (r.message && r.message.success) {
                render_reference_list(frm, section, r.message.data, r.message.total_count);
            } else {
                const error_msg = r.message ? r.message.message : 'Unknown error';
                $c.html(`<div class="form-section card-section">
                    <div class="section-body">
                        <div class="alert alert-warning">
                            <p>Error loading ${frappe.utils.escape_html(section.doctype)}: ${frappe.utils.escape_html(error_msg)}</p>
                            <button class="btn btn-sm btn-default retry-section-btn">Try Again</button>
                        </div>
                    </div>
                </div>`);
                $c.off('click', '.retry-section-btn').on('click', '.retry-section-btn', function() {
                    load_reference_section(frm, section);
                });
            }
        },
        error: function(xhr, status, error) {
            $c.html(`<div class="form-section card-section">
                <div class="section-body">
                    <div class="alert alert-danger">
                        <p>Network error loading ${frappe.utils.escape_html(section.doctype)}: ${frappe.utils.escape_html(error || '')}</p>
                        <button class="btn btn-sm btn-default retry-section-btn">Try Again</button>
                    </div>
                </div>
            </div>`);
            $c.off('click', '.retry-section-btn').on('click', '.retry-section-btn', function() {
                load_reference_section(frm, section);
            });
        }
    });
}

function render_reference_list(frm, section, rows, total_count) {
    const $c = section_container(frm, section);
    if (!$c) return;

    const esc = frappe.utils.escape_html;

    let html = `<div class="frappe-control" style="margin-bottom: 15px;">
        <div class="clearfix">
            <div class="pull-left">
                <h6 class="text-muted">${esc(section.doctype)} (${total_count} total)</h6>
            </div>
            <div class="pull-right">
                <button class="btn btn-xs btn-default refresh-section-btn">
                    <i class="octicon octicon-sync"></i> Refresh
                </button>
            </div>
        </div>
    </div>`;

    if (rows && rows.length > 0) {
        html += '<div class="form-section card-section">';
        html += '<div class="section-body">';
        html += '<table class="table table-bordered">';
        html += '<thead><tr>';
        section.columns.forEach(function(col) { html += '<th>' + esc(__(col.label)) + '</th>'; });
        html += '</tr></thead>';
        html += '<tbody>';

        rows.forEach(function(row) {
            html += '<tr>';
            section.columns.forEach(function(col) {
                const val = row[col.field];
                html += '<td>' + render_cell(row, col, val, section) + '</td>';
            });
            html += '</tr>';
        });

        html += '</tbody></table>';
        html += '</div>'; // section-body
        html += '</div>'; // form-section

        if (total_count > rows.length) {
            html += `<div class="text-center" style="margin-top: 10px;">
                <p class="text-muted small">Showing ${rows.length} of ${total_count}</p>
                <a href="${section.list_route}" class="btn btn-default btn-xs">View All ${esc(section.doctype)}</a>
            </div>`;
        }
    } else {
        html += '<div class="form-section card-section">';
        html += '<div class="section-body">';
        html += '<div class="empty-state">';
        html += '<p class="text-muted">No records found. Use "Data Loading" to import from E-Taxes.</p>';
        html += '</div>';
        html += '</div>';
        html += '</div>';
    }

    $c.html(html);

    $c.off('click', '.refresh-section-btn').on('click', '.refresh-section-btn', function() {
        $c.html('<div class="text-center" style="padding: 20px;"><i class="fa fa-spinner fa-spin"></i> Loading...</div>');
        load_reference_section(frm, section);
    });
}

function render_cell(row, col, val, section) {
    const esc = frappe.utils.escape_html;
    if (val == null || val === '') return '-';

    if (col.indicator) {
        const color = col.indicator[val] || 'gray';
        return '<span class="indicator-pill ' + color + '">' + esc(String(val)) + '</span>';
    }
    if (col.format === 'date') {
        return esc(frappe.datetime.str_to_user(val));
    }
    if (col.link_to_item) {
        return '<a href="' + section.list_route + '/' + encodeURIComponent(row.name) + '">' +
               esc(String(val)) + '</a>';
    }
    if (typeof col.link_to === 'function') {
        return '<a href="' + col.link_to(val) + '">' + esc(String(val)) + '</a>';
    }
    return esc(String(val));
}

// Ordered list of data types loadable from the Company → Data Loading dialog.
// Adding a new loader = append an entry here.
const DATA_LOADERS = [
    {
        key: 'load_objects',
        label: __('Load Objects'),
        description: __('Load company objects (taxpayer registered locations) from E-Taxes'),
        default: 1,
        method: 'invoice_az.company_api.load_company_objects',
        freezeMessage: __('Loading objects from E-Taxes...')
    },
    {
        key: 'load_cash_registers',
        label: __('Load Cash Registers'),
        description: __('Load cash registers (kassa aparatları) from E-Taxes. Uses pagination.'),
        default: 1,
        method: 'invoice_az.company_api.load_company_cash_registers',
        freezeMessage: __('Loading cash registers from E-Taxes...')
    },
    {
        key: 'load_pos_terminals',
        label: __('Load POS Terminals'),
        description: __('Load POS terminals from E-Taxes. Uses pagination.'),
        default: 1,
        method: 'invoice_az.company_api.load_company_pos_terminals',
        freezeMessage: __('Loading POS terminals from E-Taxes...')
    },
    {
        key: 'load_bank_accounts',
        label: __('Load Bank Accounts'),
        description: __('Load bank accounts (bank hesabları) from E-Taxes'),
        default: 1,
        method: 'invoice_az.company_api.load_company_bank_accounts',
        freezeMessage: __('Loading bank accounts from E-Taxes...')
    },
    {
        key: 'load_presented_certificates',
        label: __('Load Presented Certificates'),
        description: __('Load presented/accepted e-certificates from E-Taxes.'),
        default: 1,
        method: 'invoice_az.company_api.load_company_presented_certificates',
        freezeMessage: __('Loading presented certificates from E-Taxes...')
    }
];

function show_data_loading_dialog(frm) {
    const fields = [{
        fieldname: 'data_types_section',
        fieldtype: 'Section Break',
        label: __('Data Types to Load')
    }];

    DATA_LOADERS.forEach(function(loader) {
        fields.push({
            fieldname: loader.key,
            fieldtype: 'Check',
            label: loader.label,
            default: loader.default,
            description: loader.description
        });
    });

    const d = new frappe.ui.Dialog({
        title: __('Load Company Reference Data from E-Taxes'),
        fields: fields,
        size: 'small',
        primary_action_label: __('Load'),
        primary_action: function() {
            const values = d.get_values();
            const selected = DATA_LOADERS.filter(function(l) { return values[l.key]; });
            if (!selected.length) {
                frappe.msgprint(__('Please select at least one data type to load.'));
                return;
            }
            d.hide();
            ETaxes.auth.checkAndProcess(function() {
                run_data_loading(frm, selected);
            });
        }
    });
    d.show();
}

const PROGRESS_EVENT = 'company_data_loading_progress';
const COMPLETE_EVENT = 'company_data_loading_complete';

function run_data_loading(frm, loaders) {
    const keys = loaders.map(function(l) { return l.key; });

    // Handlers are closed over per-run so we can detach cleanly at end
    let progress_handler = null;
    let complete_handler = null;
    // Защита от гонки realtime: 'complete' вызывает hide_progress() (обнуляет
    // frappe.cur_progress). Опоздавший 'progress' иначе пересоздаёт модал, который
    // уже никто не закрывает. Флаг делает обработчик прогресса no-op после finish.
    let importFinished = false;
    // Надёжное закрытие прогресс-бара: frappe.hide_progress() в этом окружении
    // (jey_theme/Bootstrap) не всегда убирает модал — он зависает. Принудительно.
    const closeProgress = function() {
        if (frappe.cur_progress) {
            try {
                frappe.cur_progress.$wrapper.modal('hide');
                frappe.cur_progress.$wrapper.remove();
            } catch (e) {}
            frappe.cur_progress = null;
        }
        if ($('.modal:visible').length === 0) {
            $('.modal-backdrop').remove();
            $('body').removeClass('modal-open');
        }
    };

    const detach = function() {
        if (progress_handler) frappe.realtime.off(PROGRESS_EVENT, progress_handler);
        if (complete_handler) frappe.realtime.off(COMPLETE_EVENT, complete_handler);
        progress_handler = null;
        complete_handler = null;
    };

    progress_handler = function(data) {
        if (importFinished) return;
        if (!data || !data.total) return;
        const pct = Math.round((data.current / data.total) * 100);
        const desc = data.message || '';
        frappe.show_progress(__('Loading E-Taxes Data'), pct, 100, desc);
    };

    complete_handler = function(data) {
        importFinished = true;
        detach();
        closeProgress();

        if (data && data.error === 'unauthorized') {
            frappe.confirm(
                __('Your E-Taxes session has expired. Would you like to authenticate now?'),
                function() {
                    ETaxes.auth.checkAndProcess(function() {
                        run_data_loading(frm, loaders);
                    });
                }
            );
            return;
        }

        const lines = [];
        (data.summary || []).forEach(function(item) {
            const res = item.result || {};
            if (res.success) {
                lines.push('<b>' + item.label + ':</b> ' + (res.message || __('OK')));
            } else {
                lines.push('<b style="color:#d9534f">' + item.label + ':</b> ' +
                           (res.message || __('Unknown error')));
            }
        });

        frappe.msgprint({
            title: __('Data Loading Complete'),
            message: lines.join('<br>') || __('Nothing was loaded.'),
            indicator: 'green'
        });
    };

    frappe.realtime.on(PROGRESS_EVENT, progress_handler);
    frappe.realtime.on(COMPLETE_EVENT, complete_handler);

    frappe.show_progress(__('Loading E-Taxes Data'), 0, 100, __('Starting...'));

    frappe.call({
        method: 'invoice_az.company_api.load_company_data_bulk',
        args: { company: frm.doc.name, selections: JSON.stringify(keys) },
        callback: function(r) {
            const msg = r.message || {};
            if (!msg.enqueued) {
                detach();
                closeProgress();
                frappe.msgprint({
                    title: __('Failed to Start'),
                    message: msg.message || __('Could not enqueue the loading job.'),
                    indicator: 'red'
                });
            }
        },
        error: function() {
            detach();
            closeProgress();
        }
    });
}
