(function () {
    const form = document.getElementById('payment-form');
    if (!form) return;

    const isReceived = form.dataset.isReceived === '1';
    const isAdvance = form.dataset.isAdvance === '1';
    const kind = form.dataset.kind || 'received';
    const unpaidUrl = form.dataset.unpaidUrl || '';
    const customers = JSON.parse(form.dataset.customers || '[]');
    const vendors = JSON.parse(form.dataset.vendors || '[]');
    const initialAllocations = JSON.parse(form.dataset.allocations || '[]');

    const amountInput = document.getElementById('payment-amount');
    const amountDisplay = document.getElementById('payment-amount-display') || document.getElementById('payment-advance-display');
    const tbody = document.getElementById('unpaid-documents-body');
    const monthsFilter = document.getElementById('unpaid-months-filter');

    function fmt(n) {
        return '₹ ' + Number(n || 0).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
    }

    function getPartyId() {
        if (isReceived) {
            const el = form.querySelector('[name="customer_id"]');
            return el?.value || '';
        }
        return document.getElementById('billing-vendor-id')?.value || '';
    }

    function findParty(id) {
        if (!id) return null;
        if (isReceived && window.BillingClientPicker?.findClient) {
            return window.BillingClientPicker.findClient(id);
        }
        const catalog = isReceived ? customers : vendors;
        return catalog.find(p => String(p.id) === String(id)) || null;
    }

    function updatePartyPanel() {
        const placeholder = document.getElementById('payment-party-placeholder');
        const details = document.getElementById('payment-party-details');
        const billing = document.getElementById('payment-party-billing');
        const gstin = document.getElementById('payment-party-gstin');
        const party = findParty(getPartyId());

        if (!party) {
            placeholder?.classList.remove('d-none');
            details?.classList.add('d-none');
            return;
        }

        placeholder?.classList.add('d-none');
        details?.classList.remove('d-none');
        if (billing) billing.textContent = party.billing_short || party.name || '';
        if (gstin) gstin.textContent = party.gstin || '—';
    }

    function sumPaymentValues() {
        let total = 0;
        tbody?.querySelectorAll('[data-allocated]').forEach(inp => {
            total += parseFloat(inp.value) || 0;
        });
        return total;
    }

    /** Sum line Payment values into header Amount (next to Method). */
    function syncAmountFromPaymentValues() {
        if (!amountInput || isAdvance) return;
        const total = sumPaymentValues();
        amountInput.value = total > 0 ? total.toFixed(2) : '';
        if (amountDisplay) amountDisplay.textContent = fmt(total);
        recalcSummary();
    }

    function updateAmountDisplays() {
        const amt = parseFloat(amountInput?.value) || 0;
        if (amountDisplay) amountDisplay.textContent = fmt(amt);
        recalcSummary();
    }

    function recalcSummary() {
        const paid = parseFloat(amountInput?.value) || 0;
        const used = sumPaymentValues();
        const excess = Math.max(0, paid - used);

        const paidEl = document.getElementById('summary-amount-paid');
        const usedEl = document.getElementById('summary-amount-used');
        const excessEl = document.getElementById('summary-amount-excess');
        if (paidEl) paidEl.textContent = fmt(paid);
        if (usedEl) usedEl.textContent = fmt(used);
        if (excessEl) excessEl.textContent = fmt(excess);
    }

    function renderUnpaidRows(documents) {
        if (!tbody) return;

        if (!documents.length) {
            tbody.innerHTML = '<tr class="text-muted"><td colspan="5" class="text-center py-4">No unpaid documents found.</td></tr>';
            recalcSummary();
            return;
        }

        const allocMap = {};
        initialAllocations.forEach(a => {
            const key = a.invoice_id ? 'invoice-'+a.invoice_id : 'bill-'+a.purchase_bill_id;
            allocMap[key] = a.allocated_amount;
        });

        tbody.innerHTML = documents.map((doc, idx) => {
            const key = doc.type === 'invoice' ? 'invoice-'+doc.id : 'bill-'+doc.id;
            const idField = doc.type === 'invoice'
                ? `<input type="hidden" name="allocations[${idx}][invoice_id]" value="${doc.id}">`
                : `<input type="hidden" name="allocations[${idx}][purchase_bill_id]" value="${doc.id}">`;
            const prefill = allocMap[key] ?? '';
            return `<tr>
                <td>${doc.date}</td>
                <td>${doc.number}</td>
                <td class="text-end">${fmt(doc.amount)}</td>
                <td class="text-end">${fmt(doc.amount_due)}
                    <input type="hidden" name="allocations[${idx}][amount_due]" value="${doc.amount_due}">
                </td>
                <td class="text-end">
                    ${idField}
                    <input type="number" step="0.01" min="0" max="${doc.amount_due}" name="allocations[${idx}][allocated_amount]"
                        data-allocated class="form-control form-control-sm text-end" value="${prefill}" placeholder="0">
                </td>
            </tr>`;
        }).join('');

        tbody.querySelectorAll('[data-allocated]').forEach(inp => {
            inp.addEventListener('input', syncAmountFromPaymentValues);
            inp.addEventListener('change', syncAmountFromPaymentValues);
        });
        syncAmountFromPaymentValues();
    }

    async function loadUnpaidDocuments() {
        if (isAdvance || !tbody) return;
        const partyId = getPartyId();
        if (!partyId) {
            tbody.innerHTML = '<tr class="text-muted"><td colspan="5" class="text-center py-4">Select '+(isReceived?'a client':'a vendor')+' to load unpaid documents.</td></tr>';
            return;
        }

        const params = new URLSearchParams({
            kind,
            months: monthsFilter?.value || '6',
        });
        if (isReceived) params.set('customer_id', partyId);
        else params.set('vendor_id', partyId);

        tbody.innerHTML = '<tr><td colspan="5" class="text-center py-4 text-muted">Loading…</td></tr>';

        try {
            const res = await fetch(unpaidUrl + '?' + params.toString(), {
                headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
            });
            const data = await res.json();
            renderUnpaidRows(data.documents || []);
        } catch (e) {
            tbody.innerHTML = '<tr><td colspan="5" class="text-center py-4 text-danger">Could not load documents.</td></tr>';
        }
    }

    function initVendorPicker() {
        const picker = form.querySelector('[data-vendor-picker]');
        if (!picker || picker.dataset.initialized) return;
        picker.dataset.initialized = '1';
        const hidden = picker.querySelector('[data-field="vendor_id"]');
        const label = picker.querySelector('.billing-unit-picker__label');
        const list = picker.querySelector('.billing-vendor-picker__list');
        const search = picker.querySelector('.billing-unit-picker__search');

        function render(filter) {
            const q = (filter || '').toLowerCase();
            const rows = vendors.filter(v => !q || `${v.name} ${v.city || ''}`.toLowerCase().includes(q));
            list.innerHTML = rows.map(v => `
                <li class="billing-unit-picker__option" role="option" data-id="${v.id}" tabindex="0">
                    <span>${v.name}${v.city ? ' - ' + v.city : ''}</span>
                </li>
            `).join('') || '<li class="text-muted small px-2 py-2">No vendors found</li>';
        }

        function select(id) {
            const v = vendors.find(x => String(x.id) === String(id));
            if (hidden) hidden.value = v ? String(v.id) : '';
            if (label) {
                label.textContent = v ? `${v.name}${v.city ? ' - ' + v.city : ''}` : 'Select Vendor';
                label.classList.toggle('text-muted', !v);
            }
            picker.querySelector('.billing-unit-picker__dropdown')?.classList.add('d-none');
            updatePartyPanel();
            loadUnpaidDocuments();
        }

        picker.querySelector('.billing-unit-picker__trigger')?.addEventListener('click', e => {
            e.preventDefault();
            picker.querySelector('.billing-unit-picker__dropdown')?.classList.toggle('d-none');
            render('');
        });
        search?.addEventListener('input', e => render(e.target.value));
        list?.addEventListener('click', e => {
            const opt = e.target.closest('.billing-unit-picker__option');
            if (opt?.dataset.id) select(opt.dataset.id);
        });
        if (hidden?.value) select(hidden.value);
    }

    amountInput?.addEventListener('input', updateAmountDisplays);
    monthsFilter?.addEventListener('change', loadUnpaidDocuments);

    function onCustomerChanged() {
        updatePartyPanel();
        loadUnpaidDocuments();
    }

    form.querySelector('[name="customer_id"]')?.addEventListener('change', onCustomerChanged);
    document.addEventListener('billing-customer-changed', onCustomerChanged);

    function boot() {
        if (isReceived && window.BillingClientPicker) {
            const catalog = window.__billingClients?.length
                ? window.__billingClients
                : customers;
            BillingClientPicker.configure({ clients: catalog });
            BillingClientPicker.initAll(form);
        }
        initVendorPicker();
        updateAmountDisplays();
        updatePartyPanel();
        if (!isAdvance && (getPartyId() || initialAllocations.length)) {
            loadUnpaidDocuments();
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', boot);
    } else {
        boot();
    }
})();
