(function(){
    const bindings=[];
    const on=(target,event,handler,options)=>{if(!target||!target.addEventListener)return;target.addEventListener(event,handler,options||false);bindings.push([target,event,handler,options||false]);};
    window.ICY_PAGE_CLEANUPS=window.ICY_PAGE_CLEANUPS||[];
    window.ICY_PAGE_CLEANUPS.push(()=>bindings.forEach(([target,event,handler,options])=>{try{target.removeEventListener(event,handler,options);}catch(_){}}));

    const state={centersLoaded:false,currentKey:null,currentEnvironment:'sandbox',paymentDocument:null,paymentOptions:null};
    const $=id=>document.getElementById(id);
    const esc=value=>String(value==null?'':value).replace(/[&<>'"]/g,char=>({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[char]));
    const money=value=>'$'+Math.round(Number(value||0)).toLocaleString('es-CL');
    const foreignMoney=(value,currency)=>`${String(currency||'').toUpperCase()} ${Number(value||0).toLocaleString('es-CL',{minimumFractionDigits:2,maximumFractionDigits:2})}`;
    const dualMoney=(clpValue,row,foreignField)=>{
        const currency=String(row&&row.currency_code||'CLP').toUpperCase();
        const foreignValue=row&&row[foreignField];
        if(currency==='CLP'||foreignValue==null||foreignValue==='')return `<strong>${money(clpValue)}</strong>`;
        return `<strong>${esc(foreignMoney(foreignValue,currency))}</strong><small style="display:block;margin-top:2px">Equiv. ${money(clpValue)}</small>`;
    };
    const dateText=value=>{if(!value)return '-';const p=String(value).slice(0,10).split('-');return p.length===3?`${p[2]}-${p[1]}-${p[0]}`:String(value);};
    const today=()=>new Date().toISOString().slice(0,10);
    const refreshIcons=()=>{if(window.lucide&&typeof window.lucide.createIcons==='function')window.lucide.createIcons();};
    const paymentRequestKey = (prefix) => {
        const random = (window.crypto && typeof window.crypto.randomUUID === 'function')
            ? window.crypto.randomUUID()
            : (Date.now().toString(36) + '-' + Math.random().toString(36).slice(2) + '-' + Math.random().toString(36).slice(2));
        return String(prefix || 'payment') + ':' + random;
    };

    function params(extra){
        const p=new URLSearchParams();
        p.set('environment',$('customerAgingEnv').value||'sandbox');
        p.set('search',$('customerAgingSearch').value||'');
        p.set('bucket',$('customerAgingBucket').value||'all');
        p.set('center_id',$('customerAgingCenter').value||'all');
        Object.entries(extra||{}).forEach(([k,v])=>p.set(k,v));
        return p;
    }
    async function requestJson(url,options){
        const r=await fetch(url,options||{headers:{Accept:'application/json'}});
        const text=await r.text();let j;try{j=JSON.parse(text);}catch(_){throw new Error(text||'Respuesta no válida.');}
        if(!r.ok||!j||j.ok===false||j.success===false)throw new Error(j&&j.message?j.message:'Error al procesar la solicitud.');
        return j;
    }
    async function fetchData(url){const j=await requestJson(url,{headers:{Accept:'application/json'}});return j.data;}
    function optionHtml(items,valueKey,labelKey){return '<option value="">Seleccionar</option>'+(items||[]).map(item=>`<option value="${esc(item[valueKey])}">${esc(item[labelKey]||item[valueKey])}</option>`).join('');}

    function renderCenters(centers){
        if(state.centersLoaded)return;
        const opts=['<option value="all">Todos los centros</option>','<option value="none">Sin centro</option>'];
        (centers||[]).forEach(c=>opts.push(`<option value="${esc(c.id)}">${esc(c.center_name||c.center_code||'Centro')}</option>`));
        $('customerAgingCenter').innerHTML=opts.join('');state.centersLoaded=true;
    }
    function renderKpis(k){
        const values=[k.customers_count||0,money(k.open_balance),money(k.overdue_balance),money(k.due_7_balance),k.documents_count||0,k.unlinked_customers||0];
        $('customerAgingKpis').querySelectorAll('strong').forEach((n,i)=>n.textContent=values[i]);
    }
    function pill(row){
        if(Number(row.overdue_balance||0)>0)return `<span class="customer-aging-pill is-danger">${Number(row.max_days_overdue||0)} d venc.</span>`;
        if(Number(row.due_7_balance||0)>0)return '<span class="customer-aging-pill is-warning">Por vencer</span>';
        return '<span class="customer-aging-pill is-ok">Al día</span>';
    }
    function renderRows(rows){
        if(!(rows||[]).length){
            $('customerAgingRows').innerHTML='<tr><td colspan="12">Sin clientes con saldo abierto para los filtros seleccionados.</td></tr>';
            return;
        }
        $('customerAgingRows').innerHTML=rows.map(row=>`<tr>
            <td class="crm-mobile-primary"><div class="crm-ui-cell-stack"><strong>${esc(row.customer_name||'Cliente sin vincular')}</strong><small>${pill(row)}</small></div></td>
            <td class="crm-mobile-hidden">${esc(row.customer_tax_id||'-')}</td>
            <td class="crm-mobile-hidden">${esc(row.documents_count||0)}</td>
            <td class="money crm-mobile-metric"><strong>${money(row.open_balance)}</strong></td>
            <td class="money crm-mobile-hidden">${money(row.overdue_balance)}</td>
            <td class="money crm-mobile-hidden">${money(row.due_7_balance)}</td>
            <td class="money crm-mobile-hidden">${money(row.bucket_1_30)}</td>
            <td class="money crm-mobile-hidden">${money(row.bucket_31_60)}</td>
            <td class="money crm-mobile-hidden">${money(row.bucket_61_90)}</td>
            <td class="money crm-mobile-hidden">${money(row.bucket_90_plus)}</td>
            <td class="crm-mobile-hidden">${esc(row.finance_center_name||'Sin centro')}</td>
            <td class="crm-ui-action-cell"><button type="button" class="btn btn-outline crm-ui-action-btn" data-customer-aging-detail="${esc(row.customer_key)}" aria-label="Ver aging de ${esc(row.customer_name||'cliente')}"><i data-lucide="eye" aria-hidden="true"></i></button></td>
        </tr>`).join('');
        refreshIcons();
    }

    async function load(){
        $('customerAgingRows').innerHTML='<tr><td colspan="12">Cargando...</td></tr>';
        const data=await fetchData('/modules/billing/customer_aging_ajax.php?'+params().toString());
        renderCenters(data.centers||[]);renderKpis(data.kpis||{});renderRows(data.rows||[]);
    }
    function setFooter(html){$('customerAgingModalFooter').innerHTML=html;refreshIcons();}
    async function openDetail(key){
        state.currentKey=key;state.currentEnvironment=$('customerAgingEnv').value||'sandbox';
        const data=await fetchData('/modules/billing/customer_aging_detail_ajax.php?'+params({customer_key:key}).toString());
        const customer=data.customer||{};const rows=data.rows||[];
        $('customerAgingModal').style.display='flex';$('customerAgingModal').classList.add('show');$('customerAgingModal').setAttribute('aria-hidden','false');document.body.classList.add('is-modal-open');
        $('customerAgingModalTitle').textContent=customer.customer_name||'Cliente';
        $('customerAgingModalSubtitle').textContent=(customer.customer_tax_id||'-')+' · '+rows.length+' documentos abiertos';
        $('customerAgingModalBody').innerHTML=`
            <div class="customer-aging-summary crm-ui-summary-grid">
                <div class="customer-aging-summary-card crm-ui-summary-card"><span>Saldo abierto neto</span><strong>${money(customer.open_balance)}</strong></div>
                <div class="customer-aging-summary-card crm-ui-summary-card"><span>Vencido neto</span><strong>${money(customer.overdue_balance)}</strong></div>
                <div class="customer-aging-summary-card crm-ui-summary-card"><span>Por vencer 7d neto</span><strong>${money(customer.due_7_balance)}</strong></div>
                <div class="customer-aging-summary-card crm-ui-summary-card"><span>Máx. atraso</span><strong>${Number(customer.max_days_overdue||0)} días</strong></div>
            </div>
            <div class="customer-aging-detail-wrap crm-ui-inner-table-wrap"><table class="customer-aging-detail customer-aging-detail--documents crm-ui-inner-table"><thead><tr><th>Emisión</th><th>Vence</th><th>Folio</th><th>Cotización</th><th>Total neto</th><th>Pagado neto equiv.</th><th>Saldo neto</th><th>Días atraso</th><th>Estado</th><th></th></tr></thead><tbody>
            ${rows.map(row=>`<tr><td>${esc(dateText(row.issue_date))}</td><td>${esc(dateText(row.aging_due_date))}</td><td><strong>${esc(row.document_number||'-')}</strong></td><td>${esc(row.quote_number||'-')}</td><td class="money">${dualMoney(row.collection_net_total||row.net_amount,row,'foreign_net_total')}</td><td class="money">${dualMoney(row.paid_net_amount,row,'foreign_paid_net_amount')}</td><td class="money">${dualMoney(row.aging_balance,row,'foreign_net_balance_amount')}</td><td>${esc(row.days_overdue||0)}</td><td>${esc(row.collection_status||row.payment_status||'por_cobrar')}</td><td><button type="button" class="btn btn-secondary" data-aging-collect-id="${esc(row.id)}">Ir a cobrar</button></td></tr>`).join('')}
            </tbody></table></div>`;
        setFooter('<div class="modal-footer-actions-right"><button type="button" class="btn btn-outline" id="closeCustomerAgingFooterBtn"><i data-lucide="x"></i><span>Cerrar</span></button></div>');
        refreshIcons();
    }

    async function openCollection(id){
        const env=state.currentEnvironment||$('customerAgingEnv').value||'sandbox';
        const data=await requestJson('/modules/billing/receivable_detail_ajax.php?id='+encodeURIComponent(id)+'&env='+encodeURIComponent(env),{headers:{Accept:'application/json'}});
        state.paymentDocument=data.document;state.paymentOptions=data.options||{};
        renderCollection(data.document,data.payments||[],data.options||{},false);
    }
    function renderCollection(doc,payments,options,saved){
        const balance=Number(doc.balance_amount!=null?doc.balance_amount:doc.collection_balance!=null?doc.collection_balance:doc.total_amount||0)-0;
        const netBalance=Number(doc.net_balance_amount!=null?doc.net_balance_amount:doc.net_amount||0)-0;
        const status=doc.collection_status||doc.payment_status||'por_cobrar';
        $('customerAgingModalTitle').textContent='Registrar cobro · '+(doc.document_number||'-');
        $('customerAgingModalSubtitle').textContent=(doc.customer_name||doc.receiver_legal_name||'Cliente')+' · neto '+money(netBalance)+' · cobro bruto '+money(balance);
        const methods=optionHtml(options.payment_methods,'id','method_name');
        const accounts=optionHtml(options.cash_accounts,'id','account_name');
        const history=(payments||[]).length?(payments||[]).map(p=>`<tr><td>${esc(dateText(p.payment_date))}</td><td>${dualMoney(p.amount,p,'foreign_amount')}</td><td>${esc(p.method_name||'-')}</td><td>${esc(p.account_name||'-')}</td></tr>`).join(''):'<tr><td colspan="4">Sin cobros registrados.</td></tr>';
        $('customerAgingModalBody').innerHTML=`<div class="customer-aging-summary crm-ui-summary-grid">
            <div class="customer-aging-summary-card crm-ui-summary-card"><span>Total neto</span>${dualMoney(doc.collection_net_total!=null?doc.collection_net_total:doc.net_amount,doc,'foreign_net_total')}<small style="display:block">Factura bruta ${money(doc.collection_total!=null?doc.collection_total:doc.total_amount)}</small></div>
            <div class="customer-aging-summary-card crm-ui-summary-card"><span>Pagado neto equivalente</span>${dualMoney(doc.paid_net_amount,doc,'foreign_paid_net_amount')}<small style="display:block">Cobrado bruto ${money(doc.paid_amount)}</small></div>
            <div class="customer-aging-summary-card crm-ui-summary-card"><span>Saldo neto</span>${dualMoney(netBalance,doc,'foreign_net_balance_amount')}<small style="display:block">Por cobrar bruto ${money(balance)}</small></div>
            <div class="customer-aging-summary-card crm-ui-summary-card"><span>Estado</span><strong>${esc(status)}</strong></div>
        </div>
        ${saved?'<div class="receive-info-note" style="margin-bottom:12px;border-radius:12px"><strong>Cobro guardado.</strong> La cuenta y el aging fueron actualizados.</div>':''}
        <div class="customer-aging-payment-grid crm-ui-form-grid">
            <section class="customer-aging-payment-card crm-ui-section"><h3>Documento</h3><p><strong>Cliente:</strong> ${esc(doc.customer_name||doc.receiver_legal_name||'-')}</p><p><strong>RUT:</strong> ${esc(doc.customer_tax_id||doc.receiver_tax_id_code||'-')}</p><p><strong>Folio:</strong> ${esc(doc.document_number||'-')}</p><p><strong>Vence:</strong> ${esc(dateText(doc.due_date||doc.payment_due_date))}</p></section>
            <section class="customer-aging-payment-card crm-ui-section"><h3>Registrar cobro</h3>${balance>0.5?`<form id="agingCollectionForm"><input type="hidden" name="idempotency_key" value="${esc(paymentRequestKey('aging-cxc'))}"><input type="hidden" name="expected_collection_id" value="${esc(doc.collection_id || '')}"><input type="hidden" name="expected_document_id" value="${esc(doc.document_id || '')}"><input type="hidden" name="expected_balance" value="${esc(balance.toFixed(2))}">
                <div class="customer-aging-payment-field crm-ui-field"><label>Fecha</label><input type="date" name="payment_date" value="${today()}" required></div>
                <div class="customer-aging-payment-field crm-ui-field"><label>Monto recibido bruto</label><input type="number" name="amount" min="1" max="${esc(balance)}" step="0.01" value="${esc(balance)}" required><small>El saldo de aging se recalcula en neto proporcional.</small></div>
                <div class="customer-aging-payment-field crm-ui-field"><label>Método</label><select name="payment_method_id" required>${methods}</select></div>
                <div class="customer-aging-payment-field crm-ui-field"><label>Caja / cuenta</label><select name="cash_account_id" required>${accounts}</select></div>
                <div class="customer-aging-payment-field crm-ui-field"><label>Referencia</label><input type="text" name="external_reference" maxlength="120" ${state.currentEnvironment==='production'?'required':''}></div>
                <div class="customer-aging-payment-field crm-ui-field"><label>Nota</label><textarea name="notes"></textarea></div>
            </form>`:'<p>El documento está completamente pagado.</p>'}</section>
        </div>
        <section class="customer-aging-payment-card crm-ui-section" style="margin-top:12px"><h3>Historial de cobros brutos</h3><div class="customer-aging-detail-wrap crm-ui-inner-table-wrap"><table class="customer-aging-detail customer-aging-detail--history crm-ui-inner-table"><thead><tr><th>Fecha</th><th>Monto bruto</th><th>Método</th><th>Cuenta</th></tr></thead><tbody>${history}</tbody></table></div></section>`;
        setFooter(`<div class="modal-footer-actions-left"><button type="button" class="btn btn-outline" id="backCustomerAgingBtn"><i data-lucide="arrow-left"></i><span>Volver a aging</span></button></div><div class="modal-footer-actions-right">${balance>0.5?`<button type="button" class="btn btn-success" id="registerAgingCollectionBtn"><i data-lucide="badge-dollar-sign"></i><span>${saved?'Registrar otro cobro':'Registrar cobro'}</span></button>`:'<span class="billing-save-confirmation"><i data-lucide="circle-check"></i> Cuenta pagada</span>'}</div>`);
    }
    async function registerCollection(){
        const form=$('agingCollectionForm');if(!form||!form.reportValidity())return;
        const amount=Number(form.amount.value||0);const reference=String(form.external_reference.value||'').trim();
        if(!window.confirm(`Registrar cobro por ${money(amount)}?\nReferencia: ${reference||'sin referencia'}`))return;
        const button=$('registerAgingCollectionBtn');if(button)button.disabled=true;
        try{const fd=new FormData(form);fd.append('id',state.paymentDocument.id);fd.append('environment',state.currentEnvironment);
        const data=await requestJson('/modules/billing/receivable_register_payment_ajax.php',{method:'POST',body:fd});
        state.paymentDocument=data.document;renderCollection(data.document,data.payments||[],state.paymentOptions||{},true);await load();}
        finally{if(button&&document.body.contains(button))button.disabled=false;}
    }
    async function backToAging(){if(state.currentKey)await openDetail(state.currentKey);}
    function syncModalBodyLock(){
        const hasOpenModal=Array.from(document.querySelectorAll('.product-modal-backdrop.show')).some(modal=>modal.getAttribute('aria-hidden')!=='true');
        document.body.classList.toggle('is-modal-open',hasOpenModal);
    }
    function close(){
        $('customerAgingModal').style.display='none';$('customerAgingModal').classList.remove('show');$('customerAgingModal').setAttribute('aria-hidden','true');
        syncModalBodyLock();
    }

    on(document,'click',e=>{
        if(e.target===$('customerAgingModal')){close();return;}
        const btn=e.target.closest('[data-customer-aging-detail]');if(btn){openDetail(btn.getAttribute('data-customer-aging-detail')).catch(err=>alert(err.message));return;}
        const collect=e.target.closest('[data-aging-collect-id]');if(collect){e.preventDefault();openCollection(collect.getAttribute('data-aging-collect-id')).catch(err=>alert(err.message));return;}
        const action=e.target.closest('button,a');const id=action?action.id:'';
        if(id==='reloadCustomerAgingBtn'){load().catch(err=>alert(err.message));return;}
        if(id==='registerAgingCollectionBtn'){registerCollection().catch(err=>alert(err.message));return;}
        if(id==='backCustomerAgingBtn'){backToAging().catch(err=>alert(err.message));return;}
        if(['closeCustomerAgingModalBtn','closeCustomerAgingFooterBtn'].includes(id)){close();}
    });
    ['customerAgingEnv','customerAgingBucket','customerAgingCenter'].forEach(id=>on($(id),'change',()=>load().catch(err=>alert(err.message))));
    on($('customerAgingSearch'),'keydown',e=>{if(e.key==='Enter')load().catch(err=>alert(err.message));});
    on(document,'keydown',e=>{if(e.key==='Escape'&&$('customerAgingModal')?.classList.contains('show'))close();});
    load().catch(err=>{$('customerAgingRows').innerHTML=`<tr><td colspan="12">${esc(err.message)}</td></tr>`;});
})();
