// SLAB CUTTING
function sqftFromMM(L, W){ const sqft = (Number(L||0)/304.8) * (Number(W||0)/304.8); return isFinite(sqft) ? sqft : 0; }

// Populate the Supplier modal payment terms dropdown from payment_terms table
function loadSupplierPaymentTermsDropdown(selected) {
  $.get('api/payment_terms.php', { action: 'list' }, function(res){
    const sel = $('#payment_terms').empty();
    sel.append('<option value=""></option>');
    (res.data || []).forEach(x => {
      const nm = escapeHtml(x.name || '');
      sel.append(`<option value="${nm}">${nm}</option>`);
    });
    if (selected != null) sel.val(String(selected));
  });
}

function loadExpPaymentTermsDropdown(selected, done) {
  $.get('api/payment_terms.php', { action: 'list' }, function(res){
    const sel = $('#exp_payment').empty();
    sel.append('<option value="">Select Method</option>');
    (res.data || []).forEach(x => {
      const nm = escapeHtml(x.name || '');
      sel.append(`<option value="${nm}">${nm}</option>`);
    });
    if (selected != null) sel.val(String(selected));
    if (done) done();
  });
}
function loadCutSources(){
  const type = $('#source_type').val() || 'raw';
  const q = ($('#source_search').val()||'').trim();
  $.get('api/slab_cutting.php', { action:'list_sources', type, q }, function(res){
    const sel = $('#source_id').empty();
    const rows = res.data||[];
    if (!rows.length) { sel.append('<option value="">No results</option>'); return; }
    rows.forEach(s => {
      const parts = [];
      parts.push(escapeHtml(s.code||''));
      if (s.slab_no) parts.push(`SLAB: ${escapeHtml(s.slab_no)}`);
      if (s.finish_name) parts.push(`Finish: ${escapeHtml(s.finish_name)}`);
      if (s.po_no) parts.push(`PO: ${escapeHtml(s.po_no)}`);
      parts.push(`${Math.round(s.length_mm||0)}x${Math.round(s.width_mm||0)} mm`);
      const label = parts.join(' | ');
      // attach parent area for cut_piece to validate client-side
      let extra = '';
      if (($('#source_type').val()||'') === 'cut_piece'){
        const area = sqftFromMM(s.length_mm, s.width_mm);
        extra = ` data-area-sqft="${area}"`;
      }
      sel.append(`<option value="${s.id}"${extra}>${label}</option>`);
    });
  });
}
function fetchCutPieces(){
  $.get('api/slab_cutting.php', { action:'list_pieces' }, function(res){
    const tbody = $('#cut-pieces-table tbody').empty();
    const rows = res.data || [];
    if (!rows.length) { tbody.append('<tr><td colspan="6" class="text-center text-muted">No cut pieces</td></tr>'); return; }
    rows.forEach(p => {
      const tr = $('<tr>');
      tr.append(`<td>${p.id}</td>`);
      tr.append(`<td>${p.job_id}</td>`);
      tr.append(`<td>${p.piece_no}</td>`);
      tr.append(`<td>${Math.round(p.length_mm)} x ${Math.round(p.width_mm)}</td>`);
      tr.append(`<td>${Number(p.area_sq_ft||0).toFixed(3)}</td>`);
      tr.append(`<td>${parseInt(p.is_available)?'Yes':'No'}</td>`);
        tbody.append(tr);
      });
    })
    .fail(function(xhr, text){
      const tbody = $('#po-table tbody').empty();
      let msg = 'Failed to load purchase orders';
      if (xhr && xhr.responseText) {
        // show the first line of response for quick hint
        const firstLine = xhr.responseText.split('\n')[0].slice(0,200);
        msg += `: ${firstLine}`;
      } else if (text) { msg += `: ${text}`; }
      tbody.append(`<tr><td colspan="7" class="text-center text-danger">${escapeHtml(msg)}</td></tr>`);
      console.error('PO list error:', text, xhr);
    });
}
function fetchCutJobs(){
  $.get('api/slab_cutting.php', { action:'list_jobs' }, function(res){
    const tbody = $('#cut-jobs-table tbody').empty();
    const rows = res.data || [];
    if (!rows.length) { tbody.append('<tr><td colspan="6" class="text-center text-muted">No jobs</td></tr>'); return; }
    rows.forEach(j => {
      const tr = $('<tr>');
      tr.append(`<td>${j.id}</td>`);
      tr.append(`<td>${escapeHtml(j.job_date||'')}</td>`);
      tr.append(`<td>${escapeHtml(j.source_type)}-${j.source_id}</td>`);
      tr.append(`<td>${escapeHtml(j.operator_name||'')}</td>`);
      tr.append(`<td>${escapeHtml(j.status||'')}</td>`);
      tr.append(`<td><button class="btn btn-sm btn-outline-danger btn-cut-job-del" data-id="${j.id}"><i class="bi bi-trash"></i></button></td>`);
      tbody.append(tr);
    });
  });
}
function slabsInitPiecesTable(){
  const $tb = $('#piecesTable tbody');
  function renumber(){
    $tb.find('tr').each(function(i){ $(this).find('.row-no').text(i+1); });
  }
  function recalcRow($tr){
    const L = parseFloat($tr.find('.len').val()||'0');
    const W = parseFloat($tr.find('.wid').val()||'0');
    const area = sqftFromMM(L,W);
    $tr.find('.area').text(area.toFixed(3));
    recalcTotal();
  }
  function recalcTotal(){
    let tot=0; $tb.find('tr').each(function(){ tot += parseFloat($(this).find('.area').text()||'0'); });
    $('#piecesTotal').text(tot.toFixed(3));
  }
  function addRow(L='',W=''){
    const tr = $(`<tr>
      <td class="text-center row-no"></td>
      <td><input type="number" step="0.1" class="form-control form-control-sm len" value="${L}"></td>
      <td><input type="number" step="0.1" class="form-control form-control-sm wid" value="${W}"></td>
      <td class="text-end"><span class="area">0.000</span></td>
      <td class="text-center"><button type="button" class="btn btn-sm btn-outline-danger btn-del-piece">×</button></td>
    </tr>`);
    $tb.append(tr); renumber(); recalcRow(tr);
  }
  // expose within module
  window._sc_addPieceRow = addRow;
  // default one row
  if ($tb.children().length===0) addRow();
  $tb.on('input','.len,.wid',function(){ recalcRow($(this).closest('tr')); });
  $tb.on('click','.btn-del-piece',function(){ $(this).closest('tr').remove(); renumber(); recalcTotal(); if($tb.children().length===0) addRow(); });
}

function bindSlabCuttingEvents(){
  $('#source_type').on('change', loadCutSources);
  $('#source_search').on('input', function(){
    // debounce quick search
    clearTimeout(window._sc_src_t);
    window._sc_src_t = setTimeout(loadCutSources, 250);
  });
  $('#btnRefreshSources').on('click', loadCutSources);
  $('#btnAddPiece').on('click', function(){ if (typeof window._sc_addPieceRow==='function') window._sc_addPieceRow(); });
  $('#btnClearPieces').on('click', function(){ const $tb=$('#piecesTable tbody'); $tb.empty(); if (typeof window._sc_addPieceRow==='function') window._sc_addPieceRow(); $('#piecesTotal').text('0.000'); });
  $('#btnRefreshPieces').on('click', fetchCutPieces);
  $('#btnClearCutForm').on('click', function(){ $('#cutJobForm')[0].reset(); $('#piecesTable tbody').empty(); if (typeof window._sc_addPieceRow==='function') window._sc_addPieceRow(); $('#piecesTotal').text('0.000'); loadCutSources(); });
  $('#cutJobForm').on('submit', function(e){
    e.preventDefault();
    // collect pieces
    const pieces = [];
    $('#piecesTable tbody tr').each(function(i){
      const L = parseFloat($(this).find('.len').val()||'0');
      const W = parseFloat($(this).find('.wid').val()||'0');
      if (L>0 && W>0) pieces.push({ piece_no: i+1, length_mm: L, width_mm: W });
    });
    if (pieces.length === 0){
      alert('Add at least one piece with valid Length and Width (mm).');
      return;
    }
    // client-side validation for re-cut: total <= parent area
    const srcType = ($('#source_type').val()||'');
    if (srcType === 'cut_piece'){
      const parentArea = parseFloat($('#source_id option:selected').data('areaSqft')||'0');
      const newTotal = pieces.reduce((sum,p)=> sum + sqftFromMM(p.length_mm, p.width_mm), 0);
      if (parentArea>0 && newTotal - parentArea > 1e-6){
        alert(`Total new area (${newTotal.toFixed(3)} sqft) exceeds parent piece area (${parentArea.toFixed(3)} sqft).`);
        return;
      }
    }
    const data = $(this).serializeArray();
    const payload = {};
    data.forEach(x=>payload[x.name]=x.value);
    payload['pieces_json'] = JSON.stringify(pieces);
    $.post('api/slab_cutting.php?action=create_job', payload, function(){
      fetchCutPieces(); fetchCutJobs(); $('#cutJobForm')[0].reset(); $('#piecesTable tbody').empty(); if (typeof window._sc_addPieceRow==='function') window._sc_addPieceRow(); $('#piecesTotal').text('0.000');
    }).fail(function(xhr){ alert(xhr.responseJSON?.message || 'Error'); });
  });
}
// Ensure escapeHtml is defined early for all modules
if (typeof window.escapeHtml !== 'function') {
  window.escapeHtml = function(text) {
    return $('<div/>').text(text ?? '').html();
  };
}
if (typeof escapeHtml !== 'function') {
  var escapeHtml = window.escapeHtml;
}

// CUSTOMERS
function fetchCustomers(){
  const q = $('#custSearch').val() || '';
  $.get('api/customers.php', { action:'list', q }, function(res){
    const tbody = $('#customers-table tbody').empty();
    const rows = res.data || [];
    if (!rows.length) { tbody.append('<tr><td colspan="9" class="text-center text-muted">No customers</td></tr>'); return; }
    rows.forEach((c, i) => {
      const tr = $('<tr>');
      tr.append(`<td>${c.id}</td>`);
      tr.append(`<td>${escapeHtml(c.name||'')}</td>`);
      tr.append(`<td>${escapeHtml(c.company_name||'')}</td>`);
      tr.append(`<td>${escapeHtml(c.phone||'')}</td>`);
      tr.append(`<td>${escapeHtml(c.email||'')}</td>`);
      tr.append(`<td>${escapeHtml(c.city||'')}</td>`);
      tr.append(`<td>${escapeHtml(c.country||'')}</td>`);
      tr.append(`<td>${escapeHtml(c.gst_no||'')}</td>`);
      tr.append(`<td>
        <button class="btn btn-sm btn-primary me-2 btn-cust-edit" data-id="${c.id}"><i class="bi bi-pencil-square"></i></button>
        <button class="btn btn-sm btn-danger btn-cust-delete" data-id="${c.id}"><i class="bi bi-trash"></i></button>
      </td>`);
      tbody.append(tr);
    });
  });
}

function bindCustomersEvents(){
  $('#btnCustSearch').on('click', fetchCustomers);
  $('#custSearch').on('keyup', function(e){ if (e.key === 'Enter') fetchCustomers(); });

  $('#btnAddCustomer').on('click', function(){
    $('#customerForm')[0].reset();
    $('#customerId').val('');
    $('#customerModal').modal('show');
  });

  $('#customers-table').on('click', '.btn-cust-edit', function(){
    const id = $(this).data('id');
    $.get('api/customers.php', { action:'get', id }, function(res){
      const c = res.data || {};
      $('#customerId').val(c.id||'');
      $('#cust_name').val(c.name||'');
      $('#company_name').val(c.company_name||'');
      $('#cust_phone').val(c.phone||'');
      $('#cust_email').val(c.email||'');
      $('#cust_address').val(c.address||'');
      $('#cust_city').val(c.city||'');
      $('#cust_state').val(c.state||'');
      $('#cust_country').val(c.country||'');
      $('#gst_no').val(c.gst_no||'');
      $('#customerModal').modal('show');
    });
  });

  $('#customers-table').on('click', '.btn-cust-delete', function(){
    if(!confirm('Delete this customer?')) return;
    const id = $(this).data('id');
    $.post('api/customers.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchCustomers(); });
  });

  $('#customerForm').on('submit', function(e){
    e.preventDefault();
    const hasId = !!$('#customerId').val();
    const data = $(this).serialize();
    $.post('api/customers.php?action='+(hasId?'update':'create'), data, function(){
      $('#customerModal').modal('hide');
      fetchCustomers();
    }).fail(function(xhr){ alert(xhr.responseJSON?.message || 'Error'); });
  });
}
// Global app JS
$(function () {
  // Sidebar collapse / expand
  (function(){
    try{
      const KEY = 'sidebar_collapsed_v1';
      const btn = document.getElementById('btnSidebarToggle');
      const apply = (collapsed) => {
        document.body.classList.toggle('sidebar-collapsed', !!collapsed);
        try { localStorage.setItem(KEY, collapsed ? '1' : '0'); } catch(e) {}
        // help DataTables / layouts recalc widths
        window.dispatchEvent(new Event('resize'));
      };
      let collapsed = false;
      try { collapsed = localStorage.getItem(KEY) === '1'; } catch(e) {}
      apply(collapsed);
      if (btn){
        btn.addEventListener('click', function(){
          collapsed = !document.body.classList.contains('sidebar-collapsed');
          apply(collapsed);
        });
      }
    }catch(e){}
  })();

  // Toast helper
  window.showToast = function(message, type){
    try{
      const container = document.getElementById('appToastContainer');
      if (!container) return alert(message);
      const id = 't_'+Date.now()+Math.random().toString(16).slice(2);
      const bg = (type==='success')?'bg-success':(type==='error'||type==='danger')?'bg-danger':(type==='warning')?'bg-warning text-dark':'bg-secondary';
      const el = document.createElement('div');
      el.className = 'toast align-items-center text-white '+bg;
      el.id = id;
      el.setAttribute('role','alert'); el.setAttribute('aria-live','assertive'); el.setAttribute('aria-atomic','true');
      el.innerHTML = `
        <div class="d-flex">
          <div class="toast-body">${$('<div>').text(String(message||'')).html()}</div>
          <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
        </div>`;
      container.appendChild(el);
      const toast = new bootstrap.Toast(el, { delay: 3000 });
      toast.show();
      el.addEventListener('hidden.bs.toast', ()=>{ el.remove(); });
    }catch(e){ /* fallback */ alert(message); }
  }

  // Global AJAX notifications
  $(document).ajaxSuccess(function(event, xhr, settings, data){
    try{
      const method = (settings.type||settings.method||'GET').toUpperCase();
      if (method === 'POST' && data && (data.message || data.msg)) {
        window.showToast(data.message || data.msg, 'success');
      }
    }catch(e){}
  });
  $(document).ajaxError(function(event, xhr){
    try{
      const msg = (xhr && xhr.responseJSON && (xhr.responseJSON.message||xhr.responseJSON.error)) || 'Request failed';
      window.showToast(msg, 'danger');
    }catch(e){}
  });
  // Activate current menu link based on URL
  const params = new URLSearchParams(window.location.search);
  const page = params.get('page') || 'dashboard';
  $("a.nav-link").each(function () {
    const href = new URL($(this).attr('href'), window.location.origin);
    const hp = new URLSearchParams(href.search).get('page');
    if ((hp || 'dashboard') === page) {
      $(this).addClass('active');
    }
  });

  // Polishing: Complete modal live area calc from inches (SQ.FT and SQ.M)
  if (page === 'polishing') {
    function pjCalcFinalArea(){
      const $h = $("#pjCompleteForm [name='final_height']");
      const $l = $("#pjCompleteForm [name='final_length']");
      const hIn = parseFloat($h.val()||'0');
      const lIn = parseFloat($l.val()||'0');
      const hFt = (isNaN(hIn)?0:hIn)/12.0;
      const lFt = (isNaN(lIn)?0:lIn)/12.0;
      const sqft = (hFt*lFt) || 0;
      const sqm = sqft * 0.092903;
      const $wrap = $('#pj_final_area_wrap');
      if ($wrap.length) {
        $wrap.find('.pj-final-sqft').text(sqft.toFixed(3));
        $wrap.find('.pj-final-sqm').text(sqm.toFixed(3));
      } else {
        const ui = `
          <div id="pj_final_area_wrap" class="mt-2 small text-muted">
            Area: <strong class="pj-final-sqft">${sqft.toFixed(3)}</strong> sq.ft / <strong class="pj-final-sqm">${sqm.toFixed(3)}</strong> sq.m
          </div>`;
        $("#pjCompleteForm [name='finish_id']").closest('.col-12').before(ui);
      }
    }
    $(document).on('input', "#pjCompleteForm [name='final_height'], #pjCompleteForm [name='final_length']", pjCalcFinalArea);
    $('#pjCompleteModal').on('shown.bs.modal', function(){ pjCalcFinalArea(); });
  }

function fetchIncentives(){
  const d = new Date();
  const month = $('#pay_month').val() || (d.getMonth()+1);
  const year = $('#pay_year').val() || d.getFullYear();
  $.get('api/salary_incentives.php',{ action:'list', month, year }, function(res){
    const tbody = $('#inc-table tbody').empty();
    (res.data||[]).forEach(i => {
      const tr = $('<tr>');
      tr.append(`<td>${escapeHtml(formatDate(i.inc_date))}</td>`);
      tr.append(`<td>${escapeHtml(i.employee_name || '')}</td>`);
      tr.append(`<td>${formatCurrency(i.amount || 0)}</td>`);
      tr.append(`<td>${escapeHtml(i.reason || '')}</td>`);
      tr.append(`<td><button class="btn btn-sm btn-danger btn-inc-delete" data-id="${i.id}"><i class="bi bi-trash"></i></button></td>`);
      tbody.append(tr);
    });
  });
}

function fetchAllowances(){
  const d = new Date();
  const month = $('#pay_month').val() || (d.getMonth()+1);
  const year = $('#pay_year').val() || d.getFullYear();
  $.get('api/salary_allowances.php',{ action:'list', month, year }, function(res){
    const tbody = $('#all-table tbody').empty();
    (res.data||[]).forEach(a => {
      const tr = $('<tr>');
      tr.append(`<td>${escapeHtml(formatDate(a.all_date))}</td>`);
      tr.append(`<td>${escapeHtml(a.employee_name || '')}</td>`);
      tr.append(`<td>${formatCurrency(a.amount || 0)}</td>`);
      tr.append(`<td>${escapeHtml(a.reason || '')}</td>`);
      tr.append(`<td><button class="btn btn-sm btn-danger btn-all-delete" data-id="${a.id}"><i class="bi bi-trash"></i></button></td>`);
      tbody.append(tr);
    });
  });
}
// SALARY MANAGEMENT
window.EMP_CACHE = [];
function fetchEmployees(done){
  $.get('api/employees.php',{ action:'list' }, function(res){
    window.EMP_CACHE = res.data || [];
    // Let page-level script render the employees table; only refresh dependent selects here
    refreshEmployeeSelects();
    if (done) done();
    $(document).trigger('employees:updated');
  });
}

function refreshEmployeeSelects(){
  const s1 = $('#adv_emp').empty();
  const s2 = $('#ded_emp').empty();
  const s3 = $('#inc_emp').empty();
  const s4 = $('#all_emp').empty();
  s1.append('<option value="">Select Employee</option>');
  s2.append('<option value="">Select Employee</option>');
  s3.append('<option value="">Select Employee</option>');
  s4.append('<option value="">Select Employee</option>');
  window.EMP_CACHE.forEach(e => {
    const opt = `<option value="${e.id}">${escapeHtml(e.full_name)}</option>`;
    s1.append(opt);
    s2.append(opt);
    s3.append(opt);
    s4.append(opt);
  });
}

function fetchAdvances(){
  const d = new Date();
  const month = $('#pay_month').val() || (d.getMonth()+1);
  const year = $('#pay_year').val() || d.getFullYear();
  $.get('api/salary_advances.php',{ action:'list', month, year }, function(res){
    const tbody = $('#adv-table tbody').empty();
    (res.data||[]).forEach(a => {
      const tr = $('<tr>');
      tr.append(`<td>${escapeHtml(formatDate(a.adv_date))}</td>`);
      tr.append(`<td>${escapeHtml(a.employee_name || '')}</td>`);
      tr.append(`<td>${formatCurrency(a.amount || 0)}</td>`);
      tr.append(`<td>${escapeHtml(a.notes || '')}</td>`);
      tr.append(`<td><button class="btn btn-sm btn-danger btn-adv-delete" data-id="${a.id}"><i class="bi bi-trash"></i></button></td>`);
      tbody.append(tr);
    });
  });
}

function fetchDeductions(){
  $.get('api/salary_deductions.php',{ action:'list' }, function(res){
    const tbody = $('#ded-table tbody').empty();
    (res.data||[]).forEach(d => {
      const tr = $('<tr>');
      tr.append(`<td>${escapeHtml(formatDate(d.ded_date))}</td>`);
      tr.append(`<td>${escapeHtml(d.employee_name || '')}</td>`);
      tr.append(`<td>${formatCurrency(d.amount || 0)}</td>`);
      tr.append(`<td>${escapeHtml(d.reason || '')}</td>`);
      tr.append(`<td><button class="btn btn-sm btn-danger btn-ded-delete" data-id="${d.id}"><i class="bi bi-trash"></i></button></td>`);
      tbody.append(tr);
    });
  });
}

function bindSalaryEvents(){
  // Employees table is managed by page-level script to avoid column mismatch.
  // Keep only advances/deductions/payroll bindings here.
  // Advances
  $('#btnAddAdvance, #btnAddAdvanceCard').on('click', function(){ refreshEmployeeSelects(); $('#advForm')[0].reset(); $('#advId').val(''); $('#advModal').modal('show'); });
  $('#advForm').on('submit', function(e){ e.preventDefault(); const data=$(this).serialize(); $.post('api/salary_advances.php?action=create', data, function(){ $('#advModal').modal('hide'); fetchAdvances(); }); });
  $('#adv-table').on('click', '.btn-adv-delete', function(){ if(!confirm('Delete this advance?')) return; const id=$(this).data('id'); $.post('api/salary_advances.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchAdvances(); }); });

  // Deductions
  $('#btnAddDeduction, #btnAddDeductionCard').on('click', function(){ refreshEmployeeSelects(); $('#dedForm')[0].reset(); $('#dedId').val(''); $('#dedModal').modal('show'); });
  $('#dedForm').on('submit', function(e){ e.preventDefault(); const data=$(this).serialize(); $.post('api/salary_deductions.php?action=create', data, function(){ $('#dedModal').modal('hide'); fetchDeductions(); }); });
  $('#ded-table').on('click', '.btn-ded-delete', function(){ if(!confirm('Delete this deduction?')) return; const id=$(this).data('id'); $.post('api/salary_deductions.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchDeductions(); }); });

  // Payroll
  $('#btnGeneratePayroll').on('click', function(){
    const month=$('#pay_month').val(), year=$('#pay_year').val();
    $.post('api/salary_payroll.php?action=generate', { month, year, csrf: $('#csrf').val() }, function(){ fetchPayroll(); });
  });
  $('#pay_month, #pay_year').on('change', fetchPayroll);
  $('#pay_month, #pay_year').on('change', fetchIncentives);
  $('#pay_month, #pay_year').on('change', fetchAllowances);
  $('#pay_month, #pay_year').on('change', fetchAdvances);
  $('#payroll-table').on('click', '.btn-pay-mark', function(){ const id=$(this).data('id'); $.post('api/salary_payroll.php?action=mark_paid', { id, csrf: $('#csrf').val() }, function(){ fetchPayroll(); }); });
  $('#payroll-table').on('click', '.btn-payroll-delete', function(){
    if(!confirm('Delete this payroll entry?')) return;
    const id=$(this).data('id');
    $.post('api/salary_payroll.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchPayroll(); });
  });
  $('#btnExportPayroll').on('click', function(){ exportPayrollCsv(); });
  // Monthly Report
  $('#btnPayrollReport').on('click', function(){
    const month=$('#pay_month').val(), year=$('#pay_year').val();
    // Ensure latest payroll loaded
    $.get('api/salary_payroll.php', { action:'list', month, year }, function(res){
      const rows = res.data || [];
      // Summary
      let gross=0, inc=0, allw=0, adv=0, ded=0, net=0, paid=0, unpaid=0;
      const tbody = $('#payReportTbody').empty();
      rows.forEach(p => {
        gross += Number(p.gross_salary||0);
        inc   += Number(p.total_incentives||0);
        allw  += Number(p.total_allowances||0);
        adv   += Number(p.total_advances||0);
        ded   += Number(p.total_deductions||0);
        net   += Number(p.net_salary||0);
        if (p.paid_on) paid++; else unpaid++;
        const tr = $('<tr>');
        tr.append(`<td>${escapeHtml(p.employee_name||'')}</td>`);
        tr.append(`<td class="text-end">${formatCurrency(p.gross_salary||0)}</td>`);
        tr.append(`<td class="text-end">${formatCurrency(p.total_incentives||0)}</td>`);
        tr.append(`<td class="text-end">${formatCurrency(p.total_allowances||0)}</td>`);
        tr.append(`<td class="text-end">${formatCurrency(p.total_advances||0)}</td>`);
        tr.append(`<td class="text-end">${formatCurrency(p.total_deductions||0)}</td>`);
        tr.append(`<td class="text-end">${formatCurrency(p.net_salary||0)}</td>`);
        tr.append(`<td>${p.paid_on?'<span class="badge bg-success">Paid</span>':'<span class="badge bg-warning text-dark">Unpaid</span>'}</td>`);
        tbody.append(tr);
      });
      $('#payReportPeriod').text(`Period: ${String(year)}-${String(month).padStart(2,'0')}`);
      $('#repGross').text(formatCurrency(gross));
      $('#repInc').text(formatCurrency(inc));
      $('#repAll').text(formatCurrency(allw));
      $('#repAdv').text(formatCurrency(adv));
      $('#repDed').text(formatCurrency(ded));
      $('#repNet').text(formatCurrency(net));
      $('#repPaidCnt').text(paid);
      $('#repUnpaidCnt').text(unpaid);
      $('#payReportModal').modal('show');
    });
  });
  // In report modal, add print button handler if present
  $(document).on('click', '#btnReportPrint', function(){
    const month=$('#pay_month').val(), year=$('#pay_year').val();
    const url = `salary_report.php?month=${encodeURIComponent(month)}&year=${encodeURIComponent(year)}`;
    window.open(url, '_blank');
  });

  // Incentives
  $('#btnAddIncentive').on('click', function(){ refreshEmployeeSelects(); $('#incForm')[0].reset(); $('#incId').val(''); $('#incModal').modal('show'); });
  $('#incForm').on('submit', function(e){ e.preventDefault(); const data=$(this).serialize(); $.post('api/salary_incentives.php?action=create', data, function(){ $('#incModal').modal('hide'); fetchIncentives(); fetchPayroll(); }); });
  $('#inc-table').on('click', '.btn-inc-delete', function(){ if(!confirm('Delete this incentive?')) return; const id=$(this).data('id'); $.post('api/salary_incentives.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchIncentives(); fetchPayroll(); }); });

  // Allowances
  $('#btnAddAllowance').on('click', function(){ refreshEmployeeSelects(); $('#allForm')[0].reset(); $('#allId').val(''); $('#allModal').modal('show'); });
  $('#allForm').on('submit', function(e){ e.preventDefault(); const data=$(this).serialize(); $.post('api/salary_allowances.php?action=create', data, function(){ $('#allModal').modal('hide'); fetchAllowances(); fetchPayroll(); }); });
  $('#all-table').on('click', '.btn-all-delete', function(){ if(!confirm('Delete this allowance?')) return; const id=$(this).data('id'); $.post('api/salary_allowances.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchAllowances(); fetchPayroll(); }); });
}

function fetchPayroll(){
  const month=$('#pay_month').val(), year=$('#pay_year').val();
  $.get('api/salary_payroll.php', { action:'list', month, year }, function(res){
    const tbody=$('#payroll-table tbody').empty();
    const rows = res.data||[];
    (rows).forEach(p=>{
      const tr=$('<tr>');
      tr.append(`<td>${escapeHtml(p.employee_name||'')}</td>`);
      tr.append(`<td>${formatCurrency(p.gross_salary||0)}</td>`);
      tr.append(`<td>${formatCurrency(p.total_incentives||0)}</td>`);
      tr.append(`<td>${formatCurrency(p.total_allowances||0)}</td>`);
      tr.append(`<td>${formatCurrency(p.total_advances||0)}</td>`);
      tr.append(`<td>${formatCurrency(p.total_deductions||0)}</td>`);
      tr.append(`<td>${formatCurrency(p.net_salary||0)}</td>`);
      tr.append(`<td>${escapeHtml(p.paid_on||'')}</td>`);
      const btnPaid = p.paid_on ? '' : `<button class="btn btn-sm btn-success btn-pay-mark" data-id="${p.id}">Mark Paid</button>`;
      const slip = `<a class="btn btn-sm btn-outline-secondary ms-1" target="_blank" href="salary_slip.php?id=${p.id}">Slip</a>`;
      const del = `<button class="btn btn-sm btn-outline-danger ms-1 btn-payroll-delete" data-id="${p.id}"><i class="bi bi-trash"></i></button>`;
      tr.append(`<td>${btnPaid} ${slip} ${del}</td>`);
      tbody.append(tr);
    });
    // store for CSV export
    $('#payroll-table').data('rows', rows);
  });
}

function exportPayrollCsv(){
  const month=$('#pay_month').val(), year=$('#pay_year').val();
  const rows = $('#payroll-table').data('rows') || [];
  const header = ['Employee','Gross','Incentives','Allowances','Advances','Deductions','Net','Paid On'];
  const csv = [header.join(',')].concat(rows.map(p => [
    (p.employee_name||'').replaceAll(',', ' '),
    Number(p.gross_salary||0).toFixed(2),
    Number(p.total_incentives||0).toFixed(2),
    Number(p.total_allowances||0).toFixed(2),
    Number(p.total_advances||0).toFixed(2),
    Number(p.total_deductions||0).toFixed(2),
    Number(p.net_salary||0).toFixed(2),
    (p.paid_on||'')
  ].join(','))).join('\n');
  const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `payroll_${year}-${String(month).padStart(2,'0')}.csv`;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);
}

// EXPENDITURES
function loadExpCategories(done){
  $.get('api/expenditure_categories.php', { action:'list' }, function(res){
    const sel1 = $('#expCategoryFilter').empty(); sel1.append('<option value="">All Categories</option>');
    const sel2 = $('#exp_category_id').empty(); sel2.append('<option value="">Select Category</option>');
    (res.data||[]).forEach(c=>{ if (parseInt(c.is_active)) { sel1.append(`<option value="${c.id}">${escapeHtml(c.name)}</option>`); sel2.append(`<option value="${c.id}">${escapeHtml(c.name)}</option>`);} });
    if (done) done();
  });
}

function fetchExpStats(){
  const branch_id = ($('#expBranchFilter').length ? ($('#expBranchFilter').val()||'') : '');
  const params = { action:'stats' };
  if (branch_id) params.branch_id = branch_id;
  $.get('api/expenditures.php', params, function(res){
    $('#exp_today_total').text(formatCurrency(res.today||0));
    $('#exp_month_total').text(formatCurrency(res.month||0));
    $('#exp_year_total').text(formatCurrency(res.year||0));
    $('#exp_daily_avg').text(formatCurrency(res.daily_avg||0));
  });
}

function fetchExpenditures(){
  const q=$('#expSearch').val()||'';
  const category_id=$('#expCategoryFilter').val()||'';
  const from=$('#expFromDate').val()||'';
  const to=$('#expToDate').val()||'';
  const branch_id = ($('#expBranchFilter').length ? ($('#expBranchFilter').val()||'') : '');
  const params = { action:'list', q, category_id, from, to };
  if (branch_id) params.branch_id = branch_id;
  $.get('api/expenditures.php', params, function(res){
    const tbody=$('#exp-table tbody').empty();
    if(!res.data || !res.data.length){
      $('#exp_filter_total').text(formatCurrency(0));
      tbody.append('<tr><td colspan="9" class="text-center text-muted">No Expenditures Found</td></tr>');
      return;
    }

    let filterTotal = 0;
    res.data.forEach(x=>{
      filterTotal += Number(x.amount || 0);
      const tr=$('<tr>');
      tr.append(`<td>${escapeHtml(formatDate(x.expense_date))}</td>`);
      tr.append(`<td>${escapeHtml(x.category_name||'')}</td>`);
      tr.append(`<td>${escapeHtml(x.description||'')}</td>`);
      tr.append(`<td>${escapeHtml(x.vendor||'')}</td>`);
      tr.append(`<td>${formatCurrency(x.amount)}</td>`);
      tr.append(`<td>${escapeHtml(x.payment_method||'')}</td>`);
      tr.append(`<td>${escapeHtml(x.invoice_no||'')}</td>`);
      (function(){
        const rp = (x.receipt_path || '').toString().trim();
        if (!rp) { tr.append('<td class="text-muted">-</td>'); return; }
        if (rp.indexOf('..') !== -1) { tr.append('<td class="text-muted">-</td>'); return; }
        if (/^https?:/i.test(rp)) { tr.append('<td class="text-muted">-</td>'); return; }
        const basePath = ($('#basePath').val() || '').toString().replace(/\/+$/, '');
        // Allow stored values like:
        // - uploads/receipts/x.pdf
        // - /uploads/receipts/x.pdf
        // - /new_sw/uploads/receipts/x.pdf
        let url = rp;
        if (basePath && url.indexOf(basePath + '/') !== 0) {
          url = url.replace(/^\/+/, '');
          url = basePath + '/' + url;
        }
        tr.append(`<td><a href="${encodeURI(url)}" target="_blank" rel="noopener">View</a></td>`);
      })();
      tr.append(`<td>
        <button class="btn btn-sm btn-primary me-2 btn-exp-edit" data-id="${x.id}"><i class="bi bi-pencil-square"></i></button>
        <button class="btn btn-sm btn-danger btn-exp-delete" data-id="${x.id}"><i class="bi bi-trash"></i></button>
      </td>`);
      tbody.append(tr);
    });

    $('#exp_filter_total').text(formatCurrency(filterTotal));
  });
}

function bindExpendituresEvents(){
  // open modal
  $('#btnAddExpenditure').on('click', function(){
    $('#expForm')[0].reset();
    $('#expId').val('');
    let pending = 2;
    function after(){ if(--pending===0) $('#expModal').modal('show'); }
    loadExpCategories(after);
    loadExpPaymentTermsDropdown(null, after);
  });

  // search
  $('#btnExpSearch').on('click', fetchExpenditures);
  $('#btnExpClear').on('click', function(){ $('#expSearch').val(''); $('#expCategoryFilter').val(''); $('#expFromDate').val(''); $('#expToDate').val(''); if($('#expBranchFilter').length){ $('#expBranchFilter').val(''); } fetchExpenditures(); fetchExpStats(); });

  // edit
  $('#exp-table').on('click', '.btn-exp-edit', function(){
    const id=$(this).data('id');
    $.get('api/expenditures.php',{action:'get',id}, function(res){
      const e=res.data||{};
      let pending = 2;
      function after(){ if(--pending===0){
        $('#expId').val(e.id||'');
        $('#exp_category_id').val(e.category_id||'');
        $('#exp_date').val(e.expense_date||'');
        $('#exp_description').val(e.description||'');
        $('#exp_amount').val(e.amount||'');
        $('#exp_payment').val(e.payment_method||'');
        $('#exp_vendor').val(e.vendor||'');
        $('#exp_invoice').val(e.invoice_no||'');
        $('#exp_recurring').prop('checked', !!parseInt(e.is_recurring||0));
        $('#exp_notes').val(e.notes||'');
        $('#expModal').modal('show');
      }}
      loadExpCategories(after);
      loadExpPaymentTermsDropdown(e.payment_method || '', after);
    });
  });

  // delete
  $('#exp-table').on('click', '.btn-exp-delete', function(){
    if(!confirm('Delete this expenditure?')) return;
    const id=$(this).data('id');
    $.post('api/expenditures.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchExpenditures(); fetchExpStats(); });
  });

  // submit form (multipart)
  $('#expForm').on('submit', function(e){
    e.preventDefault();
    const hasId = !!$('#expId').val();
    const formData = new FormData(this);
    const url = 'api/expenditures.php?action=' + (hasId ? 'update' : 'create');
    $.ajax({ url, method:'POST', data: formData, contentType:false, processData:false })
      .done(function(){ $('#expModal').modal('hide'); fetchExpenditures(); fetchExpStats(); })
      .fail(function(xhr){ alert(xhr.responseJSON?.message || 'Error'); });
  });

  // Categories modal
  $('#btnExpCategories').on('click', function(){ fetchExpCategoriesTable(); $('#expCatModal').modal('show'); });
  $('#btnAddExpCat').on('click', function(){ const name=$('#expCatName').val().trim(); if(!name) return; $.post('api/expenditure_categories.php?action=create',{ name, csrf: $('#csrf').val() }, function(){ $('#expCatName').val(''); fetchExpCategoriesTable(); loadExpCategories(); }); });
  $('#exp-cat-table').on('click', '.btn-exp-cat-edit', function(){
    const id = $(this).data('id');
    $.get('api/expenditure_categories.php', { action:'get', id }, function(res){
      const d = res.data || {};
      const current = (d.name || '').toString();
      const name = prompt('Edit category name', current);
      if (name == null) return;
      const trimmed = name.toString().trim();
      if (!trimmed) return;
      $.post('api/expenditure_categories.php?action=update', { id, name: trimmed, csrf: $('#csrf').val() }, function(){
        fetchExpCategoriesTable();
        loadExpCategories();
      }).fail(function(xhr){ alert(xhr.responseJSON?.message || 'Update failed'); });
    }).fail(function(xhr){ alert(xhr.responseJSON?.message || 'Failed to load category'); });
  });
  $('#exp-cat-table').on('click', '.btn-exp-cat-toggle', function(){ const id=$(this).data('id'); const active=$(this).data('active')?0:1; $.post('api/expenditure_categories.php?action=toggle',{ id, is_active: active, csrf: $('#csrf').val() }, function(){ fetchExpCategoriesTable(); loadExpCategories(); }); });
  $('#exp-cat-table').on('click', '.btn-exp-cat-delete', function(){ if(!confirm('Delete this category?')) return; const id=$(this).data('id'); $.post('api/expenditure_categories.php?action=delete',{ id, csrf: $('#csrf').val() }, function(){ fetchExpCategoriesTable(); loadExpCategories(); }); });

  // Reports modal open
  $('#btnExpReports').on('click', function(){
    const today = new Date().toISOString().slice(0,10);
    const monthStart = new Date(new Date().getFullYear(), new Date().getMonth(), 1).toISOString().slice(0,10);
    $('#expRepFrom').val(monthStart); $('#expRepTo').val(today);
    loadExpCategories(function(){
      const $dst = $('#expRepCategory'); $dst.empty(); $dst.append('<option value="">All</option>');
      $('#exp_category_id option').each(function(){ const v=$(this).val(); if(!v) return; $dst.append(`<option value="${v}">${escapeHtml($(this).text())}</option>`); });
    });
    if ($('#expRepBranch').length){
      $.get('api/branches.php',{ action:'list' }, function(res){ const $b=$('#expRepBranch'); $b.empty(); $b.append('<option value="">All</option>'); (res.data||[]).forEach(br=>{ if(parseInt(br.is_active)) $b.append(`<option value="${br.id}">${escapeHtml(br.name||'')}</option>`); }); });
    }
    $('#expReportModal').modal('show');
  });
  // Run report
  $('#btnExpRepRun').on('click', function(){
    const params={ action:'report_category', period: $('#expRepPeriod').val()||'month', from: $('#expRepFrom').val()||'', to: $('#expRepTo').val()||'', category_id: $('#expRepCategory').val()||'' };
    if ($('#expRepBranch').length){ const b=$('#expRepBranch').val(); if(b) params.branch_id=b; }
    $.get('api/expenditures.php', params, function(res){ const $tb=$('#expRepTable tbody'); $tb.empty(); const rows=res.data||[]; if(!rows.length){ $tb.append('<tr><td colspan="3" class="text-center text-muted">No data</td></tr>'); return; } rows.forEach(r=>{ $tb.append(`<tr><td>${escapeHtml(r.bucket||'')}</td><td>${escapeHtml(r.category_name||'')}</td><td class=\"text-end\">${formatCurrency(r.total||0)}</td></tr>`); }); });
  });

  // Export report (Excel-readable CSV)
  $('#btnExpRepExport').on('click', function(){
    const params={ action:'export_report_category_excel', period: $('#expRepPeriod').val()||'month', from: $('#expRepFrom').val()||'', to: $('#expRepTo').val()||'', category_id: $('#expRepCategory').val()||'' };
    if ($('#expRepBranch').length){ const b=$('#expRepBranch').val(); if(b) params.branch_id=b; }
    const qs = new URLSearchParams(params).toString();
    window.location.href = 'api/expenditures.php?' + qs;
  });
  // Print report
  $('#btnExpRepPrint').on('click', function(){ const html='<!doctype html><html><head><meta charset="utf-8"><title>Expenditure Report</title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"></head><body><div class="container p-3"><h5>Expenditure Report</h5>'+document.getElementById('expRepTable').outerHTML+'</div></body></html>'; const w=window.open('', '_blank'); if(!w) return; w.document.write(html); w.document.close(); w.focus(); w.print(); });
}

function fetchExpCategoriesTable(){
  $.get('api/expenditure_categories.php',{ action:'list' }, function(res){
    const tbody=$('#exp-cat-table tbody').empty();
    (res.data||[]).forEach(c=>{
      const tr=$('<tr>');
      tr.append(`<td>${c.id}</td>`);
      tr.append(`<td>${escapeHtml(c.name)}</td>`);
      tr.append(`<td>${parseInt(c.is_active)?'Yes':'No'}</td>`);
      const isActive = parseInt(c.is_active);
      const toggleIcon = isActive ? 'bi-toggle-off' : 'bi-toggle-on';
      const toggleTitle = isActive ? 'Disable' : 'Enable';
      tr.append(`<td>
        <button class="btn btn-sm btn-outline-primary me-2 btn-exp-cat-edit" data-id="${c.id}" title="Edit" aria-label="Edit"><i class="bi bi-pencil-square"></i></button>
        <button class="btn btn-sm btn-outline-secondary me-2 btn-exp-cat-toggle" data-id="${c.id}" data-active="${c.is_active}" title="${toggleTitle}" aria-label="${toggleTitle}"><i class="bi ${toggleIcon}"></i></button>
        <button class="btn btn-sm btn-outline-danger btn-exp-cat-delete" data-id="${c.id}" title="Delete" aria-label="Delete"><i class="bi bi-trash"></i></button>
      </td>`);
      tbody.append(tr);
    });
  });
}



// SHIP MODES
function fetchShipModes(){
  $.get('api/ship_modes.php', { action:'list' }, function(res){
    const tbody=$('#ship-table tbody').empty();
    res.data.forEach(x=>{
      const tr = $('<tr>');
      tr.append(`<td>${x.id}</td>`);
      tr.append(`<td>${escapeHtml(x.name)}</td>`);
      tr.append(`<td><button class="btn btn-sm btn-primary me-2 btn-edit" data-id="${x.id}">Edit</button><button class="btn btn-sm btn-danger btn-delete" data-id="${x.id}">Delete</button></td>`);
      tbody.append(tr);
    });
  });

  // Status change from dropdown
  $('#po-table').on('click', '.po-status-change', function(e){
    e.preventDefault();
    const id = $(this).data('id');
    const status = $(this).data('status');
    $.post('api/purchase_orders.php?action=update_status', { id, status, csrf: $('#csrf').val() }, function(){
      fetchPOs();
    }).fail(function(xhr){ alert(xhr.responseJSON?.message || 'Error'); });
  });

  // Search and filters
  $('#btnPOSearch').on('click', function(){ fetchPOs(); });
  $('#poSearch').on('keyup', function(e){ if (e.key === 'Enter') fetchPOs(); });
  // Clickable chips: store current in hidden select for convenience
  $(document).on('click', '.po-filter', function(){
    $('.po-filter').removeClass('border-dark');
    $(this).addClass('border-dark');
    $('#poStatusFilter').val($(this).data('status'));
    fetchPOs();
  });
}
function bindShipModesEvents(){
  $('#btnAddShip').on('click', function(){ $('#shipForm')[0].reset(); $('#shipId').val(''); $('#shipModal').modal('show'); });
  $('#ship-table').on('click', '.btn-edit', function(){ const id=$(this).data('id'); $.get('api/ship_modes.php',{action:'get',id}, function(res){ $('#shipId').val(res.data.id); $('#ship_name').val(res.data.name); $('#shipModal').modal('show'); });});
  $('#ship-table').on('click', '.btn-delete', function(){ if(!confirm('Delete this ship mode?')) return; const id=$(this).data('id'); $.post('api/ship_modes.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchShipModes(); }); });
  $('#shipForm').on('submit', function(e){ e.preventDefault(); const form=$(this).serialize(); const action=$('#shipId').val()?'update':'create'; $.post('api/ship_modes.php?action='+action, form, function(){ $('#shipModal').modal('hide'); fetchShipModes(); }).fail(function(xhr){ alert(xhr.responseJSON?.message||'Error'); }); });
}

// Close document ready


// DELIVERY TERMS
function fetchDeliveryTerms(){
  $.get('api/delivery_terms.php', { action:'list' }, function(res){
    const tbody=$('#delivery-table tbody').empty();
    res.data.forEach(x=>{
      const tr = $('<tr>');
      tr.append(`<td>${x.id}</td>`);
      tr.append(`<td>${escapeHtml(x.name)}</td>`);
      tr.append(`<td><button class="btn btn-sm btn-primary me-2 btn-edit" data-id="${x.id}">Edit</button><button class="btn btn-sm btn-danger btn-delete" data-id="${x.id}">Delete</button></td>`);
      tbody.append(tr);
    });
  });
}
function bindDeliveryTermsEvents(){
  $('#btnAddDelivery').on('click', function(){ $('#deliveryForm')[0].reset(); $('#deliveryId').val(''); $('#deliveryModal').modal('show'); });
  $('#delivery-table').on('click', '.btn-edit', function(){ const id=$(this).data('id'); $.get('api/delivery_terms.php',{action:'get',id}, function(res){ $('#deliveryId').val(res.data.id); $('#delivery_name').val(res.data.name); $('#deliveryModal').modal('show'); });});
  $('#delivery-table').on('click', '.btn-delete', function(){ if(!confirm('Delete this delivery term?')) return; const id=$(this).data('id'); $.post('api/delivery_terms.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchDeliveryTerms(); }); });
  $('#deliveryForm').on('submit', function(e){ e.preventDefault(); const form=$(this).serialize(); const action=$('#deliveryId').val()?'update':'create'; $.post('api/delivery_terms.php?action='+action, form, function(){ $('#deliveryModal').modal('hide'); fetchDeliveryTerms(); }).fail(function(xhr){ alert(xhr.responseJSON?.message||'Error'); }); });
}

// PAYMENT TERMS
function fetchPaymentTerms(){
  $.get('api/payment_terms.php', { action:'list' }, function(res){
    const tbody=$('#payment-table tbody').empty();
    res.data.forEach(x=>{
      const tr = $('<tr>');
      tr.append(`<td>${x.id}</td>`);
      tr.append(`<td>${escapeHtml(x.name)}</td>`);
      tr.append(`<td><button class="btn btn-sm btn-primary me-2 btn-edit" data-id="${x.id}">Edit</button><button class="btn btn-sm btn-danger btn-delete" data-id="${x.id}">Delete</button></td>`);
      tbody.append(tr);
    });
  });
}
function bindPaymentTermsEvents(){
  $('#btnAddPayment').on('click', function(){ $('#paymentForm')[0].reset(); $('#paymentId').val(''); $('#paymentModal').modal('show'); });
  $('#payment-table').on('click', '.btn-edit', function(){ const id=$(this).data('id'); $.get('api/payment_terms.php',{action:'get',id}, function(res){ $('#paymentId').val(res.data.id); $('#payment_name').val(res.data.name); $('#paymentModal').modal('show'); });});
  $('#payment-table').on('click', '.btn-delete', function(){ if(!confirm('Delete this payment term?')) return; const id=$(this).data('id'); $.post('api/payment_terms.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchPaymentTerms(); }); });
  $('#paymentForm').on('submit', function(e){ e.preventDefault(); const form=$(this).serialize(); const action=$('#paymentId').val()?'update':'create'; $.post('api/payment_terms.php?action='+action, form, function(){ $('#paymentModal').modal('hide'); fetchPaymentTerms(); }).fail(function(xhr){ alert(xhr.responseJSON?.message||'Error'); }); });
}

  // Users module events
  if ($('.page-users').length) {
    bindUsersEvents();
    fetchUsers();
  }

  // Suppliers module events
  if ($('.page-suppliers').length) {
    bindSuppliersEvents();
    fetchSuppliers();
  }

  // Purchase Orders module events
  if ($('.page-purchase_orders').length) {
    bindPOEvents();
    fetchPOs();
  }

  // Materials module events
  if ($('.page-materials').length) {
    bindMaterialsEvents();
    fetchMaterials();
    loadMaterialDropdowns();
  }

  if ($('.page-types').length) {
    bindTypesEvents();
    fetchTypes();
  }
  if ($('.page-colors').length) {
    bindColorsEvents();
    fetchColors();
  }
  if ($('.page-finishes').length) {
    bindFinishesEvents();
    fetchFinishes();
  }
  if ($('.page-ship_modes').length) {
    bindShipModesEvents();
    fetchShipModes();
  }
  if ($('.page-delivery_terms').length) {
    bindDeliveryTermsEvents();
    fetchDeliveryTerms();
  }
  if ($('.page-payment_terms').length) {
    bindPaymentTermsEvents();
    fetchPaymentTerms();
  }
  if ($('.page-expenditures').length) {
    bindExpendituresEvents();
    // default to current month if no dates set
    const $from = $('#expFromDate'), $to = $('#expToDate');
    const today = new Date().toISOString().slice(0,10);
    const monthStart = new Date(new Date().getFullYear(), new Date().getMonth(), 1).toISOString().slice(0,10);
    if (!$from.val()) $from.val(monthStart);
    if (!$to.val()) $to.val(today);
    loadExpCategories(function(){
      fetchExpenditures();
      fetchExpStats();
    });
  }
  if ($('.page-salary_management').length) {
    fetchEmployees(function(){
      fetchAdvances();
      fetchDeductions();
    });
    bindSalaryEvents();
  }
  if ($('.page-shop_settings').length) {
    bindShopSettingsEvents();
    fetchShopSettings();
  }

  // Customers module
  if ($('.page-customers').length) {
    bindCustomersEvents();
    fetchCustomers();
  }

  // Cutting Inventory module (handled inline in pages/cutting_inventory.php)
  if (false && $('.page-cutting_inventory').length) {
    // load locations for filter and edit
    function ciLoadLocations(){
      $.get('api/cut_pieces.php', { action:'locations' }, function(res){
        const opts=['<option value="">All</option>'];
        (res.data||[]).forEach(l=>opts.push(`<option value="${l.id}">${escapeHtml(l.name)}</option>`));
        $('#ci_loc').html(opts.join(''));
      });
    }
    function ciLoad(){
      const params = { action:'list', q: $('#ci_q').val().trim(), status: $('#ci_status').val(), avail: $('#ci_avail').val(), location_id: $('#ci_loc').val(),
        slab_q: $('#ci_slab').val().trim(), len_min: $('#ci_len_min').val(), len_max: $('#ci_len_max').val(), wid_min: $('#ci_wid_min').val(), wid_max: $('#ci_wid_max').val() };
      // fetch locations first to render selects with correct selected values
      $.get('api/cut_pieces.php', { action:'locations' }, function(locRes){
        const locs = locRes.data||[];
        $.get('api/cut_pieces.php', params, function(res){
          const $tb=$('#ci_table tbody').empty(); const rows=res.data||[];
          if (!rows.length){ $tb.append('<tr><td colspan="12" class="text-center text-muted">No pieces</td></tr>'); return; }
          rows.forEach(r=>{
            const tr=$('<tr>').attr('data-id', r.id).attr('data-loc', r.store_location_id||'');
            tr.append(`<td>${r.id}</td>`);
            tr.append(`<td>${escapeHtml(r.slab_no||'')}</td>`);
            tr.append(`<td>${r.job_id}</td>`);
            tr.append(`<td>${r.piece_no}</td>`);
            tr.append(`<td><input type="number" class="form-control form-control-sm ci-len" data-id="${r.id}" value="${Number(r.length_mm||0).toFixed(2)}"></td>`);
            tr.append(`<td><input type="number" class="form-control form-control-sm ci-wid" data-id="${r.id}" value="${Number(r.width_mm||0).toFixed(2)}"></td>`);
            tr.append(`<td><input type="number" class="form-control form-control-sm ci-thk" data-id="${r.id}" value="${r.thickness_mm!=null?Number(r.thickness_mm).toFixed(2):''}"></td>`);
            tr.append(`<td>${Number(r.area_sq_ft||0).toFixed(3)}</td>`);
            tr.append(`<td><select class="form-select form-select-sm ci-status" data-id="${r.id}"><option ${r.status==='usable'?'selected':''} value="usable">Usable</option><option ${r.status==='unusable'?'selected':''} value="unusable">Unusable</option></select></td>`);
            tr.append(`<td>${r.is_available? 'Available' : (r.reserved_invoice_item_id? 'Reserved' : 'Consumed')}</td>`);
            const sel = $('<select class="form-select form-select-sm ci-loc" data-id="'+r.id+'"></select>');
            sel.append('<option value="">(none)</option>');
            locs.forEach(l=> sel.append(`<option value="${l.id}">${escapeHtml(l.name)}</option>`));
            sel.val(r.store_location_id||'');
            tr.append($('<td>').append(sel));
            tr.append(`<td>
              <button class="btn btn-sm btn-outline-secondary me-1 ci-view" data-id="${r.id}" title="View"><i class="bi bi-eye"></i></button>
              <button class="btn btn-sm btn-outline-danger ci-del" data-id="${r.id}" title="Delete"><i class="bi bi-trash"></i></button>
            </td>`);
            $tb.append(tr);
          });
        });
      });
    }
    // bind events
    $('#btnRefreshCutInv').on('click', ciLoad);
    $('#ci_q,#ci_status,#ci_avail,#ci_loc,#ci_slab,#ci_len_min,#ci_len_max,#ci_wid_min,#ci_wid_max').on('change keyup', function(e){ if(e.type==='keyup' && e.keyCode!==13) return; ciLoad(); });
    $(document).on('change', '.ci-status, .ci-loc', function(){
      const id=$(this).data('id'); const status=$(this).closest('tr').find('.ci-status').val(); const store_location_id=$(this).closest('tr').find('.ci-loc').val();
      $.ajax({ url:'api/cut_pieces.php?action=update', method:'POST', dataType:'json', data:{ csrf: $('#csrf').val(), id, status, store_location_id } })
        .done(function(){ /* ok */ })
        .fail(function(xhr, text){
          if (xhr.status===200 || text==='parsererror') return; // treat parse-only issues as success
          alert((xhr.responseJSON && xhr.responseJSON.message) || 'Update failed');
        });
    });
    // Inline size update: post on blur or Enter, update area cell without reloading table
    function ciPostSize($row){
      const id=$row.find('.ci-len').data('id'); if(!id) return;
      if ($row.data('busy')) return; $row.data('busy', true);
      const length_mm=$row.find('.ci-len').val();
      const width_mm=$row.find('.ci-wid').val();
      const thickness_mm=$row.find('.ci-thk').val();
      $.ajax({ url:'api/cut_pieces.php?action=update', method:'POST', dataType:'json', data:{ csrf: $('#csrf').val(), id, length_mm, width_mm, thickness_mm } })
        .done(function(){
          const L=parseFloat(length_mm||'0'); const W=parseFloat(width_mm||'0');
          const area = (L>0 && W>0) ? ((L/304.8)*(W/304.8)) : 0;
          $row.find('td').eq(7).text(area.toFixed(3)); // area column index after edits
        })
        .fail(function(xhr, text){
          if (xhr.status===200 || text==='parsererror'){
            const L=parseFloat(length_mm||'0'); const W=parseFloat(width_mm||'0');
            const area = (L>0 && W>0) ? ((L/304.8)*(W/304.8)) : 0;
            $row.find('td').eq(7).text(area.toFixed(3));
            return; // treat as success
          }
          alert((xhr.responseJSON && xhr.responseJSON.message) || 'Update failed');
        })
        .always(function(){ $row.data('busy', false); });
    }
    let ciSkipBlur=false;
    $(document).on('blur', '.ci-len, .ci-wid, .ci-thk', function(){
      if (ciSkipBlur) { ciSkipBlur=false; return; }
      ciPostSize($(this).closest('tr'));
    });
    $(document).on('keypress', '.ci-len, .ci-wid, .ci-thk', function(e){
      if (e.which===13){ e.preventDefault(); ciSkipBlur=true; ciPostSize($(this).closest('tr')); }
    });
    $(document).on('click', '.ci-del', function(){
      const id=$(this).data('id'); if(!confirm('Delete this cut piece?')) return;
      $.post('api/cut_pieces.php?action=delete', { csrf: $('#csrf').val(), id }, function(){ ciLoad(); }).fail(function(xhr){ alert((xhr.responseJSON && xhr.responseJSON.message) || 'Delete failed'); });
    });
    $(document).on('click', '.ci-view', function(){
      const id=$(this).data('id');
      $.get('api/cut_pieces.php', { action:'get', id }, function(res){
        const d=res.data||{};
        $('#ci_d_id').text(d.id);
        $('#ci_d_slab').text(d.slab_no||'');
        $('#ci_d_job').text(d.job_id||'');
        $('#ci_d_size').text(`${Math.round(d.length_mm||0)} x ${Math.round(d.width_mm||0)} x ${d.thickness_mm!=null?Number(d.thickness_mm).toFixed(2):''}`);
        $('#ci_d_area').text(Number(d.area_sq_ft||0).toFixed(3));
        $('#ci_d_status').text(d.status||'');
        $('#ci_d_loc').text(d.location_name||'');
        $('#ciDetailModal').modal('show');
      });
    });
    // init
    ciLoadLocations();
    ciLoad();
  }

  // Slab Cutting module
  // Skip legacy init if page declares v2 via window flag or data attribute
  var _isV2Slab = ($('.page-slab_cutting').attr('data-slab-v2') === '1') || !!window.SLAB_CUT_V2;
  if ($('.page-slab_cutting').length && !_isV2Slab) {
    bindSlabCuttingEvents();
    loadCutSources();
    slabsInitPiecesTable();
    fetchCutPieces();
    fetchCutJobs();
  }


// USERS
function loadBranchesForSelect() {
  $.get('api/branches.php', { action: 'list' }, function(res) {
    const $sel = $('#branch_id');
    $sel.html('<option value="">-- Select Branch --</option>');
    (res.data || []).forEach(b => {
      $sel.append(`<option value="${b.id}">${escapeHtml(b.name)}</option>`);
    });
  });
}

function fetchUsers() {
  $.get('api/users.php', { action: 'list' }, function (res) {
    const tbody = $('#users-table tbody').empty();
    res.data.forEach(u => {
      const tr = $('<tr>');
      tr.append(`<td>${u.id}</td>`);
      tr.append(`<td>${escapeHtml(u.username)}</td>`);
      tr.append(`<td>${escapeHtml(u.full_name || '')}</td>`);
      tr.append(`<td><span class="badge text-bg-secondary">${u.role}</span></td>`);
      tr.append(`<td>${escapeHtml(u.branch_name || '-')}</td>`);
      tr.append(`<td>${u.is_active ? 'Active' : 'Inactive'}</td>`);
      tr.append(`<td>
          <button class="btn btn-sm btn-primary me-2 btn-edit" data-id="${u.id}">Edit</button>
          <button class="btn btn-sm btn-danger btn-delete" data-id="${u.id}">Delete</button>
        </td>`);
      tbody.append(tr);
    });
  });
}

function bindUsersEvents() {
  $('#btnAddUser').on('click', function(){
    $('#userForm')[0].reset();
    $('#userId').val('');
    loadBranchesForSelect();
    if (typeof toggleBranchField === 'function') toggleBranchField();
    $('#userModal').modal('show');
  });

  $('#users-table').on('click', '.btn-edit', function(){
    const id = $(this).data('id');
    $.get('api/users.php', { action: 'get', id }, function(res){
      const u = res.data;
      loadBranchesForSelect();
      $('#userId').val(u.id);
      $('#username').val(u.username);
      $('#full_name').val(u.full_name);
      $('#role').val(u.role);
      $('#branch_id').val(u.branch_id || '');
      $('#is_active').prop('checked', !!parseInt(u.is_active));
      $('#password').val('');
      if (typeof toggleBranchField === 'function') toggleBranchField();
      $('#userModal').modal('show');
    });
  });

  $('#users-table').on('click', '.btn-delete', function(){
    if(!confirm('Are you sure you want to delete this user?')) return;
    const id = $(this).data('id');
    $.post('api/users.php?action=delete', { id, csrf: $('#csrf').val() }, function(){
      fetchUsers();
    });
  });

  $('#userForm').on('submit', function(e){
    e.preventDefault();
    const formData = $(this).serialize();
    const action = $('#userId').val() ? 'update' : 'create';
    $.post('api/users.php?action=' + action, formData, function(){
      $('#userModal').modal('hide');
      fetchUsers();
    }).fail(function(xhr){
      alert(xhr.responseJSON?.message || 'Error');
    });
  });
}

// SUPPLIERS
function fetchSuppliers() {
  $.get('api/suppliers.php', { action: 'list' }, function (res) {
    const tbody = $('#suppliers-table tbody').empty();
    res.data.forEach(s => {
      const tr = $('<tr>');
      tr.append(`<td>${s.id}</td>`);
      tr.append(`<td>${escapeHtml(s.supplier_code || '')}</td>`);
      tr.append(`<td>${escapeHtml(s.name)}</td>`);
      tr.append(`<td>${escapeHtml(s.contact_person || '')}</td>`);
      tr.append(`<td>${escapeHtml(s.phone || '')}</td>`);
      tr.append(`<td>${escapeHtml(s.country || '')}</td>`);
      tr.append(`<td>${s.is_active ? 'Active' : 'Inactive'}</td>`);
      tr.append(`<td>
          <button class="btn btn-sm btn-primary me-2 btn-edit" data-id="${s.id}" title="Edit"><i class="bi bi-pencil"></i></button>
          <button class="btn btn-sm btn-danger btn-delete" data-id="${s.id}" title="Delete"><i class="bi bi-trash"></i></button>
        </td>`);
      tbody.append(tr);
    });
  });
}

function bindSuppliersEvents() {
  $('#btnAddSupplier').on('click', function(){
    $('#supplierForm')[0].reset();
    $('#supplierId').val('');
    $('#is_active').prop('checked', true);
    // Load payment terms into supplier modal dropdown
    loadSupplierPaymentTermsDropdown('');
    $('#supplierModal').modal('show');
  });

  $('#suppliers-table').on('click', '.btn-edit', function(){
    const id = $(this).data('id');
    $.get('api/suppliers.php', { action: 'get', id }, function(res){
      const s = res.data;
      $('#supplierId').val(s.id);
      $('#supplier_code').val(s.supplier_code);
      $('#s_name').val(s.name);
      $('#contact_person').val(s.contact_person);
      $('#email').val(s.email);
      $('#phone').val(s.phone);
      $('#address').val(s.address);
      $('#country').val(s.country);
      $('#tax_id').val(s.tax_id);
      // Populate payment terms list and set selected
      loadSupplierPaymentTermsDropdown(s.payment_terms || '');
      $('#currency').val(s.currency);
      $('#is_active').prop('checked', !!parseInt(s.is_active));
      $('#supplierModal').modal('show');
    });
  });

  $('#suppliers-table').on('click', '.btn-delete', function(){
    if(!confirm('Are you sure you want to delete this supplier?')) return;
    const id = $(this).data('id');
    $.post('api/suppliers.php?action=delete', { id, csrf: $('#csrf').val() }, function(){
      fetchSuppliers();
    });
  });

  $('#supplierForm').on('submit', function(e){
    e.preventDefault();
    const formData = $(this).serialize();
    const action = $('#supplierId').val() ? 'update' : 'create';
    $.post('api/suppliers.php?action=' + action, formData, function(){
      $('#supplierModal').modal('hide');
      fetchSuppliers();
    }).fail(function(xhr){
      alert(xhr.responseJSON?.message || 'Error');
    });
  });

  $('#btnGenCode').on('click', function(){
    $.get('api/suppliers.php', { action: 'generate_code' }, function(res){
      $('#supplier_code').val(res.code);
    });
  });
}

// PURCHASE ORDERS (basic)
function fetchPOs() {
  const q = $('#poSearch').val() || '';
  const status = $('#poStatusFilter').val() || '';
  $.ajax({ url:'api/purchase_orders.php', method:'GET', dataType:'text', data:{ action:'list', q, status } })
    .done(function (txt) {
      // tolerate stray HTML/warnings before JSON
      let res=null;
      try {
        // fast path
        res = JSON.parse(txt);
      } catch(e){
        // try to extract last JSON object in the text
        const i = txt.lastIndexOf('{');
        if (i !== -1){
          try { res = JSON.parse(txt.slice(i)); } catch(_) { /* ignore */ }
        }
      }
      if (!res || typeof res !== 'object') {
        const tbody = $('#po-table tbody').empty();
        const firstLine = String(txt||'').split('\n')[0].slice(0,200) || 'Invalid JSON';
        tbody.append(`<tr><td colspan="7" class="text-center text-danger">Failed to load purchase orders: ${escapeHtml(firstLine)}</td></tr>`);
        console.error('PO list parse error', txt);
        return;
      }
      const tbody = $('#po-table tbody').empty();
      const rows = res && res.data ? res.data : [];
      if (!rows.length) { tbody.append('<tr><td colspan="7" class="text-center text-muted">No purchase orders</td></tr>'); return; }
      rows.forEach(po => {
        const tr = $('<tr>');
      // PO Number as bold link style
      tr.append(`<td><strong>${escapeHtml(po.order_no)}</strong></td>`);
      // Supplier with contact under
      const supplierCell = `<div>${escapeHtml(po.supplier_name || '')}</div><div class="text-muted small">${escapeHtml(po.supplier_contact || '')}</div>`;
      tr.append(`<td>${supplierCell}</td>`);
      tr.append(`<td>${escapeHtml(formatDate(po.order_date))}</td>`);
      tr.append(`<td>${escapeHtml(formatDate(po.expected_date || ''))}</td>`);
      // Status badge with dropdown menu trigger
      const statusClass = statusBadgeClass(po.status);
      const st = (po.status||'').toLowerCase();
      const stDate = st === 'confirmed' ? po.confirmed_at : st === 'shipped' ? po.shipped_at : st === 'received' ? po.received_at : st === 'cancelled' ? po.cancelled_at : '';
      const dateStr = stDate ? ` <span class="text-muted small">${escapeHtml(stDate)}</span>` : '';
      const statusHtml = `
        <div class="dropdown">
          <button class="btn btn-sm dropdown-toggle ${statusClass}" type="button" data-bs-toggle="dropdown" aria-expanded="false">${toTitle(po.status)}${dateStr}</button>
          <ul class="dropdown-menu">
            <li><a class="dropdown-item po-status-change" data-id="${po.id}" data-status="pending" href="#">Pending</a></li>
            <li><a class="dropdown-item po-status-change" data-id="${po.id}" data-status="confirmed" href="#">Confirmed</a></li>
            <li><a class="dropdown-item po-status-change" data-id="${po.id}" data-status="shipped" href="#">Shipped</a></li>
            <li><a class="dropdown-item po-status-change" data-id="${po.id}" data-status="received" href="#">Received</a></li>
            <li><hr class="dropdown-divider"></li>
            <li><a class="dropdown-item text-danger po-status-change" data-id="${po.id}" data-status="cancelled" href="#">Cancelled</a></li>
          </ul>
        </div>`;
      tr.append(`<td>${statusHtml}</td>`);
      const cur = po.supplier_currency || 'USD';
      tr.append(`<td>${formatByCurrency(cur, po.total_amount)}</td>`);
        const canDelete = !(st === 'shipped' || st === 'received');
        const canEdit = !(st === 'shipped' || st === 'received');
        const actions = [];
        actions.push(`<a class=\"btn btn-sm btn-outline-secondary me-2\" title=\"View/Print\" href=\"po_print.php?id=${po.id}\" target=\"_blank\"><i class=\"bi bi-eye\"></i></a>`);
        actions.push(`<button class=\"btn btn-sm btn-outline-primary me-2 btn-po-invoices\" data-id=\"${po.id}\" data-po-no=\"${escapeHtml(po.order_no)}\" title=\"Invoices\"><i class=\"bi bi-receipt\"></i></button>`);
        if (canEdit) { actions.push(`<button class=\"btn btn-sm btn-primary me-2 btn-edit\" data-id=\"${po.id}\" title=\"Edit\"><i class=\"bi bi-pencil-square\"></i></button>`); }
        if (canDelete) { actions.push(`<button class=\"btn btn-sm btn-danger btn-delete\" data-id=\"${po.id}\" title=\"Delete\"><i class=\"bi bi-trash\"></i></button>`); }
        tr.append(`<td>${actions.join(' ')}</td>`);
        tbody.append(tr);
      });
    })
    .fail(function(xhr, text){
      const tbody = $('#po-table tbody').empty();
      let msg = 'Failed to load purchase orders';
      if (xhr && xhr.responseText) {
        const firstLine = xhr.responseText.split('\n')[0].slice(0,200);
        msg += `: ${firstLine}`;
      } else if (text) { msg += `: ${text}`; }
      tbody.append(`<tr><td colspan="7" class="text-center text-danger">${escapeHtml(msg)}</td></tr>`);
      console.error('PO list error:', text, xhr);
    });
}

function bindPOEvents() {
  // Top-search and status filter
  $('#btnPOSearch').on('click', function(){ fetchPOs(); });
  $('#poSearch').on('keyup', function(e){ if (e.key === 'Enter') fetchPOs(); });
  // Make badges look and act like buttons
  $('.po-filter').css('cursor','pointer').attr('role','button').attr('tabindex','0');
  $(document).on('click', '.po-filter', function(){
    const status = ($(this).data('status') || '').toString().toLowerCase();
    $('#poStatusFilter').val(status);
    // visual active state
    $('.po-filter').removeClass('border-2').removeClass('active');
    $(this).addClass('border-2 active');
    fetchPOs();
  });
  // Keyboard support for badges
  $(document).on('keydown', '.po-filter', function(e){
    if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); $(this).click(); }
  });
  $('#btnAddPO').on('click', function(){
    $('#poForm')[0].reset();
    $('#poId').val('');
    $('#status').val('pending');
    loadPOMasters();
    ensureMaterialsForPO(function(){
      resetPOItems();
      // default currency display (from current supplier selection or USD)
      updatePOModalCurrency(getSelectedSupplierCurrency()||'USD');
      $('#poModal').modal('show');
    });
  });

  $('#po-table').on('click', '.btn-edit', function(){
    const id = $(this).data('id');
    $.get('api/purchase_orders.php', { action: 'get', id }, function(res){
      const p = res.data;
      loadPOMasters(function(){
        $('#ship_mode').val(p.ship_mode || '');
        $('#delivery_term').val(p.delivery_term || '');
        $('#payment_term').val(p.payment_term || '');
      });
      ensureMaterialsForPO(function(){
        // Load items after materials cache is ready
        resetPOItems();
        (p.items || []).forEach(addPOItemRowFromData);
        recalcPOItemsTotal();
        // Filter description options to exclude already selected materials
        refreshAllDescriptionOptions();
      });
      $('#poId').val(p.id);
      $('#order_no').val(p.order_no);
      $('#supplier_id').val(p.supplier_id);
      $('#order_date').val(p.order_date);
      $('#expected_date').val(p.expected_date || '');
      $('#status').val(p.status || 'pending');
      $('#supplier_contact').val(p.supplier_contact || '');
      $('#supplier_email').val(p.supplier_email || '');
      $('#notes').val(p.notes || '');
      $('#total_amount').val(p.total_amount);
      // Force USD labels regardless of supplier
      updatePOModalCurrency('USD');
      // After modal shows, ensure options are unique
      $('#poModal').modal('show');
    });
  });

  $('#po-table').on('click', '.btn-delete', function(){
    if(!confirm('Are you sure you want to delete this purchase order?')) return;
    const id = $(this).data('id');
    $.post('api/purchase_orders.php?action=delete', { id, csrf: $('#csrf').val() }, function(){
      fetchPOs();
    });
  });

  // Change status and maintain date (handled server-side)
  $('#po-table').on('click', '.po-status-change', function(e){
    e.preventDefault();
    const id = $(this).data('id');
    const status = $(this).data('status');
    $.post('api/purchase_orders.php?action=update_status', { id, status, csrf: $('#csrf').val() }, function(){
      fetchPOs();
    }).fail(function(xhr){
      alert(xhr.responseJSON?.message || 'Failed to update status');
    });
  });

  $('#poForm').on('submit', function(e){
    e.preventDefault();
    // Serialize items to JSON
    const items = collectPOItems();
    $('#items_json').val(JSON.stringify(items));
    // sync total from items to total_amount field
    $('#total_amount').val($('#items_total').val() || 0);
    const formData = $(this).serialize();
    const action = $('#poId').val() ? 'update' : 'create';
    $.post('api/purchase_orders.php?action=' + action, formData, function(){
      $('#poModal').modal('hide');
      fetchPOs();
    }).fail(function(xhr){
      alert(xhr.responseJSON?.message || 'Error');
    });
  });

  // Auto-fill supplier contact/email when supplier changes
  $('#supplier_id').on('change', function(){
    const id = $(this).val();
    if(!id) { $('#supplier_contact').val(''); $('#supplier_email').val(''); return; }
    $.get('api/suppliers.php', { action: 'get', id }, function(res){
      const s = res.data;
      $('#supplier_contact').val(s.contact_person || '');
      $('#supplier_email').val(s.email || '');
    });
    // Force USD labels regardless of supplier
    updatePOModalCurrency('USD');
  });

  // Generate Order No
  $('#btnGenPONo').on('click', function(){
    $.get('api/purchase_orders.php', { action: 'generate_no' }, function(res){
      $('#order_no').val(res.order_no);
    });
  });

  // Quick add masters
  $('#btnAddShipMode').on('click', function(){
    const name = prompt('New Ship Mode'); if(!name) return;
    $.post('api/ship_modes.php?action=create', { name, csrf: $('#csrf').val() }, function(){ loadPOMasters(); });
  });
  $('#btnAddDeliveryTerm').on('click', function(){
    const name = prompt('New Delivery Term'); if(!name) return;
    $.post('api/delivery_terms.php?action=create', { name, csrf: $('#csrf').val() }, function(){ loadPOMasters(); });
  });
  $('#btnAddPaymentTerm').on('click', function(){
    const name = prompt('New Payment Term'); if(!name) return;
    $.post('api/payment_terms.php?action=create', { name, csrf: $('#csrf').val() }, function(){ loadPOMasters(); });
  });

  // Invoices modal handlers
  $('#po-table').on('click', '.btn-po-invoices', function(){
    const po_id = $(this).data('id');
    const po_no = $(this).data('po-no') || '';
    $('#poi_po_id').val(po_id);
    $('#poi_po_no').text(po_no);
    loadPOInvoices(po_id);
    $('#poInvoicesModal').modal('show');
  });

  function loadPOInvoices(po_id){
    $.get('api/purchase_orders.php', { action:'list_invoices', po_id }, function(res){
      const $tb = $('#poi_table tbody').empty();
      const rows = res.data || [];
      if (!rows.length){ $tb.append('<tr><td colspan="6" class="text-center text-muted">No invoices</td></tr>'); return; }
      rows.forEach(inv=>{
        const link = `<a href="${inv.file_path}" target="_blank" rel="noopener">${escapeHtml(inv.file_name||'File')}</a>`;
        const amt = inv.currency ? `${escapeHtml(inv.currency)} ${Number(inv.amount||0).toFixed(2)}` : Number(inv.amount||0).toFixed(2);
        const tr = $('<tr>');
        tr.append(`<td>${escapeHtml(inv.invoice_no||'')}</td>`);
        tr.append(`<td>${escapeHtml(inv.invoice_date||'')}</td>`);
        tr.append(`<td>${amt}</td>`);
        tr.append(`<td>${link}</td>`);
        tr.append(`<td>${escapeHtml(inv.uploaded_at||'')}</td>`);
        tr.append(`<td><button class="btn btn-sm btn-outline-danger poi-del" data-id="${inv.id}"><i class="bi bi-trash"></i></button></td>`);
        $tb.append(tr);
      });
    }).fail(function(xhr){
      const $tb = $('#poi_table tbody').empty();
      $tb.append('<tr><td colspan="6" class="text-center text-danger">Failed to load invoices</td></tr>');
    });
  }

  $('#poInvoiceUploadForm').on('submit', function(e){
    e.preventDefault();
    const fd = new FormData(this);
    fd.append('action','upload_invoice');
    $.ajax({ url:'api/purchase_orders.php', method:'POST', data:fd, contentType:false, processData:false })
      .done(function(){ const po_id=$('#poi_po_id').val(); loadPOInvoices(po_id); $('#poInvoiceUploadForm')[0].reset(); })
      .fail(function(xhr){ alert((xhr.responseJSON && xhr.responseJSON.message) || 'Upload failed'); });
  });

  $('#poi_table').on('click', '.poi-del', function(){
    if(!confirm('Delete this invoice?')) return;
    const id=$(this).data('id');
    $.post('api/purchase_orders.php?action=delete_invoice', { id, csrf: $('#csrf').val() }, function(){
      const po_id=$('#poi_po_id').val(); loadPOInvoices(po_id);
    }).fail(function(xhr){ alert((xhr.responseJSON && xhr.responseJSON.message) || 'Delete failed'); });
  });

  // Load PO master dropdowns
  function loadPOMasters(done){
    const after = done || function(){};
    let pending = 3;
    $.get('api/ship_modes.php', { action: 'list' }, function(res){
      const sel = $('#ship_mode').empty(); sel.append('<option value=""></option>');
      res.data.forEach(x => sel.append(`<option value="${escapeHtml(x.name)}">${escapeHtml(x.name)}</option>`));
      if(--pending===0) after();
    });
    $.get('api/delivery_terms.php', { action: 'list' }, function(res){
      const sel = $('#delivery_term').empty(); sel.append('<option value=""></option>');
      res.data.forEach(x => sel.append(`<option value="${escapeHtml(x.name)}">${escapeHtml(x.name)}</option>`));
      if(--pending===0) after();
    });
    $.get('api/payment_terms.php', { action: 'list' }, function(res){
      const sel = $('#payment_term').empty(); sel.append('<option value=""></option>');
      res.data.forEach(x => sel.append(`<option value="${escapeHtml(x.name)}">${escapeHtml(x.name)}</option>`));
      if(--pending===0) after();
    });
  }

  // Items: add/remove/recalc
  $('#btnAddItem').on('click', function(){
    addPOItemRowFromData({ description: '', hs_code: '', quantity: '', unit: '', unit_price: '', line_total: '' });
    // After adding a row, update dropdown options to keep uniqueness
    refreshAllDescriptionOptions();
  });

  $('#po-items-table').on('input', '.qty, .unit_price', function(){
    const row = $(this).closest('tr');
    const qty = parseFloat(row.find('.qty').val() || '0');
    const price = parseFloat(row.find('.unit_price').val() || '0');
    const total = qty * price;
    row.find('.line_total').val(total.toFixed(2));
    recalcPOItemsTotal();
  });

  $('#po-items-table').on('click', '.btn-remove-item', function(){
    $(this).closest('tr').remove();
    renumberPOItemRows();
    recalcPOItemsTotal();
    // Free up the removed material for selection again
    refreshAllDescriptionOptions();
  });

  // When material description changes, refresh all selects to exclude chosen ones
  $('#po-items-table').on('change', '.description_select', function(){
    refreshAllDescriptionOptions();
  });
}

function addPOItemRowFromData(item) {
  const tbody = $('#po-items-table tbody');
  const idx = tbody.children('tr').length + 1;
  // Build materials options
  let options = '<option value="">-- Select Material --</option>';
  if (window.PO_MATERIALS && Array.isArray(PO_MATERIALS)) {
    PO_MATERIALS.forEach(m => {
      const labelRaw = [m.code, m.name, m.finish, m.color].filter(Boolean).join(' - ');
      const label = escapeHtml(labelRaw);
      const matchById = item.material_id && String(item.material_id) === String(m.id);
      const desc = item.description || '';
      const matchByText = desc === m.name || desc === labelRaw || desc.startsWith(m.name) || (m.code && desc.startsWith(m.code));
      const selected = (matchById || matchByText) ? 'selected' : '';
      options += `<option value="${m.id}" ${selected}>${label}</option>`;
    });
  }
  // Try to extract a note from description if provided (schema-less notes)
  let initialNote = '';
  if (!item.note && item.description && Array.isArray(window.PO_MATERIALS)) {
    const desc = String(item.description);
    const match = window.PO_MATERIALS.find(m => {
      const labelRaw = m.code ? `${m.name} (${m.code})` : `${m.name}`;
      return desc === m.name || desc === labelRaw || desc.startsWith(m.name);
    });
    if (match) {
      const labelRaw = match.code ? `${match.name} (${match.code})` : `${match.name}`;
      if (desc.length > labelRaw.length) {
        const rest = desc.slice(labelRaw.length).trim();
        if (rest.startsWith('-')) initialNote = rest.slice(1).trim();
      }
    }
  }
  const tr = $(`
    <tr>
      <td class="text-center align-middle line_no">${String(idx).padStart(2,'0')}</td>
      <td>
        <select class="form-select description_select">
          ${options}
        </select>
      </td>
      <td><input type="text" class="form-control hs_code" value="${escapeHtml(item.hs_code || '')}"></td>
      <td><input type="number" step="0.001" class="form-control qty text-end" value="${item.quantity ?? ''}"></td>
      <td><input type="number" step="0.001" class="form-control unit_price text-end" style="min-width:160px;" value="${item.unit_price ?? ''}"></td>
      <td><input type="number" step="0.01" class="form-control line_total text-end" style="min-width:180px;" value="${item.line_total ?? ''}" readonly></td>
      <td><textarea class="form-control item_note" rows="1" placeholder="Note">${escapeHtml(item.note || initialNote || '')}</textarea></td>
      <td class="text-center"><button type="button" class="btn btn-sm btn-outline-danger btn-remove-item">×</button></td>
    </tr>
  `);
  tbody.append(tr);
  // Ensure options reflect current selections
  if (typeof refreshAllDescriptionOptions === 'function') {
    refreshAllDescriptionOptions();
  }
}

function resetPOItems() {
  $('#po-items-table tbody').empty();
  $('#items_total').val('0.00');
}

function recalcPOItemsTotal() {
  let total = 0;
  $('#po-items-table tbody tr').each(function(){
    const v = parseFloat($(this).find('.line_total').val() || '0');
    total += isNaN(v) ? 0 : v;
  });
  $('#items_total').val(total.toFixed(2));
}

function renumberPOItemRows() {
  $('#po-items-table tbody tr').each(function(i){
    $(this).find('.line_no').text(String(i+1).padStart(2,'0'));
  });
}

function collectPOItems() {
  const items = [];
  $('#po-items-table tbody tr').each(function(i){
    const $tr = $(this);
    const descBase = $tr.find('.description_select option:selected').text() || '';
    const noteVal = ($tr.find('.item_note').val() || '').trim();
    const desc = descBase;
    items.push({
      line_no: i + 1,
      description: desc,
      note: noteVal,
      hs_code: $tr.find('.hs_code').val(),
      quantity: parseFloat($tr.find('.qty').val() || '0'),
      unit: '',
      unit_price: parseFloat($tr.find('.unit_price').val() || '0'),
      line_total: parseFloat($tr.find('.line_total').val() || '0')
    });
  });
  return items;
}

// Utility
function escapeHtml(text) {
  return $('<div/>').text(text ?? '').html();
}

function toTitle(s){ if(!s) return ''; return s.charAt(0).toUpperCase()+s.slice(1); }
function statusBadgeClass(st){
  switch(st){
    case 'pending': return 'btn-outline-warning';
    case 'confirmed': return 'btn-outline-info';
    case 'shipped': return 'btn-outline-secondary';
    case 'received': return 'btn-outline-success';
    case 'cancelled': return 'btn-outline-danger';
    default: return 'btn-outline-secondary';
  }
}
function formatDate(d){ if(!d) return ''; try { const dt = new Date(d); return dt.toLocaleDateString(undefined, { month:'short', day:'2-digit', year:'numeric' }); } catch(e){ return d; } }
function formatCurrency(n){ const v = Number(n||0); try { return v.toLocaleString('en-LK', { style:'currency', currency:'LKR', minimumFractionDigits:2}); } catch(e){ return 'LKR ' + v.toFixed(2); } }
// USD currency for Purchase Management module
function formatCurrencyUSD(n){ const v = Number(n||0); try { return v.toLocaleString('en-US', { style:'currency', currency:'USD', minimumFractionDigits:2}); } catch(e){ return '$' + v.toFixed(2); } }
// Generic by currency code
function formatByCurrency(code, n){
  const v = Number(n||0);
  try{
    switch(String(code||'').toUpperCase()){
      case 'USD': return v.toLocaleString('en-US', {style:'currency', currency:'USD', minimumFractionDigits:2});
      case 'LKR': return v.toLocaleString('en-LK', {style:'currency', currency:'LKR', minimumFractionDigits:2});
      case 'INR': return v.toLocaleString('en-IN', {style:'currency', currency:'INR', minimumFractionDigits:2});
      case 'AED': return v.toLocaleString('ar-AE', {style:'currency', currency:'AED', minimumFractionDigits:2});
      case 'CNY': return v.toLocaleString('zh-CN', {style:'currency', currency:'CNY', minimumFractionDigits:2});
      default: return v.toLocaleString(undefined, {style:'currency', currency: String(code||'USD').toUpperCase(), minimumFractionDigits:2});
    }
  }catch(e){ return (code?String(code).toUpperCase():'')+' '+v.toFixed(2); }
}

// ===== Purchase Order currency helpers (global) =====
function currencySymbolFor(code){
  switch(String(code||'').toUpperCase()){
    case 'USD': return '$';
    case 'LKR': return 'LKR';
    case 'INR': return '₹';
    case 'AED': return 'د.إ';
    case 'CNY': return '¥';
    default: return String(code||'').toUpperCase();
  }
}
function getSelectedSupplierCurrency(){
  const opt = $('#supplier_id option:selected');
  return (opt.data('currency') || '').toString().toUpperCase();
}
function updatePOModalCurrency(code){
  const sym = currencySymbolFor(code);
  $('.po-cur-code').text(code||'');
  $('.po-currency-prefix').text(sym||'');
}
// expose globally to avoid scope issues
window.currencySymbolFor = currencySymbolFor;
window.getSelectedSupplierCurrency = getSelectedSupplierCurrency;
window.updatePOModalCurrency = updatePOModalCurrency;

// SHOP SETTINGS
function fetchShopSettings(){
  $.get('api/shop_settings.php', { action:'get' }, function(res){
    const s = res.data || {};
    $('#shop_id').val(s.id || '');
    $('#company_name').val(s.company_name || '');
    $('#address_line').val(s.address_line || '');
    $('#city_country').val(s.city_country || '');
    $('#company_email').val(s.company_email || '');
    $('#phone').val(s.phone || '');
  });
}
function bindShopSettingsEvents(){
  $('#shopSettingsForm').on('submit', function(e){
    e.preventDefault();
    const form = $(this).serialize();
    $.post('api/shop_settings.php?action=update', form, function(){
      fetchShopSettings();
    }).fail(function(xhr){ alert(xhr.responseJSON?.message || 'Error'); });
  });
}

// Global: Materials cache for PO description dropdown
window.PO_MATERIALS = window.PO_MATERIALS || null;
function ensureMaterialsForPO(done){
  if (window.PO_MATERIALS) { if (done) done(); return; }
  $.get('api/materials.php', { action: 'list' }, function(res){
    window.PO_MATERIALS = (res.data || []).map(m => ({
      id: m.id,
      name: m.name,
      code: m.material_code,
      finish: m.finish_name || '',
      color: m.color_name || ''
    }));
    if (done) done();
  });
}

// Helpers to enforce unique material selection across PO item rows
function getSelectedMaterialIds() {
  const ids = new Set();
  $('#po-items-table tbody .description_select').each(function(){
    const v = $(this).val();
    if (v) ids.add(String(v));
  });
  return ids;
}

function buildMaterialOptions(excludeIds, selectedId) {
  let opts = '<option value="">-- Select Material --</option>';
  if (!Array.isArray(window.PO_MATERIALS)) return opts;
  window.PO_MATERIALS.forEach(m => {
    const idStr = String(m.id);
    const isSelected = selectedId && String(selectedId) === idStr;
    if (!isSelected && excludeIds.has(idStr)) return; // skip already used
    const parts = [m.code, m.name, m.finish, m.color].filter(Boolean).map(escapeHtml);
    const label = parts.join(' - ');
    opts += `<option value="${idStr}" ${isSelected ? 'selected' : ''}>${label}</option>`;
  });
  return opts;
}

function refreshAllDescriptionOptions() {
  const used = getSelectedMaterialIds();
  $('#po-items-table tbody tr').each(function(){
    const sel = $(this).find('.description_select');
    const current = sel.val();
    // Temporarily allow keeping current by removing it from used set
    if (current) used.delete(String(current));
    const html = buildMaterialOptions(used, current || null);
    sel.html(html);
    // Re-add current for subsequent rows to respect uniqueness
    if (current) used.add(String(current));
  });
}

// TYPES
function fetchTypes(){
  $.get('api/types.php', { action: 'list' }, function(res){
    const tbody = $('#types-table tbody').empty();
    res.data.forEach(t => {
      const tr = $('<tr>');
      tr.append(`<td>${t.id}</td>`);
      tr.append(`<td>${escapeHtml(t.name)}</td>`);
      tr.append(`<td>
        <button class="btn btn-sm btn-primary me-2 btn-edit" data-id="${t.id}">Edit</button>
        <button class="btn btn-sm btn-danger btn-delete" data-id="${t.id}">Delete</button>
      </td>`);
      tbody.append(tr);
    });
  });
}
function bindTypesEvents(){
  $('#btnAddType').on('click', function(){
    $('#typeForm')[0].reset(); $('#typeId').val(''); $('#typeModal').modal('show');
  });
  $('#types-table').on('click', '.btn-edit', function(){
    const id=$(this).data('id');
    $.get('api/types.php', { action:'get', id }, function(res){
      $('#typeId').val(res.data.id); $('#t_name').val(res.data.name); $('#typeModal').modal('show');
    });
  });
  $('#types-table').on('click', '.btn-delete', function(){
    if(!confirm('Delete this type?')) return; const id=$(this).data('id');
    $.post('api/types.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchTypes(); });
  });
  $('#typeForm').on('submit', function(e){
    e.preventDefault(); const form=$(this).serialize(); const action=$('#typeId').val()? 'update':'create';
    $.post('api/types.php?action='+action, form, function(){ $('#typeModal').modal('hide'); fetchTypes(); }).fail(function(xhr){ alert(xhr.responseJSON?.message||'Error'); });
  });
}

// COLORS
function fetchColors(){
  $.get('api/colors.php', { action: 'list' }, function(res){
    const tbody = $('#colors-table tbody').empty();
    res.data.forEach(c => {
      const tr = $('<tr>');
      tr.append(`<td>${c.id}</td>`);
      tr.append(`<td>${escapeHtml(c.name)}</td>`);
      tr.append(`<td>
        <button class="btn btn-sm btn-primary me-2 btn-edit" data-id="${c.id}">Edit</button>
        <button class="btn btn-sm btn-danger btn-delete" data-id="${c.id}">Delete</button>
      </td>`);
      tbody.append(tr);
    });
  });
}
function bindColorsEvents(){
  $('#btnAddColor').on('click', function(){ $('#colorForm')[0].reset(); $('#colorId').val(''); $('#colorModal').modal('show'); });
  $('#colors-table').on('click', '.btn-edit', function(){ const id=$(this).data('id'); $.get('api/colors.php', { action:'get', id }, function(res){ $('#colorId').val(res.data.id); $('#c_name').val(res.data.name); $('#colorModal').modal('show'); }); });
  $('#colors-table').on('click', '.btn-delete', function(){ if(!confirm('Delete this color?')) return; const id=$(this).data('id'); $.post('api/colors.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchColors(); }); });
  $('#colorForm').on('submit', function(e){ e.preventDefault(); const form=$(this).serialize(); const action=$('#colorId').val()? 'update':'create'; $.post('api/colors.php?action='+action, form, function(){ $('#colorModal').modal('hide'); fetchColors(); }).fail(function(xhr){ alert(xhr.responseJSON?.message||'Error'); }); });
}

// FINISHES
function fetchFinishes(){
  $.get('api/finishes.php', { action: 'list' }, function(res){
    const tbody = $('#finishes-table tbody').empty();
    res.data.forEach(f => {
      const tr = $('<tr>');
      tr.append(`<td>${f.id}</td>`);
      tr.append(`<td>${escapeHtml(f.name)}</td>`);
      tr.append(`<td>
        <button class="btn btn-sm btn-primary me-2 btn-edit" data-id="${f.id}">Edit</button>
        <button class="btn btn-sm btn-danger btn-delete" data-id="${f.id}">Delete</button>
      </td>`);
      tbody.append(tr);
    });
  });
}
function bindFinishesEvents(){
  $('#btnAddFinish').on('click', function(){ $('#finishForm')[0].reset(); $('#finishId').val(''); $('#finishModal').modal('show'); });
  $('#finishes-table').on('click', '.btn-edit', function(){ const id=$(this).data('id'); $.get('api/finishes.php', { action:'get', id }, function(res){ $('#finishId').val(res.data.id); $('#f_name').val(res.data.name); $('#finishModal').modal('show'); }); });
  $('#finishes-table').on('click', '.btn-delete', function(){ if(!confirm('Delete this finish?')) return; const id=$(this).data('id'); $.post('api/finishes.php?action=delete', { id, csrf: $('#csrf').val() }, function(){ fetchFinishes(); }); });
  $('#finishForm').on('submit', function(e){ e.preventDefault(); const form=$(this).serialize(); const action=$('#finishId').val()? 'update':'create'; $.post('api/finishes.php?action='+action, form, function(){ $('#finishModal').modal('hide'); fetchFinishes(); }).fail(function(xhr){ alert(xhr.responseJSON?.message||'Error'); }); });
}

// MATERIALS
function fetchMaterials() {
  $.get('api/materials.php', { action: 'list' }, function (res) {
    const tbody = $('#materials-table tbody').empty();
    res.data.forEach(m => {
      const tr = $('<tr>');
      tr.append(`<td>${m.id}</td>`);
      tr.append(`<td>${escapeHtml(m.material_code || '')}</td>`);
      tr.append(`<td>${escapeHtml(m.name)}</td>`);
      tr.append(`<td>${escapeHtml(m.type_name || '')}</td>`);
      tr.append(`<td>${escapeHtml(m.finish_name || '')}</td>`);
      tr.append(`<td>${escapeHtml(m.color_name || '')}</td>`);
      tr.append(`<td>${m.length_mm ?? ''}</td>`);
      tr.append(`<td>${m.width_mm ?? ''}</td>`);
      tr.append(`<td>${m.thickness_mm ?? ''}</td>`);
      tr.append(`<td>${m.is_active ? 'Active' : 'Inactive'}</td>`);
      tr.append(`<td>
          <button class="btn btn-sm btn-primary me-2 btn-edit" data-id="${m.id}">Edit</button>
          <button class="btn btn-sm btn-danger btn-delete" data-id="${m.id}">Delete</button>
        </td>`);
      tbody.append(tr);
    });
  });
}

function loadMaterialDropdowns(selected = {}) {
  $.get('api/materials.php', { action: 'list_types' }, function(res){
    const sel = $('#type_id').empty();
    sel.append('<option value="">--</option>');
    res.data.forEach(x => sel.append(`<option value="${x.id}">${escapeHtml(x.name)}</option>`));
    if (selected.type_id != null) sel.val(String(selected.type_id));
  });
  $.get('api/materials.php', { action: 'list_finishes' }, function(res){
    const sel = $('#finish_id').empty();
    sel.append('<option value="">--</option>');
    res.data.forEach(x => sel.append(`<option value="${x.id}">${escapeHtml(x.name)}</option>`));
    if (selected.finish_id != null) sel.val(String(selected.finish_id));
  });
  $.get('api/materials.php', { action: 'list_colors' }, function(res){
    const sel = $('#color_id').empty();
    sel.append('<option value="">--</option>');
    res.data.forEach(x => sel.append(`<option value="${x.id}">${escapeHtml(x.name)}</option>`));
    if (selected.color_id != null) sel.val(String(selected.color_id));
  });
}

function bindMaterialsEvents() {
  $('#btnAddMaterial').on('click', function(){
    $('#materialForm')[0].reset();
    $('#materialId').val('');
    $('#m_is_active').prop('checked', true);
    loadMaterialDropdowns();
    $('#materialModal').modal('show');
  });

  function fetchExpCategoryReport() {
    const period = $('#repPeriod').val() || 'day';
    const from = $('#repFromDate').val() || '';
    const to = $('#repToDate').val() || '';
    const category_id = $('#repCategory').val() || '';
    $.get('api/expenditures.php', { action: 'report_category', period, from, to, category_id }, function(res){
      const tbody = $('#exp-report-table tbody').empty();
      const rows = res.data || [];
      if (!rows.length) { tbody.append('<tr><td colspan="3" class="text-center text-muted">No data</td></tr>'); return; }
      rows.forEach(r => {
        const tr = $('<tr>');
        tr.append(`<td>${escapeHtml(r.bucket)}</td>`);
        tr.append(`<td>${escapeHtml(r.category_name || '')}</td>`);
        tr.append(`<td>${formatCurrency(r.total || 0)}</td>`);
        tbody.append(tr);
      });
    });
  }

  $('#materials-table').on('click', '.btn-edit', function(){
    const id = $(this).data('id');
    $.get('api/materials.php', { action: 'get', id }, function(res){
      const m = res.data;
      $('#materialId').val(m.id);
      $('#material_code').val(m.material_code);
      $('#m_name').val(m.name);
      loadMaterialDropdowns({ type_id: m.type_id || '', finish_id: m.finish_id || '', color_id: m.color_id || '' });
      $('#length_mm').val(m.length_mm || '');
      $('#width_mm').val(m.width_mm || '');
      $('#thickness_mm').val(m.thickness_mm || '');
      $('#m_notes').val(m.notes || '');
      $('#m_is_active').prop('checked', !!parseInt(m.is_active));
      $('#materialModal').modal('show');
    });
  });

  $('#materials-table').on('click', '.btn-delete', function(){
    if(!confirm('Are you sure you want to delete this material?')) return;
    const id = $(this).data('id');
    $.post('api/materials.php?action=delete', { id, csrf: $('#csrf').val() }, function(){
      fetchMaterials();
    });
  });

  $('#materialForm').on('submit', function(e){
    e.preventDefault();
    const formData = $(this).serialize();
    const action = $('#materialId').val() ? 'update' : 'create';
    $.post('api/materials.php?action=' + action, formData, function(){
      $('#materialModal').modal('hide');
      fetchMaterials();
    }).fail(function(xhr){ alert(xhr.responseJSON?.message || 'Error'); });
  });

  $('#btnGenMaterialCode').on('click', function(){
    $.get('api/materials.php', { action: 'generate_code' }, function(res){
      $('#material_code').val(res.code);
    });
  });

  // Add quick master entries
  $('#btnAddType').on('click', function(){
    const name = prompt('New Type name'); if(!name) return;
    $.post('api/materials.php?action=add_type', { name, csrf: $('#csrf').val() }, function(){ loadMaterialDropdowns(); });
  });
  $('#btnAddFinish').on('click', function(){
    const name = prompt('New Finish name'); if(!name) return;
    $.post('api/materials.php?action=add_finish', { name, csrf: $('#csrf').val() }, function(){ loadMaterialDropdowns(); });
  });
  $('#btnAddColor').on('click', function(){
    const name = prompt('New Color name'); if(!name) return;
    $.post('api/materials.php?action=add_color', { name, csrf: $('#csrf').val() }, function(){ loadMaterialDropdowns(); });
  });
}
});
