

--- update_app_final2.js ---
const fs = require('fs');
let code = fs.readFileSync('app_final.js', 'utf8');

const updatedLogic = `
window.renderClientAbstracts = function() {
  const tbody = document.getElementById('client-abstracts-tbody');
  if(!tbody) return;
  tbody.innerHTML = '';
  const search = document.getElementById('client-abstract-search').value.toLowerCase();
  const statusFilter = document.getElementById('client-abstract-status-filter').value;
  
  let filtered = currentClientAbstracts.filter(a => {
    let match = true;
    if(statusFilter && a.status !== statusFilter) match = false;
    if(search) {
      let pName = currentProjects.find(p => p.id === parseInt(a.project_id))?.name || '';
      if(!pName.toLowerCase().includes(search) && !(a.client_name||'').toLowerCase().includes(search)) match = false;
    }
    return match;
  });
  
  filtered.sort((a,b) => new Date(b.date) - new Date(a.date));
  
  filtered.forEach(ab => {
    let pName = currentProjects.find(p => p.id === parseInt(ab.project_id))?.name || '';
    let tr = document.createElement('tr');
    
    // Check how much has been received for this abstract
    let paid = 0;
    const linkedVouchers = allInvoices.filter(j => j.type === 'receipt' && j.status === 'posted' && j.linked_invoice_id === 'cab-' + ab.id);
    linkedVouchers.forEach(v => {
        paid += parseFloat(v.amount) || 0;
    });
    
    let actions = \`
      <button class="action-btn btn-view" onclick="printClientAbstract(\${ab.id})">طباعة</button>
      \${ab.status === 'draft' ? \`<button class="action-btn" style="background:var(--success); color:#fff; border:none;" onclick="approveClientAbstract(\${ab.id})">اعتماد</button>\` : ''}
      \${ab.status === 'approved' ? \`<button class="action-btn" style="background:var(--success); color:#fff; border:none;" onclick="payClientAbstract(\${ab.id})">سند قبض</button>\` : ''}
      \${ab.status === 'draft' ? \`<button class="action-btn btn-edit" onclick="openClientAbstractModal(\${ab.id})">تعديل</button>\` : ''}
      \${ab.status === 'draft' ? \`<button class="action-btn btn-danger" onclick="deleteClientAbstract(\${ab.id})">حذف</button>\` : ''}
    \`;
    
    let paidText = paid > 0 ? \`<div style="font-size:0.85em; color:var(--primary); margin-top:5px;">المقبوض: \${paid.toLocaleString('ar-EG')}</div>\` : '';
    
    tr.innerHTML = \`
      <td>\${ab.abstract_number || ('#' + ab.id)}</td>
      <td>\${new Date(ab.date).toLocaleDateString('ar-EG')}</td>
      <td>\${pName}</td>
      <td>\${ab.client_name || ''}</td>
      <td style="font-weight:bold; color:var(--success);">\${(parseFloat(ab.net_value) || 0).toLocaleString('ar-EG')} ج.م\${paidText}</td>
      <td><span class="status-badge \${ab.status==='approved'?'status-posted':'status-draft'}">\${ab.status==='approved'?'معتمد':'مسودة'}</span></td>
      <td>\${actions}</td>
    \`;
    tbody.appendChild(tr);
  });
};

window.openClientAbstractModal = function(id = null) {
  document.getElementById('client-abstract-modal-title').innerText = id ? 'تعديل مستخلص إيراد عميل #' + id : 'مستخلص إيراد عميل جديد';
  document.getElementById('edit-client-abstract-id').value = id || '';
  
  // Load projects
  const pSel = document.getElementById('client-abstract-project');
  pSel.innerHTML = '<option value="">اختر المشروع...</option>' + currentProjects.map(p => \`<option value="\${p.id}">\${p.name}</option>\`).join('');
  
  const tbody = document.getElementById('client-abstract-items-tbody');
  tbody.innerHTML = '';
  
  document.getElementById('client-abstract-attachment-view').style.display = 'none';
  document.getElementById('client-abstract-attachment-view').href = '#';
  
  if (id) {
    const ab = currentClientAbstracts.find(a => a.id === id);
    if(ab) {
      document.getElementById('client-abstract-number').value = ab.abstract_number || '';
      document.getElementById('client-abstract-date').value = ab.date || new Date().toISOString().split('T')[0];
      document.getElementById('client-abstract-period').value = ab.period || '';
      document.getElementById('client-abstract-project').value = ab.project_id || '';
      document.getElementById('client-abstract-client-name').value = ab.client_name || '';
      document.getElementById('client-abstract-advance-payment').value = ab.advance_payment || 0;
      document.getElementById('client-abstract-tax-percent').value = ab.tax_percent || 0;
      document.getElementById('client-abstract-retention-percent').value = ab.retention_percent || 0;
      document.getElementById('client-abstract-other-deductions').value = ab.other_deductions || 0;
      
      if(ab.attachment) {
          document.getElementById('client-abstract-attachment-view').style.display = 'block';
          document.getElementById('client-abstract-attachment-view').href = ab.attachment;
      }
      
      if(ab.items) {
        ab.items.forEach((it, idx) => {
           let tr = document.createElement('tr');
           tr.innerHTML = \`
             <td>\${it.name}<input type="hidden" class="ca-item-name" value="\${it.name}"></td>
             <td>\${it.unit}<input type="hidden" class="ca-item-unit" value="\${it.unit}"></td>
             <td>\${parseFloat(it.price).toLocaleString('ar-EG')}<input type="hidden" class="ca-item-price" value="\${it.price}"></td>
             <td>\${it.total_qty}<input type="hidden" class="ca-item-total-qty" value="\${it.total_qty}"></td>
             <td><input type="number" class="ca-item-prev-qty" value="\${it.prev_qty||0}" step="0.01" style="width:70px;" oninput="window.calcClientAbstractTotals()"></td>
             <td><input type="number" class="ca-item-curr-qty" value="\${it.curr_qty||0}" step="0.01" style="width:70px;" oninput="window.calcClientAbstractTotals()"></td>
             <td class="ca-item-total-exec">0</td>
             <td class="ca-item-prev-val">0</td>
             <td class="ca-item-curr-val" style="color:var(--primary); font-weight:bold;">0</td>
             <td class="ca-item-total-val" style="font-weight:bold;">0</td>
             <td class="ca-item-pct">0%</td>
           \`;
           tbody.appendChild(tr);
        });
      }
      window.calcClientAbstractTotals();
    }
  } else {
    document.getElementById('client-abstract-number').value = '';
    document.getElementById('client-abstract-date').value = new Date().toISOString().split('T')[0];
    document.getElementById('client-abstract-period').value = '';
    document.getElementById('client-abstract-project').value = '';
    document.getElementById('client-abstract-client-name').value = '';
    document.getElementById('client-abstract-attachment').value = '';
    
    document.getElementById('client-abstract-advance-payment').value = 0;
    document.getElementById('client-abstract-tax-percent').value = 0;
    document.getElementById('client-abstract-retention-percent').value = 0;
    document.getElementById('client-abstract-other-deductions').value = 0;
    window.calcClientAbstractTotals();
  }
  
  document.getElementById('client-abstract-modal').classList.add('active');
};

window.onClientAbstractProjectChange = function() {
  const pId = document.getElementById('client-abstract-project').value;
  const cNameInput = document.getElementById('client-abstract-client-name');
  const tbody = document.getElementById('client-abstract-items-tbody');
  tbody.innerHTML = '';
  cNameInput.value = '';
  
  if(!pId) { window.calcClientAbstractTotals(); return; }
  
  const p = currentProjects.find(x => x.id === parseInt(pId));
  if(!p) { window.calcClientAbstractTotals(); return; }
  
  cNameInput.value = p.client || '';
  
  // Previous abstracts for this project to get prev quantities
  let prevAbstracts = currentClientAbstracts.filter(a => a.project_id == pId && a.id !== parseInt(document.getElementById('edit-client-abstract-id').value) && a.status === 'approved');
  let prevQtys = {};
  prevAbstracts.forEach(ab => {
      ab.items.forEach(it => {
          if(!prevQtys[it.name]) prevQtys[it.name] = 0;
          prevQtys[it.name] += (parseFloat(it.curr_qty)||0);
      });
  });
  
  if(p.boq_items) {
      p.boq_items.forEach(it => {
         let pQty = prevQtys[it.name] || 0;
         let tr = document.createElement('tr');
         tr.innerHTML = \`
             <td>\${it.name}<input type="hidden" class="ca-item-name" value="\${it.name}"></td>
             <td>\${it.unit}<input type="hidden" class="ca-item-unit" value="\${it.unit}"></td>
             <td>\${parseFloat(it.price).toLocaleString('ar-EG')}<input type="hidden" class="ca-item-price" value="\${it.price}"></td>
             <td>\${it.qty}<input type="hidden" class="ca-item-total-qty" value="\${it.qty}"></td>
             <td><input type="number" class="ca-item-prev-qty" value="\${pQty}" step="0.01" style="width:70px;" oninput="window.calcClientAbstractTotals()"></td>
             <td><input type="number" class="ca-item-curr-qty" value="0" step="0.01" style="width:70px;" oninput="window.calcClientAbstractTotals()"></td>
             <td class="ca-item-total-exec">0</td>
             <td class="ca-item-prev-val">0</td>
             <td class="ca-item-curr-val" style="color:var(--primary); font-weight:bold;">0</td>
             <td class="ca-item-total-val" style="font-weight:bold;">0</td>
             <td class="ca-item-pct">0%</td>
         \`;
         tbody.appendChild(tr);
      });
  }
  
  window.calcClientAbstractTotals();
};

window.calcClientAbstractTotals = function() {
    let prevTotal = 0;
    let currTotal = 0;
    let grossTotal = 0;
    const tbody = document.getElementById('client-abstract-items-tbody');
    const rows = tbody.querySelectorAll('tr');
    
    rows.forEach(tr => {
        let price = parseFloat(tr.querySelector('.ca-item-price').value) || 0;
        let totalQty = parseFloat(tr.querySelector('.ca-item-total-qty').value) || 0;
        let pQty = parseFloat(tr.querySelector('.ca-item-prev-qty').value) || 0;
        let cQty = parseFloat(tr.querySelector('.ca-item-curr-qty').value) || 0;
        
        let totalExec = pQty + cQty;
        
        let pVal = pQty * price;
        let cVal = cQty * price;
        let tVal = totalExec * price;
        
        prevTotal += pVal;
        currTotal += cVal;
        grossTotal += tVal;
        
        tr.querySelector('.ca-item-total-exec').innerText = totalExec.toFixed(2);
        tr.querySelector('.ca-item-prev-val').innerText = pVal.toLocaleString('ar-EG');
        tr.querySelector('.ca-item-curr-val').innerText = cVal.toLocaleString('ar-EG');
        tr.querySelector('.ca-item-total-val').innerText = tVal.toLocaleString('ar-EG');
        let pct = totalQty > 0 ? ((totalExec / totalQty) * 100).toFixed(1) : 0;
        tr.querySelector('.ca-item-pct').innerText = pct + '%';
    });
    
    document.getElementById('client-abstract-prev-works').innerText = prevTotal.toLocaleString('ar-EG');
    document.getElementById('client-abstract-current-works').innerText = currTotal.toLocaleString('ar-EG');
    document.getElementById('client-abstract-total-works').innerText = grossTotal.toLocaleString('ar-EG');
    
    let advance = parseFloat(document.getElementById('client-abstract-advance-payment').value) || 0;
    
    let taxPct = parseFloat(document.getElementById('client-abstract-tax-percent').value) || 0;
    let taxVal = currTotal * (taxPct / 100);
    document.getElementById('client-abstract-tax-value').innerText = taxVal.toLocaleString('ar-EG');
    
    let retPct = parseFloat(document.getElementById('client-abstract-retention-percent').value) || 0;
    let retVal = currTotal * (retPct / 100);
    document.getElementById('client-abstract-retention-value').innerText = retVal.toLocaleString('ar-EG');
    
    let otherDed = parseFloat(document.getElementById('client-abstract-other-deductions').value) || 0;
    
    let totalDed = advance + taxVal + retVal + otherDed;
    let net = currTotal - totalDed;
    
    document.getElementById('client-abstract-total-deductions').innerText = totalDed.toLocaleString('ar-EG');
    document.getElementById('client-abstract-net-total').innerText = net.toLocaleString('ar-EG');
    
    return { currTotal, grossTotal, totalDed, net, taxVal, retVal, advance, otherDed };
};

const btnSaveClientAbstract = document.getElementById('btn-save-client-abstract');
if (btnSaveClientAbstract) {
    // Need to make sure we don't duplicate event listeners, so we replace it with an onclick
    btnSaveClientAbstract.onclick = async () => {
        try {
            const editIdStr = document.getElementById('edit-client-abstract-id').value;
            const abstract_number = document.getElementById('client-abstract-number').value;
            const date = document.getElementById('client-abstract-date').value;
            const period = document.getElementById('client-abstract-period').value;
            const project_id = document.getElementById('client-abstract-project').value;
            const client_name = document.getElementById('client-abstract-client-name').value;
            
            if(!project_id) { alert('يجب اختيار المشروع'); return; }
            
            const fileInput = document.getElementById('client-abstract-attachment');
            let attachment = document.getElementById('client-abstract-attachment-view').href;
            if(attachment === window.location.href || attachment.endsWith('#')) attachment = null;
            
            if (fileInput.files && fileInput.files[0]) {
                const file = fileInput.files[0];
                attachment = await new Promise((resolve, reject) => {
                    const reader = new FileReader();
                    reader.onload = (e) => resolve(e.target.result);
                    reader.onerror = (e) => reject(e);
                    reader.readAsDataURL(file);
                });
            }
            
            const tbody = document.getElementById('client-abstract-items-tbody');
            const rows = tbody.querySelectorAll('tr');
            let items = [];
            rows.forEach(tr => {
                items.push({
                    name: tr.querySelector('.ca-item-name').value,
                    unit: tr.querySelector('.ca-item-unit').value,
                    price: parseFloat(tr.querySelector('.ca-item-price').value) || 0,
                    total_qty: parseFloat(tr.querySelector('.ca-item-total-qty').value) || 0,
                    prev_qty: parseFloat(tr.querySelector('.ca-item-prev-qty').value) || 0,
                    curr_qty: parseFloat(tr.querySelector('.ca-item-curr-qty').value) || 0
                });
            });
            
            const totals = window.calcClientAbstractTotals();
            
            const obj = {
                abstract_number, date, period, project_id, client_name, attachment,
                items,
                advance_payment: totals.advance,
                tax_percent: parseFloat(document.getElementById('client-abstract-tax-percent').value) || 0,
                tax_value: totals.taxVal,
                retention_percent: parseFloat(document.getElementById('client-abstract-retention-percent').value) || 0,
                retention_value: totals.retVal,
                other_deductions: totals.otherDed,
                gross_value: totals.grossTotal,
                current_value: totals.currTotal,
                total_deductions: totals.totalDed,
                net_value: totals.net,
                status: 'draft'
            };
            
            if (editIdStr) {
                obj.id = parseInt(editIdStr);
                const existing = currentClientAbstracts.find(a => a.id === obj.id);
                if(existing) obj.status = existing.status;
                if(obj.status === 'approved') { alert('لا يمكن تعديل مستخلص معتمد'); return; }
                if(!attachment && existing && existing.attachment) obj.attachment = existing.attachment;
                await window.DB.update('client_abstracts', obj);
            } else {
                await window.DB.add('client_abstracts', obj);
            }
            
            closeModal('client-abstract-modal');
            await loadData();
            alert('تم الحفظ بنجاح');
        } catch(e) {
            alert('خطأ: ' + e.message);
        }
    };
}
`;

// Replace everything from window.renderClientAbstracts to the end of btnSaveClientAbstract listener
const startStr = 'window.renderClientAbstracts = function() {';
const endStr = 'window.deleteClientAbstract = async function(id) {';

const startIndex = code.indexOf(startStr);
const endIndex = code.indexOf(endStr);

if (startIndex !== -1 && endIndex !== -1) {
    const pre = code.substring(0, startIndex);
    const post = code.substring(endIndex);
    code = pre + updatedLogic + post;
    fs.writeFileSync('app_final.js', code, 'utf8');
    console.log('app_final.js updated successfully!');
} else {
    console.log('Could not find boundaries for replacement.');
}


--- update_pay_client_abstract.js ---
const fs = require('fs');
let code = fs.readFileSync('app_final.js', 'utf8');

const newCode = `
window.payClientAbstract = function(id, suggestedAmount = null) {
    const ab = currentClientAbstracts.find(a => a.id === id);
    if (!ab) return;
    
    // Find client in contacts list (might need to map project client_name to contact)
    // Or just leave contact empty if not easily mapped
    
    if (suggestedAmount === null) {
        const linkedVouchers = allInvoices.filter(v => (v.type === 'receipt' || v.type === 'payment') && v.linked_invoice_id == 'cab-' + id && v.status === 'posted');
        let totalPaid = 0;
        linkedVouchers.forEach(v => totalPaid += parseFloat(v.amount) || 0);
        suggestedAmount = Math.max(0, parseFloat(ab.net_value) - totalPaid);
    }
    
    window.openVoucherModal('receipt');
    
    setTimeout(() => {
        // Find contact by name to prefill if possible
        const contact = currentContacts.find(c => c.name === ab.client_name);
        if(contact) {
            document.getElementById('voucher-contact').value = contact.id;
        }
        
        document.getElementById('voucher-amount').value = suggestedAmount;
        document.getElementById('voucher-notes').value = 'دفعة من مستخلص إيراد رقم ' + (ab.abstract_number || ab.id);
        document.getElementById('voucher-status').value = 'posted';
        document.getElementById('voucher-modal-title').innerText = 'سند قبض لمستخلص إيراد (' + (ab.abstract_number || ab.id) + ')';
        window.currentLinkedInvoiceId = 'cab-' + ab.id;
    }, 300);
};
`;

if (!code.includes('window.payClientAbstract = function')) {
    code += newCode;
    fs.writeFileSync('app_final.js', code, 'utf8');
    console.log('payClientAbstract added to app_final.js');
} else {
    console.log('payClientAbstract already exists.');
}


--- remove_pct.js ---
const fs = require('fs');
let code = fs.readFileSync('app_final.js', 'utf8');
code = code.replace(/<td class="ca-item-pct">0%<\/td>/g, '');
fs.writeFileSync('app_final.js', code, 'utf8');
console.log('ca-item-pct removed from HTML template in app_final.js');


--- update_taxes.js ---
const fs = require('fs');

// 1. Update index.html
let html = fs.readFileSync('index.html', 'utf8');

const oldTaxesHtml = `          <div style="display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 10px; margin-bottom: 10px; align-items: center;">
            <span>ضرائب:</span>
            <div style="display: flex; align-items: center; gap: 5px;">
              <input type="number" id="client-abstract-tax-percent" value="0" oninput="window.calcClientAbstractTotals()" style="width: 60px; padding: 5px; background: #222; color: #fff; border: 1px solid #555; border-radius: 4px; text-align: center;">
              <span>%</span>
            </div>
            <span id="client-abstract-tax-value" style="font-weight: bold; text-align: center; color: #ff6b6b;">0</span>
          </div>`;

const newTaxesHtml = `          <div style="margin-bottom: 15px; padding: 10px; background: rgba(0,0,0,0.2); border: 1px solid #555; border-radius: 4px;">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
                <span style="font-weight: bold;">الضرائب:</span>
                <button type="button" class="btn-primary" style="padding: 2px 8px; font-size: 0.9em;" onclick="window.addClientAbstractTaxRow()">+ إضافة ضريبة</button>
            </div>
            <div id="client-abstract-taxes-list"></div>
            <div style="display: flex; justify-content: space-between; margin-top: 10px; border-top: 1px dashed #555; padding-top: 5px;">
                <span>إجمالي الضرائب:</span>
                <span id="client-abstract-tax-total-value" style="font-weight: bold; color: #ff6b6b;">0</span>
            </div>
          </div>`;

if(html.includes('id="client-abstract-tax-percent"')) {
    html = html.replace(oldTaxesHtml, newTaxesHtml);
    fs.writeFileSync('index.html', html, 'utf8');
    console.log('index.html updated successfully.');
} else {
    console.log('Could not find taxes block in index.html');
}

// 2. Update app_final.js
let js = fs.readFileSync('app_final.js', 'utf8');

const jsAddTaxFunc = `
window.addClientAbstractTaxRow = function(name = '', pct = 0, isRefundable = 'false', val = 0) {
    const list = document.getElementById('client-abstract-taxes-list');
    const div = document.createElement('div');
    div.className = 'tax-row flex-row';
    div.style.gap = '5px';
    div.style.marginBottom = '5px';
    div.style.alignItems = 'center';
    
    div.innerHTML = \`
        <input type="text" class="tax-name" placeholder="بيان الضريبة" value="\${name}" style="flex: 2; padding: 5px; background: #222; color: #fff; border: 1px solid #555; border-radius: 4px;">
        <div style="display: flex; align-items: center; gap: 2px; flex: 1;">
            <input type="number" class="tax-pct" value="\${pct}" oninput="window.calcClientAbstractTotals()" style="width: 100%; padding: 5px; background: #222; color: #fff; border: 1px solid #555; border-radius: 4px; text-align: center;">
            <span>%</span>
        </div>
        <select class="tax-refundable" style="flex: 1.5; padding: 5px; background: #222; color: #fff; border: 1px solid #555; border-radius: 4px;">
            <option value="false" \${isRefundable === 'false' ? 'selected' : ''}>غير مستردة</option>
            <option value="true" \${isRefundable === 'true' ? 'selected' : ''}>مستردة</option>
        </select>
        <span class="tax-value" style="flex: 1; text-align: center; color: #ff6b6b; font-weight: bold;">\${val.toLocaleString('ar-EG')}</span>
        <button class="btn-danger" style="padding: 2px 8px; border-radius: 4px;" onclick="this.parentElement.remove(); window.calcClientAbstractTotals()">x</button>
    \`;
    list.appendChild(div);
};
`;

// Inject addTaxFunc before renderClientAbstracts if not already there
if (!js.includes('window.addClientAbstractTaxRow')) {
    js = js.replace('window.renderClientAbstracts = function() {', jsAddTaxFunc + '\\nwindow.renderClientAbstracts = function() {');
}

// Update logic in openClientAbstractModal
js = js.replace("document.getElementById('client-abstract-tax-percent').value = ab.tax_percent || 0;", `
      document.getElementById('client-abstract-taxes-list').innerHTML = '';
      if(ab.taxes && ab.taxes.length > 0) {
          ab.taxes.forEach(t => window.addClientAbstractTaxRow(t.name, t.pct, String(t.is_refundable), t.value));
      } else {
          // fallback for older abstracts
          if(ab.tax_percent > 0) window.addClientAbstractTaxRow('ضريبة قيمة مضافة', ab.tax_percent, 'false', ab.tax_value);
      }
`);

js = js.replace("document.getElementById('client-abstract-tax-percent').value = 0;", `
    document.getElementById('client-abstract-taxes-list').innerHTML = '';
`);

// Update logic in calcClientAbstractTotals
js = js.replace(`    let taxPct = parseFloat(document.getElementById('client-abstract-tax-percent').value) || 0;
    let taxVal = currTotal * (taxPct / 100);
    document.getElementById('client-abstract-tax-value').innerText = taxVal.toLocaleString('ar-EG');`, `
    let totalTaxVal = 0;
    document.querySelectorAll('#client-abstract-taxes-list .tax-row').forEach(row => {
        let pct = parseFloat(row.querySelector('.tax-pct').value) || 0;
        let tVal = currTotal * (pct / 100);
        totalTaxVal += tVal;
        row.querySelector('.tax-value').innerText = tVal.toLocaleString('ar-EG');
    });
    document.getElementById('client-abstract-tax-total-value').innerText = totalTaxVal.toLocaleString('ar-EG');
    let taxVal = totalTaxVal;
`);

// Update saving logic in btnSaveClientAbstract
js = js.replace(`                tax_percent: parseFloat(document.getElementById('client-abstract-tax-percent').value) || 0,
                tax_value: totals.taxVal,`, `
                taxes: Array.from(document.querySelectorAll('#client-abstract-taxes-list .tax-row')).map(row => ({
                    name: row.querySelector('.tax-name').value,
                    pct: parseFloat(row.querySelector('.tax-pct').value) || 0,
                    is_refundable: row.querySelector('.tax-refundable').value === 'true',
                    value: totals.currTotal * ((parseFloat(row.querySelector('.tax-pct').value) || 0) / 100)
                })),
`);

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('app_final.js updated successfully.');


--- update_abstracts_features.js ---
const fs = require('fs');

// 1. Update index.html
let html = fs.readFileSync('index.html', 'utf8');

const commentsHTML = (type) => `
      <!-- Comments Section -->
      <div id="${type}-chat-section" style="margin-top: 20px; border-top: 1px solid var(--border); padding-top:15px; display: none;">
        <h4 style="margin-bottom:10px;">إضافة تعليق ومناقشة</h4>
        <div id="${type}-comments-list" style="max-height:150px; overflow-y:auto; margin-bottom:10px; background:rgba(0,0,0,0.1); padding:10px; border-radius:5px;"></div>
        <div style="display:flex; gap:10px; align-items:center; position:relative;">
          <input type="text" id="${type}-new-comment" placeholder="اكتب تعليقاً... استخدم @ لعمل منشن" style="flex:1;" oninput="window.handleMentionInput(this)">
          <div class="mention-dropdown" style="display:none; position:absolute; bottom:100%; right:0; background:white; color:black; border:1px solid #ccc; border-radius:5px; max-height:150px; overflow-y:auto; z-index:1000; min-width:150px; box-shadow:0 0 5px rgba(0,0,0,0.5);"></div>
          <button type="button" class="btn-primary" style="width:auto; padding: 10px 20px;" onclick="window.addAbstractComment('${type}')">إرسال</button>
        </div>
      </div>
`;

// Insert into abstract-modal before modal-actions
if (!html.includes('id="abstract-chat-section"')) {
    html = html.replace(
        '<div class="modal-actions" id="abstract-action-buttons" style="margin-top:20px;">',
        commentsHTML('abstract') + '\n      <div class="modal-actions" id="abstract-action-buttons" style="margin-top:20px;">'
    );
}

// Insert into client-abstract-modal before modal-actions
if (!html.includes('id="client-abstract-chat-section"')) {
    html = html.replace(
        '<div class="modal-actions" id="client-abstract-action-buttons" style="margin-top:20px;">',
        commentsHTML('client-abstract') + '\n      <div class="modal-actions" id="client-abstract-action-buttons" style="margin-top:20px;">'
    );
}

fs.writeFileSync('index.html', html, 'utf8');
console.log('index.html updated successfully.');

// 2. Update app_final.js
let js = fs.readFileSync('app_final.js', 'utf8');

// --- Add abstract comments functions ---
const abstractCommentsJS = `
window.renderAbstractComments = function(type, ab) {
  const section = document.getElementById(type + '-chat-section');
  if(section) section.style.display = ab.id ? 'block' : 'none';
  
  const listId = type + '-comments-list';
  const list = document.getElementById(listId);
  if(!list) return;
  list.innerHTML = '';
  if (!ab.comments || ab.comments.length === 0) {
    list.innerHTML = '<div style="color:var(--text-secondary); text-align:center; font-size:12px;">لا توجد تعليقات بعد.</div>';
    return;
  }
  ab.comments.forEach(c => {
    let text = c.text;
    text = text.replace(/@([\\w\\u0600-\\u06FF]+)/g, '<span style="color:var(--primary); font-weight:bold;">@$1</span>');
    list.innerHTML += \`<div style="margin-bottom:8px; padding-bottom:8px; border-bottom:1px solid rgba(255,255,255,0.05);">
      <strong style="font-size:12px; color:var(--text-secondary);">\${c.user} - \${new Date(c.date).toLocaleString('ar-EG')}</strong>
      <div style="margin-top:4px;">\${text}</div>
    </div>\`;
  });
  list.scrollTop = list.scrollHeight;
};

window.addAbstractComment = async function(type) {
  try {
    const input = document.getElementById(type + '-new-comment');
    const text = input.value.trim();
    if(!text || !window.currentViewingAbstractId) return;
    
    let isClient = type === 'client-abstract';
    let dbTable = isClient ? 'client_abstracts' : 'abstracts';
    let allData = isClient ? allClientAbstracts : allAbstracts;
    
    const abIndex = allData.findIndex(i => i.id === window.currentViewingAbstractId);
    if(abIndex === -1) return;
    
    const ab = allData[abIndex];
    if(!ab.comments) ab.comments = [];
    
    const commentObj = { user: currentUser.username, text: text, date: new Date().toISOString() };
    ab.comments.push(commentObj);
    
    const mentions = text.match(/@([\\w\\u0600-\\u06FF]+)/g);
    if(mentions) {
      for(let m of mentions) {
        const username = m.substring(1);
        const mentionedUser = currentUsers.find(u => u.username === username);
        if(mentionedUser) {
          let notifs = await window.DB.getAll('notifications') || [];
          notifs.push({
            id: Date.now().toString() + Math.random().toString(36).substring(2),
            user: mentionedUser.username,
            text: \`تم عمل منشن لك في مستخلص رقم \${ab.doc_no}\`,
            link: \`#\`,
            date: new Date().toISOString(),
            read: false
          });
          await window.DB.put('notifications', notifs);
        }
      }
    }
    
    await window.DB.put(dbTable, ab);
    input.value = '';
    window.renderAbstractComments(type, ab);
    
    const allNotifications = await window.DB.getAll('notifications') || [];
    const myNotifs = allNotifications.filter(n => n.user === currentUser.username && !n.read);
    if(window.renderNotifications) renderNotifications(myNotifs);
  } catch(e) {
    alert("حدث خطأ أثناء إضافة التعليق: " + e.message);
  }
};
`;

if (!js.includes('window.addAbstractComment')) {
    js = js.replace('window.renderClientAbstracts = function() {', abstractCommentsJS + '\\nwindow.renderClientAbstracts = function() {');
}

// --- Modify openAbstractModal ---
js = js.replace("window.openAbstractModal = function(id = null) {", "window.openAbstractModal = function(id = null) {\\n  window.currentViewingAbstractId = id;");
js = js.replace("document.getElementById('abstract-tax-percent').value = ab.tax_percent || 0;", "document.getElementById('abstract-tax-percent').value = ab.tax_percent || 0;\\n      if(window.renderAbstractComments) window.renderAbstractComments('abstract', ab);");
js = js.replace("document.getElementById('abstract-tax-percent').value = 0;", "document.getElementById('abstract-tax-percent').value = 0;\\n    if(document.getElementById('abstract-chat-section')) document.getElementById('abstract-chat-section').style.display = 'none';");

// --- Modify openClientAbstractModal ---
js = js.replace("window.openClientAbstractModal = function(id = null) {", "window.openClientAbstractModal = function(id = null) {\\n  window.currentViewingAbstractId = id;");
js = js.replace("document.getElementById('client-abstract-retention-percent').value = ab.retention_percent || 0;", "document.getElementById('client-abstract-retention-percent').value = ab.retention_percent || 0;\\n      if(window.renderAbstractComments) window.renderAbstractComments('client-abstract', ab);");
js = js.replace("document.getElementById('client-abstract-taxes-list').innerHTML = '';", "document.getElementById('client-abstract-taxes-list').innerHTML = '';\\n    if(document.getElementById('client-abstract-chat-section')) document.getElementById('client-abstract-chat-section').style.display = 'none';");

// --- Quantity Warnings in calculateAbstractTotals ---
js = js.replace("tr.querySelector('.ca-item-total-val').innerText = tVal.toLocaleString('ar-EG');", `tr.querySelector('.ca-item-total-val').innerText = tVal.toLocaleString('ar-EG');
        if (totalQty > 0 && tQty > totalQty) {
            tr.style.backgroundColor = 'rgba(255, 0, 0, 0.2)';
            let titleElement = tr.querySelector('td:nth-child(2)');
            if(titleElement && !titleElement.innerHTML.includes('تجاوز')) {
                titleElement.innerHTML += '<span style="color: #ff6b6b; font-size: 0.8em; margin-right: 5px; font-weight: bold;">(تجاوز!)</span>';
            }
        } else {
            tr.style.backgroundColor = '';
            let titleElement = tr.querySelector('td:nth-child(2)');
            if(titleElement && titleElement.innerHTML.includes('تجاوز')) {
                titleElement.innerHTML = titleElement.innerHTML.replace(/<span.*>\\(تجاوز!\\)<\\/span>/, '');
            }
        }
`);

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('app_final.js updated successfully.');


--- fix_newlines.js ---
const fs = require('fs');
let js = fs.readFileSync('app_final.js', 'utf8');

// The script inserted literal backslash n instead of newlines, let's fix it
js = js.replace(/\\n  window.currentViewingAbstractId = id;/g, '\n  window.currentViewingAbstractId = id;');
js = js.replace(/\\n      if\(window.renderAbstractComments\) window.renderAbstractComments\('abstract', ab\);/g, '\n      if(window.renderAbstractComments) window.renderAbstractComments(\'abstract\', ab);');
js = js.replace(/\\n    if\(document.getElementById\('abstract-chat-section'\)\) document.getElementById\('abstract-chat-section'\).style.display = 'none';/g, '\n    if(document.getElementById(\'abstract-chat-section\')) document.getElementById(\'abstract-chat-section\').style.display = \'none\';');
js = js.replace(/\\n      if\(window.renderAbstractComments\) window.renderAbstractComments\('client-abstract', ab\);/g, '\n      if(window.renderAbstractComments) window.renderAbstractComments(\'client-abstract\', ab);');
js = js.replace(/\\n    if\(document.getElementById\('client-abstract-chat-section'\)\) document.getElementById\('client-abstract-chat-section'\).style.display = 'none';/g, '\n    if(document.getElementById(\'client-abstract-chat-section\')) document.getElementById(\'client-abstract-chat-section\').style.display = \'none\';');
js = js.replace(/\\nwindow.renderClientAbstracts = function\(\) {/g, '\nwindow.renderClientAbstracts = function() {');

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('Fixed literal \\n to actual newlines');


--- update_sa_warning.js ---
const fs = require('fs');
let js = fs.readFileSync('app_final.js', 'utf8');

js = js.replace("tr.querySelector('.sa-item-total-val').innerText = tVal.toLocaleString('ar-EG');", `tr.querySelector('.sa-item-total-val').innerText = tVal.toLocaleString('ar-EG');
        if (totalQty > 0 && tQty > totalQty) {
            tr.style.backgroundColor = 'rgba(255, 0, 0, 0.2)';
            let titleElement = tr.querySelector('td:nth-child(2)');
            if(titleElement && !titleElement.innerHTML.includes('تجاوز')) {
                titleElement.innerHTML += '<span style="color: #ff6b6b; font-size: 0.8em; margin-right: 5px; font-weight: bold;">(تجاوز!)</span>';
            }
        } else {
            tr.style.backgroundColor = '';
            let titleElement = tr.querySelector('td:nth-child(2)');
            if(titleElement && titleElement.innerHTML.includes('تجاوز')) {
                titleElement.innerHTML = titleElement.innerHTML.replace(/<span.*>\\(تجاوز!\\)<\\/span>/, '');
            }
        }
`);

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('Added sa-item warning');


--- fix_comments_visibility.js ---
const fs = require('fs');

let html = fs.readFileSync('index.html', 'utf8');
html = html.replace(/<div id="abstract-chat-section" style="([^"]*?) display: none;">/g, '<div id="abstract-chat-section" style="$1">');
html = html.replace(/<div id="client-abstract-chat-section" style="([^"]*?) display: none;">/g, '<div id="client-abstract-chat-section" style="$1">');
fs.writeFileSync('index.html', html, 'utf8');
console.log('Fixed display: none in index.html');

let js = fs.readFileSync('app_final.js', 'utf8');
js = js.replace(/if\(section\) section.style.display = ab.id \? 'block' : 'none';/g, '');
// Also fix openClientAbstractModal if it hides it initially:
js = js.replace(/if\(document.getElementById\('client-abstract-chat-section'\)\) document.getElementById\('client-abstract-chat-section'\).style.display = 'none';/g, '');
js = js.replace(/if\(document.getElementById\('abstract-chat-section'\)\) document.getElementById\('abstract-chat-section'\).style.display = 'none';/g, '');
fs.writeFileSync('app_final.js', js, 'utf8');
console.log('Fixed comment visibility in app_final.js');


--- fix_save.js ---
const fs = require('fs');
let js = fs.readFileSync('app_final.js', 'utf8');

// 1. Add fetching of client abstracts to loadData
if (!js.includes("currentClientAbstracts = await window.DB.getAll('client_abstracts')")) {
    js = js.replace(/(currentAbstracts = await window\.DB\.getAll\('subcontract_abstracts'\);)/, "$1\n  currentClientAbstracts = await window.DB.getAll('client_abstracts') || [];");
}

// 2. Ensure currentClientAbstracts is also loaded in renderClientAbstracts just in case
if (!js.includes("currentClientAbstracts = await window.DB.getAll('client_abstracts') || [];", js.indexOf('window.renderClientAbstracts = function'))) {
    js = js.replace(/window\.renderClientAbstracts = (async )?function\(\) \{/, "window.renderClientAbstracts = async function() {\n  currentClientAbstracts = await window.DB.getAll('client_abstracts') || [];");
}

// 3. Make sure to render it after save
if (!js.includes("window.renderClientAbstracts()", js.indexOf('btnSaveClientAbstract.onclick'))) {
    js = js.replace(/await loadData\(\);\s*alert\('تم حفظ المستخلص بنجاح'\);/, "await loadData();\n            if(typeof window.renderClientAbstracts === 'function') window.renderClientAbstracts();\n            alert('تم حفظ المستخلص بنجاح');");
}

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('Fixed client abstracts save and render logic!');


--- fix_numbering.js ---
const fs = require('fs');
let js = fs.readFileSync('app_final.js', 'utf8');

// Auto-numbering for client abstracts when project changes
if (!js.includes("allProjAbstractsCount")) {
    js = js.replace(/cNameInput\.value = p\.client \|\| '';/, `cNameInput.value = p.client || '';
  
  let allProjAbstractsCount = currentClientAbstracts.filter(a => a.project_id == pId).length;
  if (!document.getElementById('edit-client-abstract-id').value) {
      document.getElementById('client-abstract-number').value = 'مستخلص ' + (allProjAbstractsCount + 1);
  }`);
}

// Fixing the save render issue properly without relying on Arabic text match
let loadDataMatch = js.match(/await loadData\(\);\s*alert\([^)]+\);/);
if (loadDataMatch && !js.includes('window.renderClientAbstracts();', loadDataMatch.index - 50)) {
    js = js.replace(/await loadData\(\);\s*alert\(([^)]+)\);/, "await loadData();\n            if(typeof window.renderClientAbstracts === 'function') window.renderClientAbstracts();\n            alert($1);");
}

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('Fixed auto-numbering and rendering on save!');


--- fix_save_render.js ---
const fs = require('fs');
let js = fs.readFileSync('app_final.js', 'utf8');

js = js.replace(/closeModal\('client-abstract-modal'\);\s*await loadData\(\);\s*alert\('[^']+'\);/g, 
`closeModal('client-abstract-modal');
            await loadData();
            if (typeof window.renderClientAbstracts === 'function') {
                window.renderClientAbstracts();
            }
            alert('تم الحفظ بنجاح');`);

fs.writeFileSync('app_final.js', js, 'utf8');


--- restore_modal.js ---
const fs = require('fs');
let html = fs.readFileSync('index.html', 'utf8');

const missingBlock = `

  <!-- Voucher Modal -->
  <div id="voucher-modal" class="modal" style="z-index: 9999999 !important;">
    <div class="modal-content" style="width: 500px; max-width: 95%; max-height: 90vh; overflow-y: auto;">
      <h3 id="voucher-modal-title">إنشاء سند</h3>
      <input type="hidden" id="edit-voucher-id">
      <input type="hidden" id="voucher-type">
      <div class="flex-col" style="margin-bottom: 10px;">
        <label>التاريخ</label>
        <input type="datetime-local" id="voucher-date">
      </div>
      <div class="flex-col" style="margin-bottom: 10px;">
        <label>رقم المستند / المرجع</label>
        <input type="text" id="voucher-doc-no" placeholder="اختياري">`;

html = html.replace(/<\/div>\s*<\/div>\s*<\/div>\s*<\/div>\s*<div class="flex-col" style="margin-bottom: 10px;">\s*<label id="voucher-contact-label">جهة \/ مستفيد<\/label>/, 
`</div>
    </div>
  </div>${missingBlock}
      </div>
      <div class="flex-col" style="margin-bottom: 10px;">
        <label id="voucher-contact-label">جهة / مستفيد</label>`);

// Also apply the cache buster safely at the end of the file
html = html.replace(/<script src="db\.js(?!.*?\?)"><\/script>/, '<script src="db.js?v=202606030939"></script>');
html = html.replace(/<script src="app_final\.js\?v=\d+" defer><\/script>/, '<script src="app_final.js?v=202606030939" defer></script>');
html = html.replace(/<script src="vouchers_returns\.js\?v=\d+" defer><\/script>/, '<script src="vouchers_returns.js?v=202606030939" defer></script>');

fs.writeFileSync('index.html', html, 'utf8');
console.log('Restored voucher modal and updated cache busters safely.');


--- fix_app_final.js ---
const fs = require('fs');
let js = fs.readFileSync('app_final.js', 'utf8');

const regex = /document\.getElementById\('btn-login'\)\.addEventListener\('click', async \(\) => \{\s*const user = document\.getElementById\('login-username'\)\.value;\s*const pass = document\.getElementById\('login-password'\)\.value;\s*const error = document\.getElementById\('login-error'\);\s*const res = await window\.DB\.login\(user, pass\);\s*if \(res\) \{\s*currentUser = res;\s*sessionStorage\.setItem\('currentUser', JSON\.stringify\(res\)\);\s*\} else \{\s*window\.addJournalLine\(\); window\.addJournalLine\(\);\s*\}(?:.|\n)*?\/\/ Listeners\s*document\.getElementById\('btn-login'\)\.addEventListener\('click', async \(\) => \{\s*const user = document\.getElementById\('login-username'\)\.value;\s*const pass = document\.getElementById\('login-password'\)\.value;\s*const error = document\.getElementById\('login-error'\);\s*const res = await window\.DB\.login\(user, pass\);\s*if \(res\) \{\s*currentUser = res;\s*sessionStorage\.setItem\('currentUser', JSON\.stringify\(res\)\);\s*loginScreen\.classList\.remove\('active'\);\s*appScreen\.classList\.add\('active'\);\s*setupUserUI\(\);\s*await loadData\(\);\s*\} else \{\s*error\.innerText = '.*?';\s*\}\s*\}\);\s*document\.getElementById\('btn-logout'\)\.addEventListener\('click', \(\) => \{\s*currentUser = null;\s*sessionStorage\.removeItem\('currentUser'\);\s*appScreen\.classList\.remove\('active'\);\s*loginScreen\.classList\.add\('active'\);\s*\}\);\s*navItems\.forEach\(item => \{\s*item\.addEventListener\('click', \(e\) => \{\s*if\(e\.target\.id === 'btn-logout'\) return;\s*navItems\.forEach\(n => n\.classList\.remove\('active'\)\);\s*e\.target\.classList\.add\('active'\);\s*views\.forEach\(v => v\.classList\.remove\('active'\)\);\s*document\.getElementById\(\`view-\$\{e\.target\.dataset\.view\}\`\)\.classList\.add\('active'\);\s*if\(e\.target\.dataset\.view === 'project-reports'\) renderProjectReports\(\);\s*if\(e\.target\.dataset\.view === 'subcontracts'\) window\.renderSubcontracts\(\);\s*if\(e\.target\.dataset\.view === 'subcontract-abstracts'\) window\.renderAbstracts\(\);/;

const replacement = `document.getElementById('btn-login').addEventListener('click', async () => {
  const user = document.getElementById('login-username').value;
  const pass = document.getElementById('login-password').value;
  const error = document.getElementById('login-error');

  const res = await window.DB.login(user, pass);
  if (res) {
    currentUser = res;
    sessionStorage.setItem('currentUser', JSON.stringify(res));
    loginScreen.classList.remove('active');
    appScreen.classList.add('active');
    setupUserUI();
    await loadData();
  } else {
    error.innerText = 'بيانات الدخول غير صحيحة';
  }
});

document.getElementById('btn-logout').addEventListener('click', () => {
  currentUser = null;
  sessionStorage.removeItem('currentUser');
  appScreen.classList.remove('active');
  loginScreen.classList.add('active');
});

navItems.forEach(item => {
  item.addEventListener('click', (e) => {
    if(e.target.id === 'btn-logout') return;
    navItems.forEach(n => n.classList.remove('active'));
    e.target.classList.add('active');
    views.forEach(v => v.classList.remove('active'));
    document.getElementById(\`view-\${e.target.dataset.view}\`).classList.add('active');
    if(e.target.dataset.view === 'project-reports') renderProjectReports();
    if(e.target.dataset.view === 'subcontracts') window.renderSubcontracts();
    if(e.target.dataset.view === 'subcontract-abstracts') window.renderAbstracts();
    if(e.target.dataset.view === 'client-abstracts' && typeof window.renderClientAbstracts === 'function') window.renderClientAbstracts();`;

const newJs = js.replace(regex, replacement);

fs.writeFileSync('app_final.js', newJs, 'utf8');
console.log('Fixed app_final.js!');


--- fix_actions.js ---
const fs = require('fs');
let js = fs.readFileSync('app_final.js', 'utf8');

js = js.replace(/window\.deleteClientAbstract = async function\(id\) \{[\s\S]*?\};/, `window.deleteClientAbstract = async function(id) {
    if(confirm('هل أنت متأكد من حذف هذا المستخلص؟')) {
        await window.DB.remove('client_abstracts', id);
        if (typeof window.renderClientAbstracts === 'function') window.renderClientAbstracts();
    }
};`);

js = js.replace(/window\.approveClientAbstract = async function\(id\) \{[\s\S]*?\};/, `window.approveClientAbstract = async function(id) {
    if(confirm('هل أنت متأكد من اعتماد هذا المستخلص؟ لا يمكن التعديل عليه بعد الاعتماد وسيتم إنشاء قيد يومية تلقائي.')) {
        const ab = currentClientAbstracts.find(a => a.id === id);
        if(ab) {
            ab.status = 'approved';
            await window.DB.update('client_abstracts', ab);
            await generateClientAbstractJournal(ab);
            if (typeof window.renderClientAbstracts === 'function') window.renderClientAbstracts();
            alert('تم اعتماد المستخلص وإنشاء القيد بنجاح.');
        }
    }
};`);

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('Fixed actions in app_final.js!');


--- fix_view.js ---
const fs = require('fs');
let js = fs.readFileSync('app_final.js', 'utf8');

// 1. Change the button in renderClientAbstracts
js = js.replace(/\$\{ab\.status === 'draft' \? \`\<button class="action-btn btn-edit" onclick="openClientAbstractModal\(\$\{ab\.id\}\)"\>.*?<\/button>\` : ''\}/,
    `<button class="action-btn btn-edit" style="background:#17a2b8" onclick="openClientAbstractModal(\${ab.id})">\${ab.status === 'draft' ? 'تعديل' : 'عرض'}</button>`);

// 2. Hide save button in openClientAbstractModal
js = js.replace(/window\.openClientAbstractModal = function\(id = null\) \{/, 
    `window.openClientAbstractModal = function(id = null) {\n    const btnSave = document.getElementById('btn-save-client-abstract');\n    if(btnSave) btnSave.style.display = 'inline-block';`);

js = js.replace(/document\.getElementById\('client-abstract-advance-payment'\)\.value = ab\.advance_payment \|\| 0;/, 
    `document.getElementById('client-abstract-advance-payment').value = ab.advance_payment || 0;\n      if(ab.status === 'approved' && btnSave) btnSave.style.display = 'none';`);

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('Fixed view abstract in app_final.js!');


--- add_modal_actions.js ---
const fs = require('fs');

// 1. UPDATE index.html
let html = fs.readFileSync('index.html', 'utf8');

const modalActionsRegex = /<button class="btn-secondary" onclick="closeModal\('client-abstract-modal'\)" style="font-size: 1\.1rem; padding: 10px 20px;">إلغاء<\/button>\s*<button class="btn-primary" id="btn-save-client-abstract" style="font-size: 1\.1rem; padding: 10px 30px;">حفظ المستخلص<\/button>/;

const newActionsHTML = `<button class="btn-secondary" onclick="closeModal('client-abstract-modal')" style="font-size: 1.1rem; padding: 10px 20px;">إلغاء</button>
        <button class="btn-primary" id="btn-save-client-abstract" style="font-size: 1.1rem; padding: 10px 30px;">حفظ المستخلص</button>
        <button class="btn-primary" id="btn-approve-client-abstract" style="font-size: 1.1rem; padding: 10px 30px; background:var(--success); color:#fff; border:none; display:none;" onclick="approveClientAbstractFromModal()">اعتماد المستخلص</button>
        <button class="btn-primary" id="btn-pay-client-abstract" style="font-size: 1.1rem; padding: 10px 30px; background:var(--success); color:#fff; border:none; display:none;" onclick="payClientAbstractFromModal()">سند قبض</button>
        <button class="btn-primary" id="btn-print-client-abstract" style="font-size: 1.1rem; padding: 10px 30px; background:#17a2b8; color:#fff; border:none; display:none;" onclick="printClientAbstractFromModal()">طباعة</button>`;

html = html.replace(modalActionsRegex, newActionsHTML);
fs.writeFileSync('index.html', html, 'utf8');

// 2. UPDATE app_final.js
let js = fs.readFileSync('app_final.js', 'utf8');

// Add the wrapper functions at the end of the file
const wrapperFunctions = `
window.approveClientAbstractFromModal = function() {
    const id = parseInt(document.getElementById('edit-client-abstract-id').value);
    if(id) {
        closeModal('client-abstract-modal');
        window.approveClientAbstract(id);
    }
};
window.payClientAbstractFromModal = function() {
    const id = parseInt(document.getElementById('edit-client-abstract-id').value);
    if(id) {
        closeModal('client-abstract-modal');
        window.payClientAbstract(id);
    }
};
window.printClientAbstractFromModal = function() {
    const id = parseInt(document.getElementById('edit-client-abstract-id').value);
    if(id) {
        window.printClientAbstract(id);
    }
};
`;

if (!js.includes('approveClientAbstractFromModal')) {
    js += wrapperFunctions;
}

// Update openClientAbstractModal to toggle buttons
const openModalRegex = /if\(ab\.status === 'approved' && btnSave\) btnSave\.style\.display = 'none';/;
const openModalReplacement = `if(ab.status === 'approved' && btnSave) {
          btnSave.style.display = 'none';
          document.getElementById('btn-approve-client-abstract').style.display = 'none';
          document.getElementById('btn-pay-client-abstract').style.display = 'inline-block';
          document.getElementById('btn-print-client-abstract').style.display = 'inline-block';
      } else {
          document.getElementById('btn-approve-client-abstract').style.display = 'inline-block';
          document.getElementById('btn-pay-client-abstract').style.display = 'none';
          document.getElementById('btn-print-client-abstract').style.display = 'inline-block';
      }`;
js = js.replace(openModalRegex, openModalReplacement);

// Also handle the if (!id) case where it's a new abstract
const newModalRegex = /btnSave\.style\.display = 'inline-block';/;
const newModalReplacement = `btnSave.style.display = 'inline-block';
      if(document.getElementById('btn-approve-client-abstract')) {
          document.getElementById('btn-approve-client-abstract').style.display = 'none';
          document.getElementById('btn-pay-client-abstract').style.display = 'none';
          document.getElementById('btn-print-client-abstract').style.display = 'none';
      }`;
js = js.replace(newModalRegex, newModalReplacement);

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('Added modal actions!');


--- add_client_payments.js ---
const fs = require('fs');

// 1. UPDATE index.html
let html = fs.readFileSync('index.html', 'utf8');

const regex = /<span style="color: #aaa; margin-top: 10px;">جنيه مصري<\/span>\s*<\/div>\s*<\/div>\s*<div class="modal-actions"/;

const replacement = `<span style="color: #aaa; margin-top: 10px;">جنيه مصري</span>
        </div>
      </div>
      
      <div id="client-ab-linked-vouchers-container" style="display: none; margin-top: 20px; padding: 20px; background: rgba(0,0,0,0.2); border-radius: 8px; border: 1px solid #444; clear: both; width: 100%; box-sizing: border-box;">
        <div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #555; padding-bottom: 10px; margin-bottom: 15px;">
          <h3 style="margin:0; color: var(--primary);"><i class="fas fa-receipt"></i> الدفعات المحصلة لهذا المستخلص</h3>
          <button class="action-btn" id="btn-pay-client-abstract-inner" style="background:var(--success); color:#fff; padding:5px 15px; font-size:1rem; border:none;" onclick="payClientAbstractFromModal()">+ سند قبض</button>
        </div>
        <div style="display: flex; gap: 40px; font-weight: bold; font-size: 1.3rem; margin-bottom: 15px;">
          <div style="color: var(--success);">إجمالي المحصل: <span id="client-ab-total-paid">0</span></div>
          <div style="color: var(--danger);">المتبقي من المستخلص: <span id="client-ab-remaining">0</span></div>
        </div>
        <ul id="client-ab-linked-vouchers-list" style="list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 5px;"></ul>
      </div>

      <div class="modal-actions"`;

html = html.replace(regex, replacement);
fs.writeFileSync('index.html', html, 'utf8');

// 2. UPDATE app_final.js
let js = fs.readFileSync('app_final.js', 'utf8');

const jsRegex = /document\.getElementById\('client-abstract-attachment-view'\)\.style\.display = 'none';\s*document\.getElementById\('client-abstract-attachment-view'\)\.href = '#';/;

const jsReplacement = `document.getElementById('client-abstract-attachment-view').style.display = 'none';
    document.getElementById('client-abstract-attachment-view').href = '#';
    
    const paymentsContainer = document.getElementById('client-ab-linked-vouchers-container');
    const paymentsList = document.getElementById('client-ab-linked-vouchers-list');
    const paidSpan = document.getElementById('client-ab-total-paid');
    const remainingSpan = document.getElementById('client-ab-remaining');
    
    if (id) {
        const linkedVouchers = allInvoices.filter(v => v.type === 'receipt' && v.linked_invoice_id == 'cab-' + id && v.status === 'posted');
        let totalPaid = 0;
        let html = '';
        if (linkedVouchers.length > 0) {
            linkedVouchers.forEach(v => {
                totalPaid += parseFloat(v.amount) || 0;
                let d = new Date(v.created_at || Date.now()).toLocaleDateString('ar-EG');
                let accName = '-';
                let acc = currentAccounts.find(a => a.id === parseInt(v.treasury_account_id));
                if(acc) accName = acc.name;
                html += \`<li style="padding: 10px; background: rgba(255,255,255,0.05); border-radius: 4px; display: flex; justify-content: space-between;">
                    <span>سند قبض: \${v.id} | التاريخ: \${d} | الخزنة/البنك: \${accName}</span>
                    <span style="font-weight:bold; color:var(--success);">\${parseFloat(v.amount).toLocaleString('ar-EG')} ج.م</span>
                </li>\`;
            });
            paymentsList.innerHTML = html;
        } else {
            paymentsList.innerHTML = '<li style="color:#aaa;">لا توجد أي دفعات محصلة حتى الآن.</li>';
        }
        
        const abObjForVal = currentClientAbstracts.find(a => a.id === id);
        const netVal = abObjForVal ? parseFloat(abObjForVal.net_value) || 0 : 0;
        const remaining = netVal - totalPaid;
        
        paidSpan.innerText = totalPaid.toLocaleString('ar-EG', {minimumFractionDigits:2});
        remainingSpan.innerText = remaining.toLocaleString('ar-EG', {minimumFractionDigits:2});
        
        window.currentClientAbstractRemaining = remaining;
        paymentsContainer.style.display = 'block';
    } else {
        paymentsContainer.style.display = 'none';
        window.currentClientAbstractRemaining = 0;
    }`;

js = js.replace(jsRegex, jsReplacement);

// Hide the inner payment button if abstract is not approved
const jsRegex2 = /document\.getElementById\('btn-pay-client-abstract'\)\.style\.display = 'inline-block';/;
const jsReplacement2 = `document.getElementById('btn-pay-client-abstract').style.display = 'inline-block';
          if(document.getElementById('btn-pay-client-abstract-inner')) document.getElementById('btn-pay-client-abstract-inner').style.display = 'inline-block';`;
js = js.replace(jsRegex2, jsReplacement2);

const jsRegex3 = /document\.getElementById\('btn-pay-client-abstract'\)\.style\.display = 'none';/g;
const jsReplacement3 = `document.getElementById('btn-pay-client-abstract').style.display = 'none';
          if(document.getElementById('btn-pay-client-abstract-inner')) document.getElementById('btn-pay-client-abstract-inner').style.display = 'none';`;
js = js.replace(jsRegex3, jsReplacement3);

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('Added client abstract payments list!');


--- find_remaining.js ---
const fs = require('fs');
const text = fs.readFileSync('index.html', 'utf8');
const lines = text.split('\n');
for(let i=0; i<lines.length; i++) {
    if(lines[i].includes('المتبقي')) {
        console.log(`Line ${i+1}: ${lines[i].trim()}`);
    }
}
console.log('--- app_final.js ---');
const text2 = fs.readFileSync('app_final.js', 'utf8');
const lines2 = text2.split('\n');
for(let i=0; i<lines2.length; i++) {
    if(lines2[i].includes('المتبقي')) {
        console.log(`Line ${i+1}: ${lines2[i].trim()}`);
    }
}


--- update_client_ab_table.js ---
const fs = require('fs');

// 1. UPDATE index.html
let html = fs.readFileSync('index.html', 'utf8');

const thRegex = /<th>الصافي \(إيراد\)<\/th>\s*<th>الحالة<\/th>\s*<th>إجراءات<\/th>/;
const thReplacement = `<th>الصافي (إيراد)</th>
                <th>المحصل</th>
                <th>المتبقي</th>
                <th>الحالة</th>
                <th>إجراءات</th>`;
html = html.replace(thRegex, thReplacement);
fs.writeFileSync('index.html', html, 'utf8');

// 2. UPDATE app_final.js
let js = fs.readFileSync('app_final.js', 'utf8');

const jsFix = `
let replaceBlockMatch = js.match(/let paidText = paid > 0[\\s\\S]*?<\\/span><\\/td>\\s*<td>\\$\\{actions\\}<\\/td>/);
if (replaceBlockMatch) {
    let replaceBlock = replaceBlockMatch[0];
    let newBlock = \`let remaining = Math.max(0, (parseFloat(ab.net_value) || 0) - paid);
        
        tr.innerHTML = \\\`
          <td>\\\${ab.abstract_number || ('#' + ab.id)}</td>
          <td>\\\${new Date(ab.date).toLocaleDateString('ar-EG')}</td>
          <td>\\\${pName}</td>
          <td>\\\${ab.client_name || ''}</td>
          <td style="font-weight:bold; color:var(--success);">\\\${(parseFloat(ab.net_value) || 0).toLocaleString('ar-EG')} ج.م</td>
          <td style="color:var(--primary); font-weight:bold;">\\\${paid.toLocaleString('ar-EG')} ج.م</td>
          <td style="color:var(--danger); font-weight:bold;">\\\${remaining.toLocaleString('ar-EG')} ج.م</td>
          <td><span class="status-badge \\\${ab.status==='approved'?'status-posted':'status-draft'}">\\\${ab.status==='approved'?'معتمد':'مسودة'}</span></td>
          <td>\\\${actions}</td>\`;
    js = js.replace(replaceBlock, newBlock);
} else {
    console.log("Could not find the block in app_final.js");
}
`;

eval(jsFix);

fs.writeFileSync('app_final.js', js, 'utf8');
console.log('Updated client abstract table columns!');


--- fix_buttons.js ---
const fs = require('fs');

let js = fs.readFileSync('app_final.js', 'utf8');

const oldActionsRegex = /let actions = `[\s\S]*?`;/;

// Replace actions inside renderClientAbstracts specifically!
// I'll use a string replacement to be extremely precise.
const targetText = `let actions = \`
      <button class="action-btn btn-view" onclick="printClientAbstract(\${ab.id})">طباعة</button>
      \${ab.status === 'draft' ? \`<button class="action-btn" style="background:var(--success); color:#fff; border:none;" onclick="approveClientAbstract(\${ab.id})">اعتماد</button>\` : ''}
      \${ab.status === 'approved' ? \`<button class="action-btn" style="background:var(--success); color:#fff; border:none;" onclick="payClientAbstract(\${ab.id})">سند قبض</button>\` : ''}
      <button class="action-btn btn-edit" style="background:#17a2b8" onclick="openClientAbstractModal(\${ab.id})">\${ab.status === 'draft' ? 'تعديل' : 'عرض'}</button>
      \${ab.status === 'draft' ? \`<button class="action-btn btn-danger" onclick="deleteClientAbstract(\${ab.id})">حذف</button>\` : ''}
    \`;`;

const newActionsText = `let actions = \`
      <button class="action-btn" style="background:#6c757d; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;" onclick="printClientAbstract(\${ab.id})">طباعة</button>
      \${ab.status === 'draft' ? \`<button class="action-btn" style="background:#28a745; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;" onclick="approveClientAbstract(\${ab.id})">اعتماد</button>\` : ''}
      \${ab.status === 'approved' ? \`<button class="action-btn" style="background:#28a745; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;" onclick="payClientAbstract(\${ab.id})">سند قبض</button>\` : ''}
      <button class="action-btn" style="background:#17a2b8; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;" onclick="openClientAbstractModal(\${ab.id})">\${ab.status === 'draft' ? 'تعديل' : 'عرض'}</button>
      <button class="action-btn" style="background:#dc3545; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;" onclick="deleteClientAbstract(\${ab.id})">حذف</button>
    \`;`;

let replaced = false;
let lines = js.split('\n');
for (let i = 0; i < lines.length; i++) {
    if (lines[i].includes('let actions = `') && lines[i+5].includes('openClientAbstractModal')) {
        lines[i] = `    let actions = \`
      <button class="action-btn" style="background:#6c757d; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;" onclick="printClientAbstract(\${ab.id})">طباعة</button>
      \${ab.status === 'draft' ? \\\`<button class="action-btn" style="background:#28a745; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;" onclick="approveClientAbstract(\${ab.id})">اعتماد</button>\\\` : ''}
      \${ab.status === 'approved' ? \\\`<button class="action-btn" style="background:#28a745; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;" onclick="payClientAbstract(\${ab.id})">سند قبض</button>\\\` : ''}
      <button class="action-btn" style="background:#17a2b8; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;" onclick="openClientAbstractModal(\${ab.id})">\${ab.status === 'draft' ? 'تعديل' : 'عرض'}</button>
      <button class="action-btn" style="background:#dc3545; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem;" onclick="deleteClientAbstract(\${ab.id})">حذف</button>
    \`;`;
        lines[i+1] = '';
        lines[i+2] = '';
        lines[i+3] = '';
        lines[i+4] = '';
        lines[i+5] = '';
        lines[i+6] = '';
        replaced = true;
        break;
    }
}

if (replaced) {
    fs.writeFileSync('app_final.js', lines.join('\n'), 'utf8');
    console.log('Fixed buttons inside app_final.js!');
} else {
    console.log('Failed to find actions block!');
}



--- fix_client_buttons.js ---
const fs = require('fs');

let js = fs.readFileSync('app_final.js', 'utf8');

const jsFix = `
let replaceBlockMatch = js.match(/let actions = \\\`[\\s\\S]*?<button class="action-btn btn-danger" onclick="deleteClientAbstract\\(\\\\\\$\\{ab\\.id\\}\\)">حذف<\\/button>\\\` : ''\\}\\s*\\\`;/);
if (replaceBlockMatch) {
    let replaceBlock = replaceBlockMatch[0];
    let newBlock = \`let actions = \\\`
      <button class="action-btn" style="background:#6c757d; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; margin: 2px;" onclick="printClientAbstract(\\\${ab.id})">طباعة</button>
      \\\${ab.status === 'draft' ? \\\`<button class="action-btn" style="background:#28a745; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; margin: 2px;" onclick="approveClientAbstract(\\\${ab.id})">اعتماد</button>\\\` : ''}
      \\\${ab.status === 'approved' ? \\\`<button class="action-btn" style="background:#28a745; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; margin: 2px;" onclick="payClientAbstract(\\\${ab.id})">سند قبض</button>\\\` : ''}
      <button class="action-btn" style="background:#17a2b8; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; margin: 2px;" onclick="openClientAbstractModal(\\\${ab.id})">\\\${ab.status === 'draft' ? 'تعديل' : 'عرض'}</button>
      <button class="action-btn" style="background:#dc3545; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; margin: 2px;" onclick="deleteClientAbstract(\\\${ab.id})">حذف</button>
    \\\`;\`;
    js = js.replace(replaceBlock, newBlock);
    console.log("Found and replaced actions block.");
} else {
    // Attempt 2: More generic match
    let replaceBlockMatch2 = js.match(/let actions = \\\`[\\s\\S]*?deleteClientAbstract[\\s\\S]*?\\\`;/);
    if(replaceBlockMatch2) {
        let replaceBlock = replaceBlockMatch2[0];
        let newBlock = \`let actions = \\\`
      <button class="action-btn" style="background:#6c757d; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; margin: 2px;" onclick="printClientAbstract(\\\${ab.id})">طباعة</button>
      \\\${ab.status === 'draft' ? \\\`<button class="action-btn" style="background:#28a745; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; margin: 2px;" onclick="approveClientAbstract(\\\${ab.id})">اعتماد</button>\\\` : ''}
      \\\${ab.status === 'approved' ? \\\`<button class="action-btn" style="background:#28a745; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; margin: 2px;" onclick="payClientAbstract(\\\${ab.id})">سند قبض</button>\\\` : ''}
      <button class="action-btn" style="background:#17a2b8; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; margin: 2px;" onclick="openClientAbstractModal(\\\${ab.id})">\\\${ab.status === 'draft' ? 'تعديل' : 'عرض'}</button>
      <button class="action-btn" style="background:#dc3545; color:#fff; border:none; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; margin: 2px;" onclick="deleteClientAbstract(\\\${ab.id})">حذف</button>
    \\\`;\`;
        js = js.replace(replaceBlock, newBlock);
        console.log("Found and replaced actions block using generic match.");
    } else {
        console.log("Could not find the block in app_final.js at all!");
    }
}
`;

eval(jsFix);

fs.writeFileSync('app_final.js', js, 'utf8');
