/* ====================================================================
   বধুবরণ জুয়েলার্স ERP — Sales Module
   File: ui/js/sales.js
   v2.2 (2026-06-05):
     - FALLBACK_ACCOUNTS ঠিক করা (DB-র আসল id দিয়ে)
     - Gold rate auto-fill: আইটেম select হলে karat অনুযায়ী rate/ভরি বসে
     - Exchange rate-ও auto-fill হয়
     - FIX: API গ্রামে rate দেয়, ×11.664 করে ভরিতে convert করা হয়েছে
   ==================================================================== */

(function(){
'use strict';

const API_BASE = '../api/sales/';
const KARAT_PURITY = {'24K':100.000,'22K':91.667,'21K':87.500,'18K':75.000};

// DB-র আসল cash_accounts (id 1,2,3,4 — fallback শুধু API fail হলে)
const FALLBACK_ACCOUNTS = [
  {id:1, account_name:'শোরুম ক্যাশ'},
  {id:2, account_name:'ব্যাংক হিসাব'},
  {id:3, account_name:'bKash পার্সোনাল'},
  {id:4, account_name:'মেইন ক্যাশ (দোকান)'}
];

const state = {
  items: [], exchanges: [],
  payments: [{cash_account_id:1, amount:0, reference_no:''}],
  selectedItem: null, cashAccounts: [], searchSource: 'both',
  goldRates: null   // API থেকে load হওয়া rate
};

const $  = s => document.querySelector(s);
const $$ = s => document.querySelectorAll(s);

const fmtTk = n => '৳ ' + (Number(n)||0).toLocaleString('en-IN', {minimumFractionDigits:2, maximumFractionDigits:2});

// ===== ওজন: গ্রাম ↔ ভরি/আনা/রতি/পয়েন্ট =====
const POINT_G = 11.664 / 960;
const BN_DIGITS = ['০','১','২','৩','৪','৫','৬','৭','৮','৯'];
const toBn = n => String(n).replace(/[0-9]/g, d => BN_DIGITS[+d]);

function gramToVARP(gram){
  let pts = Math.round((Number(gram)||0) / POINT_G);
  if(pts < 0) pts = 0;
  const vori = Math.floor(pts/960); pts -= vori*960;
  const ana  = Math.floor(pts/60);  pts -= ana*60;
  const roti = Math.floor(pts/10);  pts -= roti*10;
  return {vori, ana, roti, point:pts};
}
function varpToGram(v,a,r,p){
  return ((v||0)*960+(a||0)*60+(r||0)*10+(p||0)) * POINT_G;
}
function varpText(gram){
  const w = gramToVARP(gram);
  return toBn(w.vori)+' ভরি '+toBn(w.ana)+' আনা '+toBn(w.roti)+' রতি '+toBn(w.point)+' পয়েন্ট';
}
const fmtW = g => { const grams=Number(g)||0; return grams.toFixed(3)+'g ('+varpText(grams)+')'; };

function syncGramToVARP(gramId){
  const row = document.querySelector('.varp-row[data-varp-for="'+gramId+'"]');
  if(!row) return;
  const w = gramToVARP(parseFloat($('#'+gramId).value)||0);
  row.querySelector('[data-varp="vori"]').value  = w.vori  || '';
  row.querySelector('[data-varp="ana"]').value   = w.ana   || '';
  row.querySelector('[data-varp="roti"]').value  = w.roti  || '';
  row.querySelector('[data-varp="point"]').value = w.point || '';
}
function syncVARPToGram(row){
  const gramId = row.getAttribute('data-varp-for');
  const g = varpToGram(
    parseInt(row.querySelector('[data-varp="vori"]').value,10),
    parseInt(row.querySelector('[data-varp="ana"]').value,10),
    parseInt(row.querySelector('[data-varp="roti"]').value,10),
    parseInt(row.querySelector('[data-varp="point"]').value,10)
  );
  $('#'+gramId).value = g ? g.toFixed(3) : '';
  return gramId;
}

function escapeHtml(s){
  if(s==null) return '';
  return String(s).replace(/[&<>"']/g, c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
}
function debounce(fn, ms){ let t; return (...a)=>{ clearTimeout(t); t=setTimeout(()=>fn(...a),ms); }; }
function toast(msg, type='info'){
  const t=$('#toast'); t.className='toast toast-'+type; t.textContent=msg;
  requestAnimationFrame(()=>t.classList.add('show'));
  clearTimeout(t._tm); t._tm=setTimeout(()=>t.classList.remove('show'),3500);
}
function openModal(id){ $('#'+id).classList.add('show'); }
function closeModal(id){ $('#'+id).classList.remove('show'); }

// ===== API =====
async function api(url, opts={}){
  try{ const res=await fetch(url,{credentials:'same-origin',...opts}); return await res.json(); }
  catch(e){ console.error('API error:',url,e); return {ok:false,error:'Network error'}; }
}

async function fetchInvoiceNo(){
  const r = await api(API_BASE+'get_next_invoice_no.php');
  if(r.ok) $('#invoiceNoTag').textContent = r.preview;
}

async function fetchCashAccounts(){
  for(const path of ['../api/cash/get_accounts.php','../api/cash/list_accounts.php','../api/cash/accounts.php']){
    try{
      const r = await api(path);
      if(r && r.ok && Array.isArray(r.accounts) && r.accounts.length){ state.cashAccounts=r.accounts; return; }
      if(Array.isArray(r) && r.length){ state.cashAccounts=r; return; }
    }catch(e){}
  }
  // Fallback: DB-র আসল account
  state.cashAccounts = FALLBACK_ACCOUNTS;
  toast('Account list সরাসরি load হয়নি, fallback ব্যবহার হচ্ছে','info');
}

// ===== Gold Rate Auto-fill (NEW) =====
async function fetchGoldRate(){
  try{
    const r = await api('../api/gold/get_rate.php');
    if(r && r.success && r.data){
      // API গ্রামে rate দেয় → ×11.664 করে ভরিতে convert
      state.goldRates = {
        '24K': Math.round((parseFloat(r.data.rate_24k)||0) * 11.664),
        '22K': Math.round((parseFloat(r.data.rate_22k)||0) * 11.664),
        '21K': Math.round((parseFloat(r.data.rate_21k)||0) * 11.664),
        '18K': Math.round((parseFloat(r.data.rate_18k)||0) * 11.664),
        rate_date: r.data.rate_date || ''
      };
      // Rate badge UI-তে দেখাই (যদি element থাকে)
      const badge = $('#goldRateBadge');
      if(badge && state.goldRates['22K']){
        badge.textContent = '22K: ৳'+Math.round(state.goldRates['22K']).toLocaleString('en-IN')+'/ভরি';
        badge.style.display='inline-block';
      }
    }
  }catch(e){
    console.warn('Gold rate fetch failed:', e);
  }
}

// karat দিলে সেই rate return করে (ভরি-তে)
function getRateByKarat(karat){
  if(!state.goldRates) return 0;
  return state.goldRates[karat] || state.goldRates['22K'] || 0;
}

// ===== গ্রাহক Search =====
const doCustomerSearch = debounce(async (q) => {
  const r = await api(`../api/sales/search_customers.php?q=${encodeURIComponent(q)}`);
  if(r.ok && r.customers && r.customers.length){
    renderCustomerDropdown(r.customers);
  } else {
    hideCustomerDropdown();
  }
}, 300);

function renderCustomerDropdown(customers){
  const el = $('#customerDropdown');
  el._customers = customers;
  el.innerHTML = customers.map((c,i) => `
    <div class="customer-item" data-cust-idx="${i}">
      <div class="c-name">${escapeHtml(c.name||'-')}</div>
      ${c.phone ? `<div class="c-phone">📞 ${escapeHtml(c.phone)}</div>` : ''}
    </div>
  `).join('');
  el.classList.remove('hidden');
}

function hideCustomerDropdown(){
  const el = $('#customerDropdown');
  if(el) el.classList.add('hidden');
}

function selectCustomer(idx){
  const el = $('#customerDropdown');
  const c  = el._customers && el._customers[idx];
  if(!c) return;
  $('#customerSearch').value = c.name + (c.phone ? ' — ' + c.phone : '');
  $('#customerName').value   = c.name  || '';
  $('#customerPhone').value  = c.phone || '';
  $('#customerId').value     = c.id;
  hideCustomerDropdown();
  toast(escapeHtml(c.name)+' নির্বাচিত ✓', 'success');
}

// ===== Item Search =====
const doSearch = debounce(async () => {
  const q = $('#itemSearchInput').value.trim();
  const url = `${API_BASE}search_items.php?q=${encodeURIComponent(q)}&source=${state.searchSource}&limit=20`;
  const r = await api(url);
  renderSearchResults(r.ok ? r.results : []);
}, 250);

function renderSearchResults(rows){
  const el = $('#itemSearchResults');
  if(!rows||!rows.length){ el.innerHTML='<div class="empty-state">কোন আইটেম পাওয়া যায়নি</div>'; el._rows=[]; return; }
  el.innerHTML = rows.map((r,idx)=>{
    const isBar = r.source_type==='barcode';
    return `<div class="search-result" data-idx="${idx}">
      <span class="badge ${isBar?'badge-barcode':'badge-newstock'}">${isBar?'Barcode':'Stock'}</span>
      <span class="item-name">${escapeHtml(r.product_name||'-')}</span>
      <div class="item-meta">
        ${isBar?'Barcode: '+escapeHtml(r.barcode||''):'Category: '+escapeHtml(r.category||'-')}
        • ${escapeHtml(r.karat||'-')} • ${fmtW(r.gross_weight_gram)}
        ${r.sale_price?'• '+fmtTk(r.sale_price):''}
      </div></div>`;
  }).join('');
  el._rows = rows;
}

function selectSearchResult(idx){
  const rows = $('#itemSearchResults')._rows;
  if(!rows||!rows[idx]) return;
  const r = rows[idx];
  state.selectedItem = r;
  $('#selectedItemTitle').textContent = (r.source_type==='barcode'?'Barcode':'Stock')+': '+(r.product_name||'-');
  $('#aiWeight').value = r.gross_weight_gram || '';
  syncGramToVARP('aiWeight');

  // ===== AUTO-FILL RATE =====
  // ১) barcode-এ sale_price থাকলে সেটা থেকে rate বের করো
  // ২) না থাকলে gold rate API থেকে karat অনুযায়ী দাও
  let autoRate = 0;
  if(r.source_type==='barcode' && r.sale_price && r.gross_weight_gram > 0){
    autoRate = Math.round((r.sale_price / r.gross_weight_gram) * 11.664);
  }
  if(!autoRate && r.karat){
    autoRate = Math.round(getRateByKarat(r.karat));
  }
  $('#aiRate').value = autoRate || '';

  $('#aiMaking').value = 0;
  $('#aiStone').value  = 0;
  if(r.source_type==='new_stock'){
    $('#aiQtyField').classList.remove('hidden'); $('#aiQty').value = 1;
  } else {
    $('#aiQtyField').classList.add('hidden');    $('#aiQty').value = 1;
  }
  $('#addItemForm').classList.remove('hidden');
  $('#itemSearchResults').classList.add('hidden');
  calcItemTotal();

  // Rate-এর উৎস জানিয়ে দাও
  if(autoRate){
    const src = (r.source_type==='barcode' && r.sale_price) ? 'বিদ্যমান মূল্য থেকে' : 'আজকের gold rate থেকে';
    toast('রেট auto-fill হয়েছে ('+src+')', 'info');
  }
}

function calcItemTotal(){
  const w=parseFloat($('#aiWeight').value)||0, rv=parseFloat($('#aiRate').value)||0;
  const m=parseFloat($('#aiMaking').value)||0, s=parseFloat($('#aiStone').value)||0;
  const total = (w/11.664)*rv + m + s;
  $('#aiTotal').textContent = fmtTk(total);
  return total;
}

function confirmAddItem(){
  const w=parseFloat($('#aiWeight').value)||0, rv=parseFloat($('#aiRate').value)||0;
  if(w<=0){ toast('ওজন দিন','error'); return; }
  if(rv<=0){ toast('রেট দিন','error'); return; }
  const qty=parseInt($('#aiQty').value)||1;
  const m=parseFloat($('#aiMaking').value)||0, s=parseFloat($('#aiStone').value)||0;
  const goldValue=(w/11.664)*rv, total=goldValue+m+s;
  const sel=state.selectedItem, purity=KARAT_PURITY[sel.karat]||null;
  state.items.push({
    source_type:sel.source_type,
    barcode_stock_id:sel.source_type==='barcode'?sel.id:null,
    new_stock_id:sel.source_type==='new_stock'?sel.id:null,
    product_name:sel.product_name, category:sel.category||null, barcode:sel.barcode||null,
    karat:sel.karat, purity_percent:purity,
    gross_weight_gram:w, stone_weight_gram:0, net_weight_gram:w,
    rate_per_gram:rv/11.664, rate_per_vori:rv,
    gold_value:goldValue, making_charge:m, stone_value:s, item_total:total, qty
  });
  state.selectedItem=null;
  $('#itemSearchInput').value='';
  $('#addItemForm').classList.add('hidden');
  $('#itemSearchResults').classList.remove('hidden');
  $('#itemSearchResults').innerHTML='';
  closeModal('itemSearchModal');
  renderItems(); recalc();
  toast('আইটেম যোগ হয়েছে','success');
}

function cancelAddItem(){
  state.selectedItem=null;
  $('#addItemForm').classList.add('hidden');
  $('#itemSearchResults').classList.remove('hidden');
}

function renderItems(){
  const el=$('#itemsList'), empty=$('#itemsEmpty');
  if(!state.items.length){ el.innerHTML=''; empty.classList.remove('hidden'); $('#itemCount').textContent=''; return; }
  empty.classList.add('hidden');
  $('#itemCount').textContent = state.items.length+'টি';
  el.innerHTML = state.items.map((it,i)=>`
    <div class="item-row">
      <div class="item-info">
        <div class="item-name">${escapeHtml(it.product_name)}
          ${it.qty>1?`<span class="badge badge-barcode" style="margin-left:6px;">${it.qty}পিস</span>`:''}
        </div>
        <div class="item-meta">
          ${escapeHtml(it.karat||'-')} • ${fmtW(it.gross_weight_gram)}<br>
          × ৳${Math.round(it.rate_per_vori||0).toLocaleString('en-IN')}/ভরি
          ${it.making_charge?' + Mk ৳'+it.making_charge:''}
        </div>
      </div>
      <div class="item-total num">${fmtTk(it.item_total)}</div>
      <button class="remove-btn" data-action="remove-item" data-idx="${i}">×</button>
    </div>`).join('');
}
function removeItem(i){ state.items.splice(i,1); renderItems(); recalc(); }

// ===== Exchange =====
function toggleExchangeForm(){
  const f=$('#exchangeForm'); f.classList.toggle('hidden');
  $('#toggleExchange').textContent = f.classList.contains('hidden')?'যোগ করুন +':'বন্ধ করুন ×';
  // Exchange form খুললে rate auto-fill
  if(!f.classList.contains('hidden')){
    const k=$('#exKarat').value;
    if(!$('#exRate').value && state.goldRates){
      const r=Math.round(getRateByKarat(k));
      if(r){ $('#exRate').value=r; toast('Exchange রেট auto-fill ('+k+')', 'info'); }
    }
  }
}
function addExchange(){
  const k=$('#exKarat').value, p=parseFloat($('#exPurity').value)||0;
  const w=parseFloat($('#exWeight').value)||0, rv=parseFloat($('#exRate').value)||0;
  const d=$('#exDesc').value.trim();
  if(w<=0){ toast('ওজন দিন','error'); return; }
  if(rv<=0){ toast('রেট দিন','error'); return; }
  const pureG=w*(p/100), value=(pureG/11.664)*rv;
  state.exchanges.push({karat:k,purity_percent:p,gross_weight_gram:w,pure_gold_gram:pureG,
    rate_per_gram:rv/11.664,rate_per_vori:rv,exchange_value:value,item_description:d||null,goes_to_old_gold_stock:1});
  $('#exWeight').value=''; syncGramToVARP('exWeight');
  $('#exRate').value=''; $('#exDesc').value='';
  renderExchanges(); recalc(); toast('Exchange যোগ হয়েছে','success');
}
function renderExchanges(){
  const el=$('#exchangeList');
  if(!state.exchanges.length){ el.innerHTML=''; return; }
  el.innerHTML = state.exchanges.map((ex,i)=>`
    <div class="item-row">
      <div class="item-info">
        <div class="item-name">${escapeHtml(ex.item_description||'পুরনো সোনা')}</div>
        <div class="item-meta">
          ${escapeHtml(ex.karat)} (${ex.purity_percent}%) • ${fmtW(ex.gross_weight_gram)}<br>
          → pure ${fmtW(ex.pure_gold_gram)} × ৳${Math.round(ex.rate_per_vori||0).toLocaleString('en-IN')}/ভরি
        </div>
      </div>
      <div class="item-total num" style="color:var(--red);">−${fmtTk(ex.exchange_value)}</div>
      <button class="remove-btn" data-action="remove-exchange" data-idx="${i}">×</button>
    </div>`).join('');
}
function removeExchange(i){ state.exchanges.splice(i,1); renderExchanges(); recalc(); }
function updateExPurity(){
  const k=$('#exKarat').value;
  if(KARAT_PURITY[k]) $('#exPurity').value=KARAT_PURITY[k];
  // Karat বদলালে rate-ও update করো
  if(state.goldRates){
    const r=Math.round(getRateByKarat(k));
    if(r) $('#exRate').value=r;
  }
}

// ===== Payment =====
function renderPayments(){
  const el=$('#paymentsList');
  if(!state.cashAccounts.length){ el.innerHTML='<div class="empty-state">Account load হচ্ছে<span class="dots"></span></div>'; return; }
  el.innerHTML = state.payments.map((p,i)=>`
    <div class="pay-row">
      <select data-field="cash_account_id" data-idx="${i}">
        ${state.cashAccounts.map(a=>`<option value="${a.id}" ${a.id==p.cash_account_id?'selected':''}>${escapeHtml(a.account_name)}</option>`).join('')}
      </select>
      <input type="number" step="0.01" placeholder="0.00" class="num" data-field="amount" data-idx="${i}" value="${p.amount||''}">
      ${state.payments.length>1?`<button class="remove-btn" data-action="remove-payment" data-idx="${i}">×</button>`:''}
    </div>`).join('');
}
function addPayment(){ state.payments.push({cash_account_id:state.cashAccounts[0]?.id||1,amount:0,reference_no:''}); renderPayments(); }
function removePayment(i){ state.payments.splice(i,1); renderPayments(); recalc(); }
function updatePayment(idx,field,value){
  if(!state.payments[idx]) return;
  if(field==='cash_account_id') state.payments[idx].cash_account_id=parseInt(value,10);
  else if(field==='amount') state.payments[idx].amount=parseFloat(value)||0;
  recalc();
}

// ===== Recalculate =====
function recalc(){
  const itemsSub=state.items.reduce((s,i)=>s+(i.item_total||0),0);
  const exVal=state.exchanges.reduce((s,e)=>s+(e.exchange_value||0),0);
  const making=parseFloat($('#makingCharge').value)||0;
  const discount=parseFloat($('#discount').value)||0;
  const vatPct=parseFloat($('#vatPercent').value)||0;
  const vatAmt=(itemsSub+making)*vatPct/100;
  let grand=itemsSub+making+vatAmt-discount-exVal; if(grand<0) grand=0;
  const paid=state.payments.reduce((s,p)=>s+(parseFloat(p.amount)||0),0);
  $('#sumItems').textContent=fmtTk(itemsSub); $('#sumVat').textContent=fmtTk(vatAmt);
  $('#sumExchange').textContent=exVal>0?'− '+fmtTk(exVal):'৳ 0.00';
  $('#sumGrand').textContent=fmtTk(grand); $('#sumPaid').textContent=fmtTk(paid);
  $('#sumDue').textContent=fmtTk(Math.max(0,grand-paid));
}

// ===== Submit =====
async function submitSale(){
  if(!state.items.length){ toast('কমপক্ষে একটি item যোগ করুন','error'); return; }
  const validPayments=state.payments.filter(p=>(parseFloat(p.amount)||0)>0);
  if(!validPayments.length){ toast('পেমেন্ট amount দিন','error'); return; }
  const btn=$('#btnSubmit'); btn.disabled=true; const oldText=btn.textContent; btn.textContent='Save হচ্ছে...';
  const dt=$('#saleDate').value;
  const r = await api(API_BASE+'create_sale.php',{
    method:'POST', headers:{'Content-Type':'application/json'},
    body:JSON.stringify({
      customer_id:$('#customerId').value?parseInt($('#customerId').value,10):null,
      customer_name:$('#customerName').value.trim(),
      customer_phone:$('#customerPhone').value.trim(),
      sale_date:dt?dt.replace('T',' ')+':00':'',
      items:state.items, exchanges:state.exchanges, payments:validPayments,
      making_charge_total:parseFloat($('#makingCharge').value)||0,
      vat_percent:parseFloat($('#vatPercent').value)||0,
      discount_amount:parseFloat($('#discount').value)||0,
      notes:$('#notes').value.trim()
    })
  });
  btn.disabled=false; btn.textContent=oldText;
  if(r.ok){
    toast('✓ '+(r.invoice_no||'Saved')+' সংরক্ষিত','success');
    setTimeout(()=>{ if(confirm('✓ '+r.invoice_no+' সফল!\nনতুন বিক্রি শুরু করবেন?')) location.reload(); },800);
  } else { toast(r.error||'Save fail','error'); }
}

// ===== Event Delegation =====
document.addEventListener('click', e => {
  const t = e.target;

  if(!t.closest('#customerDropdown') && !t.matches('#customerSearch')){
    hideCustomerDropdown();
  }

  const ci = t.closest('.customer-item');
  if(ci) return selectCustomer(parseInt(ci.dataset.custIdx, 10));

  if(t.matches('[data-close]')) return closeModal(t.getAttribute('data-close'));
  if(t.matches('.modal-bg') && t.id) return closeModal(t.id);

  if(t.matches('#btnAddItem')){
    $('#addItemForm').classList.add('hidden');
    $('#itemSearchResults').classList.remove('hidden');
    $('#itemSearchInput').value=''; $('#itemSearchResults').innerHTML='';
    openModal('itemSearchModal');
    setTimeout(()=>$('#itemSearchInput').focus(),100);
    doSearch(); return;
  }

  const sr = t.closest('.search-result');
  if(sr){ selectSearchResult(parseInt(sr.dataset.idx,10)); return; }

  if(t.classList.contains('source-tab')){
    $$('.source-tab').forEach(x=>x.classList.remove('active'));
    t.classList.add('active'); state.searchSource=t.dataset.source; doSearch(); return;
  }

  if(t.matches('#btnConfirmAddItem')) return confirmAddItem();
  if(t.matches('#btnCancelAddItem'))  return cancelAddItem();
  if(t.matches('[data-action="remove-item"]'))     return removeItem(parseInt(t.dataset.idx,10));
  if(t.matches('#toggleExchange'))                 return toggleExchangeForm();
  if(t.matches('#btnAddExchange'))                 return addExchange();
  if(t.matches('[data-action="remove-exchange"]')) return removeExchange(parseInt(t.dataset.idx,10));
  if(t.matches('#btnAddPayment'))                  return addPayment();
  if(t.matches('[data-action="remove-payment"]'))  return removePayment(parseInt(t.dataset.idx,10));
  if(t.matches('#btnSubmit'))                      return submitSale();
});

document.addEventListener('input', e => {
  const t = e.target;

  if(t.matches('#customerSearch')){
    $('#customerId').value='';
    $('#customerName').value=''; $('#customerPhone').value='';
    doCustomerSearch(t.value.trim());
    return;
  }

  if(t.matches('.varp-row [data-varp]')){
    const gramId=syncVARPToGram(t.closest('.varp-row'));
    if(gramId==='aiWeight') calcItemTotal(); return;
  }
  if(t.matches('#itemSearchInput'))             return doSearch();
  if(t.matches('#aiWeight'))                    { syncGramToVARP('aiWeight'); return calcItemTotal(); }
  if(t.matches('#aiRate, #aiMaking, #aiStone')) return calcItemTotal();
  if(t.matches('#exWeight'))                    { syncGramToVARP('exWeight'); return; }
  if(t.matches('#makingCharge, #discount, #vatPercent')) return recalc();
  if(t.matches('[data-field="cash_account_id"], [data-field="amount"]')){
    return updatePayment(parseInt(t.dataset.idx,10),t.dataset.field,t.value);
  }
});

document.addEventListener('change', e => {
  if(e.target.matches('#exKarat')) updateExPurity();
});

// ===== Init =====
async function init(){
  const now=new Date(); now.setMinutes(now.getMinutes()-now.getTimezoneOffset());
  $('#saleDate').value=now.toISOString().slice(0,16);
  // সব একসাথে load করো
  await Promise.all([fetchInvoiceNo(), fetchCashAccounts(), fetchGoldRate()]);
  if(state.cashAccounts.length) state.payments=[{cash_account_id:state.cashAccounts[0].id,amount:0,reference_no:''}];
  renderItems(); renderExchanges(); renderPayments(); recalc();
}
init();

})();
