import { InvoiceFormatter } from './formatter.js';
import {
    Big, parseStrict, parseStrictOr, formatRaw, format2,
    setRaw, getRaw, markDirty, lineTotal as numericLineTotal, wireDatasetRaw, withinTolerance
} from './numeric.js';
import { getJSON, setJSON, cacheGet, cacheSet } from './storage.js';
import JSZip from './vendor/jszip.mjs';
import { validateCIF } from './validation/cif.js';
import { validateIBAN } from './validation/iban.js';
import { runBRRules } from './validation/br-ro.js';
import { probeReceiver, anafValidate, anafCifLookup, anafPdf } from './anaf.js';
import { catalogAdd, catalogSearch, catalogDelete } from './catalog.js';

// Constants
const XML_NAMESPACES = {
    ubl: "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2",
    cbc: "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2",
    cac: "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
};

const VAT_TYPES = {
    "S": "Cotă Standard",
    "AE": "Taxare Inversă",
    "O": "Neplătitor TVA",
    "Z": "Cotă 0% TVA",
    "E": "Neimpozabil"
};

// PR-TIPURI (A4): UN/CEFACT 1001 InvoiceTypeCode — subset folosit în RO.
//   380 = Factură comercială (default)
//   381 = Notă de credit (storno)
//   384 = Factură corectată (rectificare)
//   389 = Autofactură (self-billed)
const INVOICE_TYPES = {
    '380': 'Factură comercială',
    '381': 'Notă de credit',
    '384': 'Factură corectată',
    '389': 'Autofactură'
};

// PR-TODO (A5): cod-uri UN/CEFACT 4461 PaymentMeansCode folosite frecvent în RO.
const PAYMENT_MEANS_CODES = {
    '30': 'Transfer bancar',
    '10': 'Numerar',
    '48': 'Card',
    '58': 'Transfer SEPA',
    '42': 'Plată în cont furnizor',
    '49': 'Debit direct',
    '97': 'Compensare',
    '1': 'Instrument neidentificat'
};

const VAT_EXEMPTION_CODES = {
    'AE': {
        code: 'VATEX-EU-AE',
        reason: 'Taxare inversa'
    },
    'K': {
        code: 'VATEX-EU-IC',
        reason: 'Livrare intracomunitara'
    },
    'O': {
        code: 'VATEX-EU-O',
        reason: 'Neplatitor TVA'
    },
    'E': [
        {
            code: '',
            reason: 'Scutit'
        },
        {
            code: 'VATEX-EU-F',
            reason: 'Bunuri second hand'
        },
        {
            code: 'VATEX-EU-D',
            reason: 'Regim special agentii de turism'
        }
    ]
};

const UNIT_CODES = new Map([
    ['EA', 'Bucată (EA)'],
    ['XPP', 'Bucată (XPP)'],
    ['KGM', 'Kilogram (KGM)'],
    ['MTR', 'Metri (MTR)'],
    ['LTR', 'Litru (LTR)'],
    ['H87', 'Bucată (H87)'],
    ['MTQ', 'Metri cubi (MTQ)']
]);

const ISO_3166_1_CODES = new Set([
    'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AO', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 
    'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 
    'BR', 'BS', 'BT', 'BV', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 
    'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 
    'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 
    'GA', 'GB', 'GD', 'GE', 'GF', 'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 
    'GT', 'GU', 'GW', 'GY', 'HK', 'HM', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 
    'IO', 'IQ', 'IR', 'IS', 'IT', 'JE', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 
    'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 
    'LY', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 
    'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 
    'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 
    'PN', 'PR', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 
    'SD', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 
    'SX', 'SY', 'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 
    'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'UM', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 
    'VN', 'VU', 'WF', 'WS', 'XI', 'YE', 'YT', 'ZA', 'ZM', 'ZW'
]);

const ROMANIAN_COUNTY_CODES = new Set([
    'RO-AB', 'RO-AG', 'RO-AR', 'RO-B', 'RO-BC', 'RO-BH', 'RO-BN', 'RO-BR', 'RO-BT', 'RO-BV', 
    'RO-BZ', 'RO-CJ', 'RO-CL', 'RO-CS', 'RO-CT', 'RO-CV', 'RO-DB', 'RO-DJ', 'RO-GJ', 'RO-GL', 
    'RO-GR', 'RO-HD', 'RO-HR', 'RO-IF', 'RO-IL', 'RO-IS', 'RO-MH', 'RO-MM', 'RO-MS', 'RO-NT', 
    'RO-OT', 'RO-PH', 'RO-SB', 'RO-SJ', 'RO-SM', 'RO-SV', 'RO-TL', 'RO-TM', 'RO-TR', 'RO-VL', 
    'RO-VN', 'RO-VS'
]);

const CHARGE_REASON_CODES = {
    'TV': 'Cheltuieli de transport',
    'FC': 'Taxe transport',
    'ZZZ': 'Definite reciproc'
};

const ALLOWANCE_REASON_CODES = {
    '95': 'Reducere',
    '41': 'Bonus lucrări în avans',
    '42': 'Alt bonus',
    '60': 'Reducere volum',
    '62': 'Alte reduceri',
    '63': 'Reducere producător',
    '64': 'Din cauza războiului',
    '65': 'Reducere outlet nou',
    '66': 'Reducere mostre',
    '67': 'Reducere end-of-range',
    '68': 'Cost ambalaj returnabil',
    '70': 'Reducere Incoterm',
    '71': 'Prag vânzări',
    '88': 'Suprataxă/deducere materiale',
    '100': 'Reducere specială',
    '102': 'Termen lung fix',
    '103': 'Temporar',
    '104': 'Standard',
    '105': 'Cifră de afaceri anuală'
};

// Structure for item identifications
const IDENTIFICATION_TYPES = {
    SELLERS: {
        type: 'sellers',
        label: 'Cod Furnizor',
        xmlTag: 'SellersItemIdentification'
    },
    BUYERS: {
        type: 'buyers',
        label: 'Cod Client',
        xmlTag: 'BuyersItemIdentification'
    },
    STANDARD: {
        type: 'standard',
        label: 'Cod Bare',
        xmlTag: 'StandardItemIdentification',
        schemeID: '0160'
    },
    COMMODITY: {
        type: 'commodity',
        label: 'Cod Clasificare',
        xmlTag: 'CommodityClassification',
        schemes: [
            { id: 'CV', name: 'Cod Vamal' },
            { id: 'TSP', name: 'Cod CPV' },
            { id: 'STI', name: 'Cod NC8' }
        ]
    }
};

const formatter = new InvoiceFormatter()

const resolver = {
    lookupNamespaceURI: prefix => {
        const ns = {
            'cbc': 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
            'cac': 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
            'ubl': 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2'
        };
        return ns[prefix] || null;
    }
};

// Global variables
let currentInvoice = null;
let originalTotals = null;
let vatRates = new Map();
let manuallyEditedVatRows = new Set();

// PR-A14: Multi-XML bulk state
let _multiXmlFiles = [];   // [{name, content, dirty}]
let _activeFileIdx = -1;   // index în _multiXmlFiles (-1 = single-file mode)
let _loadingFile = false;  // suprimă dirty events cât timp parseXML populează formularul

// Initialize event listeners
document.addEventListener('DOMContentLoaded', async function() {
    document.getElementById('fileInput').addEventListener('change', handleFileSelect);
    setupDragAndDrop();
    initializeUI();
    
    if (!currentInvoice) {
        currentInvoice = createEmptyInvoice();
    }

    const totalElements = [
        'subtotal', 'totalAllowances', 'totalCharges', 
        'netAmount', 'vat', 'total'
    ];
    
    totalElements.forEach(elementId => {
        const element = document.getElementById(elementId);
        setupInlineEditing(element);
    });

    // Add currency code validation
    const currencyInputs = document.querySelectorAll('[name="documentCurrencyCode"], [name="taxCurrencyCode"]');
    currencyInputs.forEach(input => {
        input.addEventListener('input', function(e) {
            // Convert to uppercase
            this.value = this.value.toUpperCase();
            // Remove any non-letter characters
            this.value = this.value.replace(/[^A-Z]/g, '');
            // Limit to 3 characters
            if (this.value.length > 3) {
                this.value = this.value.slice(0, 3);
            }
        });
    });
    
    // Make document currency code required
    const documentCurrencyInput = document.querySelector('[name="documentCurrencyCode"]');
    if (documentCurrencyInput) {
        documentCurrencyInput.required = true;
    }    

    const supplierVATInput = document.querySelector('[name="supplierVAT"]');
    if (supplierVATInput) {
        supplierVATInput.addEventListener('change', function() {
            updateAllVATTypes();
        });
    }
        
    addExchangeRateField();

    initializeLocationSelectors();  
    
    // Verifică dacă avem parametru XML în URL
    const urlParams = new URLSearchParams(window.location.search);
    const xmlFileName = urlParams.get('xml');
    
    if (xmlFileName) {
        try {
            // Încarcă XML-ul din fișierul temporar
            const response = await fetch('temp/' + xmlFileName);
            if (response.ok) {
                const xmlContent = await response.text();
                parseXML(xmlContent);
                
                // Curăță fișierul temporar
                fetch('receiver.php?cleanup=' + xmlFileName)
                    .catch(error => console.error('Eroare la ștergerea fișierului temporar:', error));
            }
        } catch (error) {
            console.error('Eroare la încărcarea XML:', error);
        }
    }

    // Pre-populare număr factură din secvență dacă câmpul e gol
    const numEl = document.querySelector('[name="invoiceNumber"]');
    if (numEl && !numEl.value) {
        const seq = _seqRead();
        numEl.value = _seqFormat(seq);
    }
});

// Initialize event listeners for existing line items
document.querySelectorAll('.line-item').forEach((item, index) => {
    handleLineItemChange(index);
});

// Inline editing setup function
function setupInlineEditing(element) {
    let originalValue;

    element.addEventListener('click', function() {
        this.setAttribute('contenteditable', 'true');
        // Store exact displayed value
        originalValue = this.textContent;
        this.focus();
    });

    element.addEventListener('blur', function() {
        this.setAttribute('contenteditable', 'false');
        if (this.textContent !== originalValue) {
            updateTotals();
        }
    });

    element.addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
            event.preventDefault();
            this.blur();
        }
    });
}

function updateTotalDisplay(elementId, value) {
    const element = document.getElementById(elementId);
    if (element) {
        // Convertim la număr folosind parseFloat pentru a evita probleme de truncare
        const numValue = parseFloat(value);
        element.textContent = formatter.formatCurrency(numValue);
    }
}

function displayTotals(totals) {
    // Actualizează toate totalurile cu formatare
    updateTotalDisplay('subtotal', totals.subtotal);
    updateTotalDisplay('totalAllowances', totals.allowances);
    updateTotalDisplay('totalCharges', totals.charges);
    updateTotalDisplay('netAmount', totals.netAmount);
    updateTotalDisplay('vat', totals.totalVat);
    updateTotalDisplay('total', totals.total);

    // Actualizează defalcarea TVA dacă există
    const container = document.getElementById('vatBreakdownRows');
    if (container) {
        container.innerHTML = '';
        if (totals.vatBreakdown) {
            totals.vatBreakdown.forEach((data, key) => {
                const [rate, type] = key.split('-');
                addVATBreakdownRow(
                    parseFloat(rate),
                    data.baseAmount,
                    data.vatAmount,
                    type
                );
            });
        }
    }
}

function updateVATDisplay(row, amount, type = 'amount') {
    const input = row.querySelector(`.vat-${type}`);
    if (input) {
        input.value = formatter.formatCurrency(amount);
    }
}

function validateVATExemption() {
    const vatRows = document.querySelectorAll('.vat-row');
    let isValid = true;
    
    vatRows.forEach(row => {
        const vatType = row.querySelector('.vat-type').value;
        if (['E', 'K', 'AE', 'O'].includes(vatType)) {
            const exemptionCodeInput = row.querySelector('.vat-exemption-code');
            const exemptionReasonInput = row.querySelector('.vat-exemption-reason');
            const exemptionCode = exemptionCodeInput?.value;
            const exemptionReason = exemptionReasonInput?.value;
            
            // Pentru neplătitori de TVA (tip O), verificăm să aibă valorile corecte
            if (vatType === 'O') {
                if (exemptionCode !== 'VATEX-EU-O') {
                    isValid = false;
                    exemptionCodeInput?.classList.add('invalid');
                }
            }
            // Pentru celelalte tipuri de scutire, trebuie să aibă cel puțin unul dintre câmpuri completat
            else if (!exemptionCode && !exemptionReason) {
                isValid = false;
                exemptionCodeInput?.classList.add('invalid');
                exemptionReasonInput?.classList.add('invalid');
            } else {
                exemptionCodeInput?.classList.remove('invalid');
                exemptionReasonInput?.classList.remove('invalid');
            }
        }
    });

    return isValid;
}

function addDynamicVatExemptionCode(vatType, exemptionCode, exemptionReason) {
    if (!vatType || !exemptionCode) return;
    
    if (vatType === 'E') {
        // Verifică dacă codul există deja
        const exists = VAT_EXEMPTION_CODES.E.some(e => e.code === exemptionCode);
        if (!exists) {
            VAT_EXEMPTION_CODES.E.push({
                code: exemptionCode,
                reason: exemptionReason || exemptionCode
            });
        }
    } else if (!VAT_EXEMPTION_CODES[vatType]) {
        // Adaugă un nou tip de TVA dacă nu există
        VAT_EXEMPTION_CODES[vatType] = {
            code: exemptionCode,
            reason: exemptionReason || exemptionCode
        };
    }
}

function getDisplayValue(elementId) {
    const element = document.getElementById(elementId);
    return element ? formatter.parseCurrency(element.textContent) : 0;
}

// Event delegation for dynamic elements
document.addEventListener('click', function(event) {
    const target = event.target;
    
    if (target.matches('.delete-line-item')) {
        const lineItem = target.closest('.line-item');
        if (lineItem) {
            removeLineItem(parseInt(lineItem.dataset.index));
        }
    }
    
    if (target.matches('.delete-allowance-charge')) {
        const charge = target.closest('.allowance-charge');
        if (charge) {
            removeAllowanceCharge(parseInt(charge.dataset.index));
        }
    }
});

// File handling functions

// ZIP magic bytes: "PK\x03\x04" — local file header signature.
async function isZipFile(file) {
    if (!file || file.size < 4) return false;
    const head = await file.slice(0, 4).arrayBuffer();
    const b = new Uint8Array(head);
    return b[0] === 0x50 && b[1] === 0x4B && b[2] === 0x03 && b[3] === 0x04;
}

// Încarcă un fișier (XML simplu sau ZIP cu un XML eFactura înăuntru).
// Detectează ZIP pe magic bytes (PK\x03\x04). Fallback la text() pentru XML.
async function loadInvoiceFile(file) {
    if (!file) return;
    try {
        if (await isZipFile(file)) {
            const buf = await file.arrayBuffer();
            const zip = await JSZip.loadAsync(buf);
            const xmlEntries = Object.values(zip.files).filter(f => !f.dir && f.name.toLowerCase().endsWith('.xml'));
            if (xmlEntries.length === 0) {
                alert('Arhiva ZIP nu conține niciun fișier .xml.');
                return;
            }
            // Primul .xml din arhivă (sortat după nume pentru determinism).
            xmlEntries.sort((a, b) => a.name.localeCompare(b.name));
            const xmlContent = await xmlEntries[0].async('string');
            parseXML(xmlContent);
        } else {
            const xmlContent = await file.text();
            parseXML(xmlContent);
        }
    } catch (err) {
        console.error('Eroare la încărcarea fișierului:', err);
        alert('Nu s-a putut încărca fișierul: ' + (err && err.message ? err.message : err));
    }
}

function handleFileSelect(event) {
    const files = event.target.files;
    if (!files || files.length === 0) return;
    if (files.length === 1) {
        loadInvoiceFile(files[0]);
    } else {
        loadMultipleFiles(Array.from(files));
    }
    // Reset input so same file(s) can be re-selected
    event.target.value = '';
}

// ─────────────────────────────────────────────────────────
// PR-A14: Multi-XML bulk mode
// ─────────────────────────────────────────────────────────

/**
 * Citește conținutul text al unui fișier XML sau al primului XML dintr-un ZIP.
 * @param {File} file
 * @returns {Promise<string|null>} conținut XML sau null la eroare
 */
async function _readFileContent(file) {
    try {
        if (await isZipFile(file)) {
            const buf = await file.arrayBuffer();
            const zip = await JSZip.loadAsync(buf);
            const xmlEntries = Object.values(zip.files)
                .filter(f => !f.dir && f.name.toLowerCase().endsWith('.xml'));
            if (xmlEntries.length === 0) return null;
            xmlEntries.sort((a, b) => a.name.localeCompare(b.name));
            return await xmlEntries[0].async('string');
        } else {
            return await file.text();
        }
    } catch (err) {
        console.error('_readFileContent:', file.name, err);
        return null;
    }
}

/**
 * Încarcă mai multe fișiere XML/ZIP în modul bulk.
 * - Citește fișierele async cu yield între ele (responsivitate UI).
 * - Aplică limitarea la 50 de fișiere, cu toast de avertizare.
 * - Afișează sidebar-ul și încarcă primul fișier în formular.
 * @param {File[]} files
 */
async function loadMultipleFiles(files) {
    const MAX = 50;
    const existing = _multiXmlFiles.length;
    const available = Math.max(0, MAX - existing);
    let dropped = 0;

    if (files.length > available) {
        dropped = files.length - available;
        files = files.slice(0, available);
    }

    if (files.length === 0) {
        if (dropped > 0) {
            showToast(`Limita de ${MAX} fișiere atinsă — ${dropped} fișier(e) ignorat(e).`, 'warning');
        }
        return;
    }

    // Citire async cu yield între iterații
    const newEntries = [];
    for (const file of files) {
        const content = await _readFileContent(file);
        if (content !== null) {
            newEntries.push({ name: file.name, content, dirty: false });
        }
        // yield pentru ca UI să rămână responsiv
        await new Promise(r => setTimeout(r, 0));
    }

    if (newEntries.length === 0) {
        showToast('Niciun fișier XML valid găsit.', 'error');
        return;
    }

    const wasEmpty = _multiXmlFiles.length === 0;
    _multiXmlFiles.push(...newEntries);

    if (dropped > 0) {
        showToast(`Limita de ${MAX} fișiere: ${dropped} fișier(e) ignorat(e).`, 'warning');
    }

    // Prima activare: dacă nu era niciun fișier activ sau era single-file mode
    if (wasEmpty) {
        _activeFileIdx = 0;
    }
    // Altfel păstrăm indexul activ curent

    _renderXmlSidebar();
    _activateFile(_activeFileIdx, false /* nu salva — tocmai am intrat în bulk mode */);
}

/**
 * Salvează starea curentă a formularului înapoi în _multiXmlFiles[idx].content.
 * Apelat înaintea switch-ului de fișier.
 */
function _saveCurrentFileState() {
    if (_activeFileIdx < 0 || _activeFileIdx >= _multiXmlFiles.length) return;
    const xml = _currentXMLString();
    if (xml) {
        _multiXmlFiles[_activeFileIdx].content = xml;
    }
}

/**
 * Activează fișierul la indexul dat: parsează XML-ul în formular.
 * @param {number} idx
 * @param {boolean} [saveFirst=true] dacă să salveze starea fișierului activ înainte de switch
 */
function _activateFile(idx, saveFirst = true) {
    if (idx < 0 || idx >= _multiXmlFiles.length) return;

    if (saveFirst && _activeFileIdx >= 0 && _activeFileIdx !== idx) {
        _saveCurrentFileState();
    }

    _activeFileIdx = idx;
    const entry = _multiXmlFiles[idx];

    _loadingFile = true;
    parseXML(entry.content);
    // Suprimă dirty events generate de popularea formularului
    queueMicrotask(() => { _loadingFile = false; });

    _renderXmlSidebar();
}

/**
 * Marchează fișierul activ ca dirty (modificat).
 * Apelat din event delegation pe formularul de editare.
 */
function _markActiveDirty() {
    if (_loadingFile) return;
    if (_activeFileIdx < 0 || _activeFileIdx >= _multiXmlFiles.length) return;
    if (_multiXmlFiles[_activeFileIdx].dirty) return; // deja marcat
    _multiXmlFiles[_activeFileIdx].dirty = true;
    _updateSidebarItem(_activeFileIdx);
}

/** Redă întregul sidebar cu lista de fișiere. */
function _renderXmlSidebar() {
    const hasBulk = _multiXmlFiles.length >= 2;
    document.body.classList.toggle('has-xml-sidebar', hasBulk);

    if (!hasBulk) {
        const old = document.getElementById('xml-sidebar');
        if (old) old.remove();
        return;
    }

    let sidebar = document.getElementById('xml-sidebar');
    if (!sidebar) {
        sidebar = document.createElement('div');
        sidebar.id = 'xml-sidebar';
        sidebar.setAttribute('role', 'navigation');
        sidebar.setAttribute('aria-label', 'Fișiere XML');
        document.body.insertBefore(sidebar, document.body.firstChild);
    }

    sidebar.innerHTML = '';

    // Header
    const hdr = document.createElement('div');
    hdr.className = 'xml-sidebar-header';
    hdr.textContent = `Fișiere (${_multiXmlFiles.length})`;
    sidebar.appendChild(hdr);

    // Items
    const list = document.createElement('ul');
    list.className = 'xml-sidebar-list';
    _multiXmlFiles.forEach((entry, idx) => {
        const li = _buildSidebarItem(entry, idx);
        list.appendChild(li);
    });
    sidebar.appendChild(list);
}

/** Construiește un <li> pentru un fișier din sidebar. */
function _buildSidebarItem(entry, idx) {
    const li = document.createElement('li');
    li.className = 'xml-sidebar-item' + (idx === _activeFileIdx ? ' is-active' : '');
    li.dataset.idx = idx;
    li.title = entry.name;

    const nameSpan = document.createElement('span');
    nameSpan.className = 'xml-sidebar-item-name';
    nameSpan.textContent = entry.name;

    const dirtyDot = document.createElement('span');
    dirtyDot.className = 'xml-sidebar-dirty' + (entry.dirty ? ' is-dirty' : '');
    dirtyDot.title = entry.dirty ? 'Modificat (nesalvat)' : '';
    dirtyDot.setAttribute('aria-hidden', 'true');

    li.appendChild(nameSpan);
    li.appendChild(dirtyDot);

    li.addEventListener('click', () => {
        if (idx === _activeFileIdx) return;
        _activateFile(idx, true);
    });

    return li;
}

/** Actualizează doar un item din sidebar (fără re-render complet). */
function _updateSidebarItem(idx) {
    const sidebar = document.getElementById('xml-sidebar');
    if (!sidebar) return;
    const list = sidebar.querySelector('.xml-sidebar-list');
    if (!list) return;
    const items = list.querySelectorAll('.xml-sidebar-item');
    if (!items[idx]) return;
    const entry = _multiXmlFiles[idx];
    const old = items[idx];
    const replacement = _buildSidebarItem(entry, idx);
    list.replaceChild(replacement, old);
}

// Expune pe window pentru butonul "Salvează XML" în bulk mode
window.saveCurrentFileAndMark = function() {
    if (_activeFileIdx < 0) return;
    _saveCurrentFileState();
    _multiXmlFiles[_activeFileIdx].dirty = false;
    _updateSidebarItem(_activeFileIdx);
};

// ─────────────────────────────────────────────────────────

// Drag-and-drop: acceptă XML sau ZIP la drop pe oriunde în pagină.
function setupDragAndDrop() {
    const target = document.body;
    const prevent = (e) => { e.preventDefault(); e.stopPropagation(); };
    ['dragenter', 'dragover'].forEach(ev => {
        target.addEventListener(ev, (e) => {
            if (e.dataTransfer && Array.from(e.dataTransfer.types || []).includes('Files')) {
                prevent(e);
                e.dataTransfer.dropEffect = 'copy';
                target.classList.add('drag-over');
            }
        });
    });
    ['dragleave', 'dragend'].forEach(ev => {
        target.addEventListener(ev, (e) => {
            if (e.target === target) target.classList.remove('drag-over');
        });
    });
    target.addEventListener('drop', (e) => {
        if (!e.dataTransfer || !e.dataTransfer.files || e.dataTransfer.files.length === 0) return;
        prevent(e);
        target.classList.remove('drag-over');
        const files = Array.from(e.dataTransfer.files);
        if (files.length === 1) {
            loadInvoiceFile(files[0]);
        } else {
            loadMultipleFiles(files);
        }
    });
}

function parseXML(xmlContent) {
    try {
        const parser = new DOMParser();
        const xmlDoc = parser.parseFromString(xmlContent, "text/xml");
        
        const parserError = xmlDoc.querySelector('parsererror');
        if (parserError) {
            throw new Error('Eroare la parsarea XML: ' + parserError.textContent);
        }

        // Extrage și adaugă codurile de scutire din TaxTotal
        const taxSubtotals = xmlDoc.querySelectorAll('cac\\:TaxSubtotal, TaxSubtotal');
        taxSubtotals.forEach(subtotal => {
            const taxCategory = subtotal.querySelector('cac\\:TaxCategory, TaxCategory');
            if (taxCategory) {
                const vatType = getXMLValue(taxCategory, 'cbc\\:ID, ID');
                const exemptionCode = getXMLValue(taxCategory, 'cbc\\:TaxExemptionReasonCode, TaxExemptionReasonCode');
                const exemptionReason = getXMLValue(taxCategory, 'cbc\\:TaxExemptionReason, TaxExemptionReason');
                
                if (vatType && exemptionCode) {
                    addDynamicVatExemptionCode(vatType, exemptionCode, exemptionReason);
                }
            }
        });

        currentInvoice = xmlDoc;
        manuallyEditedVatRows.clear();

        populateBasicDetails(xmlDoc);
        populatePartyDetails(xmlDoc);
        populateBillingReference(xmlDoc);
        populatePaymentMeans(xmlDoc);
        populateAllowanceCharges(xmlDoc);
        populateLineItems(xmlDoc);
        storeOriginalTotals(xmlDoc);
        restoreOriginalTotals();
        displayVATBreakdown(xmlDoc);

        // PR-A11: după ce toate elementele sunt populate, rulează math
        // validation pentru a popula badge-urile (per-line + per-VAT-row + footer).
        if (typeof validateMath === 'function') validateMath();

        // PR-BR: inițializează panelul de validare după load XML.
        _updateBRPanel();
    } catch (error) {
        handleError(error, 'Eroare la parsarea fișierului XML');
    }
}

// Create allowance charge HTML
function createAllowanceChargeHTML(index, charge) {
    return `
        <div class="allowance-charge" data-index="${index}">
            <div class="grid">
                <div class="form-group">
                    <label class="form-label">Tip</label>
                    <select class="form-input" name="chargeType${index}" onchange="updateReasonCodeOptions(${index})">
                        <option value="true" ${charge.isCharge ? 'selected' : ''}>Taxă</option>
                        <option value="false" ${!charge.isCharge ? 'selected' : ''}>Reducere</option>
                    </select>
                </div>
                <div class="form-group">
                    <label class="form-label">Cod Motiv</label>
                    <select class="form-input" name="chargeReasonCode${index}">
                        ${createReasonCodeOptions(charge.isCharge, charge.reasonCode)}
                    </select>
                </div>
                <div class="form-group">
                    <label class="form-label">Motiv</label>
                    <input type="text" class="form-input" name="chargeReason${index}" 
                           value="${charge.reason || ''}">
                </div>
                <div class="form-group">
                    <label class="form-label">Valoare</label>
                    <input type="number" step="0.01" class="form-input num" name="chargeAmount${index}"
                           value="${charge.amount}" onchange="updateTotals()">
                </div>
                <div class="form-group">
                    <label class="form-label">Bază de calcul</label>
                    <input type="number" step="0.01" class="form-input num" name="chargeBaseAmount${index}"
                           value="${charge.baseAmount}" onchange="updateTotals()">
                </div>
                <div class="form-group">
                    <label class="form-label">Tip TVA</label>
                    <select class="form-input" name="chargeVatType${index}">
                        ${Object.entries(VAT_TYPES).map(([key, value]) => 
                            `<option value="${key}" ${key === charge.vatTypeId ? 'selected' : ''}>${value}</option>`
                        ).join('')}
                    </select>
                </div>
                <div class="form-group">
                    <label class="form-label">Cotă TVA (%)</label>
                    <input type="number" step="0.1" class="form-input num" name="chargeVatRate${index}"
                           value="${charge.vatRate}" ${charge.vatTypeId !== 'S' ? 'disabled' : ''}>
                </div>
            </div>
            <button type="button" class="button button-small button-danger remove-line-item" onclick="removeAllowanceCharge(${index})">
                ✕
            </button>
        </div>
    `;
}

function createReasonCodeOptions(isCharge, selectedCode = '') {
    const codes = isCharge ? CHARGE_REASON_CODES : ALLOWANCE_REASON_CODES;
    return Object.entries(codes)
        .map(([code, description]) => 
            `<option value="${code}" ${code === selectedCode ? 'selected' : ''}>${description} (${code})</option>`
        ).join('');
}

window.updateReasonCodeOptions = function(index) {
    const chargeTypeSelect = document.querySelector(`[name="chargeType${index}"]`);
    const reasonCodeSelect = document.querySelector(`[name="chargeReasonCode${index}"]`);
    const reasonInput = document.querySelector(`[name="chargeReason${index}"]`);
    
    const isCharge = chargeTypeSelect.value === 'true';
    reasonCodeSelect.innerHTML = createReasonCodeOptions(isCharge);
    
    // Update reason text based on selected code
    const selectedCode = reasonCodeSelect.value;
    const codes = isCharge ? CHARGE_REASON_CODES : ALLOWANCE_REASON_CODES;
    reasonInput.value = codes[selectedCode] || '';
}

// Create line item HTML
function createLineItemHTML(index, description = '', quantity = '1', price = '0', vatRate = '19', 
    unitCode = 'EA', vatTypeId = 'S', itemDescription = '', lineDiscount = '0', discountReasonCode = '') {
    
    return `
        <div class="line-item" data-index="${index}">
            <div class="grid">
                <div class="form-group">
                    <label class="form-label">Denumire</label>
                    <div class="description-wrapper">
                        <input type="text" class="form-input" name="description${index}" value="${description}"
                               autocomplete="off" data-catalog-input="${index}">
                    </div>
                </div>
                <div class="form-group">
                    <label class="form-label">Cantitate</label>
                    <input type="number" step="0.001" class="form-input num" name="quantity${index}"
                        value="${quantity}" onchange="updateTotals()">
                </div>
                <div class="form-group">
                    <label class="form-label">UM</label>
                    <select class="form-input" name="unit${index}">
                        ${createUnitCodeOptionsHTML(unitCode)}
                    </select>
                </div>
                <div class="form-group">
                    <label class="form-label">Preț</label>
                    <input type="number" step="0.01" class="form-input num" name="price${index}"
                        value="${price}" onchange="updateTotals()">
                </div>
                <div class="form-group">
                    <label class="form-label">Discount</label>
                    <input type="number" step="0.01" class="form-input num" name="lineDiscount${index}"
                        value="${lineDiscount}" onchange="updateTotals()">
                </div>
                <div class="form-group">
                    <label class="form-label">Cod Motiv Reducere</label>
                    <select class="form-input" name="discountReasonCode${index}" ${lineDiscount == 0 ? 'disabled' : ''}>
                        ${createLineDiscountReasonOptions(discountReasonCode)}
                    </select>
                </div>
                <div class="form-group">
                    <label class="form-label">Tip TVA</label>
                    <select class="form-input" name="vatType${index}" onchange="handleVatTypeChange(${index})">
                        ${Object.entries(VAT_TYPES).map(([key, value]) => 
                            `<option value="${key}" ${key === vatTypeId ? 'selected' : ''}>${value}</option>`
                        ).join('')}
                    </select>
                </div>
                <div class="form-group">
                    <label class="form-label">Cotă TVA (%)</label>
                    <input type="number" step="1" class="form-input num" name="vatRate${index}"
                        value="${vatRate}" onchange="updateTotals()">
                </div>
            </div>

            <div class="line-total-row">
                <span class="line-total-label">Total linie:</span>
                <span class="line-total-value mono" data-line-total-index="${index}">0,00</span>
                <span class="badge" data-line-badge-index="${index}"></span>
            </div>

            <div class="optional-details-toggle">
                <button type="button" class="button button-secondary"
                    onclick="toggleOptionalDetails(${index})">
                    ▼ Detalii Suplimentare
                </button>
            </div>

            <div class="optional-details" id="optionalDetails${index}" style="display: none;">
                <div class="optional-details-content">
                    <div class="form-group description-group">
                        <label class="form-label">Descriere</label>
                        <textarea class="form-input" name="itemDescription${index}" rows="2">${itemDescription}</textarea>
                    </div>
                    <div class="form-group" style="margin-top:4px">
                        <button type="button" class="button button-secondary button-small"
                                onclick="window.saveLineToLocalCatalog(${index})"
                                title="Salvează articolul curent în catalogul local (IndexedDB)">
                            Salvează în catalog
                        </button>
                    </div>
                    <div class="identifications-container" id="identifications${index}">
                        <div class="identifications-header">
                            <h4>Coduri de Identificare</h4>
                            <div class="identification-buttons">
                                ${Object.entries(IDENTIFICATION_TYPES).map(([type, info]) => `
                                    <button type="button" class="button button-small" 
                                            onclick="window.addIdentification(${index}, '${type}')">
                                        + ${info.label}
                                    </button>
                                `).join('')}
                            </div>
                        </div>
                        <div class="identifications-list"></div>
                    </div>
                </div>
            </div>

            <button type="button" class="button button-small button-danger remove-line-item" onclick="removeLineItem(${index})">
                ✕
            </button>
        </div>
    `;
}

function createLineDiscountReasonOptions(selectedCode = '') {
    return Object.entries(ALLOWANCE_REASON_CODES)
        .map(([code, description]) => 
            `<option value="${code}" ${code === selectedCode ? 'selected' : ''}>${description} (${code})</option>`
        ).join('');
}

// Add VAT breakdown row
let _vatRowCounter = 0;
function addVATBreakdownRow(rate, baseAmount, vatAmount, vatType = 'S', existingRowId = null, exemptionCode = '', exemptionReason = '') {
    const container = document.getElementById('vatBreakdownRows');
    // ID unic chiar dacă mai multe rânduri sunt create în același ms (Date.now()
    // singur cauza coliziuni → querySelector(#id) pică pe primul match și
    // dataset.raw al rândurilor noi era fie suprascris, fie nesetat → BR-CO-15
    // false positive după Recalculează Totaluri.
    const rowId = existingRowId || `vat-row-${Date.now()}-${++_vatRowCounter}`;

    const rowHtml = `
        <div class="vat-row" id="${rowId}">
            <div class="total-row">
                <div class="vat-inputs">
                    <label>Tip:</label>
                    <select class="form-input vat-type" onchange="window.updateVATRow('${rowId}', 'manual')">
                        ${Object.entries(VAT_TYPES).map(([key, value]) =>
                            `<option value="${key}" ${key === vatType ? 'selected' : ''}>${value}</option>`
                        ).join('')}
                    </select>
                    <label>Cotă:</label>
                    <input type="text" class="form-input vat-rate num" value="${rate}"
                           onchange="window.updateVATRow('${rowId}', 'manual')">%
                    <label>Bază Impozabilă:</label>
                    <input type="text" class="form-input vat-base num" value="${baseAmount}"
                           onchange="window.updateVATRow('${rowId}', 'manual')">
                    <label>Valoare TVA:</label>
                    <input type="text" class="form-input vat-amount num" value="${vatAmount}"
                           onchange="window.updateVATRowFromAmount('${rowId}')">
                    <span class="badge vat-amount-badge"></span>
                </div>
                <div class="vat-exemption ${['E', 'K', 'O', 'AE'].includes(vatType) ? '' : 'hidden'}">
                    <div class="form-group">
                        <label>Cod Scutire:</label>
                        <select class="form-input vat-exemption-code" onchange="window.updateExemptionReason('${rowId}')">
                            ${generateExemptionCodeOptions(vatType, exemptionCode)}
                        </select>
                    </div>
                    <div class="form-group">
                        <label>Motiv Scutire:</label>
                        <input type="text" class="form-input vat-exemption-reason" value="${exemptionReason}"
                               placeholder="Motiv scutire TVA">
                    </div>
                </div>
                <button type="button" class="button button-small button-danger delete-identification"
                        onclick="window.removeVATRow('${rowId}')">✕</button>
            </div>
        </div>
    `;

    container.insertAdjacentHTML('beforeend', rowHtml);

    // PR-E E1: seed dataset.raw pentru rate/base/amount + wire blur listeners.
    const rateEl = document.querySelector(`#${rowId} .vat-rate`);
    const baseEl = document.querySelector(`#${rowId} .vat-base`);
    const amountEl = document.querySelector(`#${rowId} .vat-amount`);
    [
        { el: rateEl, val: rate, decimals: 2 },
        { el: baseEl, val: baseAmount, decimals: 2 },
        { el: amountEl, val: vatAmount, decimals: 2 }
    ].forEach(f => {
        if (!f.el) return;
        const big = parseStrict(f.val);
        if (big !== null) f.el.dataset.raw = big.toFixed(f.decimals);
        wireDatasetRaw(f.el, f.decimals);
    });

    // Add event listener for VAT type changes
    const vatTypeSelect = document.querySelector(`#${rowId} .vat-type`);
    vatTypeSelect.addEventListener('change', () => {
        const exemptionContainer = document.querySelector(`#${rowId} .vat-exemption`);
        const newVatType = vatTypeSelect.value;

        if (['E', 'K', 'O', 'AE'].includes(newVatType)) {
            exemptionContainer.classList.remove('hidden');

            // Update exemption code options
            const codeSelect = document.querySelector(`#${rowId} .vat-exemption-code`);
            codeSelect.innerHTML = generateExemptionCodeOptions(newVatType);

            // Set default values
            const defaultExemption = getDefaultExemption(newVatType);
            if (defaultExemption) {
                codeSelect.value = defaultExemption.code;
                document.querySelector(`#${rowId} .vat-exemption-reason`).value = defaultExemption.reason;
            }
        } else {
            exemptionContainer.classList.add('hidden');
        }
    });
}

function generateExemptionCodeOptions(vatType, selectedCode = '') {
    if (vatType === 'E') {
        return VAT_EXEMPTION_CODES.E.map(exemption => 
            `<option value="${exemption.code}" ${exemption.code === selectedCode ? 'selected' : ''}>
                ${exemption.code || 'Scutit'}
            </option>`
        ).join('');
    } else if (vatType === 'K' || vatType === 'AE' || vatType === 'O') {
        const exemption = VAT_EXEMPTION_CODES[vatType];
        return `<option value="${exemption.code}" selected>${exemption.code}</option>`;
    }
    return '<option value="">-</option>';
}

function getDefaultExemption(vatType) {
    if (vatType === 'E') {
        return VAT_EXEMPTION_CODES.E[0];
    }
    return VAT_EXEMPTION_CODES[vatType];
}

// Add this to window object
window.updateExemptionReason = function(rowId) {
    const row = document.getElementById(rowId);
    if (!row) return;
    
    const vatType = row.querySelector('.vat-type').value;
    const codeSelect = row.querySelector('.vat-exemption-code');
    const reasonInput = row.querySelector('.vat-exemption-reason');
    
    if (vatType === 'E') {
        const selectedExemption = VAT_EXEMPTION_CODES.E.find(e => e.code === codeSelect.value);
        if (selectedExemption) {
            reasonInput.value = selectedExemption.reason;
        }
    } else if (vatType === 'K' || vatType === 'AE') {
        reasonInput.value = VAT_EXEMPTION_CODES[vatType].reason;
    }
};

// Toggle optional details
window.toggleOptionalDetails = function(index) {
    const optionalDetails = document.getElementById(`optionalDetails${index}`);
    const button = optionalDetails.previousElementSibling.querySelector('button');
    
    if (optionalDetails.style.display === 'none') {
        optionalDetails.style.display = 'block';
        button.innerHTML = '▲ Detalii Suplimentare';
    } else {
        optionalDetails.style.display = 'none';
        button.innerHTML = '▼ Detalii Suplimentare';
    }
}

// Form validation
function validateForm(silent = false) {
    let isValid = true;
    let firstInvalidField = null;

    // Validare câmpuri existente...
    const requiredFields = [
        'invoiceNumber',
        'issueDate',
        'dueDate',
        'supplierName',
        'supplierVAT',
        'customerName',
    ];

    requiredFields.forEach(fieldName => {
        const field = document.querySelector(`[name="${fieldName}"]`);
        if (!field || !field.value.trim()) {
            field.classList.add('invalid');
            isValid = false;
            if (!firstInvalidField)
                firstInvalidField = field;
        } else {
            field.classList.remove('invalid');
        }
    });

    // Adaugă validarea TVA
    const vatExemptionValid = validateVATExemption();
    if (!vatExemptionValid) {
        isValid = false;
        if (!silent) {
            alert('Vă rugăm să completați codul și/sau motivul scutirii de TVA pentru toate categoriile care necesită această informație.');
        }
    }

    // Restul validărilor existente...
    const lineItems = document.querySelectorAll('.line-item');
    if (lineItems.length === 0) {
        isValid = false;
        if (!silent) {
            alert('Este necesară cel puțin o linie în factură');
        }
        return false;
    }

    lineItems.forEach((item, index) => {
        const quantity = parseFloat(document.querySelector(`[name="quantity${index}"]`).value);
        const price = parseFloat(document.querySelector(`[name="price${index}"]`).value);
        const description = document.querySelector(`[name="description${index}"]`).value;

        if (!description.trim()) {
            document.querySelector(`[name="description${index}"]`).classList.add('invalid');
            isValid = false;
        }
        if (isNaN(quantity)) {
            document.querySelector(`[name="quantity${index}"]`).classList.add('invalid');
            isValid = false;
        }
        if (isNaN(price)) {
            document.querySelector(`[name="price${index}"]`).classList.add('invalid');
            isValid = false;
        }
    });

    const dateInputs = document.querySelectorAll('.date-input');
    dateInputs.forEach(input => {
        if (!validateDateInput(input)) {
            isValid = false;
            if (!firstInvalidField) firstInvalidField = input;
        }
    });

    // Validare curs valutar dacă este cazul
    const taxCurrencyCode = document.querySelector('[name="taxCurrencyCode"]').value.trim();
    const documentCurrencyCode = document.querySelector('[name="documentCurrencyCode"]').value.trim();
    
    if (taxCurrencyCode && taxCurrencyCode !== documentCurrencyCode) {
        const exchangeRate = document.querySelector('[name="exchangeRate"]');
        if (!exchangeRate || !exchangeRate.value || parseFloat(exchangeRate.value) <= 0) {
            exchangeRate.classList.add('invalid');
            isValid = false;
            if (!firstInvalidField) {
                firstInvalidField = exchangeRate;
            }
        } else {
            exchangeRate.classList.remove('invalid');
        }
    }

    if (!isValid && !silent) {
        if (firstInvalidField) {
            firstInvalidField.focus();
        }
        alert('Vă rugăm să completați toate câmpurile obligatorii');
    }

    return isValid;
}

function handleError(error, message) {
    console.error(message, error);
    alert(`${message}\nVă rugăm să verificați consola pentru detalii.`);
}

function formatDateToRomanian(date) {
    const day = String(date.getDate()).padStart(2, '0');
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const year = date.getFullYear();
    return `${day}.${month}.${year}`;
}

function parseRomanianDate(dateStr) {
    const [day, month, year] = dateStr.split('.');
    return `${year}-${month}-${day}`;
}

function createDatePicker(input, button) {
    const picker = new Pikaday({
        field: input,
        trigger: button,
        format: 'DD.MM.YYYY',
        i18n: {
            previousMonth: 'Luna anterioară',
            nextMonth: 'Luna următoare',
            months: ['Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai', 'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie', 'Decembrie'],
            weekdays: ['Duminică', 'Luni', 'Marți', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],
            weekdaysShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm']
        },
        firstDay: 1,
        onSelect: function(date) {
            input.value = formatDateToRomanian(date);
            validateDateInput(input);
        }
    });
    return picker;
}

function validateDateInput(input) {
    const value = input.value;

    // Câmp gol = valid (regula "required" e tratată separat în validateForm).
    if (value === '') {
        input.classList.remove('invalid');
        return true;
    }

    const regex = /^(\d{2})\.(\d{2})\.(\d{4})$/;
    const match = value.match(regex);

    if (match) {
        const day = parseInt(match[1]);
        const month = parseInt(match[2]);
        const year = parseInt(match[3]);

        const date = new Date(year, month - 1, day);
        if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) {
            input.classList.remove('invalid');
            return true;
        }
    }

    input.classList.add('invalid');
    return false;
}

function restrictDateInput(input) {
    input.addEventListener('input', function(e) {
        let value = e.target.value;
        
        // Remove any non-digit characters except dots
        value = value.replace(/[^\d.]/g, '');
        
        // Auto-add dots after day and month
        if (value.length >= 2 && value.charAt(2) !== '.') {
            value = value.slice(0, 2) + '.' + value.slice(2);
        }
        if (value.length >= 5 && value.charAt(5) !== '.') {
            value = value.slice(0, 5) + '.' + value.slice(5);
        }
        
        // Restrict to exactly 10 characters (dd.mm.yyyy)
        value = value.slice(0, 10);
        
        e.target.value = value;
    });

    input.addEventListener('blur', function() {
        validateDateInput(input);
    });
}

function createCountryOptions() {
    return Array.from(ISO_3166_1_CODES).map(code => 
        `<option value="${code}" ${code === 'RO' ? 'selected' : ''}>${code}</option>`
    ).join('');
}

function createCountyOptions() {
    return Array.from(ROMANIAN_COUNTY_CODES).map(code => {
        const label = code.replace('RO-', '');
        const counties = {
            'AB': 'Alba', 'AR': 'Arad', 'AG': 'Argeș', 'BC': 'Bacău', 'BH': 'Bihor', 
            'BN': 'Bistrița-Năsăud', 'BT': 'Botoșani', 'BV': 'Brașov', 'BR': 'Brăila', 
            'B': 'București', 'BZ': 'Buzău', 'CS': 'Caraș-Severin', 'CL': 'Călărași', 
            'CJ': 'Cluj', 'CT': 'Constanța', 'CV': 'Covasna', 'DB': 'Dâmbovița', 
            'DJ': 'Dolj', 'GL': 'Galați', 'GR': 'Giurgiu', 'GJ': 'Gorj', 'HR': 'Harghita', 
            'HD': 'Hunedoara', 'IL': 'Ialomița', 'IS': 'Iași', 'IF': 'Ilfov', 
            'MM': 'Maramureș', 'MH': 'Mehedinți', 'MS': 'Mureș', 'NT': 'Neamț', 
            'OT': 'Olt', 'PH': 'Prahova', 'SM': 'Satu Mare', 'SJ': 'Sălaj', 
            'SB': 'Sibiu', 'SV': 'Suceava', 'TR': 'Teleorman', 'TM': 'Timiș', 
            'TL': 'Tulcea', 'VS': 'Vaslui', 'VL': 'Vâlcea', 'VN': 'Vrancea'
        };
        return `<option value="${code}">${counties[label] || label} (${label})</option>`;
    }).join('');
}

function initializeLocationSelectors() {
    // Replace country inputs with selects for both supplier and customer
    ['supplier', 'customer'].forEach(party => {
        const countryInput = document.querySelector(`[name="${party}Country"]`);
        if (countryInput) {
            const select = document.createElement('select');
            select.className = 'form-input';
            select.name = countryInput.name;
            select.innerHTML = createCountryOptions();
            select.value = countryInput.dataset.xmlValue || countryInput.value || 'RO';
            countryInput.parentNode?.replaceChild(select, countryInput);
        }

        const countyInput = document.querySelector(`[name="${party}CountrySubentity"]`);
        if (countyInput) {
            const select = document.createElement('select');
            select.className = 'form-input';
            select.name = countyInput.name;
            select.innerHTML = createCountyOptions();
            select.value = countyInput.dataset.xmlValue || countyInput.value || '';
            countyInput.parentNode?.replaceChild(select, countyInput);
        }
    });

    // Initialize location handlers for both parties
    setupPartyLocationHandlers('supplier');
    setupPartyLocationHandlers('customer');
}

function updateCountyVisibility(countrySelect, countySelect) {
    if (!countrySelect || !countySelect) return;
    const showCounty = countrySelect.value === 'RO';
    countySelect.style.display = showCounty ? 'block' : 'none';
    countySelect.required = showCounty;
}

function setupPartyLocationHandlers(party) {
    const countrySelect = document.querySelector(`[name="${party}Country"]`);
    const countySelect = document.querySelector(`[name="${party}CountrySubentity"]`);
    const cityContainer = document.querySelector(`[name="${party}City"]`)?.parentNode;

    if (!countrySelect || !countySelect || !cityContainer) return;

    const handleLocationChange = () => {
        const isBucharest = countrySelect.value === 'RO' && countySelect.value === 'RO-B';
        const currentElement = cityContainer.querySelector('input, select');
        const isCurrentlySector = currentElement.tagName.toLowerCase() === 'select';

        if (isBucharest && !isCurrentlySector) {
            const sectorSelect = document.createElement('select');
            sectorSelect.className = 'form-input';
            sectorSelect.name = `${party}City`;
            sectorSelect.innerHTML = `
                <option value="">Selectați sectorul</option>
                <option value="SECTOR1">Sectorul 1</option>
                <option value="SECTOR2">Sectorul 2</option>
                <option value="SECTOR3">Sectorul 3</option>
                <option value="SECTOR4">Sectorul 4</option>
                <option value="SECTOR5">Sectorul 5</option>
                <option value="SECTOR6">Sectorul 6</option>
            `;

            // Try to preserve any existing sector value
            const currentValue = currentElement.value || '';
            if (currentValue.toUpperCase().includes('SECTOR')) {
                sectorSelect.value = currentValue.toUpperCase().replace(/\s+/g, '');
            }

            cityContainer.replaceChild(sectorSelect, currentElement);
        } else if (!isBucharest && isCurrentlySector) {
            const cityInput = document.createElement('input');
            cityInput.type = 'text';
            cityInput.className = 'form-input';
            cityInput.name = `${party}City`;
            cityInput.value = '';
            cityContainer.replaceChild(cityInput, currentElement);
        }
    };

    // Set up event listeners
    countrySelect.addEventListener('change', () => {
        updateCountyVisibility(countrySelect, countySelect);
        handleLocationChange();
    });

    countySelect.addEventListener('change', handleLocationChange);

    // Initial setup
    updateCountyVisibility(countrySelect, countySelect);
    handleLocationChange();
}

// ============================================================================
// PR-VALID-IDS (A9 + A10): Helpers validare CIF și IBAN pe blur.
// Afișează eroare inline sub câmp: border --danger + bg --danger-soft +
// mesaj 11px. Curăță eroarea la re-focus sau la câmp valid.
// ============================================================================

/**
 * Afișează sau actualizează mesajul de eroare sub un câmp de input.
 * @param {HTMLInputElement} input
 * @param {string} errorId — ID-ul elementului helper text (ex: "supplierVAT-error")
 * @param {string} message — mesajul de afișat
 */
function _setFieldError(input, errorId, message) {
    input.style.borderColor = 'var(--danger)';
    input.style.backgroundColor = 'var(--danger-soft)';
    input.setAttribute('aria-invalid', 'true');
    input.setAttribute('aria-describedby', errorId);

    let helper = document.getElementById(errorId);
    if (!helper) {
        helper = document.createElement('span');
        helper.id = errorId;
        helper.style.cssText = 'display:block;font-size:11px;color:var(--danger);margin-top:3px;';
        input.parentNode.appendChild(helper);
    }
    helper.textContent = message;
}

/**
 * Curăță eroarea de validare de pe un câmp.
 * @param {HTMLInputElement} input
 * @param {string} errorId
 */
function _clearFieldError(input, errorId) {
    input.style.borderColor = '';
    input.style.backgroundColor = '';
    input.removeAttribute('aria-invalid');
    input.removeAttribute('aria-describedby');

    const helper = document.getElementById(errorId);
    if (helper) helper.remove();
}

/**
 * Wire blur + validare CIF pe un câmp dat.
 * @param {HTMLInputElement} input
 * @param {string} errorId
 */
function _wireCIFValidation(input, errorId) {
    if (!input) return;
    input.addEventListener('blur', function() {
        const result = validateCIF(this.value);
        if (!result.valid) {
            _setFieldError(this, errorId, result.message);
        } else {
            _clearFieldError(this, errorId);
        }
    });
    // Curăță eroarea la tastare (nu re-validează — doar curăță indicatorul vizual)
    input.addEventListener('input', function() {
        _clearFieldError(this, errorId);
    });
}

/**
 * Wire blur + validare IBAN pe un câmp dat.
 * @param {HTMLInputElement} input
 * @param {string} errorId
 */
function _wireIBANValidation(input, errorId) {
    if (!input) return;
    input.addEventListener('blur', function() {
        const result = validateIBAN(this.value);
        if (!result.valid) {
            _setFieldError(this, errorId, result.message);
        } else {
            _clearFieldError(this, errorId);
        }
    });
    input.addEventListener('input', function() {
        _clearFieldError(this, errorId);
    });
}

function initializeUI() {
    document.querySelectorAll('.form-input').forEach(input => {
        input.addEventListener('input', function() {
            this.classList.remove('invalid');
            updateTotals();
        });
    });

    document.addEventListener('keydown', function(event) {
        if (event.ctrlKey || event.metaKey) {
            switch (event.key.toLowerCase()) {
                case 's':
                    event.preventDefault();
                    saveXML();
                    break;
                case 'o':
                    event.preventDefault();
                    document.getElementById('fileInput').click();
                    break;
                case 'n':
                    event.preventDefault();
                    addLineItem();
                    break;
            }
        }
    });

    // Initialize date pickers
    const dateInputs = document.querySelectorAll('.date-input');
    dateInputs.forEach(input => {
        const button = input.parentElement.querySelector('.calendar-button');
        createDatePicker(input, button);
        restrictDateInput(input);
    });

    if (!currentInvoice) {
        const today = new Date();
        const dueDate = new Date();
        dueDate.setDate(today.getDate() + 30);

        document.querySelector('[name="issueDate"]').value = formatDateToRomanian(today);
        document.querySelector('[name="dueDate"]').value = formatDateToRomanian(dueDate);
    }

    // Add note counter event listener
    const noteInput = document.querySelector('[name="invoiceNote"]');
    if (noteInput) {
        noteInput.addEventListener('input', updateNoteCounter);
        updateNoteCounter(); // Initial count
    }

    // Initialize location selectors
    initializeLocationSelectors();

    window.addLineItem = addLineItem;
    window.removeLineItem = removeLineItem;
    window.addAllowanceCharge = addAllowanceCharge;
    window.removeAllowanceCharge = removeAllowanceCharge;
    window.addPaymentMeansRow = addPaymentMeansRow;
    window.removePaymentMeansRow = removePaymentMeansRow;
    window.handleStorno = handleStorno;
    window.updateTotals = updateTotals;
    window.saveXML = saveXML;
    window.refreshTotals = refreshTotals;
    window.displayVATBreakdown = displayVATBreakdown;

    // A12: expune butoane profil furnizor și inițializează starea.
    window.saveSupplierProfile = saveSupplierProfile;
    window.useSupplierProfile = useSupplierProfile;
    window.deleteSupplierProfile = deleteSupplierProfile;
    _updateProfileButtons();

    // PR-VALID-IDS (A9 + A10): wire CIF și IBAN pe blur.
    _wireCIFValidation(document.querySelector('[name="supplierVAT"]'), 'supplierVAT-error');
    _wireCIFValidation(document.querySelector('[name="customerVAT"]'), 'customerVAT-error');

    // IBAN: delegare pe containerul de Payment Means (câmpuri dinamice).
    const pmContainer = document.getElementById('paymentMeansRows');
    if (pmContainer) {
        pmContainer.addEventListener('blur', function(e) {
            const input = e.target;
            if (!input || !input.name || !input.name.startsWith('paymentMeansIBAN')) return;
            const errorId = input.name + '-error';
            const result = validateIBAN(input.value);
            if (!result.valid) {
                _setFieldError(input, errorId, result.message);
            } else {
                _clearFieldError(input, errorId);
            }
        }, true); // capture=true pentru blur care nu bubblează
        pmContainer.addEventListener('input', function(e) {
            const input = e.target;
            if (!input || !input.name || !input.name.startsWith('paymentMeansIBAN')) return;
            _clearFieldError(input, input.name + '-error');
        });
    }

    // PR-A14: dirty tracking — marcăm fișierul activ la orice editare a formularului
    const invoiceForm = document.getElementById('invoiceForm');
    if (invoiceForm) {
        invoiceForm.addEventListener('input', () => _markActiveDirty());
        invoiceForm.addEventListener('change', () => _markActiveDirty());
    }
}

// ============================================================================
// A12: Profil furnizor (PR-PROFIL)
// Salvează / aplică / șterge datele furnizorului în localStorage.
// Cheia: efactura.profil.v1  (prefix enforced de storage.js).
// ============================================================================

const SUPPLIER_PROFILE_KEY = 'efactura.profil.v1';

const SUPPLIER_FIELDS = [
    'supplierName', 'supplierVAT', 'supplierCompanyId',
    'supplierAddress', 'supplierCity', 'supplierCountrySubentity',
    'supplierCountry', 'supplierPhone', 'supplierContactName', 'supplierEmail'
];

/** Actualizează vizibilitatea butoanelor "Folosește / Șterge profil". */
function _updateProfileButtons() {
    const profile = getJSON(SUPPLIER_PROFILE_KEY);
    const hasProfile = profile !== null;
    const btnUse    = document.getElementById('btnUseProfile');
    const btnDelete = document.getElementById('btnDeleteProfile');
    if (btnUse)    btnUse.style.display    = hasProfile ? '' : 'none';
    if (btnDelete) btnDelete.style.display = hasProfile ? '' : 'none';
}

/** Salvează câmpurile furnizorului în localStorage. */
function saveSupplierProfile() {
    const profile = {};
    SUPPLIER_FIELDS.forEach(f => {
        const el = document.querySelector(`[name="${f}"]`);
        if (el) profile[f] = el.value;
    });
    setJSON(SUPPLIER_PROFILE_KEY, profile);
    _updateProfileButtons();
    showToast('Profil furnizor salvat.', 'success');
}

/** Populează câmpurile furnizorului din profilul salvat. */
function useSupplierProfile() {
    const profile = getJSON(SUPPLIER_PROFILE_KEY);
    if (!profile) {
        showToast('Nu există profil salvat.', 'info');
        return;
    }
    SUPPLIER_FIELDS.forEach(f => {
        const el = document.querySelector(`[name="${f}"]`);
        if (el && profile[f] !== undefined) el.value = profile[f];
    });
    showToast('Profil furnizor aplicat.', 'success');
}

/** Șterge profilul furnizorului din localStorage. */
function deleteSupplierProfile() {
    localStorage.removeItem(SUPPLIER_PROFILE_KEY);
    _updateProfileButtons();
    showToast('Profil furnizor șters.', 'info');
}

// Handling VAT type changes
window.handleVatTypeChange = function(index) {
    const vatTypeSelect = document.querySelector(`[name="vatType${index}"]`);
    const vatRateInput = document.querySelector(`[name="vatRate${index}"]`);
    
    // Verifică dacă furnizorul este neplătitor TVA
    if (!isVATRegistered()) {
        vatTypeSelect.value = 'O';
        vatTypeSelect.disabled = true;  // Dezactivează selectul pentru neplătitori
        vatRateInput.value = '0';
        vatRateInput.disabled = true;
        
        // Setează codul și motivul scutirii pentru neplătitori
        const row = document.querySelector(`.vat-row`);
        if (row) {
            const exemptionCode = row.querySelector('.vat-exemption-code');
            const exemptionReason = row.querySelector('.vat-exemption-reason');
            if (exemptionCode) exemptionCode.value = 'VATEX-EU-O';
            if (exemptionReason) exemptionReason.value = 'Operațiune efectuată de neplătitor de TVA';
        }
    } else {
        vatTypeSelect.disabled = false;  // Activează selectul pentru plătitori
        
        switch(vatTypeSelect.value) {
            case 'O':  // Pentru neplătitori
                vatRateInput.value = '0';
                vatRateInput.disabled = true;
                break;
            case 'AE':  // Taxare inversă
            case 'Z':   // Cotă 0%
            case 'E':   // Scutit
                vatRateInput.value = '0';
                vatRateInput.disabled = true;
                break;
            case 'S':   // Standard
                vatRateInput.value = '19';
                vatRateInput.disabled = false;
                break;
        }
    }
    
    updateTotals();
}

function isVATRegistered() {
    const supplierVAT = document.querySelector('[name="supplierVAT"]').value.trim().toUpperCase();
    return supplierVAT.startsWith('RO');
}

function handleChargeVatTypeChange(index) {
    const vatTypeSelect = document.querySelector(`[name="chargeVatType${index}"]`);
    const vatRateInput = document.querySelector(`[name="chargeVatRate${index}"]`);
    
    if (!vatTypeSelect || !vatRateInput) return;
    
    // Verifică dacă furnizorul este neplătitor TVA
    if (!isVATRegistered()) {
        vatTypeSelect.value = 'O';
        vatTypeSelect.disabled = true;  // Dezactivează selectul pentru neplătitori
        vatRateInput.value = '0';
        vatRateInput.disabled = true;
        
        // Setează codul și motivul scutirii pentru neplătitori
        const row = document.querySelector(`.vat-row`);
        if (row) {
            const exemptionCode = row.querySelector('.vat-exemption-code');
            const exemptionReason = row.querySelector('.vat-exemption-reason');
            if (exemptionCode) exemptionCode.value = 'VATEX-EU-O';
            if (exemptionReason) exemptionReason.value = 'Operațiune efectuată de neplătitor de TVA';
        }
    } else {
        vatTypeSelect.disabled = false;  // Activează selectul pentru plătitori
        
        switch(vatTypeSelect.value) {
            case 'O':  // Pentru neplătitori
                vatRateInput.value = '0';
                vatRateInput.disabled = true;
                break;
            case 'AE':  // Taxare inversă
            case 'Z':   // Cotă 0%
            case 'E':   // Scutit
                vatRateInput.value = '0';
                vatRateInput.disabled = true;
                break;
            case 'S':   // Standard
                vatRateInput.value = '19';
                vatRateInput.disabled = false;
                break;
        }
    }
    
    // Clear manual edits and refresh
    manuallyEditedVatRows.clear();
    refreshTotals();
}

// Funcție pentru actualizarea tuturor categoriilor TVA când se modifică codul fiscal
function updateAllVATTypes() {
    const isNotVATRegistered = !isVATRegistered();
    
    // Actualizează toate liniile de articole
    document.querySelectorAll('.line-item').forEach((item, index) => {
        const vatTypeSelect = item.querySelector(`[name="vatType${index}"]`);
        const vatRateInput = item.querySelector(`[name="vatRate${index}"]`);
        
        if (isNotVATRegistered) {
            vatTypeSelect.value = 'O';
            vatTypeSelect.disabled = true;
            vatRateInput.value = '0';
            vatRateInput.disabled = true;
        } else {
            vatTypeSelect.disabled = false;
            // Restabilește valorile implicite pentru plătitori
            if (vatTypeSelect.value === 'O') {
                vatTypeSelect.value = 'S';
                vatRateInput.value = '19';
                vatRateInput.disabled = false;
            }
        }
    });

    // Actualizează breakdown-ul TVA
    updateVATBreakdown();
    refreshTotals();
}

// XML modifications
function addUnitCode(code) {
    if (!UNIT_CODES.has(code)) {
        UNIT_CODES.set(code, `${code} (${code})`);
    }
}

function createUnitCodeOptionsHTML(selectedCode = 'EA') {
    return Array.from(UNIT_CODES.entries())
        .map(([code, description]) => 
            `<option value="${code}" ${code === selectedCode ? 'selected' : ''}>${description}</option>`
        )
        .join('');
}

function storeOriginalTotals(xmlDoc) {
    const taxTotal = xmlDoc.querySelector('cac\\:TaxTotal, TaxTotal');
    const monetaryTotal = xmlDoc.querySelector('cac\\:LegalMonetaryTotal, LegalMonetaryTotal');

    originalTotals = {
        subtotal: getXMLValue(monetaryTotal, 'cbc\\:LineExtensionAmount, LineExtensionAmount'),
        allowances: getXMLValue(monetaryTotal, 'cbc\\:AllowanceTotalAmount, AllowanceTotalAmount', '0'),
        charges: getXMLValue(monetaryTotal, 'cbc\\:ChargeTotalAmount, ChargeTotalAmount', '0'),
        netAmount: getXMLValue(monetaryTotal, 'cbc\\:TaxExclusiveAmount, TaxExclusiveAmount'),
        totalVat: getXMLValue(taxTotal, 'cbc\\:TaxAmount, TaxAmount'),
        total: getXMLValue(monetaryTotal, 'cbc\\:TaxInclusiveAmount, TaxInclusiveAmount')
    };

    // console.log('Original totals from XML:', originalTotals);

    const vatBreakdown = [];
    const taxSubtotals = xmlDoc.querySelectorAll('cac\\:TaxSubtotal, TaxSubtotal');
    taxSubtotals.forEach(subtotal => {
        const taxCategory = subtotal.querySelector('cac\\:TaxCategory, TaxCategory');
        vatBreakdown.push({
            taxableAmount: getXMLValue(subtotal, 'cbc\\:TaxableAmount, TaxableAmount'),
            taxAmount: getXMLValue(subtotal, 'cbc\\:TaxAmount, TaxAmount'),
            percent: getXMLValue(taxCategory, 'cbc\\:Percent, Percent'),
            type: getXMLValue(taxCategory, 'cbc\\:ID, ID', 'S'),
            exemptionCode: getXMLValue(taxCategory, 'cbc\\:TaxExemptionReasonCode, TaxExemptionReasonCode'),
            exemptionReason: getXMLValue(taxCategory, 'cbc\\:TaxExemptionReason, TaxExemptionReason')
        });
    });
    originalTotals.vatBreakdown = vatBreakdown;
}

function restoreOriginalTotals() {
    if (!originalTotals) return;

    // Display exact values from XML with formatting
    document.getElementById('subtotal').textContent = formatter.formatCurrency(originalTotals.subtotal);
    document.getElementById('totalAllowances').textContent = formatter.formatCurrency(originalTotals.allowances);
    document.getElementById('totalCharges').textContent = formatter.formatCurrency(originalTotals.charges);
    document.getElementById('netAmount').textContent = formatter.formatCurrency(originalTotals.netAmount);
    document.getElementById('vat').textContent = formatter.formatCurrency(originalTotals.totalVat);
    
    // Bypass formatting for total
    document.getElementById('total').textContent = originalTotals.total;

    const container = document.getElementById('vatBreakdownRows');
    if (container) {
        container.innerHTML = '';

        if (originalTotals.vatBreakdown && originalTotals.vatBreakdown.length > 0) {
            originalTotals.vatBreakdown.forEach(vat => {
                addVATBreakdownRow(
                    vat.percent,
                    vat.taxableAmount,
                    vat.taxAmount,
                    vat.type,
                    null,
                    vat.exemptionCode,
                    vat.exemptionReason
                );
            });
        }
    }

    // PR-A11: run math validation după ce displayed-urile sunt setate la
    // valorile XML loaded (înainte ca user să editeze ceva).
    if (typeof validateMath === 'function') validateMath();
}

function updateNoteCounter() {
    const noteInput = document.querySelector('[name="invoiceNote"]');
    const counter = document.querySelector('.note-counter');
    if (noteInput && counter) {
        const length = noteInput.value.length;
        counter.textContent = `${length}/900 caractere`;
    }
}

function splitNoteIntoChunks(text, maxLength) {
    if (!text) return [];
    const chunks = [];
    let remainingText = text;

    while (remainingText.length > 0) {
        if (remainingText.length <= maxLength) {
            chunks.push(remainingText);
            break;
        }

        let splitPoint = remainingText.substr(0, maxLength).lastIndexOf('\n');
        if (splitPoint === -1) {
            splitPoint = remainingText.substr(0, maxLength).lastIndexOf(' ');
        }
        if (splitPoint === -1) splitPoint = maxLength;

        chunks.push(remainingText.substr(0, splitPoint));
        remainingText = remainingText.substr(splitPoint + 1);
    }

    return chunks.filter(chunk => chunk.trim().length > 0);
}

function populateBasicDetails(xmlDoc) {
    document.querySelector('[name="invoiceNumber"]').value = getXMLValue(xmlDoc, 'cbc\\:ID, ID');

    // PR-TIPURI (A4): citește cbc:InvoiceTypeCode (default 380 dacă absent).
    const invoiceTypeCode = getXMLValue(xmlDoc, 'cbc\\:InvoiceTypeCode, InvoiceTypeCode', '380');
    const typeSelect = document.querySelector('[name="invoiceTypeCode"]');
    if (typeSelect) {
        // Dacă XML conține un cod necunoscut, păstrează default-ul 380.
        typeSelect.value = INVOICE_TYPES[invoiceTypeCode] ? invoiceTypeCode : '380';
    }

    // Get and combine all Note elements
    const notes = xmlDoc.querySelectorAll('cbc\\:Note, Note');
    const combinedNotes = Array.from(notes).map(note => note.textContent).join('\n');
    document.querySelector('[name="invoiceNote"]').value = combinedNotes;
    updateNoteCounter();

    const issueDate = getXMLValue(xmlDoc, 'cbc\\:IssueDate, IssueDate');
    const dueDate = getXMLValue(xmlDoc, 'cbc\\:DueDate, DueDate');
    
    if (issueDate) {
        const [year, month, day] = issueDate.split('-');
        document.querySelector('[name="issueDate"]').value = `${day}.${month}.${year}`;
    }
    
    if (dueDate) {
        const [year, month, day] = dueDate.split('-');
        document.querySelector('[name="dueDate"]').value = `${day}.${month}.${year}`;
    }

    // Add currency code handling
    const documentCurrencyCode = getXMLValue(xmlDoc, 'cbc\\:DocumentCurrencyCode, DocumentCurrencyCode', 'RON');
    const taxCurrencyCode = getXMLValue(xmlDoc, 'cbc\\:TaxCurrencyCode, TaxCurrencyCode', '');
    
    document.querySelector('[name="documentCurrencyCode"]').value = documentCurrencyCode;
    document.querySelector('[name="taxCurrencyCode"]').value = taxCurrencyCode;
    
    // Store original totals and display them
    storeOriginalTotals(xmlDoc);
    restoreOriginalTotals();
}

function populatePartyDetails(xmlDoc) {
    function extractPartyDetails(party, prefix) {
        // Extract contact information
        const contact = party.querySelector('cac\\:Contact, Contact');
        const phone = contact?.querySelector('cbc\\:Telephone, Telephone')?.textContent || '';
        const contactName = contact?.querySelector('cbc\\:Name, Name')?.textContent || '';
        const email = contact?.querySelector('cbc\\:ElectronicMail, ElectronicMail')?.textContent || '';
    
        // Country Code Extraction
        const countryCodeElement = party.querySelector('cac\\:Country cbc\\:IdentificationCode, Country IdentificationCode');
        const countryCode = countryCodeElement ? countryCodeElement.textContent.trim() : 'RO';
     
        // Postal Address Details
        const postalAddress = party.querySelector('cac\\:PostalAddress, PostalAddress');
        const streetName = postalAddress ? 
            getXMLValue(postalAddress, 'cbc\\:StreetName, StreetName') : '';
        const cityName = postalAddress ? 
            getXMLValue(postalAddress, 'cbc\\:CityName, CityName') : '';
        const countyCode = postalAddress ? 
            getXMLValue(postalAddress, 'cbc\\:CountrySubentity, CountrySubentity') : '';
     
        // Set inputs
        document.querySelector(`[name="${prefix}Name"]`).value =
            getXMLValue(party, 'cac\\:PartyLegalEntity cbc\\:RegistrationName, PartyLegalEntity RegistrationName');

        // Cod TVA / Nr. înregistrare — derivă în funcție de prezența PartyTaxScheme.
        // Plătitor TVA: PartyTaxScheme/CompanyID e codul TVA, PartyLegalEntity/CompanyID e nr. registru.
        // Neplătitor TVA: PartyTaxScheme lipsește; CIF-ul stă în PartyLegalEntity/CompanyID,
        // iar nr. registru în PartyIdentification/ID. Trebuie inversate la încărcare ca să apară
        // în câmpurile corecte din formular (simetric cu createPartyElement la salvare).
        const taxSchemeCompanyId = getXMLValue(party, 'cac\\:PartyTaxScheme cbc\\:CompanyID, PartyTaxScheme CompanyID');
        const legalEntityCompanyId = getXMLValue(party, 'cac\\:PartyLegalEntity cbc\\:CompanyID, PartyLegalEntity CompanyID');
        const partyIdentificationId = getXMLValue(party, 'cac\\:PartyIdentification cbc\\:ID, PartyIdentification ID');
        let vatValue, companyIdValue;
        if (taxSchemeCompanyId) {
            vatValue = taxSchemeCompanyId;
            companyIdValue = legalEntityCompanyId || partyIdentificationId;
        } else {
            vatValue = legalEntityCompanyId;
            companyIdValue = partyIdentificationId;
        }
        document.querySelector(`[name="${prefix}VAT"]`).value = vatValue;
        document.querySelector(`[name="${prefix}CompanyId"]`).value = companyIdValue;
        document.querySelector(`[name="${prefix}Address"]`).value = streetName;
        document.querySelector(`[name="${prefix}City"]`).value = cityName;
        document.querySelector(`[name="${prefix}Phone"]`).value = phone;
        document.querySelector(`[name="${prefix}ContactName"]`).value = contactName;
        document.querySelector(`[name="${prefix}Email"]`).value = email;
     
        // Country Select
        const countrySelect = document.querySelector(`[name="${prefix}Country"]`);
        if (countrySelect) {
            countrySelect.value = countryCode;
            countrySelect.dataset.xmlValue = countryCode;
        }
     
        // County Select
        const countySelect = document.querySelector(`[name="${prefix}CountrySubentity"]`);
        if (countySelect) {
            countySelect.value = countyCode;
            countySelect.dataset.xmlValue = countyCode;
        }
    }
 
    const supplierParty = xmlDoc.querySelector('cac\\:AccountingSupplierParty, AccountingSupplierParty');
    if (supplierParty) {
        const supplierPartyDetails = supplierParty.querySelector('cac\\:Party, Party');
        if (supplierPartyDetails) {
            extractPartyDetails(supplierPartyDetails, 'supplier');
        }
    }
 
    const customerParty = xmlDoc.querySelector('cac\\:AccountingCustomerParty, AccountingCustomerParty');
    if (customerParty) {
        const customerPartyDetails = customerParty.querySelector('cac\\:Party, Party');
        if (customerPartyDetails) {
            extractPartyDetails(customerPartyDetails, 'customer');
        }
    }
 
    initializeLocationSelectors();
 }

 function populateAllowanceCharges(xmlDoc) {
    const charges = parseAllowanceCharges(xmlDoc);
    displayAllowanceCharges(charges);

    charges.forEach((_, index) => {
        setupAllowanceChargeListeners(index);
        addChargeVatTypeChangeListener(index);
    });
}

// ============================================================================
// A6: BillingReference (cac:BillingReference / cac:InvoiceDocumentReference)
// Populate + update helpers. UI: câmpuri billingRefId + billingRefDate în
// Detalii Factură. La Stornare, handleStorno() auto-populează cu ID + dată
// facturii originale.
// ============================================================================

function populateBillingReference(xmlDoc) {
    const refEl = xmlDoc.querySelector('cac\\:BillingReference cac\\:InvoiceDocumentReference, BillingReference InvoiceDocumentReference');
    const idInput = document.querySelector('[name="billingRefId"]');
    const dateInput = document.querySelector('[name="billingRefDate"]');
    if (!idInput || !dateInput) return;

    if (refEl) {
        idInput.value = getXMLValue(refEl, 'cbc\\:ID, ID') || '';
        const rawDate = getXMLValue(refEl, 'cbc\\:IssueDate, IssueDate') || '';
        if (rawDate) {
            const [year, month, day] = rawDate.split('-');
            dateInput.value = `${day}.${month}.${year}`;
        } else {
            dateInput.value = '';
        }
    } else {
        idInput.value = '';
        dateInput.value = '';
    }
}

function updateBillingReference(xmlDoc) {
    // Remove existing BillingReference elements.
    xmlDoc.querySelectorAll('cac\\:BillingReference, BillingReference').forEach(el => el.remove());

    const id = (document.querySelector('[name="billingRefId"]')?.value || '').trim();
    if (!id) return; // Nu scriem BillingReference dacă câmpul e gol.

    const dateRaw = (document.querySelector('[name="billingRefDate"]')?.value || '').trim();
    let isoDate = '';
    if (dateRaw && /^\d{2}\.\d{2}\.\d{4}$/.test(dateRaw)) {
        const [dd, mm, yyyy] = dateRaw.split('.');
        isoDate = `${yyyy}-${mm}-${dd}`;
    }

    const billingRef = createXMLElement(xmlDoc, XML_NAMESPACES.cac, 'cac:BillingReference');
    const docRef = createXMLElement(xmlDoc, XML_NAMESPACES.cac, 'cac:InvoiceDocumentReference');
    docRef.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 'cbc:ID', id));
    if (isoDate) {
        docRef.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 'cbc:IssueDate', isoDate));
    }
    billingRef.appendChild(docRef);

    // Insert before cac:AccountingSupplierParty (per UBL 2.1 ordering).
    const supplierParty = xmlDoc.querySelector('cac\\:AccountingSupplierParty, AccountingSupplierParty');
    if (supplierParty) {
        xmlDoc.documentElement.insertBefore(billingRef, supplierParty);
    } else {
        xmlDoc.documentElement.appendChild(billingRef);
    }
}

// ============================================================================
// A5: PaymentMeans (cac:PaymentMeans multiple)
// UI: secțiune "Modalități de Plată" cu rânduri dinamice (cod + IBAN).
// PAYMENT_MEANS_CODES definit la top lângă VAT_TYPES (nu duplicat).
// ============================================================================

let _paymentMeansCount = 0;

function createPaymentMeansRowHTML(index, code = '30', iban = '') {
    const options = Object.entries(PAYMENT_MEANS_CODES)
        .map(([val, label]) =>
            `<option value="${val}" ${val === String(code) ? 'selected' : ''}>${val} — ${label}</option>`)
        .join('');

    return `
        <div class="payment-means-row" data-pm-index="${index}">
            <div class="payment-means-grid">
                <div class="form-group">
                    <label class="form-label">Cod Modalitate</label>
                    <select class="form-input" name="paymentMeansCode${index}">${options}</select>
                </div>
                <div class="form-group">
                    <label class="form-label">IBAN</label>
                    <input type="text" class="form-input mono" name="paymentMeansIBAN${index}"
                           value="${iban}" placeholder="RO49AAAA1B31007593840000" style="text-align:left">
                </div>
                <button type="button" class="button button-small button-danger"
                        onclick="window.removePaymentMeansRow(${index})" style="align-self:flex-end">✕</button>
            </div>
        </div>
    `;
}

function addPaymentMeansRow(code = '30', iban = '') {
    const container = document.getElementById('paymentMeansRows');
    if (!container) return;
    const index = _paymentMeansCount++;
    container.insertAdjacentHTML('beforeend', createPaymentMeansRowHTML(index, code, iban));
}

function removePaymentMeansRow(index) {
    const row = document.querySelector(`.payment-means-row[data-pm-index="${index}"]`);
    if (row) row.remove();
}

function populatePaymentMeans(xmlDoc) {
    const container = document.getElementById('paymentMeansRows');
    if (!container) return;
    container.innerHTML = '';
    _paymentMeansCount = 0;

    const pmElements = xmlDoc.querySelectorAll('cac\\:PaymentMeans, PaymentMeans');
    pmElements.forEach(pmEl => {
        const code = getXMLValue(pmEl, 'cbc\\:PaymentMeansCode, PaymentMeansCode') || '30';
        const iban = getXMLValue(pmEl, 'cac\\:PayeeFinancialAccount cbc\\:ID, PayeeFinancialAccount ID') || '';
        addPaymentMeansRow(code, iban);
    });
}

function updatePaymentMeans(xmlDoc) {
    // Remove existing PaymentMeans elements.
    xmlDoc.querySelectorAll('cac\\:PaymentMeans, PaymentMeans').forEach(el => el.remove());

    const rows = document.querySelectorAll('.payment-means-row');
    if (rows.length === 0) return;

    // Insert before cac:AllowanceCharge (sau TaxTotal dacă nu există AllowanceCharge).
    const refEl = xmlDoc.querySelector('cac\\:AllowanceCharge, AllowanceCharge') ||
                  xmlDoc.querySelector('cac\\:TaxTotal, TaxTotal');

    rows.forEach(row => {
        const idx = row.dataset.pmIndex;
        const code = document.querySelector(`[name="paymentMeansCode${idx}"]`)?.value || '30';
        const iban = (document.querySelector(`[name="paymentMeansIBAN${idx}"]`)?.value || '').trim();

        const pmEl = createXMLElement(xmlDoc, XML_NAMESPACES.cac, 'cac:PaymentMeans');
        pmEl.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 'cbc:PaymentMeansCode', code));

        if (iban) {
            const account = createXMLElement(xmlDoc, XML_NAMESPACES.cac, 'cac:PayeeFinancialAccount');
            account.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 'cbc:ID', iban));
            pmEl.appendChild(account);
        }

        if (refEl) {
            xmlDoc.documentElement.insertBefore(pmEl, refEl);
        } else {
            xmlDoc.documentElement.appendChild(pmEl);
        }
    });
}

function populateLineItems(xmlDoc) {
    const lineItems = xmlDoc.querySelectorAll('cac\\:InvoiceLine, InvoiceLine');
    const lineItemsContainer = document.getElementById('lineItems');
    lineItemsContainer.innerHTML = '<h2 class="section-title">Articole Factură <button type="button" class="button button-small" onclick="addLineItem()">Adaugă Articol</button></h2>';

    lineItems.forEach((item, index) => {
        const quantity = getXMLValue(item, 'cbc\\:InvoicedQuantity, InvoicedQuantity', '0');
        const unitCode = item.querySelector('cbc\\:InvoicedQuantity, InvoicedQuantity')?.getAttribute('unitCode') || 'EA';
        const price = getXMLValue(item, 'cac\\:Price cbc\\:PriceAmount, Price PriceAmount', '0');
        // PR-A11: capture original LineExtensionAmount from XML for math validation badge.
        const xmlLineAmount = getXMLValue(item, 'cbc\\:LineExtensionAmount, LineExtensionAmount', '');
        const itemElement = item.querySelector('cac\\:Item, Item');
        const description = getXMLValue(itemElement, 'cbc\\:Name, Name', '');
        const itemDescription = getXMLValue(itemElement, 'cbc\\:Description, Description', '');

        const taxCategory = itemElement.querySelector('cac\\:ClassifiedTaxCategory, ClassifiedTaxCategory');
        const vatType = getXMLValue(taxCategory, 'cbc\\:ID, ID') || 'S';
        const vatRate = getXMLValue(taxCategory, 'cbc\\:Percent, Percent') || '19';

        // Extragem discountul și codul de motiv de pe linie dacă există
        let lineDiscount = 0;
        let discountReasonCode = '';
        const allowanceCharge = item.querySelector('cac\\:AllowanceCharge, AllowanceCharge');
        if (allowanceCharge) {
            const chargeIndicator = getXMLValue(allowanceCharge, 'cbc\\:ChargeIndicator, ChargeIndicator');
            if (chargeIndicator === 'false') {
                lineDiscount = parseFloat(getXMLValue(allowanceCharge, 'cbc\\:Amount, Amount', '0'));
                discountReasonCode = getXMLValue(allowanceCharge, 'cbc\\:AllowanceChargeReasonCode, AllowanceChargeReasonCode', '');
            }
        }

        addUnitCode(unitCode);
        const lineItemHtml = createLineItemHTML(
            index, description, quantity, price, vatRate, unitCode, vatType,
            itemDescription, lineDiscount, discountReasonCode
        );
        lineItemsContainer.insertAdjacentHTML('beforeend', lineItemHtml);

        // PR-A11: stash original XML LineExtensionAmount on the line-item element
        // for math validation badge (compare computed vs XML loaded with ±0.01 RON
        // tolerance când row-ul e clean — toate input-urile dataset.dirty='0').
        const lineItemEl = lineItemsContainer.querySelector(`.line-item[data-index="${index}"]`);
        if (lineItemEl && xmlLineAmount !== '') {
            const parsedXmlAmount = parseStrict(xmlLineAmount);
            if (parsedXmlAmount !== null) {
                lineItemEl.dataset.xmlLineAmount = parsedXmlAmount.toFixed(2);
            }
        }

        // PR-E E1: dataset.raw seeded din XML (canonical source of truth).
        // Wire blur listeners care normalizează la commit (parseStrict + setRaw).
        seedNumericRawForLineItem(index, { quantity, price, lineDiscount, vatRate });

        // Parse identifications after adding the line item HTML
        if (itemElement) {
            parseIdentifications(itemElement, index);
        }
        
        if (!isVATRegistered()) {
            const vatTypeSelect = document.querySelector(`[name="vatType${index}"]`);
            const vatRateInput = document.querySelector(`[name="vatRate${index}"]`);
            if (vatTypeSelect && vatRateInput) {
                vatTypeSelect.value = 'O';
                vatTypeSelect.disabled = true;
                vatRateInput.value = '0';
                vatRateInput.disabled = true;
            }
        }

        // Enable/disable discount reason code field based on discount value
        const discountInput = document.querySelector(`[name="lineDiscount${index}"]`);
        const reasonCodeSelect = document.querySelector(`[name="discountReasonCode${index}"]`);
        if (discountInput && reasonCodeSelect) {
            reasonCodeSelect.disabled = lineDiscount <= 0;
        }

        handleLineItemChange(index);
    });

}

// PR-E E1: helper care setează dataset.raw + wire blur normalize pe toate
// input-urile numerice ale unei linii de factură. Se apelează după
// insertAdjacentHTML, când DOM-ul există.
function seedNumericRawForLineItem(index, raw) {
    const fields = [
        { name: 'quantity', decimals: 3, value: raw.quantity },
        { name: 'price', decimals: 4, value: raw.price },
        { name: 'lineDiscount', decimals: 2, value: raw.lineDiscount },
        { name: 'vatRate', decimals: 2, value: raw.vatRate },
    ];
    fields.forEach(f => {
        const input = document.querySelector(`[name="${f.name}${index}"]`);
        if (!input) return;
        const big = parseStrict(f.value);
        if (big !== null) {
            // Stocăm raw canonical decimal-dot. NU schimbăm input.value
            // (lăsăm display ca în markup-ul existent — type=number e
            //  display-locale-agnostic în input field și are nevoie de '.').
            input.dataset.raw = big.toFixed(f.decimals);
        }
        wireDatasetRaw(input, f.decimals);
    });
}

// PR-E E1: idem pentru allowance/charge.
function seedNumericRawForCharge(index, raw) {
    const fields = [
        { name: 'chargeAmount', decimals: 2, value: raw.amount },
        { name: 'chargeBaseAmount', decimals: 2, value: raw.baseAmount },
        { name: 'chargeVatRate', decimals: 2, value: raw.vatRate },
    ];
    fields.forEach(f => {
        const input = document.querySelector(`[name="${f.name}${index}"]`);
        if (!input) return;
        const big = parseStrict(f.value);
        if (big !== null) {
            input.dataset.raw = big.toFixed(f.decimals);
        }
        wireDatasetRaw(input, f.decimals);
    });
}

function setupAllowanceChargeListeners(index) {
    const chargeAmountInput = document.querySelector(`[name="chargeAmount${index}"]`);
    const chargeTypeInput = document.querySelector(`[name="chargeType${index}"]`);
    const chargeVatTypeInput = document.querySelector(`[name="chargeVatType${index}"]`);
    const chargeVatRateInput = document.querySelector(`[name="chargeVatRate${index}"]`);
    const reasonCodeSelect = document.querySelector(`[name="chargeReasonCode${index}"]`);
    const reasonInput = document.querySelector(`[name="chargeReason${index}"]`);
    
    // Add change listeners to all inputs
    [chargeAmountInput, chargeTypeInput, chargeVatTypeInput, chargeVatRateInput].forEach(input => {
        if (input) {
            input.addEventListener('change', () => {
                manuallyEditedVatRows.clear();
                refreshTotals();
            });
        }
    });
    
    // Add reason code change listener
    if (reasonCodeSelect) {
        reasonCodeSelect.addEventListener('change', () => {
            const isCharge = chargeTypeInput.value === 'true';
            const codes = isCharge ? CHARGE_REASON_CODES : ALLOWANCE_REASON_CODES;
            reasonInput.value = codes[reasonCodeSelect.value] || '';
        });
    }
    
    // Special handling for VAT type changes
    if (chargeVatTypeInput) {
        chargeVatTypeInput.addEventListener('change', () => handleChargeVatTypeChange(index));
    }
}

function addChargeVatTypeChangeListener(index) {
    const vatTypeSelect = document.querySelector(`[name="chargeVatType${index}"]`);
    if (vatTypeSelect) {
        vatTypeSelect.addEventListener('change', function() {
            handleChargeVatTypeChange(index);
            // Force refresh of VAT breakdown
            displayVATBreakdown();
            updateTotals();
        });
    }
}

function parseAllowanceCharges(xmlDoc) {
    const charges = [];
    // Folosim Set pentru a preveni dublarea elementelor din cauza namespace-urilor
    const processedIds = new Set();
    
    // Selectăm toate elementele AllowanceCharge care sunt copii direcți ai Invoice
    const allowanceCharges = xmlDoc.querySelectorAll('cac\\:AllowanceCharge, AllowanceCharge');
    
    allowanceCharges.forEach(ac => {
        // Verificăm dacă elementul este copil direct al Invoice și nu a fost deja procesat
        if (ac.parentElement === xmlDoc.documentElement) {
            const amount = getXMLValue(ac, 'cbc\\:Amount, Amount');
            const reasonCode = getXMLValue(ac, 'cbc\\:AllowanceChargeReasonCode, AllowanceChargeReasonCode');
            
            // Creăm un ID unic bazat pe cod și valoare pentru a evita duplicatele
            const uniqueId = `${reasonCode}-${amount}`;
            
            if (!processedIds.has(uniqueId)) {
                processedIds.add(uniqueId);
                
                const charge = {
                    isCharge: getXMLValue(ac, 'cbc\\:ChargeIndicator, ChargeIndicator') === 'true',
                    reasonCode: reasonCode,
                    reason: getXMLValue(ac, 'cbc\\:AllowanceChargeReason, AllowanceChargeReason'),
                    amount: parseFloat(amount) || 0,
                    baseAmount: parseFloat(getXMLValue(ac, 'cbc\\:BaseAmount, BaseAmount')) || 0,
                    vatRate: parseFloat(getXMLValue(ac, 'cac\\:TaxCategory cbc\\:Percent, TaxCategory Percent')) || 0,
                    vatTypeId: getXMLValue(ac, 'cac\\:TaxCategory cbc\\:ID, TaxCategory ID', 'S'),
                    multiplierFactorNumeric: parseFloat(getXMLValue(ac, 'cbc\\:MultiplierFactorNumeric, MultiplierFactorNumeric')) || 0
                };
                charges.push(charge);
            }
        }
    });

    return charges;
}

function displayAllowanceCharges(charges) {
    const container = document.getElementById('allowanceCharges');
    container.innerHTML = '<h2 class="section-title">Reduceri și Taxe Suplimentare <button type="button" class="button button-small" onclick="addAllowanceCharge()">Adaugă Reducere/Taxă</button></h2>';

    charges.forEach((charge, index) => {
        const html = createAllowanceChargeHTML(index, charge);
        container.insertAdjacentHTML('beforeend', html);
        // PR-E E1: seed dataset.raw + wire blur listeners.
        seedNumericRawForCharge(index, {
            amount: charge.amount,
            baseAmount: charge.baseAmount,
            vatRate: charge.vatRate
        });
    });
}

function addAllowanceCharge() {
    const container = document.getElementById('allowanceCharges');
    const index = document.querySelectorAll('.allowance-charge').length;

    // Create new charge with default values
    const newCharge = {
        isCharge: true,
        reasonCode: 'TV',
        reason: 'Cheltuieli transport',
        amount: 0,
        vatRate: 19.0,
        vatTypeId: 'S'
    };

    // Add the HTML
    const html = createAllowanceChargeHTML(index, newCharge);
    container.insertAdjacentHTML('beforeend', html);

    // PR-E E1: seed dataset.raw + wire blur listeners.
    seedNumericRawForCharge(index, {
        amount: newCharge.amount,
        baseAmount: newCharge.baseAmount,
        vatRate: newCharge.vatRate
    });

    // Setup event listeners
    setupAllowanceChargeListeners(index);

    // Force refresh of totals and VAT
    refreshTotals();
}

function removeAllowanceCharge(index) {
    const charge = document.querySelector(`.allowance-charge[data-index="${index}"]`);
    if (charge) {
        // Remove the element
        charge.remove();
        
        // Renumber remaining charges
        renumberAllowanceCharges();
        
        // Clear manual edits and refresh totals
        manuallyEditedVatRows.clear();
        refreshTotals();
    }
}

function renumberAllowanceCharges() {
    document.querySelectorAll('.allowance-charge').forEach((charge, newIndex) => {
        // Update data-index
        charge.dataset.index = newIndex;
        
        // Update all input names
        charge.querySelectorAll('input, select').forEach(input => {
            const name = input.getAttribute('name');
            if (name) {
                const baseName = name.replace(/\d+$/, '');
                input.setAttribute('name', baseName + newIndex);
            }
        });
    });
}


function addLineItem() {
    const container = document.getElementById('lineItems');
    const index = document.querySelectorAll('.line-item').length;
    
    // Determină tipul implicit de TVA bazat pe statusul furnizorului
    const defaultVatType = isVATRegistered() ? 'S' : 'O';
    const defaultVatRate = isVATRegistered() ? '19' : '0';
    
    const lineItemHtml = createLineItemHTML(index, '', '1', '0', defaultVatRate, 'EA', defaultVatType);
    container.insertAdjacentHTML('beforeend', lineItemHtml);

    const newItem = container.lastElementChild;
    const vatTypeSelect = newItem.querySelector(`[name="vatType${index}"]`);

    // PR-E E1: seed dataset.raw + wire blur listeners.
    seedNumericRawForLineItem(index, {
        quantity: '1', price: '0', lineDiscount: '0', vatRate: defaultVatRate
    });

    if (!isVATRegistered()) {
        vatTypeSelect.disabled = true;
        newItem.querySelector(`[name="vatRate${index}"]`).disabled = true;
    }

    // Adăugăm event handlers pentru noua linie
    handleLineItemChange(index);
    
    manuallyEditedVatRows.clear();
    refreshTotals();
}

function removeLineItem(index) {
    const lineItem = document.querySelector(`.line-item[data-index="${index}"]`);
    if (lineItem) {
        lineItem.remove();
        renumberLineItems();
        manuallyEditedVatRows.clear(); // Clear manual edits
        refreshTotals(); // Recalculate all totals
    }
}

function handleLineItemChange(index) {
    const quantityInput = document.querySelector(`[name="quantity${index}"]`);
    const priceInput = document.querySelector(`[name="price${index}"]`);
    const discountInput = document.querySelector(`[name="lineDiscount${index}"]`);
    const reasonCodeSelect = document.querySelector(`[name="discountReasonCode${index}"]`);
    
    // Handler pentru schimbarea discount-ului
    discountInput?.addEventListener('input', function() {
        const discountValue = parseFloat(this.value) || 0;
        if (reasonCodeSelect) {
            reasonCodeSelect.disabled = discountValue == 0;  // activat pentru orice valoare nenulă
            // Dacă discount != 0 și nu e selectat niciun cod, selectăm codul implicit
            if (discountValue != 0 && !reasonCodeSelect.value) {
                reasonCodeSelect.value = '95'; // Cod implicit pentru reducere
            }
        }
        updateTotals();
    });

    // Handlers pentru cantitate și preț
    quantityInput?.addEventListener('change', updateTotals);
    priceInput?.addEventListener('change', updateTotals);
    
    // Force refresh
    updateTotals();
}

function handleStorno() {
    // A6: populează câmpurile BillingReference cu datele facturii curente
    // înainte de negare (referința facturii originale pentru nota de credit).
    const currentInvoiceNumber = document.querySelector('[name="invoiceNumber"]')?.value || '';
    const currentIssueDate = document.querySelector('[name="issueDate"]')?.value || '';
    const billingRefIdInput = document.querySelector('[name="billingRefId"]');
    const billingRefDateInput = document.querySelector('[name="billingRefDate"]');
    if (billingRefIdInput && !billingRefIdInput.value && currentInvoiceNumber) {
        billingRefIdInput.value = currentInvoiceNumber;
    }
    if (billingRefDateInput && !billingRefDateInput.value && currentIssueDate) {
        billingRefDateInput.value = currentIssueDate;
    }

    // PR-TIPURI (A4): la storno setăm cbc:InvoiceTypeCode = 381 (Notă de
    // credit). User poate suprascrie din dropdown dacă vrea alt cod.
    const typeSelect = document.querySelector('[name="invoiceTypeCode"]');
    if (typeSelect) typeSelect.value = '381';

    // PR-A11: folosim getRaw/setRaw/markDirty în loc de parseFloat
    // pentru a păstra dataset.raw consistent cu input.value după negare.
    document.querySelectorAll('.line-item').forEach((item, index) => {
        const quantityInput = document.querySelector(`[name="quantity${index}"]`);
        if (!quantityInput) return;
        setRaw(quantityInput, getRaw(quantityInput).times(-1), 3);
        markDirty(quantityInput);
    });

    document.querySelectorAll('.allowance-charge').forEach((item, index) => {
        const amountInput = document.querySelector(`[name="chargeAmount${index}"]`);
        if (!amountInput) return;
        setRaw(amountInput, getRaw(amountInput).times(-1), 2);
        markDirty(amountInput);
    });

    document.querySelectorAll('.vat-row').forEach(row => {
        const baseInput = row.querySelector('.vat-base');
        const amountInput = row.querySelector('.vat-amount');

        if (baseInput) {
            setRaw(baseInput, getRaw(baseInput).times(-1), 2);
            markDirty(baseInput);
        }

        if (amountInput) {
            setRaw(amountInput, getRaw(amountInput).times(-1), 2);
            markDirty(amountInput);
        }
    });

    manuallyEditedVatRows.clear();
    refreshTotals();
    
    if (currentInvoice) {
        updateTaxTotals(currentInvoice);
    }
}

function updateTotals() {
    // Calculăm totalurile liniilor (deja nete, după discount)
    const lineItemTotals = calculateLineItemTotals();
    const chargeTotals = calculateChargeTotals();

    const subtotal = lineItemTotals.subtotal;
    const allowances = chargeTotals.allowances;
    const charges = chargeTotals.charges;
    const netAmount = subtotal - allowances + charges;

    // Calculate VAT breakdown
    const { vatBreakdown } = calculateVATBreakdown();
    let totalVat = 0;
    
    vatBreakdown.forEach((entry) => {
        if (entry.type === 'S') {
            totalVat += entry.vatAmount;
        }
    });

    // Display totals with 2 decimal places
    displayTotals({
        subtotal: roundNumber(subtotal, 2),
        allowances: roundNumber(allowances, 2),
        charges: roundNumber(charges, 2),
        netAmount: roundNumber(netAmount, 2),
        totalVat: roundNumber(totalVat, 2),
        total: roundNumber(netAmount + totalVat, 2),
        vatBreakdown
    });

    // PR-A11: refresh badge-uri math validation după displayTotals.
    if (typeof validateMath === 'function') validateMath();

    // PR-BR: actualizează panelul de validare BR live pe orice editare.
    _updateBRPanel();
}

function refreshTotals() {
    // Calculate line items first
    const lineItemTotals = calculateLineItemTotals();
    const chargeTotals = calculateChargeTotals();

    const subtotal = lineItemTotals.subtotal;
    const allowances = chargeTotals.allowances;
    const charges = chargeTotals.charges;
    const netAmount = subtotal - allowances + charges;

    // Calculate VAT breakdown
    const { vatBreakdown } = calculateVATBreakdown();
    let totalVat = 0;
    if (vatBreakdown) {
        vatBreakdown.forEach(entry => {
            totalVat += entry.vatAmount;
        });
    }

    // Display totals
    displayTotals({
        subtotal,
        allowances,
        charges,
        netAmount,
        totalVat,
        total: netAmount + totalVat,
        vatBreakdown
    });

    // PR-A11: refresh badge-uri math validation după displayTotals.
    if (typeof validateMath === 'function') validateMath();

    // PR-BR: actualizează panelul de validare BR live.
    _updateBRPanel();
}

function calculateLineItemTotals() {
    // PR-E E4: pipeline Big.js. Citește din dataset.raw (canonical), fallback
    // la input.value via getRaw. Niciun parseFloat.
    let subtotal = new Big('0');

    document.querySelectorAll('.line-item').forEach((item, index) => {
        const quantity = getRaw(document.querySelector(`[name="quantity${index}"]`));
        const price = getRaw(document.querySelector(`[name="price${index}"]`));
        const lineDiscount = getRaw(document.querySelector(`[name="lineDiscount${index}"]`));

        // LineExtensionAmount = cantitate * preț - discount
        const lineAmount = quantity.times(price).minus(lineDiscount);
        subtotal = subtotal.plus(lineAmount);
    });

    return {
        subtotal: Number(subtotal.round(2, 1).toFixed(2))
    };
}

function calculateChargeTotals() {
    // PR-E E4: pipeline Big.js.
    let allowances = new Big('0');
    let charges = new Big('0');

    document.querySelectorAll('.allowance-charge').forEach((item, index) => {
        const isCharge = document.querySelector(`[name="chargeType${index}"]`).value === 'true';
        const amount = getRaw(document.querySelector(`[name="chargeAmount${index}"]`));
        if (isCharge) {
            charges = charges.plus(amount);
        } else {
            allowances = allowances.plus(amount);
        }
    });

    return {
        allowances: Number(allowances.round(2, 1).toFixed(2)),
        charges: Number(charges.round(2, 1).toFixed(2))
    };
}

function calculateTotals() {
    // PR-E E4: pipeline Big.js end-to-end. Toate citirile via getRaw → Big.
    let subtotalBig = new Big('0');
    let vatBreakdown = new Map();

    // Calculăm totalurile liniilor
    document.querySelectorAll('.line-item').forEach((item, index) => {
        const quantity = getRaw(document.querySelector(`[name="quantity${index}"]`));
        const price = getRaw(document.querySelector(`[name="price${index}"]`));
        const lineDiscount = getRaw(document.querySelector(`[name="lineDiscount${index}"]`));
        const vatType = document.querySelector(`[name="vatType${index}"]`).value;
        const vatRate = getRaw(document.querySelector(`[name="vatRate${index}"]`));

        // LineExtensionAmount = (cantitate * preț) - discount linie
        const lineNet = quantity.times(price).minus(lineDiscount);
        subtotalBig = subtotalBig.plus(lineNet);

        const rateKey = vatRate.toFixed(2);
        const key = `${rateKey}-${vatType}`;
        if (!vatBreakdown.has(key)) {
            vatBreakdown.set(key, {
                baseAmount: 0,
                vatAmount: 0,
                rate: Number(vatRate.toString()),
                type: vatType,
                _baseBig: new Big('0')
            });
        }
        const entry = vatBreakdown.get(key);
        entry._baseBig = entry._baseBig.plus(lineNet);
    });

    // Calculăm discounturile și taxele globale (returnate ca Number — convertim la Big intern)
    const { allowances, charges } = calculateChargeTotals();
    const allowancesBig = new Big(String(allowances));
    const chargesBig = new Big(String(charges));

    // Net = subtotal - allowances + charges
    const netAmountBig = subtotalBig.minus(allowancesBig).plus(chargesBig);

    // Ajustăm baza de TVA cu discount/taxe globale
    document.querySelectorAll('.allowance-charge').forEach((item, index) => {
        const amount = getRaw(document.querySelector(`[name="chargeAmount${index}"]`));
        const vatType = document.querySelector(`[name="chargeVatType${index}"]`).value;
        const vatRate = getRaw(document.querySelector(`[name="chargeVatRate${index}"]`));
        const isCharge = document.querySelector(`[name="chargeType${index}"]`).value === 'true';

        const rateKey = vatRate.toFixed(2);
        const key = `${rateKey}-${vatType}`;
        if (!vatBreakdown.has(key)) {
            vatBreakdown.set(key, {
                baseAmount: 0,
                vatAmount: 0,
                rate: Number(vatRate.toString()),
                type: vatType,
                _baseBig: new Big('0')
            });
        }
        const entry = vatBreakdown.get(key);
        entry._baseBig = isCharge ? entry._baseBig.plus(amount) : entry._baseBig.minus(amount);
    });

    // VAT pe rată — round HALF_UP la 2 zecimale
    let totalVatBig = new Big('0');
    vatBreakdown.forEach((entry) => {
        const baseRounded = entry._baseBig.round(2, 1);
        entry.baseAmount = Number(baseRounded.toFixed(2));
        if (entry.type === 'S') {
            const vatBig = entry._baseBig.times(entry.rate).div(100).round(2, 1);
            entry.vatAmount = Number(vatBig.toFixed(2));
            totalVatBig = totalVatBig.plus(vatBig);
        } else {
            entry.vatAmount = 0;
        }
        delete entry._baseBig;
    });

    const subtotal = Number(subtotalBig.round(2, 1).toFixed(2));
    const netAmount = Number(netAmountBig.round(2, 1).toFixed(2));
    const totalVat = Number(totalVatBig.round(2, 1).toFixed(2));

    return {
        subtotal,
        allowances,
        charges,
        netAmount,
        totalVat,
        total: Number(netAmountBig.plus(totalVatBig).round(2, 1).toFixed(2)),
        vatBreakdown
    };
}

function calculateVATBases(lines, globalAllowances, globalCharges) {
    // Initialize VAT bases
    const vatBases = {};
    
    // First pass: calculate base amounts per VAT rate from lines
    lines.forEach(line => {
        const vatRate = line.vatRate;
        if (!vatBases[vatRate]) {
            vatBases[vatRate] = {
                base: 0,
                allowances: 0,
                charges: 0
            };
        }
        
        const lineTotal = line.quantity * line.price;
        const lineAfterDiscount = lineTotal - line.lineDiscount;
        vatBases[vatRate].base += lineAfterDiscount;
    });
    
    // Second pass: apply global allowances and charges per VAT rate
    globalAllowances.forEach(allowance => {
        const vatRate = allowance.vatRate;
        if (vatBases[vatRate]) {
            vatBases[vatRate].allowances += allowance.amount;
        }
    });
    
    globalCharges.forEach(charge => {
        const vatRate = charge.vatRate;
        if (vatBases[vatRate]) {
            vatBases[vatRate].charges += charge.amount;
        }
    });
    
    // Calculate final VAT amounts
    Object.keys(vatBases).forEach(rate => {
        const rateData = vatBases[rate];
        const netBase = rateData.base - rateData.allowances + rateData.charges;
        rateData.vatAmount = netBase * (parseFloat(rate) / 100);
    });
    
    return vatBases;
}

function calculateTotalVAT() {
    let totalVat = Array.from(document.querySelectorAll('.vat-amount'))
        .reduce((sum, input) => sum + formatter.parseCurrency(input.value), 0);
    return roundNumber(totalVat, 2);
}

function calculateVATBreakdown() {
    // PR-E E4: pipeline Big.js. Aceeași semantică ca calculateTotals dar
    // doar partea de breakdown (folosit de displayVATBreakdown).
    let vatBreakdown = new Map();
    let totalVatBig = new Big('0');

    // Process line items
    document.querySelectorAll('.line-item').forEach((item, index) => {
        const quantity = getRaw(document.querySelector(`[name="quantity${index}"]`));
        const price = getRaw(document.querySelector(`[name="price${index}"]`));
        const lineDiscount = getRaw(document.querySelector(`[name="lineDiscount${index}"]`));
        const vatType = document.querySelector(`[name="vatType${index}"]`).value;
        const vatRate = getRaw(document.querySelector(`[name="vatRate${index}"]`));

        const lineAmount = quantity.times(price).minus(lineDiscount);
        const rateKey = vatRate.toFixed(2);
        const key = `${rateKey}-${vatType}`;

        if (!vatBreakdown.has(key)) {
            vatBreakdown.set(key, {
                baseAmount: 0,
                vatAmount: 0,
                rate: Number(vatRate.toString()),
                type: vatType,
                _baseBig: new Big('0')
            });
        }
        const entry = vatBreakdown.get(key);
        entry._baseBig = entry._baseBig.plus(lineAmount);
    });

    // Process allowances and charges
    document.querySelectorAll('.allowance-charge').forEach((charge, index) => {
        const amount = getRaw(document.querySelector(`[name="chargeAmount${index}"]`));
        const vatType = document.querySelector(`[name="chargeVatType${index}"]`).value;
        const vatRate = getRaw(document.querySelector(`[name="chargeVatRate${index}"]`));
        const isCharge = document.querySelector(`[name="chargeType${index}"]`).value === 'true';

        if (amount.eq(0)) return;

        const rateKey = vatRate.toFixed(2);
        const key = `${rateKey}-${vatType}`;

        if (!vatBreakdown.has(key)) {
            vatBreakdown.set(key, {
                baseAmount: 0,
                vatAmount: 0,
                rate: Number(vatRate.toString()),
                type: vatType,
                _baseBig: new Big('0')
            });
        }
        const entry = vatBreakdown.get(key);
        entry._baseBig = isCharge ? entry._baseBig.plus(amount) : entry._baseBig.minus(amount);
    });

    // Calculate VAT for each rate
    vatBreakdown.forEach((entry) => {
        entry.baseAmount = Number(entry._baseBig.round(2, 1).toFixed(2));
        if (entry.type === 'S') {
            const vatBig = entry._baseBig.times(entry.rate).div(100).round(2, 1);
            entry.vatAmount = Number(vatBig.toFixed(2));
            totalVatBig = totalVatBig.plus(vatBig);
        } else {
            entry.vatAmount = 0;
        }
        delete entry._baseBig;
    });

    return { vatBreakdown, totalVat: Number(totalVatBig.round(2, 1).toFixed(2)) };
}

window.updateVATRow = function(rowId, source) {
    const row = document.getElementById(rowId);
    if (!row) return;

    const typeSelect = row.querySelector('.vat-type');
    const rateInput = row.querySelector('.vat-rate');
    const baseInput = row.querySelector('.vat-base');
    const amountInput = row.querySelector('.vat-amount');
    
    if (source === 'manual') {
        manuallyEditedVatRows.add(rowId);
        // Keep existing values, just update totals
        updateTotalVAT();
        refreshTotals();
        return;
    }
    
    // Only calculate VAT amount for non-manual updates
    if (!manuallyEditedVatRows.has(rowId)) {
        // PR-E E4: Big.js pentru calcul VAT.
        const type = typeSelect.value;
        const rate = getRaw(rateInput);
        const base = getRaw(baseInput);

        let calculatedAmountBig;
        if (type === 'S') {
            calculatedAmountBig = base.times(rate).div(100).round(2, 1);
        } else {
            calculatedAmountBig = new Big('0');
        }
        const calculatedAmount = Number(calculatedAmountBig.toFixed(2));
        amountInput.value = formatter.formatCurrency(calculatedAmount);
        amountInput.dataset.raw = calculatedAmountBig.toFixed(2);

        updateTotalVAT();
        refreshTotals();
    }
};

window.updateVATRowFromAmount = function(rowId) {
    const row = document.getElementById(rowId);
    if (!row) return;

    // Just mark as manually edited and update the totals
    // Do not recalculate base amount
    manuallyEditedVatRows.add(rowId);

    const amountInput = row.querySelector('.vat-amount');
    if (amountInput) {
        // PR-E E1+E4: parse strict, sync dataset.raw, format display.
        const valueBig = parseStrictOr(amountInput.value, '0');
        amountInput.value = formatter.formatCurrency(Number(valueBig.toString()));
        amountInput.dataset.raw = valueBig.toFixed(2);
    }

    let totalVatBig = new Big('0');
    document.querySelectorAll('.vat-row').forEach(vatRow => {
        totalVatBig = totalVatBig.plus(getRaw(vatRow.querySelector('.vat-amount')));
    });

    // Update just total VAT and final total
    const netAmountBig = parseStrictOr(document.getElementById('netAmount').textContent, '0');
    document.getElementById('vat').textContent = formatter.formatCurrency(Number(totalVatBig.toFixed(2)));
    document.getElementById('total').textContent = formatter.formatCurrency(Number(netAmountBig.plus(totalVatBig).toFixed(2)));

    // PR-A11: refresh badge-uri math validation după edit manual de vat-amount.
    if (typeof validateMath === 'function') validateMath();
};

window.removeVATRow = function(rowId) {
    const row = document.getElementById(rowId);
    if (row) {
        manuallyEditedVatRows.delete(rowId);
        row.remove();
        updateTotalVAT();
        refreshTotals();
    }
};

window.addVATRate = function() {
    const container = document.getElementById('vatBreakdownRows');
    addVATBreakdownRow(19, 0, 0);
    refreshTotals();
};

function updateTotalVAT() {
    // PR-E E4: Big.js. Citește din dataset.raw → fallback parseStrict pe value.
    const totalVatBig = Array.from(document.querySelectorAll('.vat-amount'))
        .reduce((sum, input) => sum.plus(getRaw(input)), new Big('0'));

    document.getElementById('vat').textContent = totalVatBig.toFixed(2);

    const netAmountBig = parseStrictOr(document.getElementById('netAmount').textContent, '0');
    const total = netAmountBig.plus(totalVatBig);
    document.getElementById('total').textContent = total.toFixed(2);
}

function updateVATBreakdown() {
    // Șterge și reconstruiește rândurile TVA
    const container = document.getElementById('vatBreakdownRows');
    if (!container) return;

    container.innerHTML = '';
    const { vatBreakdown } = calculateVATBreakdown();
    
    vatBreakdown.forEach((data, key) => {
        const [rate, type] = key.split('-');
        addVATBreakdownRow(
            parseFloat(rate),
            data.baseAmount,
            data.vatAmount,
            type
        );
    });
}

function displayVATBreakdown(xmlDoc = null) {
    const container = document.getElementById('vatBreakdownRows');
    if (!container) return;

    // Clear container
    container.innerHTML = '';

    // If XML is provided, use its VAT breakdown
    if (xmlDoc && originalTotals && originalTotals.vatBreakdown) {
        originalTotals.vatBreakdown.forEach((vat, index) => {
            addVATBreakdownRow(
                vat.percent,
                vat.taxableAmount,
                vat.taxAmount,
                vat.type,
                `vat-row-${index}`,
                vat.exemptionCode,
                vat.exemptionReason
            );
        });
    } else {
        // Calculate current VAT breakdown
        const { vatBreakdown } = calculateVATBreakdown();
        vatBreakdown.forEach((data, key) => {
            const [rate, type] = key.split('-');
            addVATBreakdownRow(
                parseFloat(rate),
                data.baseAmount,
                data.vatAmount,
                type
            );
        });
    }
}

function createEmptyInvoice() {
    const parser = new DOMParser();
    const xmlString = `<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
         xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
         xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
    <cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1</cbc:CustomizationID>
    <cbc:ID></cbc:ID>
    <cbc:IssueDate></cbc:IssueDate>
    <cbc:DueDate></cbc:DueDate>
    <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
    <cbc:DocumentCurrencyCode>RON</cbc:DocumentCurrencyCode>
    <cac:AccountingSupplierParty>
        <cac:Party>
            <cac:PartyName>
                <cbc:Name></cbc:Name>
            </cac:PartyName>
            <cac:PostalAddress>
                <cbc:StreetName></cbc:StreetName>
                <cbc:CityName></cbc:CityName>
                <cbc:CountrySubentity></cbc:CountrySubentity>
                <cac:Country>
                    <cbc:IdentificationCode>RO</cbc:IdentificationCode>
                </cac:Country>
            </cac:PostalAddress>
            <cac:PartyTaxScheme>
                <cbc:CompanyID>RO</cbc:CompanyID>
                <cac:TaxScheme>
                    <cbc:ID>VAT</cbc:ID>
                </cac:TaxScheme>
            </cac:PartyTaxScheme>
            <cac:PartyLegalEntity>
                <cbc:RegistrationName></cbc:RegistrationName>
                <cbc:CompanyID></cbc:CompanyID>
            </cac:PartyLegalEntity>
            <cac:Contact>
                <cbc:Telephone></cbc:Telephone>
            </cac:Contact>
        </cac:Party>
    </cac:AccountingSupplierParty>
    <cac:AccountingCustomerParty>
        <cac:Party>
            <cac:PartyName>
                <cbc:Name></cbc:Name>
            </cac:PartyName>
            <cac:PostalAddress>
                <cbc:StreetName></cbc:StreetName>
                <cbc:CityName></cbc:CityName>
                <cbc:CountrySubentity></cbc:CountrySubentity>
                <cac:Country>
                    <cbc:IdentificationCode>RO</cbc:IdentificationCode>
                </cac:Country>
            </cac:PostalAddress>
            <cac:PartyTaxScheme>
                <cbc:CompanyID></cbc:CompanyID>
                <cac:TaxScheme>
                    <cbc:ID>VAT</cbc:ID>
                </cac:TaxScheme>
            </cac:PartyTaxScheme>
            <cac:PartyLegalEntity>
                <cbc:RegistrationName></cbc:RegistrationName>
                <cbc:CompanyID></cbc:CompanyID>
            </cac:PartyLegalEntity>
            <cac:Contact>
                <cbc:Telephone></cbc:Telephone>
            </cac:Contact>
        </cac:Party>
    </cac:AccountingCustomerParty>
</Invoice>`;
    return parser.parseFromString(xmlString, "text/xml");
}

function saveXML() {
    if (!validateForm()) return;

    // PR-A11: math validation pre-save. Ruleaza validateMath și dacă footer
    // diff > tolerance, afișează toast warning ORANGE — DAR NU bloca save-ul.
    try {
        if (typeof validateMath === 'function') {
            const { footerDiff, footerOver } = validateMath();
            if (footerOver) {
                showToast(
                    `Atenție: totalul afișat diferă cu ${footerDiff.toFixed(2)} RON față de calculul intern.`,
                    'warning',
                    'Verifică liniile și defalcarea TVA. Salvarea continuă.'
                );
            }
        }
    } catch (_) { /* validation must never block save */ }

    try {
        if (!currentInvoice) {
            currentInvoice = createEmptyInvoice();
        }

        const xmlDoc = currentInvoice;
        
        // Update all the data
        updateBasicDetails(xmlDoc);
        updatePartyDetails(xmlDoc);
        updateBillingReference(xmlDoc);
        updatePaymentMeans(xmlDoc);
        updateAllowanceCharges(xmlDoc);
        
        // Remove existing TaxTotal and LegalMonetaryTotal elements
        const existingTaxTotals = xmlDoc.querySelectorAll('cac\\:TaxTotal, TaxTotal');
        existingTaxTotals.forEach(el => el.remove());
        
        const existingMonetaryTotal = xmlDoc.querySelector('cac\\:LegalMonetaryTotal, LegalMonetaryTotal');
        if (existingMonetaryTotal) {
            existingMonetaryTotal.remove();
        }
        
        // Remove existing InvoiceLine elements
        const existingLines = xmlDoc.querySelectorAll('cac\\:InvoiceLine, InvoiceLine');
        existingLines.forEach(el => el.remove());
        
        // Add elements in the correct order
        updateTaxTotals(xmlDoc);
        updateMonetaryTotals(xmlDoc);
        updateLineItems(xmlDoc);
        
        downloadXML(xmlDoc);
    } catch (error) {
        handleError(error, 'Eroare la salvarea fișierului XML');
    }
}

function updateBasicDetails(xmlDoc) {
    setXMLValue(xmlDoc, 'cbc\\:ID, ID', document.querySelector('[name="invoiceNumber"]').value);

    // PR-TIPURI (A4): scrie cbc:InvoiceTypeCode din dropdown. Dacă elementul
    // lipsește (factură creată cu createEmptyInvoice care îl include deja, sau
    // XML legacy fără el), îl creăm și inserăm imediat după cbc:DueDate.
    const typeSelect = document.querySelector('[name="invoiceTypeCode"]');
    const typeCode = (typeSelect && INVOICE_TYPES[typeSelect.value]) ? typeSelect.value : '380';
    let typeEl = xmlDoc.querySelector('cbc\\:InvoiceTypeCode, InvoiceTypeCode');
    if (typeEl) {
        typeEl.textContent = typeCode;
    } else {
        typeEl = createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 'cbc:InvoiceTypeCode', typeCode);
        const after = xmlDoc.querySelector('cbc\\:DueDate, DueDate') ||
                      xmlDoc.querySelector('cbc\\:IssueDate, IssueDate');
        if (after && after.parentNode) {
            after.parentNode.insertBefore(typeEl, after.nextSibling);
        } else {
            xmlDoc.documentElement.appendChild(typeEl);
        }
    }

    // Remove existing Note elements
    const existingNotes = xmlDoc.querySelectorAll('cbc\\:Note, Note');
    existingNotes.forEach(note => note.remove());

    // Split note text and create new Note elements
    const noteText = document.querySelector('[name="invoiceNote"]').value;
    if (noteText) {
        const insertAfter = xmlDoc.querySelector('cbc\\:InvoiceTypeCode, InvoiceTypeCode');
        const chunks = splitNoteIntoChunks(noteText, 300);
        chunks.forEach(chunk => {
            const noteElement = createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:Note", chunk);
            if (insertAfter && insertAfter.parentNode) {
                insertAfter.parentNode.insertBefore(noteElement, insertAfter.nextSibling);
            }
        });
    }

    const issueDateValue = document.querySelector('[name="issueDate"]').value;
    const dueDateValue = document.querySelector('[name="dueDate"]').value;
    
    setXMLValue(xmlDoc, 'cbc\\:IssueDate, IssueDate', parseRomanianDate(issueDateValue));
    setXMLValue(xmlDoc, 'cbc\\:DueDate, DueDate', parseRomanianDate(dueDateValue));

   // Update currency codes
   const documentCurrencyCode = document.querySelector('[name="documentCurrencyCode"]').value.toUpperCase() || 'RON';
   setXMLValue(xmlDoc, 'cbc\\:DocumentCurrencyCode, DocumentCurrencyCode', documentCurrencyCode);
   
   const taxCurrencyCode = document.querySelector('[name="taxCurrencyCode"]').value.toUpperCase();
   if (taxCurrencyCode) {
       let taxCurrencyElement = xmlDoc.querySelector('cbc\\:TaxCurrencyCode, TaxCurrencyCode');
       if (!taxCurrencyElement) {
           taxCurrencyElement = createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:TaxCurrencyCode");
           const insertAfter = xmlDoc.querySelector('cbc\\:DocumentCurrencyCode, DocumentCurrencyCode');
           if (insertAfter && insertAfter.parentNode) {
               insertAfter.parentNode.insertBefore(taxCurrencyElement, insertAfter.nextSibling);
           }
       }
       taxCurrencyElement.textContent = taxCurrencyCode;
   } else {
       // Remove TaxCurrencyCode if it exists and is empty
       const taxCurrencyElement = xmlDoc.querySelector('cbc\\:TaxCurrencyCode, TaxCurrencyCode');
       if (taxCurrencyElement) {
           taxCurrencyElement.parentNode.removeChild(taxCurrencyElement);
       }
   }    
}

function createPartyElement(xmlDoc, isSupplier, partyData) {
    const party = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:Party");
    const hasVatPrefix = /^[A-Z]{2}/.test(partyData.vat?.trim() || '');
    const IsNeplatitor = vatHasO();    

    // Add PartyIdentification
    if (partyData.companyId) {
        const partyIdentification = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:PartyIdentification");
        partyIdentification.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ID", partyData.companyId));
        party.appendChild(partyIdentification);
    }

    function validateCountryCode(countryCode) {
        const code = countryCode?.trim().toUpperCase() || 'RO';
        return ISO_3166_1_CODES.has(code) ? code : 'RO';
    }

    function validateCountyCode(countryCode, countyCode) {
        if (countryCode === 'RO') {
            return ROMANIAN_COUNTY_CODES.has(countyCode) ? countyCode : 'RO-B';
        }
        return countyCode;
    }

    const postalAddress = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:PostalAddress");
    postalAddress.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:StreetName", partyData.address));
    postalAddress.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:CityName", partyData.city));
    postalAddress.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:CountrySubentity", partyData.county));
    
    const country = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:Country");
    // Ensure country code is valid ISO 3166-1 format (2 uppercase letters)
    const countryCode = partyData.country?.trim().toUpperCase() || 'RO';
    country.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:IdentificationCode", countryCode));
    postalAddress.appendChild(country);
    party.appendChild(postalAddress);

    const vatTypesInUse = new Set();
    document.querySelectorAll('.line-item').forEach((item, index) => {
        const vatType = document.querySelector(`[name="vatType${index}"]`).value;
        vatTypesInUse.add(vatType);
    });
    
    // Add PartyTaxScheme for all suppliers VAT types except 'O' or all customers with VAT prefix
    if (hasVatPrefix ) {
        const partyTaxScheme = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:PartyTaxScheme");
        partyTaxScheme.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:CompanyID", partyData.vat.toUpperCase()));
        const taxScheme = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:TaxScheme");
        if (!IsNeplatitor) {
            taxScheme.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ID", "VAT"));
        }  
        else     {
            // console.log('not adding VAT ID');
        }    
        partyTaxScheme.appendChild(taxScheme);
        
        party.appendChild(partyTaxScheme);
    }

    // Funcție pentru detectarea dacă există un VAT cu tipul 'O' Neplatitor de TVA
    // În cazul în care există, nu se va adăuga un element TaxScheme cu ID-ul 'VAT'
    function vatHasO() {
        const vatTypesInUse = new Set();
        document.querySelectorAll('.line-item').forEach((item, index) => {
            const vatType = document.querySelector(`[name="vatType${index}"]`).value;
            vatTypesInUse.add(vatType);
        });
        return vatTypesInUse.size > 0 && vatTypesInUse.has('O');
    }

    // Add PartyLegalEntity
    const partyLegalEntity = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:PartyLegalEntity");
    partyLegalEntity.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:RegistrationName", partyData.name));

    // Add CompanyID 
    if (!hasVatPrefix) {
        // For non-VAT registered supplier, use VAT number in CompanyID
        partyLegalEntity.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:CompanyID", partyData.vat));
    } else {
        // For others, use companyId
        partyLegalEntity.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:CompanyID", partyData.companyId));
    }

    party.appendChild(partyLegalEntity);

    // Add Contact if phone, email or contactName exists
    if (partyData.phone || partyData.email || partyData.contactName) {
        const contact = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:Contact");
        
        if (partyData.contactName) {
            contact.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:Name", partyData.contactName));
        }
        if (partyData.phone) {
            contact.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:Telephone", partyData.phone));
        }
        if (partyData.email) {
            contact.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ElectronicMail", partyData.email));
        }
        party.appendChild(contact);
    }
    return party;
}

function updatePartyDetails(xmlDoc) {
    // Update supplier details
    const supplierData = {
        name: document.querySelector('[name="supplierName"]').value,
        vat: document.querySelector('[name="supplierVAT"]').value,
        companyId: document.querySelector('[name="supplierCompanyId"]').value,
        address: document.querySelector('[name="supplierAddress"]').value,
        city: document.querySelector('[name="supplierCity"]').value,
        county: document.querySelector('[name="supplierCountrySubentity"]').value,
        country: document.querySelector('[name="supplierCountry"]').value,
        phone: document.querySelector('[name="supplierPhone"]').value,
        contactName: document.querySelector('[name="supplierContactName"]').value,
        email: document.querySelector('[name="supplierEmail"]').value
    };
    
    updatePartyXML(xmlDoc, true, supplierData);

    // Update customer details
    const customerData = {
        name: document.querySelector('[name="customerName"]').value,
        vat: document.querySelector('[name="customerVAT"]').value,
        companyId: document.querySelector('[name="customerCompanyId"]').value,
        address: document.querySelector('[name="customerAddress"]').value,
        city: document.querySelector('[name="customerCity"]').value,
        county: document.querySelector('[name="customerCountrySubentity"]').value,
        country: document.querySelector('[name="customerCountry"]').value,
        phone: document.querySelector('[name="customerPhone"]').value,
        contactName: document.querySelector('[name="customerContactName"]').value,
        email: document.querySelector('[name="customerEmail"]').value
    };
    
    updatePartyXML(xmlDoc, false, customerData);
}

function updatePartyXML(xmlDoc, isSupplier, partyData) {
    const partyElement = createPartyElement(xmlDoc, isSupplier, partyData);
    const parentTag = isSupplier ? 'AccountingSupplierParty' : 'AccountingCustomerParty';
    let parentElement = xmlDoc.querySelector(`cac\\:${parentTag}, ${parentTag}`);
    
    if (!parentElement) {
        parentElement = createXMLElement(xmlDoc, XML_NAMESPACES.cac, `cac:${parentTag}`);
        const insertPoint = isSupplier ? 
            xmlDoc.querySelector('cbc\\:DocumentCurrencyCode, DocumentCurrencyCode') : 
            xmlDoc.querySelector('cac\\:AccountingSupplierParty, AccountingSupplierParty');
            
        if (insertPoint && insertPoint.parentNode) {
            insertPoint.parentNode.insertBefore(parentElement, insertPoint.nextSibling);
        } else {
            xmlDoc.documentElement.appendChild(parentElement);
        }
    }

    // Remove existing Party element if it exists
    const existingParty = parentElement.querySelector('cac\\:Party, Party');
    if (existingParty) {
        existingParty.remove();
    }

    parentElement.appendChild(partyElement);
}

function getAllowanceCharges() {
    const charges = [];
    document.querySelectorAll('.allowance-charge').forEach((item, index) => {
        charges.push({
            isCharge: document.querySelector(`[name="chargeType${index}"]`).value === 'true',
            reasonCode: document.querySelector(`[name="chargeReasonCode${index}"]`).value,
            reason: document.querySelector(`[name="chargeReason${index}"]`).value,
            amount: parseFloat(document.querySelector(`[name="chargeAmount${index}"]`).value) || 0,
            vatRate: parseFloat(document.querySelector(`[name="chargeVatRate${index}"]`).value) || 19.0,
            vatTypeId: document.querySelector(`[name="chargeVatType${index}"]`).value || 'S'
        });
    });
    return charges;
}

function updateAllowanceCharges(xmlDoc) {
    const currencyID = document.querySelector('[name="documentCurrencyCode"]').value.toUpperCase() || 'RON';
    
    // Remove existing global allowances/charges
    const existingCharges = xmlDoc.querySelectorAll('Invoice > cac\\:AllowanceCharge, Invoice > AllowanceCharge');
    existingCharges.forEach(charge => charge.remove());
    
    // Add global allowances
    document.querySelectorAll('.allowance-charge').forEach((item, index) => {
        const allowanceElement = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:AllowanceCharge");
        
        const isCharge = document.querySelector(`[name="chargeType${index}"]`).value === 'true';
        const amount = parseFloat(document.querySelector(`[name="chargeAmount${index}"]`).value) || 0;
        const baseAmount = parseFloat(document.querySelector(`[name="chargeBaseAmount${index}"]`).value) || 0;
        const reasonCode = document.querySelector(`[name="chargeReasonCode${index}"]`).value;
        const reason = document.querySelector(`[name="chargeReason${index}"]`).value;
        const vatTypeId = document.querySelector(`[name="chargeVatType${index}"]`).value;
        const vatRate = parseFloat(document.querySelector(`[name="chargeVatRate${index}"]`).value) || 0;

        allowanceElement.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ChargeIndicator", 
            isCharge.toString()));
        
        if (reasonCode) {
            allowanceElement.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 
                "cbc:AllowanceChargeReasonCode", reasonCode));
        }
        
        if (reason) {
            allowanceElement.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 
                "cbc:AllowanceChargeReason", reason));
        }
        
        // Add multiplier if exists
        if (baseAmount > 0) {
            const multiplier = (amount / baseAmount) * 100;
            allowanceElement.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc,
                "cbc:MultiplierFactorNumeric", multiplier.toFixed(2)));
        }
        
        allowanceElement.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:Amount", 
            amount.toFixed(2), { currencyID }));
            
        if (baseAmount > 0) {
            allowanceElement.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:BaseAmount",
                baseAmount.toFixed(2), { currencyID }));
        }
        
        // Add tax category
        const taxCategory = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:TaxCategory");
        taxCategory.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ID", vatTypeId));
        taxCategory.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:Percent",
            vatRate.toString()));
            
        const taxScheme = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:TaxScheme");
        taxScheme.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ID", "VAT"));
        taxCategory.appendChild(taxScheme);
        
        allowanceElement.appendChild(taxCategory);
        
        // Insert before TaxTotal
        const taxTotal = xmlDoc.querySelector('cac\\:TaxTotal, TaxTotal');
        if (taxTotal) {
            xmlDoc.documentElement.insertBefore(allowanceElement, taxTotal);
        } else {
            xmlDoc.documentElement.appendChild(allowanceElement);
        }
    });
}

function updateLineItems(xmlDoc) {
    const currencyID = xmlDoc.querySelector('cbc\\:DocumentCurrencyCode, DocumentCurrencyCode').textContent;
    
    // Șterge liniile existente
    const existingLines = xmlDoc.querySelectorAll('cac\\:InvoiceLine, InvoiceLine');
    existingLines.forEach(line => line.remove());
    
    document.querySelectorAll('.line-item').forEach((item, index) => {
        const invoiceLine = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:InvoiceLine");
        
        // Obține valorile liniei
        const quantity = document.querySelector(`[name="quantity${index}"]`)?.value || '0';
        const unitCode = document.querySelector(`[name="unit${index}"]`)?.value || 'EA';
        const price = document.querySelector(`[name="price${index}"]`)?.value || '0';
        const description = document.querySelector(`[name="description${index}"]`)?.value || '';
        const itemDescription = document.querySelector(`[name="itemDescription${index}"]`)?.value || '';
        const vatType = document.querySelector(`[name="vatType${index}"]`)?.value || 'S';
        const vatRate = vatType === 'AE' ? '0.00' : 
            (document.querySelector(`[name="vatRate${index}"]`)?.value || '0');
        const lineDiscount = parseFloat(document.querySelector(`[name="lineDiscount${index}"]`)?.value) || 0;
        
        // Calculează valorile liniei
        const baseLineAmount = quantity * price;
        const lineAmount = roundNumber(baseLineAmount - lineDiscount);

        // Adaugă elementele liniei
        invoiceLine.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ID", (index + 1).toString()));
        
        const quantityElement = createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:InvoicedQuantity", quantity);
        quantityElement.setAttribute('unitCode', unitCode);
        invoiceLine.appendChild(quantityElement);
        
        // Adaugă LineExtensionAmount (valoarea după discount)
        invoiceLine.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:LineExtensionAmount", 
            lineAmount.toFixed(2), { currencyID }));
        
        // Adaugă discount pe linie dacă există
        if (lineDiscount != 0) {
            const allowanceCharge = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:AllowanceCharge");
            allowanceCharge.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ChargeIndicator", 
                lineDiscount < 0 ? "true" : "false"));
            
            const reasonCode = document.querySelector(`[name="discountReasonCode${index}"]`)?.value || '95';
            allowanceCharge.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 
                "cbc:AllowanceChargeReasonCode", reasonCode));
            allowanceCharge.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 
                "cbc:AllowanceChargeReason", ALLOWANCE_REASON_CODES[reasonCode] || 'Reducere'));
            
            // BaseAmount trebuie să fie valoarea netă înainte de discount
            const baseAmount = Math.abs(lineAmount);
            const discountAmount = Math.abs(lineDiscount);
            const multiplierFactor = (discountAmount / baseAmount * 100).toFixed(2);

            allowanceCharge.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc,
                "cbc:MultiplierFactorNumeric", multiplierFactor));
                
            allowanceCharge.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:Amount", 
                discountAmount.toFixed(2), { currencyID }));
                
            allowanceCharge.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:BaseAmount", 
                baseAmount.toFixed(2), { currencyID }));
                
            invoiceLine.appendChild(allowanceCharge);
        }

        // Adaugă detaliile articolului
        const itemElement = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:Item");
        
        if (itemDescription) {
            itemElement.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:Description", 
                itemDescription));
        }
        
        itemElement.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:Name", description));
        
        // Adaugă identificările
        const identificationsContainer = document.querySelector(`#identifications${index}`);
        if (identificationsContainer) {
            saveIdentificationsToXML(xmlDoc, itemElement, index);
        }

        // Adaugă categoria de taxă
        const taxCategory = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:ClassifiedTaxCategory");
        taxCategory.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ID", vatType));
        if (vatType !== 'O') {
            taxCategory.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:Percent", vatRate));
        }
               
        const taxScheme = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:TaxScheme");
        taxScheme.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ID", "VAT"));
        taxCategory.appendChild(taxScheme);
        itemElement.appendChild(taxCategory);

        invoiceLine.appendChild(itemElement);
        
        // Adaugă prețul
        const priceElement = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:Price");
        priceElement.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:PriceAmount", 
            price, { currencyID }));
        invoiceLine.appendChild(priceElement);
        
        xmlDoc.documentElement.appendChild(invoiceLine);
    });
}

function updateTaxTotals(xmlDoc) {
    const currencyID = document.querySelector('[name="documentCurrencyCode"]').value.toUpperCase() || 'RON';
    const taxCurrencyCode = document.querySelector('[name="taxCurrencyCode"]').value.toUpperCase();
    
    // Remove existing TaxTotal elements
    const existingTaxTotals = xmlDoc.querySelectorAll('cac\\:TaxTotal, TaxTotal');
    existingTaxTotals.forEach(element => element.parentNode.removeChild(element));

    // Create main TaxTotal for document currency
    const taxTotal = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:TaxTotal");
    
    // Use precise currency parsing for total VAT
    const uiTotalVat = formatter.parseCurrency(document.getElementById('vat').textContent);
    const taxAmountElement = createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:TaxAmount", 
        uiTotalVat.toFixed(2), { currencyID });
    taxTotal.appendChild(taxAmountElement);

    // Add TaxSubtotal elements to the main TaxTotal
    const vatRows = document.querySelectorAll('.vat-row');
    vatRows.forEach(row => {
        const taxSubtotal = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:TaxSubtotal");
        
        const baseAmount = formatter.parseCurrency(row.querySelector('.vat-base').value) || 0;
        const vatAmount = formatter.parseCurrency(row.querySelector('.vat-amount').value) || 0;
        const vatType = row.querySelector('.vat-type').value;
        const vatRate = parseFloat(row.querySelector('.vat-rate').value) || 0;

        taxSubtotal.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:TaxableAmount", 
            baseAmount.toFixed(2), { currencyID }));
        taxSubtotal.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:TaxAmount", 
            vatAmount.toFixed(2), { currencyID }));

        const taxCategory = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:TaxCategory");
        taxCategory.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ID", vatType));
        
        const percent = vatType === 'AE' ? '0.00' : vatRate.toFixed(2);
        taxCategory.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:Percent", percent));
        
        // Add exemption code and reason for special VAT types
        if (['E', 'K', 'O', 'AE'].includes(vatType)) {
            const exemptionCode = row.querySelector('.vat-exemption-code')?.value;
            const exemptionReason = row.querySelector('.vat-exemption-reason')?.value;
            
            if (exemptionCode) {
                taxCategory.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 
                    "cbc:TaxExemptionReasonCode", exemptionCode));
            }
            if (exemptionReason) {
                taxCategory.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 
                    "cbc:TaxExemptionReason", exemptionReason));
            }
        }
        
        const taxScheme = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:TaxScheme");
        taxScheme.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:ID", "VAT"));
        taxCategory.appendChild(taxScheme);
        
        taxSubtotal.appendChild(taxCategory);
        taxTotal.appendChild(taxSubtotal);
    });

    // Insert TaxTotal in the correct position
    let insertionPoint = xmlDoc.querySelector('cac\\:AllowanceCharge, AllowanceCharge');
    if (insertionPoint) {
        while (insertionPoint.nextElementSibling && 
               (insertionPoint.nextElementSibling.localName === 'AllowanceCharge' ||
                insertionPoint.nextElementSibling.localName === 'TaxTotal')) {
            insertionPoint = insertionPoint.nextElementSibling;
        }
        insertionPoint.parentNode.insertBefore(taxTotal, insertionPoint.nextSibling);
    } else {
        const monetaryTotal = xmlDoc.querySelector('cac\\:LegalMonetaryTotal, LegalMonetaryTotal');
        if (monetaryTotal) {
            monetaryTotal.parentNode.insertBefore(taxTotal, monetaryTotal);
        } else {
            xmlDoc.documentElement.appendChild(taxTotal);
        }
    }

    // If tax currency is specified, add another TaxTotal element
    if (taxCurrencyCode && taxCurrencyCode !== currencyID) {
        const taxCurrencyTotal = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:TaxTotal");
        
        const exchangeRateInput = document.querySelector('[name="exchangeRate"]');
        const exchangeRate = exchangeRateInput ? parseFloat(exchangeRateInput.value) || 1 : 1;
        const taxCurrencyVAT = uiTotalVat * exchangeRate;

        const taxCurrencyAmountElement = createXMLElement(xmlDoc, XML_NAMESPACES.cbc, "cbc:TaxAmount",
            taxCurrencyVAT.toFixed(2), { currencyID: taxCurrencyCode });
        taxCurrencyTotal.appendChild(taxCurrencyAmountElement);
        
        // Insert after the main TaxTotal
        taxTotal.parentNode.insertBefore(taxCurrencyTotal, taxTotal.nextSibling);
    }
}

function updateMonetaryTotals(xmlDoc) {
    const currencyID = document.querySelector('[name="documentCurrencyCode"]').value.toUpperCase() || 'RON';

    // Use direct parsing to preserve full precision and manual edits
    const subtotal = formatter.parseCurrency(document.getElementById('subtotal').textContent);
    const allowances = formatter.parseCurrency(document.getElementById('totalAllowances').textContent);
    const charges = formatter.parseCurrency(document.getElementById('totalCharges').textContent);
    const netAmount = formatter.parseCurrency(document.getElementById('netAmount').textContent);
    const totalVat = formatter.parseCurrency(document.getElementById('vat').textContent);
    const total = formatter.parseCurrency(document.getElementById('total').textContent);

    // Rest of the function remains the same...
    const existingMonetaryTotal = xmlDoc.querySelector('cac\\:LegalMonetaryTotal, LegalMonetaryTotal');
    if (existingMonetaryTotal) {
        existingMonetaryTotal.parentNode.removeChild(existingMonetaryTotal);
    }

    const monetaryTotal = createXMLElement(xmlDoc, XML_NAMESPACES.cac, "cac:LegalMonetaryTotal");

    const amounts = {
        "LineExtensionAmount": subtotal,
        "TaxExclusiveAmount": netAmount,
        "TaxInclusiveAmount": total,
        "AllowanceTotalAmount": allowances,
        "ChargeTotalAmount": charges,
        "PayableAmount": total
    };

    Object.entries(amounts).forEach(([elementName, value]) => {
        monetaryTotal.appendChild(createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 
            `cbc:${elementName}`, value.toFixed(2), { currencyID }));
    });

    // Insertion logic remains the same
    let insertionPoint = xmlDoc.querySelector('cac\\:TaxTotal, TaxTotal');
    if (insertionPoint) {
        while (insertionPoint.nextElementSibling && 
               insertionPoint.nextElementSibling.localName === 'TaxTotal') {
            insertionPoint = insertionPoint.nextElementSibling;
        }
        insertionPoint.parentNode.insertBefore(monetaryTotal, insertionPoint.nextSibling);
    } else {
        const firstInvoiceLine = xmlDoc.querySelector('cac\\:InvoiceLine, InvoiceLine');
        if (firstInvoiceLine) {
            firstInvoiceLine.parentNode.insertBefore(monetaryTotal, firstInvoiceLine);
        } else {
            xmlDoc.documentElement.appendChild(monetaryTotal);
        }
    }
}

function getExchangeRate(fromCurrency, toCurrency) {
    // For now, return 1 as default exchange rate
    // TODO: Implement proper exchange rate handling
    return 1;
}

// Update the invoice form to include exchange rate when tax currency is different
function addExchangeRateField() {
    const taxCurrencyInput = document.querySelector('[name="taxCurrencyCode"]');
    const documentCurrencyInput = document.querySelector('[name="documentCurrencyCode"]');
    
    function updateExchangeRateVisibility() {
        const taxCurrency = taxCurrencyInput.value.toUpperCase();
        const documentCurrency = documentCurrencyInput.value.toUpperCase();
        
        let exchangeRateContainer = document.getElementById('exchangeRateContainer');
        if (taxCurrency && taxCurrency !== documentCurrency) {
            if (!exchangeRateContainer) {
                const container = document.createElement('div');
                container.id = 'exchangeRateContainer';
                container.className = 'form-group';
                container.innerHTML = `
                    <label class="form-label">Curs Valutar ${documentCurrency}/${taxCurrency}</label>
                    <input type="number" class="form-input" name="exchangeRate" 
                           step="0.0001" min="0" value="1" 
                           onchange="refreshTotals()">
                `;
                taxCurrencyInput.parentNode.after(container);
            } else {
                // Update label if currencies changed
                const label = exchangeRateContainer.querySelector('label');
                label.textContent = `Curs Valutar ${documentCurrency}/${taxCurrency}`;
            }
        } else if (exchangeRateContainer) {
            exchangeRateContainer.remove();
        }
    }

    taxCurrencyInput.addEventListener('input', updateExchangeRateVisibility);
    documentCurrencyInput.addEventListener('input', updateExchangeRateVisibility);
    
    // Initial check
    updateExchangeRateVisibility();
}


// Utility functions
function getXMLValue(xmlDoc, selector, defaultValue = '') {
    if (!xmlDoc) return defaultValue;
    try {
        const element = xmlDoc.querySelector(selector);
        const value = element ? element.textContent : defaultValue;
        // console.log(`getXMLValue: Selector: ${selector}, Value: ${value}`);
        return value;
    } catch (error) {
        console.warn(`Eroare la obținerea valorii pentru selectorul ${selector}:`, error);
        return defaultValue;
    }
}

function setXMLValue(xmlDoc, selector, value) {
    try {
        const element = xmlDoc.querySelector(selector);
        if (element) {
            element.textContent = value;
            return true;
        }
        return false;
    } catch (error) {
        console.warn(`Eroare la setarea valorii pentru selectorul ${selector}:`, error);
        return false;
    }
}

function createXMLElement(xmlDoc, namespace, elementName, value = '', attributes = {}) {
    const element = xmlDoc.createElementNS(namespace, elementName);
    if (value) {
        element.textContent = value;
    }
    Object.entries(attributes).forEach(([key, value]) => {
        element.setAttribute(key, value);
    });
    return element;
}

function formatXML(xmlString) {
    let formatted = '';
    let indent = '';
    const tab = '  ';
    
    xmlString.split(/>\s*</).forEach(node => {
        if (node.match(/^\/\w/)) {
            indent = indent.substring(tab.length);
        }
        formatted += indent + '<' + node + '>\r\n';
        if (node.match(/^<?\w[^>]*[^\/]$/) && !node.startsWith("?")) {
            indent += tab;
        }
    });
    
    return formatted.substring(1, formatted.length - 3);
}

function downloadXML(xmlDoc) {
    const serializer = new XMLSerializer();
    let xmlString = serializer.serializeToString(xmlDoc);
    
    if (!xmlString.startsWith('<?xml')) {
        xmlString = '<?xml version="1.0" encoding="UTF-8"?>\n' + xmlString;
    }

    xmlString = formatXML(xmlString);

    const blob = new Blob([xmlString], { type: 'application/xml' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'factura_' + document.querySelector('[name="invoiceNumber"]').value + '.xml';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
}

function roundNumber(number, decimals = 2) {
    return Math.round(number * Math.pow(10, decimals)) / Math.pow(10, decimals);
}

function renumberLineItems() {
    document.querySelectorAll('.line-item').forEach((item, newIndex) => {
        item.dataset.index = newIndex;
        
        item.querySelectorAll('input, select').forEach(input => {
            const name = input.getAttribute('name');
            if (name) {
                const baseName = name.replace(/\d+$/, '');
                input.setAttribute('name', baseName + newIndex);
            }
        });
    });
}


function createIdentificationHTML(index, type, value = '', schemeId = '') {
    const typeInfo = IDENTIFICATION_TYPES[type];
    const id = `${type.toLowerCase()}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
    
    if (type === 'COMMODITY') {
        return `
            <div class="identification-row" data-type="${type}" data-id="${id}">
                <div class="identification-content">
                    <select class="form-input scheme-select" name="scheme_${id}">
                        ${typeInfo.schemes.map(scheme => 
                            `<option value="${scheme.id}" ${scheme.id === schemeId ? 'selected' : ''}>
                                ${scheme.name}
                            </option>`
                        ).join('')}
                    </select>
                    <input type="text" class="form-input" name="value_${id}" 
                           value="${value}" placeholder="${typeInfo.label}">
                    <button type="button" class="button button-small button-danger delete-identification" 
                            onclick="removeIdentification('${id}')">✕</button>
                </div>
            </div>`;
    }
    
    return `
        <div class="identification-row" data-type="${type}" data-id="${id}">
            <div class="identification-content">
                ${type === 'STANDARD' ? `<input type="hidden" name="scheme_${id}" value="0160">` : ''}
                <input type="text" class="form-input" name="value_${id}" 
                       value="${value}" placeholder="${typeInfo.label}">
                <button type="button" class="button button-small button-danger delete-identification" 
                        onclick="removeIdentification('${id}')">✕</button>
            </div>
        </div>`;
}

window.addIdentification = function(lineItemIndex, type) {
    const container = document.querySelector(`#identifications${lineItemIndex}`);
    if (container) {
        container.insertAdjacentHTML('beforeend', createIdentificationHTML(lineItemIndex, type));
        validateIdentifications(lineItemIndex);
    }
}

window.removeIdentification = function(id) {
    const element = document.querySelector(`[data-id="${id}"]`);
    if (element) {
        const lineItem = element.closest('.line-item');
        element.remove();
        if (lineItem) {
            validateIdentifications(parseInt(lineItem.dataset.index));
        }
    }
};


// Update XML parsing
function parseIdentifications(itemElement, lineItemIndex) {
    // console.log("Parsing identifications for line", lineItemIndex);

    const container = document.querySelector(`#identifications${lineItemIndex}`);
    if (!container) return;

    const listContainer = container.querySelector('.identifications-list');
    listContainer.innerHTML = '';

    // Parse BuyersItemIdentification
    const buyersId = itemElement.querySelector('cac\\:BuyersItemIdentification cbc\\:ID, BuyersItemIdentification ID');
    if (buyersId) {
        listContainer.insertAdjacentHTML('beforeend',
            createIdentificationHTML(lineItemIndex, 'BUYERS', buyersId.textContent)
        );
    }

    // Parse SellersItemIdentification
    const sellersId = itemElement.querySelector('cac\\:SellersItemIdentification cbc\\:ID, SellersItemIdentification ID');
    if (sellersId) {
        listContainer.insertAdjacentHTML('beforeend',
            createIdentificationHTML(lineItemIndex, 'SELLERS', sellersId.textContent)
        );
    }

    // Parse StandardItemIdentification
    const standardId = itemElement.querySelector('cac\\:StandardItemIdentification cbc\\:ID, StandardItemIdentification ID');
    if (standardId) {
        listContainer.insertAdjacentHTML('beforeend',
            createIdentificationHTML(lineItemIndex, 'STANDARD', standardId.textContent)
        );
    }

    // Parse CommodityClassifications
    const commodityClassifications = itemElement.querySelectorAll('cac\\:CommodityClassification cbc\\:ItemClassificationCode, CommodityClassification ItemClassificationCode');
    commodityClassifications.forEach(classification => {
        const listId = classification.getAttribute('listID') || 'CV';
        const code = classification.textContent;
        if (code && listId) {
            listContainer.insertAdjacentHTML('beforeend',
                createIdentificationHTML(lineItemIndex, 'COMMODITY', code, listId)
            );
        }
    });
}

// Update XML saving
function saveIdentificationsToXML(xmlDoc, itemElement, lineItemIndex) {
    const container = document.querySelector(`#identifications${lineItemIndex}`);
    if (!container) return;

    container.querySelectorAll('.identification-row').forEach(row => {
        const type = row.dataset.type;
        const id = row.dataset.id;
        const schemeInput = document.querySelector(`[name="scheme_${id}"]`);
        const valueInput = document.querySelector(`[name="value_${id}"]`);

        if (!valueInput?.value) return;

        if (type === 'COMMODITY') {
            const schemeSelect = document.querySelector(`[name="scheme_${id}"]`);
            if (!schemeSelect) return;

            const identificationElement = createXMLElement(xmlDoc, XML_NAMESPACES.cac, 'cac:CommodityClassification');
            const idElement = createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 'cbc:ItemClassificationCode', valueInput.value);
            idElement.setAttribute('listID', schemeSelect.value);
            identificationElement.appendChild(idElement);
            itemElement.appendChild(identificationElement);
        } else {
            const typeInfo = IDENTIFICATION_TYPES[type];
            const identificationElement = createXMLElement(xmlDoc, XML_NAMESPACES.cac, `cac:${typeInfo.xmlTag}`);
            const idElement = createXMLElement(xmlDoc, XML_NAMESPACES.cbc, 'cbc:ID', valueInput.value);
            
            if (type === 'STANDARD') {
                idElement.setAttribute('schemeID', '0160');
            }
            
            identificationElement.appendChild(idElement);
            itemElement.appendChild(identificationElement);
        }
    });
}


// Add validation
function validateIdentifications(lineItemIndex) {
    const container = document.querySelector(`#identifications${lineItemIndex}`);
    if (!container) return true;

    let isValid = true;
    container.querySelectorAll('.identification-row').forEach(row => {
        const type = row.dataset.type;
        const id = row.dataset.id;
        const input = row.querySelector(`[name="value_${id}"]`);
        
        if (type === 'COMMODITY') {
            const scheme = row.querySelector('.scheme-select').value;
            if (scheme === 'TSP' && !/^\d{8}-\d$/.test(input.value)) {
                input.classList.add('invalid');
                isValid = false;
            } else if (scheme === 'STI' && !/^\d{8}$/.test(input.value)) {
                input.classList.add('invalid');
                isValid = false;
            } else {
                input.classList.remove('invalid');
            }
        }
    });
    
    return isValid;
}

// ============================================================================
// PR-A11: math validation inline (badge per-line / per-VAT-row / footer total)
// ============================================================================

const A11_TOLERANCE_LEGACY = new Big('0.01'); // ±0.01 RON pe rows complet clean
const A11_TOLERANCE_DIRTY = new Big('0');     // zero pe rows cu dirty='1'

function _a11RowDirty(rowEl) {
    if (!rowEl) return false;
    return Array.from(rowEl.querySelectorAll('input')).some(
        i => i.dataset && i.dataset.dirty === '1'
    );
}

function _a11Tolerance(rowEl) {
    return _a11RowDirty(rowEl) ? A11_TOLERANCE_DIRTY : A11_TOLERANCE_LEGACY;
}

function _a11SetBadge(badgeEl, computedBig, displayedBig, epsBig, opts = {}) {
    if (!badgeEl) return;
    const { footer = false } = opts;
    const diff = computedBig.minus(displayedBig);
    const absDiff = diff.abs();
    badgeEl.classList.remove('badge-ok', 'badge-warn', 'badge-error');
    if (absDiff.lte(epsBig)) {
        badgeEl.classList.add('badge-ok');
        badgeEl.textContent = '✓';
        return false;
    }
    if (footer) {
        badgeEl.classList.add('badge-warn');
        badgeEl.textContent = `diferență ${absDiff.toFixed(2)} RON`;
    } else {
        badgeEl.classList.add('badge-error');
        const sign = diff.gte(0) ? '+' : '−';
        badgeEl.textContent = `${sign}${absDiff.toFixed(2)} RON`;
    }
    return true;
}

/**
 * PR-A11: validează consistența matematică a formularului și actualizează
 * badge-urile (per-line, per-VAT-row, footer total).
 *
 * Lect: input.dataset.raw (canonical decimal-dot, source of truth E1).
 * Compară:
 *   - line item: computed (qty*price-discount) vs XML loaded LineExtensionAmount.
 *   - VAT row: computed (base*rate/100, doar pentru type='S') vs vat-amount input.
 *   - footer total: computed (subtotal-allow+charges+totalVat) vs #total displayed.
 *
 * Tolerance switching pe row: dacă orice input din row are dataset.dirty='1' →
 * zero (newly computed must match exact). Altfel ±0.01 RON (legacy float
 * reconciliation pe XML încărcat).
 *
 * @returns {{footerDiff: Big, footerOver: boolean}} info pentru save toast.
 */
function validateMath() {
    // Per-line: computed line net vs XML loaded LineExtensionAmount.
    document.querySelectorAll('.line-item').forEach(item => {
        const idx = item.dataset.index;
        const qtyInput = document.querySelector(`[name="quantity${idx}"]`);
        const priceInput = document.querySelector(`[name="price${idx}"]`);
        const discountInput = document.querySelector(`[name="lineDiscount${idx}"]`);
        if (!qtyInput || !priceInput) return;

        const qty = getRaw(qtyInput);
        const price = getRaw(priceInput);
        const discount = discountInput ? getRaw(discountInput) : new Big('0');
        const computed = qty.times(price).minus(discount);

        // Update vizibilul "Total linie" la valoarea recalculată.
        const totalEl = item.querySelector(`[data-line-total-index="${idx}"]`);
        if (totalEl) totalEl.textContent = format2(computed.round(2, 1));

        const badgeEl = item.querySelector(`[data-line-badge-index="${idx}"]`);
        if (!badgeEl) return;

        // Linii nou-adăugate (fără XML referință) → badge ✓ trivial.
        const xmlAmt = item.dataset.xmlLineAmount;
        if (xmlAmt === undefined || xmlAmt === '') {
            badgeEl.textContent = '';
            badgeEl.classList.remove('badge-ok', 'badge-warn', 'badge-error');
            return;
        }
        const displayed = parseStrictOr(xmlAmt, '0');
        const eps = _a11Tolerance(item);
        _a11SetBadge(badgeEl, computed.round(2, 1), displayed, eps);
    });

    // Per-VAT-row: computed (base*rate/100) vs vat-amount input.
    document.querySelectorAll('.vat-row').forEach(row => {
        const typeSelect = row.querySelector('.vat-type');
        const baseInput = row.querySelector('.vat-base');
        const rateInput = row.querySelector('.vat-rate');
        const amountInput = row.querySelector('.vat-amount');
        const badgeEl = row.querySelector('.vat-amount-badge');
        if (!badgeEl || !typeSelect || !baseInput || !rateInput || !amountInput) return;

        const type = typeSelect.value;
        const base = getRaw(baseInput);
        const rate = getRaw(rateInput);
        const displayed = getRaw(amountInput);

        const computed = (type === 'S')
            ? base.times(rate).div(100).round(2, 1)
            : new Big('0');
        const eps = _a11Tolerance(row);
        _a11SetBadge(badgeEl, computed, displayed, eps);
    });

    // Footer total: computed (subtotal-allow+charges+totalVat) vs #total displayed.
    const totalBadge = document.getElementById('total-badge');
    let footerDiff = new Big('0');
    let footerOver = false;
    if (totalBadge) {
        const subtotalBig = parseStrictOr(document.getElementById('subtotal').textContent, '0');
        const allowancesBig = parseStrictOr(document.getElementById('totalAllowances').textContent, '0');
        const chargesBig = parseStrictOr(document.getElementById('totalCharges').textContent, '0');
        const vatBig = parseStrictOr(document.getElementById('vat').textContent, '0');
        const displayed = parseStrictOr(document.getElementById('total').textContent, '0');

        const computed = subtotalBig.minus(allowancesBig).plus(chargesBig).plus(vatBig).round(2, 1);
        // Footer tolerance: orice input dirty în întreaga formă → zero, altfel ±0.01.
        const anyDirty = Array.from(
            document.querySelectorAll('.line-item, .vat-row, .allowance-charge')
        ).some(_a11RowDirty);
        const eps = anyDirty ? A11_TOLERANCE_DIRTY : A11_TOLERANCE_LEGACY;
        footerDiff = computed.minus(displayed).abs();
        footerOver = _a11SetBadge(totalBadge, computed, displayed, eps, { footer: true }) === true;
    }
    return { footerDiff, footerOver };
}

/**
 * PR-A11: minimal toast helper. Compatibil cu DESIGN.md spec D14 (border-left
 * 3px semantic, slide-in 150ms, auto-dismiss success 4s / info 6s / warning 6s
 * / error persistent). NU bloca save — doar avertizează.
 */
function showToast(message, variant = 'info', subtext = '') {
    let container = document.getElementById('toast-container');
    if (!container) {
        container = document.createElement('div');
        container.id = 'toast-container';
        container.className = 'toast-container';
        container.setAttribute('aria-live', 'polite');
        document.body.appendChild(container);
    }
    const toast = document.createElement('div');
    toast.className = `toast toast-${variant}`;
    toast.setAttribute('role', (variant === 'warning' || variant === 'error') ? 'alert' : 'status');

    const msgEl = document.createElement('div');
    msgEl.className = 'toast-message';
    msgEl.textContent = message;
    if (subtext) {
        const subEl = document.createElement('span');
        subEl.className = 'toast-sub';
        subEl.textContent = subtext;
        msgEl.appendChild(subEl);
    }
    toast.appendChild(msgEl);

    const dismiss = document.createElement('button');
    dismiss.className = 'toast-dismiss';
    dismiss.type = 'button';
    dismiss.setAttribute('aria-label', 'Închide');
    dismiss.textContent = '×';
    dismiss.onclick = () => toast.remove();
    toast.appendChild(dismiss);

    container.appendChild(toast);

    const timeouts = { success: 4000, info: 6000, warning: 6000, error: 0 };
    const ms = timeouts[variant] ?? 6000;
    if (ms > 0) {
        setTimeout(() => { if (toast.isConnected) toast.remove(); }, ms);
    }
}

// Expose pentru consumeri externi / debugging.
window.validateMath = validateMath;
window.showToast = showToast;

// ============================================================================
// PR-BR (A2): Floating BR Validation Panel (D5)
// Panel sticky bottom-right — colecteaza snapshot form, rulează cele 30
// reguli BR/CIUS-RO și afișează violările cu link la câmp + highlight 2s.
// ============================================================================

/**
 * Colectează snapshot-ul datelor din formular pentru validarea BR.
 * Citește valorile afișate (sau dataset.raw pentru numerice).
 */
function collectInvoiceDataForBR() {
    const lineItemEls = Array.from(document.querySelectorAll('.line-item'));

    const lineItems = lineItemEls.map(el => {
        const idx = el.dataset.index;
        const qEl = document.querySelector(`[name="quantity${idx}"]`);
        const pEl = document.querySelector(`[name="price${idx}"]`);
        const dEl = document.querySelector(`[name="lineDiscount${idx}"]`);
        const tEl = document.querySelector(`[data-line-total-index="${idx}"]`);
        return {
            index: parseInt(idx, 10),
            description: (document.querySelector(`[name="description${idx}"]`)?.value || '').trim(),
            quantity: qEl ? (qEl.dataset.raw || qEl.value) : '',
            unitPrice: pEl ? (pEl.dataset.raw || pEl.value) : '',
            discount: dEl ? (dEl.dataset.raw || dEl.value || '0') : '0',
            vatType: (document.querySelector(`[name="vatType${idx}"]`)?.value || ''),
            vatRate: (document.querySelector(`[name="vatRate${idx}"]`)?.value || '0'),
            lineTotal: tEl ? tEl.textContent.replace(/[^\d,.-]/g, '') : '0',
        };
    });

    const vatRows = Array.from(document.querySelectorAll('.vat-row')).map(row => {
        const rEl = row.querySelector('.vat-rate');
        const bEl = row.querySelector('.vat-base');
        const aEl = row.querySelector('.vat-amount');
        return {
            type: (row.querySelector('.vat-type')?.value || ''),
            rate: rEl ? (rEl.dataset.raw || rEl.value) : '0',
            base: bEl ? (bEl.dataset.raw || bEl.value) : '0',
            amount: aEl ? (aEl.dataset.raw || aEl.value) : '0',
        };
    });

    // IBAN-uri din rândurile Payment Means dinamice
    const ibans = Array.from(document.querySelectorAll('[name^="paymentMeansIBAN"]'))
        .map(el => el.value.trim());

    const parseDisplay = (id) => {
        const el = document.getElementById(id);
        if (!el) return '0';
        return el.textContent.replace(/[^\d,.-]/g, '');
    };

    return {
        invoiceNumber: (document.querySelector('[name="invoiceNumber"]')?.value || '').trim(),
        issueDate: (document.querySelector('[name="issueDate"]')?.value || '').trim(),
        dueDate: (document.querySelector('[name="dueDate"]')?.value || '').trim(),
        invoiceTypeCode: (document.querySelector('[name="invoiceTypeCode"]')?.value || '').trim(),
        currencyCode: (document.querySelector('[name="documentCurrencyCode"]')?.value || '').trim(),

        supplierName: (document.querySelector('[name="supplierName"]')?.value || '').trim(),
        supplierVAT: (document.querySelector('[name="supplierVAT"]')?.value || '').trim(),
        supplierCity: (document.querySelector('[name="supplierCity"]')?.value || '').trim(),
        supplierCountry: (document.querySelector('[name="supplierCountry"]')?.value || '').trim(),

        customerName: (document.querySelector('[name="customerName"]')?.value || '').trim(),
        customerVAT: (document.querySelector('[name="customerVAT"]')?.value || '').trim(),
        customerCity: (document.querySelector('[name="customerCity"]')?.value || '').trim(),
        customerCountry: (document.querySelector('[name="customerCountry"]')?.value || '').trim(),

        lineItems,
        vatRows,
        ibans,

        subtotal: parseDisplay('subtotal'),
        allowances: parseDisplay('totalAllowances'),
        charges: parseDisplay('totalCharges'),
        totalVat: parseDisplay('vat'),
        grandTotal: parseDisplay('total'),
    };
}

/** Injectează panelul BR în DOM dacă nu există deja. */
function _ensureBRPanel() {
    if (document.getElementById('br-panel')) return;

    const panel = document.createElement('div');
    panel.id = 'br-panel';
    panel.className = 'br-panel br-panel--hidden';
    panel.setAttribute('role', 'region');
    panel.setAttribute('aria-label', 'Probleme de validare');
    panel.setAttribute('aria-live', 'polite');

    panel.innerHTML = `
        <div class="br-panel__header" id="br-panel-header" tabindex="0" aria-expanded="false">
            <span class="br-panel__summary" id="br-panel-summary">Verificare BR...</span>
            <span class="br-panel__toggle" id="br-panel-toggle">▲ extinde</span>
        </div>
        <div class="br-panel__body" id="br-panel-body" aria-labelledby="br-panel-header">
            <p class="br-panel__empty">Toate verificările trecute.</p>
        </div>
    `;

    document.body.appendChild(panel);

    // Toggle expand/collapse
    const header = panel.querySelector('#br-panel-header');
    header.addEventListener('click', () => {
        const expanded = panel.classList.toggle('is-expanded');
        header.setAttribute('aria-expanded', expanded ? 'true' : 'false');
        panel.querySelector('#br-panel-toggle').textContent = expanded ? '▼ restrânge' : '▲ extinde';
    });
    header.addEventListener('keydown', (e) => {
        if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); header.click(); }
    });
}

/**
 * Actualizează panelul BR cu lista de violări.
 * Apelat după fiecare updateTotals() și după parseXML().
 */
function _updateBRPanel() {
    _ensureBRPanel();
    const panel = document.getElementById('br-panel');
    const summary = document.getElementById('br-panel-summary');
    const body = document.getElementById('br-panel-body');
    if (!panel || !summary || !body) return;

    // Rulează regulile
    const data = collectInvoiceDataForBR();
    const violations = runBRRules(data);

    const fatals = violations.filter(v => v.severity === 'fatal').length;
    const errors = violations.filter(v => v.severity === 'error').length;
    const warnings = violations.filter(v => v.severity === 'warning').length;
    const totalIssues = fatals + errors + warnings;

    if (totalIssues === 0) {
        panel.classList.add('br-panel--hidden');
        panel.classList.remove('br-panel--errors');
        summary.className = 'br-panel__summary br-panel__summary--ok';
        summary.textContent = '✓ 0 erori BR, 0 warnings';
        body.innerHTML = '<p class="br-panel__empty">Toate verificările trecute.</p>';
        return;
    }

    panel.classList.remove('br-panel--hidden');
    panel.classList.toggle('br-panel--errors', (fatals + errors) > 0);

    // Summary text
    const parts = [];
    if (fatals > 0) parts.push(`${fatals} critice`);
    if (errors > 0) parts.push(`${errors} erori`);
    if (warnings > 0) parts.push(`${warnings} warning${warnings > 1 ? 's' : ''}`);
    summary.textContent = parts.join(' / ');
    summary.className = 'br-panel__summary ' + (
        (fatals + errors) > 0 ? 'br-panel__summary--errors' : 'br-panel__summary--warnings'
    );

    // Render items
    body.innerHTML = violations.map(v => {
        const sev = v.severity === 'fatal' ? 'fatal' : v.severity;
        return `<div class="br-panel__item br-panel__item--${sev}"
                     data-field-ref="${(v.fieldRef || '').replace(/"/g, '&quot;')}"
                     role="button" tabindex="0"
                     aria-label="${v.code}: ${v.message.replace(/"/g, '&quot;')}">
            <span class="br-panel__item-code">${v.code}</span>
            <span class="br-panel__item-msg">${_escapeHtml(v.message)}</span>
        </div>`;
    }).join('');

    // Wire click → scroll + highlight
    body.querySelectorAll('.br-panel__item').forEach(item => {
        const handler = () => {
            const ref = item.dataset.fieldRef;
            if (!ref) return;
            const target = document.querySelector(ref);
            if (!target) return;
            target.scrollIntoView({ behavior: 'smooth', block: 'center' });
            target.classList.remove('br-field-highlight');
            void target.offsetWidth; // reflow to restart animation
            target.classList.add('br-field-highlight');
            setTimeout(() => target.classList.remove('br-field-highlight'), 2100);
            target.focus?.();
        };
        item.addEventListener('click', handler);
        item.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handler(); }
        });
    });
}

function _escapeHtml(str) {
    return String(str)
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;');
}

// ============================================================================
// PR-ANAF: Integrare API ANAF (validare + CIF lookup)
// Butonul "Validare ANAF" și butoanele "Caută CIF" sunt ascunse la start;
// probeReceiver() le afișează dacă receiver.php este disponibil.
// ============================================================================

/**
 * Serializează starea curentă a formularului în XML string.
 * Atenție: mutează currentInvoice in-place (la fel ca saveXML).
 * @returns {string|null} XML string sau null dacă nu există factură.
 */
function _currentXMLString() {
    if (!currentInvoice) return null;
    const xmlDoc = currentInvoice;

    updateBasicDetails(xmlDoc);
    updatePartyDetails(xmlDoc);
    updateBillingReference(xmlDoc);
    updatePaymentMeans(xmlDoc);
    updateAllowanceCharges(xmlDoc);

    xmlDoc.querySelectorAll('cac\\:TaxTotal, TaxTotal').forEach(el => el.remove());
    const mt = xmlDoc.querySelector('cac\\:LegalMonetaryTotal, LegalMonetaryTotal');
    if (mt) mt.remove();
    xmlDoc.querySelectorAll('cac\\:InvoiceLine, InvoiceLine').forEach(el => el.remove());

    updateTaxTotals(xmlDoc);
    updateMonetaryTotals(xmlDoc);
    updateLineItems(xmlDoc);

    const serializer = new XMLSerializer();
    let xmlString = serializer.serializeToString(xmlDoc);
    if (!xmlString.startsWith('<?xml')) {
        xmlString = '<?xml version="1.0" encoding="UTF-8"?>\n' + xmlString;
    }
    return xmlString;
}

/** Setează starea loading pe un buton (spinner braille + disabled). */
function _btnLoading(btn, label) {
    btn.disabled = true;
    btn.dataset.origText = btn.textContent;
    btn.innerHTML = `<span class="spinner-mono"></span> ${label}`;
}

/** Restaurează starea normală a unui buton. */
function _btnDone(btn) {
    btn.disabled = false;
    btn.textContent = btn.dataset.origText || btn.textContent;
}

/**
 * Validează factura curentă prin API-ul ANAF.
 * Necesită receiver.php cu "anaf_token" configurat în config.json.
 */
window.validateAnaf = async function() {
    if (!currentInvoice) {
        showToast('Nicio factură încărcată. Deschideți un XML eFactura mai întâi.', 'warning');
        return;
    }
    const btn = document.getElementById('btnValidateAnaf');
    if (btn) _btnLoading(btn, 'Se validează...');
    try {
        const xmlString = _currentXMLString();
        if (!xmlString) throw new Error('Nu s-a putut genera XML-ul facturii.');

        const result = await anafValidate(xmlString);
        if (result.valid) {
            showToast('Factură validă ANAF — nicio eroare detectată.', 'success');
        } else {
            const errors = result.messages.filter(m => m.severity === 'ERROR' || m.severity === 'FATAL');
            const warns  = result.messages.filter(m => m.severity === 'WARNING');
            const parts  = [];
            if (errors.length) parts.push(`${errors.length} erori`);
            if (warns.length)  parts.push(`${warns.length} avertismente`);
            const sub = result.messages.slice(0, 3).map(m => m.message).join(' | ');
            showToast(`ANAF: ${parts.join(', ')}`, 'error', sub.slice(0, 200));
        }
    } catch (err) {
        showToast('Eroare validare ANAF: ' + err.message, 'error',
                  'Verificați că receiver.php este configurat cu anaf_token valid.');
    } finally {
        if (btn) _btnDone(btn);
    }
};

/**
 * Descarcă PDF-ul oficial generat de ANAF din XML-ul curent.
 * Apelează endpoint-ul ANAF /transformare/FACT1 (validează implicit).
 * Dacă XML-ul nu trece validarea ANAF, afișează erorile în loc să descarce.
 * Necesită receiver.php disponibil pe server (proxy CORS).
 */
window.downloadPdfAnaf = async function() {
    if (!currentInvoice) {
        showToast('Nicio factură încărcată. Deschideți un XML eFactura mai întâi.', 'warning');
        return;
    }
    const btn = document.getElementById('btnPdfAnaf');
    if (btn) _btnLoading(btn, 'Generare PDF ANAF...');

    try {
        const xmlString = _currentXMLString();
        if (!xmlString) throw new Error('Nu s-a putut genera XML-ul facturii.');

        const result = await anafPdf(xmlString);

        if (result.errors && result.errors.length) {
            // ANAF a respins XML-ul la validare; afișează primele erori în toast.
            const errs = result.errors.filter(m => m.severity === 'ERROR' || m.severity === 'FATAL');
            const sub = result.errors.slice(0, 3).map(m => m.message).join(' | ');
            showToast(
                `ANAF a respins XML-ul: ${errs.length || result.errors.length} mesaje`,
                'error',
                sub.slice(0, 220)
            );
            return;
        }

        if (!(result.pdf instanceof Blob)) {
            throw new Error('Răspuns ANAF fără PDF.');
        }

        // Descarcă blob-ul ca fișier PDF.
        const inv = printHandler.collectInvoiceData();
        const safeNum = String(inv.invoiceNumber || 'factura').replace(/[^a-z0-9_-]+/gi, '_');
        const url = URL.createObjectURL(result.pdf);
        const a = document.createElement('a');
        a.href = url;
        a.download = `${safeNum}_ANAF.pdf`;
        document.body.appendChild(a);
        a.click();
        a.remove();
        URL.revokeObjectURL(url);

        showToast('PDF ANAF descărcat.', 'success');
    } catch (err) {
        showToast('Eroare PDF ANAF: ' + err.message, 'error',
                  'Verificați că receiver.php este disponibil pe server.');
    } finally {
        if (btn) _btnDone(btn);
    }
};

/**
 * Caută datele firmei după CIF din câmpul supplierVAT / customerVAT.
 * @param {'supplier'|'customer'} party
 */
window.lookupCif = async function(party) {
    const isSupplier = party === 'supplier';
    const cifInput   = document.querySelector(`[name="${isSupplier ? 'supplier' : 'customer'}VAT"]`);
    if (!cifInput) return;

    const cif = (cifInput.value || '').trim();
    if (!cif) {
        showToast('Introduceți un CIF/CUI în câmpul Cod TVA mai întâi.', 'warning');
        return;
    }

    const btnId = isSupplier ? 'btnLookupSupplierCif' : 'btnLookupCustomerCif';
    const btn   = document.getElementById(btnId);
    if (btn) _btnLoading(btn, 'Caută...');

    try {
        const result = await anafCifLookup(cif);
        if (!result.found) {
            const note = result.async
                ? 'API ANAF asincron — rezultatele nu sunt disponibile imediat. Reîncercați.'
                : 'CIF-ul nu a fost găsit în baza de date ANAF.';
            showToast('CIF negăsit în ANAF.', 'info', note);
            return;
        }

        // Populează câmpurile firmei
        const prefix = isSupplier ? 'supplier' : 'customer';
        const set = (name, val) => {
            const el = document.querySelector(`[name="${prefix}${name}"]`);
            if (el && val) el.value = val;
        };

        set('Name',      result.denumire);
        set('CompanyId', result.nrRegCom);

        // CIF cu prefix RO dacă plătitor TVA
        if (result.cui) {
            const cifFinal = result.tvaActiv ? `RO${result.cui}` : String(result.cui);
            const vatEl = document.querySelector(`[name="${prefix}VAT"]`);
            if (vatEl) vatEl.value = cifFinal;
        }

        // Adresă structurată cu fallback la string brut
        set('Address', result.strada || result.adresa);
        set('City',    result.oras);
        // CountrySubentity este SELECT cu valori RO-XX
        if (result.judetCod) {
            const countyEl = document.querySelector(`[name="${prefix}CountrySubentity"]`);
            if (countyEl && [...countyEl.options].some(o => o.value === result.judetCod)) {
                countyEl.value = result.judetCod;
            }
        }
        // Country SELECT
        const countryEl = document.querySelector(`[name="${prefix}Country"]`);
        if (countryEl) countryEl.value = 'RO';
        set('Phone',   result.telefon);

        // Toast cu status TVA + eFactura
        const statuses = [
            result.tvaActiv ? 'Plătitor TVA' : 'Neplătitor TVA',
            result.statusEFactura ? 'Înregistrat eFactura' : null
        ].filter(Boolean).join(' · ');
        showToast(`Date ANAF importate: ${result.denumire || cif}`, 'success', statuses);
    } catch (err) {
        showToast('Eroare lookup CIF ANAF: ' + err.message, 'error',
                  'Verificați că receiver.php este disponibil pe server.');
    } finally {
        if (btn) _btnDone(btn);
    }
};

// Probează receiver.php la startup — dacă e disponibil, afișează item-urile ANAF.
(async () => {
    const available = await probeReceiver().catch(() => false);
    if (available) {
        // Item-urile ANAF din meniul "Acțiuni" sunt grupate într-un wrapper hidden.
        document.querySelector('.actions-menu-anaf')?.removeAttribute('hidden');
        document.querySelectorAll('.anaf-cif-btn').forEach(b => b.style.removeProperty('display'));
    }
})();

// ============================================================================
// PR-PDF (A8): Descarcă PDF — client-side via html2pdf.js
// Deschide template-ul de print și generează PDF fără dialog de imprimare.
// ============================================================================
import getHtml2pdf from './vendor/html2pdf.mjs';

/**
 * Generează și descarcă PDF-ul facturii curente.
 * Deschide template-ul de print, îl populează via InvoicePrintHandler,
 * apoi html2pdf capturează .invoice-container ca PDF.
 */
window.downloadPDF = async function() {
    if (!currentInvoice) {
        showToast('Nicio factură încărcată. Deschideți un XML eFactura mai întâi.', 'warning');
        return;
    }
    const btn = document.getElementById('btnDownloadPDF');
    if (btn) _btnLoading(btn, 'Generare PDF...');

    try {
        // Pasul 1: pre-încarcă html2pdf bundle (lazy, ~900KB)
        const html2pdf = await getHtml2pdf();

        // Pasul 2: colectează datele facturii
        const invoiceData = printHandler.collectInvoiceData();
        const invoiceNumber = invoiceData.invoiceNumber || 'factura';

        // Pasul 3: randează HTML-ul facturii într-un container detașat (off-screen)
        const container = document.createElement('div');
        container.style.cssText = 'position:absolute;left:-9999px;top:0;width:210mm;background:#fff;';
        container.id = 'pdf-render-container';
        document.body.appendChild(container);

        // Stiluri inline de bază pentru randarea off-screen
        container.innerHTML = `
<style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body, div { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
    #pdf-content { padding: 16mm; font-size: 10px; line-height: 1.4; color: #1e293b; }
    .pdf-header { display: flex; justify-content: space-between; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #2563eb; }
    .pdf-title { font-size: 20px; font-weight: 700; color: #2563eb; }
    .pdf-meta { font-size: 9px; color: #64748b; }
    .pdf-parties { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 12px; }
    .pdf-party-label { font-size: 9px; text-transform: uppercase; letter-spacing: 0.06em; color: #64748b; font-weight: 600; margin-bottom: 4px; }
    .pdf-party p { margin: 1px 0; }
    table { width: 100%; border-collapse: collapse; margin-bottom: 12px; font-size: 9px; }
    th { background: #f8fafc; text-align: left; padding: 5px 6px; border-bottom: 1px solid #e2e8f0; font-weight: 600; color: #64748b; text-transform: uppercase; font-size: 8px; letter-spacing: 0.04em; }
    td { padding: 4px 6px; border-bottom: 1px solid #f1f5f9; }
    .num { text-align: right; font-variant-numeric: tabular-nums; }
    .pdf-totals { margin-left: auto; width: 240px; font-size: 9px; }
    .pdf-total-row { display: flex; justify-content: space-between; padding: 3px 0; border-bottom: 1px solid #f1f5f9; }
    .pdf-total-final { font-weight: 700; font-size: 11px; border-top: 2px solid #1e293b; padding-top: 4px; margin-top: 4px; }
</style>
<div id="pdf-content">
    <div class="pdf-header">
        <div>
            <div class="pdf-title">FACTURĂ</div>
            <div class="pdf-meta">Nr. ${_escapeHtml(invoiceData.invoiceNumber)} | Data: ${_escapeHtml(invoiceData.issueDate)} | Scadent: ${_escapeHtml(invoiceData.dueDate)}</div>
        </div>
        <div class="pdf-meta" style="text-align:right">Monedă: ${_escapeHtml(invoiceData.documentCurrencyCode)}</div>
    </div>
    <div class="pdf-parties">
        <div>
            <div class="pdf-party-label">Furnizor</div>
            <p><strong>${_escapeHtml(invoiceData.supplier.name)}</strong></p>
            ${invoiceData.supplier.vat ? `<p>CUI: ${_escapeHtml(invoiceData.supplier.vat)}</p>` : ''}
            ${invoiceData.supplier.companyId ? `<p>Nr. reg.: ${_escapeHtml(invoiceData.supplier.companyId)}</p>` : ''}
            ${invoiceData.supplier.address ? `<p>${_escapeHtml(invoiceData.supplier.address)}, ${_escapeHtml(invoiceData.supplier.city)}</p>` : ''}
            ${invoiceData.supplier.country ? `<p>${_escapeHtml(invoiceData.supplier.country)}</p>` : ''}
        </div>
        <div>
            <div class="pdf-party-label">Client</div>
            <p><strong>${_escapeHtml(invoiceData.customer.name)}</strong></p>
            ${invoiceData.customer.vat ? `<p>CUI: ${_escapeHtml(invoiceData.customer.vat)}</p>` : ''}
            ${invoiceData.customer.companyId ? `<p>Nr. reg.: ${_escapeHtml(invoiceData.customer.companyId)}</p>` : ''}
            ${invoiceData.customer.address ? `<p>${_escapeHtml(invoiceData.customer.address)}, ${_escapeHtml(invoiceData.customer.city)}</p>` : ''}
            ${invoiceData.customer.country ? `<p>${_escapeHtml(invoiceData.customer.country)}</p>` : ''}
        </div>
    </div>
    <table>
        <thead>
            <tr>
                <th>#</th><th>Descriere</th><th>UM</th>
                <th class="num">Cant.</th><th class="num">Preț unit.</th>
                <th class="num">TVA%</th><th class="num">Total net</th>
            </tr>
        </thead>
        <tbody>
            ${invoiceData.items.map(it => `<tr>
                <td>${it.number}</td>
                <td>${_escapeHtml(it.description)}</td>
                <td>${_escapeHtml(it.unit)}</td>
                <td class="num">${_escapeHtml(it.quantity)}</td>
                <td class="num">${_escapeHtml(it.price)}</td>
                <td class="num">${_escapeHtml(String(it.vatRate))}%</td>
                <td class="num">${_escapeHtml(it.totalAmount)}</td>
            </tr>`).join('')}
        </tbody>
    </table>
    ${invoiceData.note ? `<p style="font-size:9px;color:#64748b;margin-bottom:8px;"><em>Notă: ${_escapeHtml(invoiceData.note)}</em></p>` : ''}
    <div style="display:flex;justify-content:flex-end;">
        <div class="pdf-totals">
            <div class="pdf-total-row"><span>Subtotal:</span><span>${_escapeHtml(invoiceData.totals.subtotal)}</span></div>
            ${invoiceData.totals.allowances ? `<div class="pdf-total-row"><span>Reduceri:</span><span>-${_escapeHtml(invoiceData.totals.allowances)}</span></div>` : ''}
            ${invoiceData.totals.charges ? `<div class="pdf-total-row"><span>Taxe:</span><span>${_escapeHtml(invoiceData.totals.charges)}</span></div>` : ''}
            <div class="pdf-total-row"><span>TVA total:</span><span>${_escapeHtml(invoiceData.totals.vat)}</span></div>
            <div class="pdf-total-row pdf-total-final"><span>TOTAL:</span><span>${_escapeHtml(invoiceData.totals.total)}</span></div>
        </div>
    </div>
</div>`;

        await html2pdf().set({
            margin: [0, 0, 0, 0],
            filename: 'factura_' + invoiceNumber.replace(/[^a-zA-Z0-9_-]/g, '_') + '.pdf',
            image: { type: 'jpeg', quality: 0.97 },
            html2canvas: { scale: 2, useCORS: true, logging: false },
            jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }
        }).from(container.querySelector('#pdf-content')).save();

        showToast('PDF generat și descărcat.', 'success');
    } catch (err) {
        showToast('Eroare la generarea PDF: ' + err.message, 'error',
                  'Verificați că js/vendor/html2pdf.bundle.min.js este prezent.');
    } finally {
        document.getElementById('pdf-render-container')?.remove();
        if (btn) _btnDone(btn);
    }
};

// ============================================================================
// PR-A19 (Track 2 D): Numerotare automată cu serie + contor + an
// Cheia localStorage: efactura.sequence.v1
// Structura: { serie: string, an: number, contor: number }
// Generează numere de forma: RFT2026-0001
// ============================================================================

const SEQ_KEY = 'efactura.sequence.v1';
const SEQ_DEFAULT = { serie: 'RFT', an: new Date().getFullYear(), contor: 1, includeAn: true, cifre: 4 };

/** Citește secvența curentă din localStorage. */
function _seqRead() {
    const stored = getJSON(SEQ_KEY, null);
    return { ...SEQ_DEFAULT, ...stored };
}

/** Salvează secvența în localStorage. */
function _seqWrite(seq) {
    setJSON(SEQ_KEY, seq);
}

/**
 * Formatează un număr de factură din secvență.
 * Cu includeAn=true:  "{serie} {an}{pad}"  → ex. "RFT 20260042"
 * Cu includeAn=false: "{serie} {pad}"      → ex. "RFT 0042"
 */
function _seqFormat(seq) {
    const cifre  = Math.max(1, Math.min(8, parseInt(seq.cifre) || 4));
    const pad    = String(seq.contor).padStart(cifre, '0');
    const serie  = (seq.serie || 'RFT').trim();
    const an     = seq.an || new Date().getFullYear();
    return seq.includeAn
        ? `${serie} ${an}${pad}`
        : `${serie} ${pad}`;
}

/** Actualizează previzualizarea din modal cu valorile curente. */
function _seqUpdatePreview() {
    const serie      = (document.getElementById('seq-serie')?.value     || '').trim().toUpperCase();
    const year       = parseInt(document.getElementById('seq-year')?.value)    || new Date().getFullYear();
    const contor     = parseInt(document.getElementById('seq-counter')?.value) || 1;
    const includeAn  = document.getElementById('seq-include-an')?.checked ?? true;
    const cifre      = Math.max(1, Math.min(8, parseInt(document.getElementById('seq-cifre')?.value) || 4));
    const preview    = document.getElementById('seq-preview');
    if (preview) {
        const pad = String(Math.max(1, contor)).padStart(cifre, '0');
        preview.textContent = includeAn
            ? `${serie || 'RFT'} ${year}${pad}`
            : `${serie || 'RFT'} ${pad}`;
    }
}

/** Injectează modal-ul în DOM dacă nu există deja. */
function _ensureNewInvoiceModal() {
    if (document.getElementById('modal-new-invoice')) return;
    const modal = document.createElement('div');
    modal.id = 'modal-new-invoice';
    modal.className = 'modal-overlay';
    modal.setAttribute('role', 'dialog');
    modal.setAttribute('aria-modal', 'true');
    modal.setAttribute('aria-labelledby', 'modal-new-invoice-title');
    modal.innerHTML = `
<div class="modal-box">
    <h2 class="modal-title" id="modal-new-invoice-title">Factură Nouă</h2>
    <p class="modal-sub">Configurați seria și numărul următor. Contorul se incrementează automat după generare.</p>
    <div class="form-group">
        <label class="form-label" for="seq-serie">Serie</label>
        <input id="seq-serie" class="form-input mono" maxlength="10" placeholder="RFT" style="text-transform:uppercase">
    </div>
    <div class="compact-grid" style="grid-template-columns:1fr 1fr;gap:8px">
        <div class="form-group">
            <label class="form-label" for="seq-year">An</label>
            <input id="seq-year" class="form-input mono" type="number" min="2000" max="2099" readonly>
        </div>
        <div class="form-group">
            <label class="form-label" for="seq-counter">Nr. următor</label>
            <input id="seq-counter" class="form-input mono" type="number" min="1" max="99999" step="1">
        </div>
    </div>
    <div class="compact-grid" style="grid-template-columns:1fr 1fr;gap:8px">
        <div class="form-group">
            <label class="form-label" for="seq-cifre">Cifre contor</label>
            <input id="seq-cifre" class="form-input mono" type="number" min="1" max="8" step="1" value="4">
        </div>
        <div class="form-group" style="display:flex;align-items:center;gap:8px;padding-top:22px">
            <input id="seq-include-an" type="checkbox" checked>
            <label for="seq-include-an" class="form-label" style="margin:0">Include an în număr</label>
        </div>
    </div>
    <div class="form-group">
        <label class="form-label">Previzualizare număr factură</label>
        <div id="seq-preview" class="modal-preview">RFT ${new Date().getFullYear()}0001</div>
    </div>
    <div class="modal-actions">
        <button type="button" class="button button-secondary" id="btnCloseNewInvoice">Anulare</button>
        <button type="button" class="button" id="btnGenerateInvoice">Generează Factură</button>
    </div>
</div>`;
    document.body.appendChild(modal);

    // Wire events
    document.getElementById('btnCloseNewInvoice').addEventListener('click', window.closeNewInvoiceModal);
    document.getElementById('btnGenerateInvoice').addEventListener('click', window.generateNewInvoice);
    document.getElementById('seq-serie').addEventListener('input', _seqUpdatePreview);
    document.getElementById('seq-counter').addEventListener('input', _seqUpdatePreview);
    document.getElementById('seq-include-an').addEventListener('change', _seqUpdatePreview);
    document.getElementById('seq-cifre').addEventListener('input', _seqUpdatePreview);

    // Close on backdrop click
    modal.addEventListener('click', function(e) {
        if (e.target === modal) window.closeNewInvoiceModal();
    });

    // Esc key
    document.addEventListener('keydown', function(e) {
        if (e.key === 'Escape' && modal.classList.contains('is-open')) {
            window.closeNewInvoiceModal();
        }
    });
}

/**
 * Deschide modal-ul "Factură Nouă" cu valorile curente din secvență.
 */
window.openNewInvoiceModal = function() {
    _ensureNewInvoiceModal();
    const seq = _seqRead();

    const serieEl      = document.getElementById('seq-serie');
    const yearEl       = document.getElementById('seq-year');
    const counterEl    = document.getElementById('seq-counter');
    const includeAnEl  = document.getElementById('seq-include-an');
    const cifreEl      = document.getElementById('seq-cifre');

    if (serieEl)      serieEl.value     = seq.serie || 'RFT';
    if (yearEl)       yearEl.value      = new Date().getFullYear();
    if (counterEl)    counterEl.value   = seq.contor || 1;
    if (includeAnEl)  includeAnEl.checked = seq.includeAn !== false;
    if (cifreEl)      cifreEl.value     = seq.cifre || 4;

    _seqUpdatePreview();

    const modal = document.getElementById('modal-new-invoice');
    modal.classList.add('is-open');
    serieEl?.focus();
};

/** Închide modal-ul "Factură Nouă". */
window.closeNewInvoiceModal = function() {
    document.getElementById('modal-new-invoice')?.classList.remove('is-open');
};

/**
 * Generează o factură nouă cu numărul din secvență, incrementează contorul.
 */
window.generateNewInvoice = function() {
    const serieEl      = document.getElementById('seq-serie');
    const counterEl    = document.getElementById('seq-counter');
    const includeAnEl  = document.getElementById('seq-include-an');
    const cifreEl      = document.getElementById('seq-cifre');

    const serie     = (serieEl?.value   || 'RFT').trim().toUpperCase();
    const contor    = Math.max(1, parseInt(counterEl?.value) || 1);
    const year      = new Date().getFullYear();
    const includeAn = includeAnEl ? includeAnEl.checked : true;
    const cifre     = Math.max(1, Math.min(8, parseInt(cifreEl?.value) || 4));

    const seq = { serie, an: year, contor, includeAn, cifre };
    const invoiceNumber = _seqFormat(seq);

    // Salvează secvența cu contorul incrementat
    _seqWrite({ ...seq, contor: contor + 1 });

    // Creează o factură goală și populează formularul
    currentInvoice = createEmptyInvoice();
    const serializer = new XMLSerializer();
    const serialized = serializer.serializeToString(currentInvoice).replace(/^<\?xml[^?]*\?>\s*/, '');
    const xmlString = '<?xml version="1.0" encoding="UTF-8"?>\n' + serialized;
    parseXML(xmlString);

    // Setează numărul de factură generat
    const numEl = document.querySelector('[name="invoiceNumber"]');
    if (numEl) numEl.value = invoiceNumber;

    // Setează data emiterii la azi
    const today = new Date();
    const pad   = n => String(n).padStart(2, '0');
    const dateStr = `${pad(today.getDate())}.${pad(today.getMonth() + 1)}.${today.getFullYear()}`;
    const dateEl = document.querySelector('[name="issueDate"]');
    if (dateEl) dateEl.value = dateStr;

    // Populează furnizorul din profil dacă există
    const profil = getJSON('efactura.profil.v1', null);
    if (profil) {
        SUPPLIER_FIELDS.forEach(f => {
            const el = document.querySelector(`[name="${f}"]`);
            if (el && profil[f] !== undefined) el.value = profil[f];
        });
    }

    window.closeNewInvoiceModal();
    _updateBRPanel();
    showToast(`Factură nouă creată: ${invoiceNumber}`, 'success', 'Contorul a fost incrementat automat.');
};

/**
 * Banner an nou (D24) — resetează contorul la 1 pentru noul an.
 */
window.yearRolloverReset = function() {
    const seq = _seqRead();
    const newYear = new Date().getFullYear();
    _seqWrite({ ...seq, an: newYear, contor: 1 });
    document.getElementById('year-rollover-banner')?.remove();
    showToast(`Seria ${seq.serie}: contor resetat la 1 pentru ${newYear}.`, 'success');
};

/**
 * Banner an nou (D24) — continuă cu contorul existent pentru noul an.
 */
window.yearRolloverContinue = function() {
    const seq = _seqRead();
    const newYear = new Date().getFullYear();
    _seqWrite({ ...seq, an: newYear });
    document.getElementById('year-rollover-banner')?.remove();
    showToast(`Seria ${seq.serie}: continuă cu nr. ${seq.contor} pentru ${newYear}.`, 'info');
};

/** Verifică dacă secvența aparține unui an anterior → injectează banner D24. */
function _checkYearRollover() {
    const seq  = _seqRead();
    const year = new Date().getFullYear();
    if (!seq.an || seq.an >= year) return; // nicio problemă

    // Evită duplicat
    if (document.getElementById('year-rollover-banner')) return;

    const banner = document.createElement('div');
    banner.id        = 'year-rollover-banner';
    banner.className = 'year-rollover-banner';
    banner.innerHTML = `
<p>
    <strong>An nou ${year} detectat.</strong>
    Seria <em>${_escapeHtml(seq.serie)}</em> are contorul la ${seq.contor} (an ${seq.an}).
    Alegeți cum să continuați numerotarea în ${year}.
</p>
<div class="banner-actions">
    <button type="button" class="button button-small button-secondary" onclick="window.yearRolloverContinue()">
        Continuă cu ${seq.contor}
    </button>
    <button type="button" class="button button-small" onclick="window.yearRolloverReset()">
        Resetează la 1
    </button>
</div>`;

    // Injectează sub header (primul copil al .container)
    const container = document.querySelector('.container');
    const header    = container?.querySelector('.header');
    if (header?.nextSibling) {
        container.insertBefore(banner, header.nextSibling);
    } else if (container) {
        container.appendChild(banner);
    }
}

// Verifică rollover la DOMContentLoaded (după ce restul UI este inițializat)
document.addEventListener('DOMContentLoaded', _checkYearRollover);

// ============================================================================
// PR-A13: Catalog produse IndexedDB — autocomplete + save (D15)
// Câmpul "Denumire" din fiecare linie factură primește sugestii din catalog.
// ============================================================================

/** ID-ul timeout-ului de debounce pentru autocomplete. */
let _catalogDebounceTimer = null;

/** Dropdown curent deschis (referință pentru cleanup). */
let _activeCatalogDropdown = null;

/**
 * Creează și afișează dropdown-ul de sugestii catalog sub input-ul dat.
 * @param {HTMLInputElement} input
 * @param {Array} items - Produse din catalog
 * @param {number} lineIndex
 */
function _showCatalogDropdown(input, items, lineIndex) {
    _hideCatalogDropdown();

    const wrapper = input.closest('.description-wrapper');
    if (!wrapper) return;

    const dd = document.createElement('div');
    dd.className = 'catalog-dropdown';
    dd.setAttribute('role', 'listbox');
    dd.setAttribute('aria-label', 'Sugestii catalog produse');

    if (!items.length) {
        dd.innerHTML = `<div class="catalog-item-empty">Niciun produs în catalog pentru "${_escapeHtml(input.value)}"</div>`;
    } else {
        dd.innerHTML = items.map((item, i) => `
<div class="catalog-dropdown-item" role="option" data-catalog-id="${_escapeHtml(item.id)}" data-catalog-idx="${i}">
    <div class="catalog-item-name">${_escapeHtml(item.name)}</div>
    <div class="catalog-item-meta">${_escapeHtml(item.unit)} · ${_escapeHtml(item.price)} RON · TVA ${_escapeHtml(item.vatType)} ${_escapeHtml(item.vatRate)}%</div>
</div>`).join('');

        // Click pe un item → aplică în linia de factură
        dd.addEventListener('mousedown', function(e) {
            const itemEl = e.target.closest('[data-catalog-id]');
            if (!itemEl) return;
            e.preventDefault(); // evită blur pe input
            const idx    = parseInt(itemEl.dataset.catalogIdx, 10);
            const chosen = items[idx];
            if (chosen) _applyCatalogItem(chosen, lineIndex);
            _hideCatalogDropdown();
        });
    }

    wrapper.appendChild(dd);
    _activeCatalogDropdown = dd;
}

/** Ascunde dropdown-ul activ. */
function _hideCatalogDropdown() {
    if (_activeCatalogDropdown) {
        _activeCatalogDropdown.remove();
        _activeCatalogDropdown = null;
    }
}

/**
 * Aplică un produs din catalog în câmpurile liniei de factură.
 * @param {Object} item - Produs din catalog
 * @param {number} lineIndex
 */
function _applyCatalogItem(item, lineIndex) {
    const set = (name, val) => {
        const el = document.querySelector(`[name="${name}${lineIndex}"]`);
        if (el && val !== undefined) el.value = val;
    };

    set('description', item.name);
    set('unit', item.unit);

    const priceEl = document.querySelector(`[name="price${lineIndex}"]`);
    if (priceEl && item.price) {
        priceEl.value = item.price;
        if (priceEl.dataset) priceEl.dataset.raw = item.price;
    }

    const vatTypeEl = document.querySelector(`[name="vatType${lineIndex}"]`);
    if (vatTypeEl && item.vatType) vatTypeEl.value = item.vatType;

    const vatRateEl = document.querySelector(`[name="vatRate${lineIndex}"]`);
    if (vatRateEl && item.vatRate !== undefined) vatRateEl.value = item.vatRate;

    if (item.description) {
        const descEl = document.querySelector(`[name="itemDescription${lineIndex}"]`);
        if (descEl) descEl.value = item.description;
    }

    updateTotals();
}

/**
 * Inițializează event delegation pe #lineItems pentru autocomplete catalog.
 * Apelat din initializeUI().
 */
function _initCatalogAutocomplete() {
    const container = document.getElementById('lineItems');
    if (!container) return;

    container.addEventListener('input', function(e) {
        const input = e.target;
        if (!input.dataset.catalogInput) return;
        const lineIndex = parseInt(input.dataset.catalogInput, 10);
        const prefix    = input.value.trim();

        clearTimeout(_catalogDebounceTimer);

        if (!prefix || prefix.length < 2) {
            _hideCatalogDropdown();
            return;
        }

        _catalogDebounceTimer = setTimeout(async () => {
            try {
                const items = await catalogSearch(prefix, 8);
                _showCatalogDropdown(input, items, lineIndex);
            } catch (err) {
                // IndexedDB indisponibil (private browsing) — ignorat silențios
            }
        }, 200);
    });

    container.addEventListener('blur', function(e) {
        if (!e.target.dataset?.catalogInput) return;
        // Delay pentru a permite click pe dropdown înainte de close
        setTimeout(_hideCatalogDropdown, 200);
    }, true);

    container.addEventListener('keydown', function(e) {
        if (e.key === 'Escape' && _activeCatalogDropdown) {
            _hideCatalogDropdown();
        }
    });
}

/**
 * Salvează linia de factură curentă în catalog local (IndexedDB).
 * @param {number} lineIndex
 */
window.saveLineToLocalCatalog = async function(lineIndex) {
    const nameInput = document.querySelector(`[name="description${lineIndex}"]`);
    const name      = (nameInput?.value || '').trim();

    if (!name) {
        showToast('Introduceți o denumire înainte de a salva în catalog.', 'warning');
        return;
    }

    const priceEl   = document.querySelector(`[name="price${lineIndex}"]`);
    const vatTypeEl = document.querySelector(`[name="vatType${lineIndex}"]`);
    const vatRateEl = document.querySelector(`[name="vatRate${lineIndex}"]`);
    const unitEl    = document.querySelector(`[name="unit${lineIndex}"]`);
    const descEl    = document.querySelector(`[name="itemDescription${lineIndex}"]`);

    const product = {
        name,
        unit:        unitEl?.value         || 'EA',
        price:       priceEl?.dataset?.raw || priceEl?.value || '0',
        vatType:     vatTypeEl?.value      || 'S',
        vatRate:     vatRateEl?.value      || '19',
        description: descEl?.value        || '',
    };

    try {
        const id = await catalogAdd(product);
        showToast(`"${name}" salvat în catalog.`, 'success', `ID: ${id.slice(0, 8)}…`);
    } catch (err) {
        const isUnavailable = err?.message?.includes('indexeddb');
        showToast(
            isUnavailable
                ? 'Catalogul nu este disponibil (private browsing sau browser blocat IndexedDB).'
                : 'Eroare la salvare în catalog: ' + err.message,
            'error'
        );
    }
};

// Inițializare catalog la DOMContentLoaded
document.addEventListener('DOMContentLoaded', _initCatalogAutocomplete);

// Export for testing if needed
if (typeof module !== 'undefined' && module.exports) {
    module.exports = {
        calculateTotals,
        validateForm,
        roundNumber,
        formatXML,
        createXMLElement,
        getXMLValue,
        setXMLValue,
        formatter,
        setupInlineEditing,
        updateTotalDisplay,
        displayTotals,
        updateVATDisplay,
        getDisplayValue
    };
}                

import { InvoicePrintHandler } from './print.js';

// Create print handler instance
const printHandler = new InvoicePrintHandler();

// Initialize when the document is ready
document.addEventListener('DOMContentLoaded', () => {
    setupActionsMenu();
});

/**
 * Cablează meniul "Acțiuni ▾" din header: toggle, click-outside, Esc, item handlers.
 * Înlocuiește vechea injecție DOM pentru print controls — toate output-urile
 * (Printează Standard/Compact, Descarcă PDF, PDF ANAF, Validare ANAF) sunt în meniu.
 */
function setupActionsMenu() {
    const trigger = document.getElementById('btnActionsMenu');
    const menu = document.getElementById('actionsMenu');
    if (!trigger || !menu) return;

    const open = () => {
        menu.hidden = false;
        trigger.setAttribute('aria-expanded', 'true');
    };
    const close = () => {
        menu.hidden = true;
        trigger.setAttribute('aria-expanded', 'false');
    };
    const toggle = () => (menu.hidden ? open() : close());

    trigger.addEventListener('click', (e) => {
        e.stopPropagation();
        toggle();
    });

    document.addEventListener('click', (e) => {
        if (!menu.hidden && !menu.contains(e.target) && e.target !== trigger) close();
    });

    document.addEventListener('keydown', (e) => {
        if (e.key === 'Escape' && !menu.hidden) {
            close();
            trigger.focus();
        }
    });

    // Item dispatch — fiecare buton are data-action (+ data-template pentru print).
    menu.addEventListener('click', (e) => {
        const item = e.target.closest('[data-action]');
        if (!item) return;
        const action = item.dataset.action;
        close();

        switch (action) {
            case 'print':
                printHandler.setTemplate(item.dataset.template || 'standard');
                printHandler.print();
                break;
            case 'downloadPdf':
                window.downloadPDF?.();
                break;
            case 'pdfAnaf':
                window.downloadPdfAnaf?.();
                break;
            case 'validateAnaf':
                window.validateAnaf?.();
                break;
        }
    });
}