<?php
// /includes/finance/finance_invoices-edit.php
if (file_exists('../../../' . ($_REQUEST['tenant'] ?? '') . '/config.php')) require_once('../../../' . $_REQUEST['tenant'] . '/config.php');
if (file_exists('/config.php')) require_once('/config.php');
$invNo = (int)($_REQUEST['invNo'] ?? 0);
$vatRateStr = function_exists('getCompanyDetails') ? getCompanyDetails('vatrate') : '0';


if (!function_exists('normaliseInvoiceItemsForStorage')) {
    function normaliseInvoiceItemsForStorage($raw): array
    {
        if (is_array($raw)) {
            return $raw;
        }

        if (!is_string($raw) || trim($raw) === '') {
            return [];
        }

        $raw = trim($raw);

        // Proper serialized PHP array
        $unserialised = @unserialize($raw);
        if (is_array($unserialised)) {
            return $unserialised;
        }

        // Serialized JSON string
        if (is_string($unserialised) && trim($unserialised) !== '') {
            $json = json_decode($unserialised, true);
            if (is_array($json)) {
                return $json;
            }
        }

        // Plain JSON
        $json = json_decode($raw, true);
        if (is_array($json)) {
            return $json;
        }

        // Wrapped serialized string with JSON inside
        if (preg_match('/^s:\d+:"(.*)";$/s', $raw, $matches)) {
            $inner = stripcslashes($matches[1]);
            $json = json_decode($inner, true);
            if (is_array($json)) {
                return $json;
            }
        }

        return [];
    }
}

if (!function_exists('isLegacyInvoiceItemsFormat')) {
    function isLegacyInvoiceItemsFormat($raw): bool
    {
        if (!is_string($raw) || trim($raw) === '') {
            return false;
        }

        $raw = trim($raw);

        // Proper serialized array is already correct
        $unserialised = @unserialize($raw);
        if (is_array($unserialised)) {
            return false;
        }

        // Serialized string that contains JSON
        if (is_string($unserialised) && trim($unserialised) !== '') {
            $json = json_decode($unserialised, true);
            if (is_array($json)) {
                return true;
            }
        }

        // Plain JSON
        $json = json_decode($raw, true);
        if (is_array($json)) {
            return true;
        }

        // Regex unwrap fallback
        if (preg_match('/^s:\d+:"(.*)";$/s', $raw, $matches)) {
            $inner = stripcslashes($matches[1]);
            $json = json_decode($inner, true);
            if (is_array($json)) {
                return true;
            }
        }

        return false;
    }
}
?>

<div class="note note-light mb-3"><strong>Invoices:</strong> Edit existing invoice.</div>

<div class="container-fluid" id="invoiceApp">
    <div class="row mb-4 align-items-end">
        <div class="col-md-2" id="invoiceNumberBlock" style="display:none">
            <div class="input-group">
                <span class="input-group-text text-light bg-info" data-mdb-tooltip-init data-mdb-placement="top"
                      title="Invoice number">Invoice No</span>
                <input type="text" id="invoiceNumber" class="form-control d-inline-block w-50" readonly />
            </div>
        </div>

        <div class="col-md-2" id="invoiceDateBlock" style="display:none">
            <div class="date-picker d-inline-block w-100" data-date-type="open" data-format="dd-mm-yyyy" data-mdb-toggle-button="false">
                <div class="input-group">
                    <span class="input-group-text text-light bg-info" data-mdb-tooltip-init data-mdb-placement="top"
                          title="Date of invoice">Invoice Date</span>
                    <input class="form-control d-inline-block w-50" data-mdb-confirm-date-on-select="true"
                           data-mdb-toggle="datepicker" data-mdb-format="dd-mm-yyyy" type="text" id="invoiceDate"
                           value="<?= date('d-m-Y') ?>" autocomplete="off" />
                </div>
            </div>
        </div>

        <div class="col-md-3" id="purchaseOrderBlock" style="display:none">
            <div class="input-group">
                <span class="input-group-text text-light bg-info" data-mdb-tooltip-init data-mdb-placement="top"
                      title="Purchase Order Number">PO Number</span>
                <input type="text" id="purchaseOrder" class="form-control d-inline-block w-75" />
            </div>
        </div>
    </div>

    <div id="invoiceContainer" style="display:none">
        <div class="row mb-3">
            <div class="col-3">
                <div class="card">
                    <div class="card-header bg-dark text-light">Billing Information</div>
                    <div class="card-body" id="billingInfo"></div>
                </div>
            </div>
            <div class="col-3">
                <div class="card">
                    <div class="card-header bg-dark text-light">Account Information</div>
                    <div class="card-body" id="accountInfo"></div>
                </div>
            </div>
            <div class="col-6">
                <div class="card">
                    <div class="card-header bg-dark text-light d-flex justify-content-between">
                        Invoice Items
                        <button class="btn btn-sm btn-secondary" onclick="openNewItemModal()" data-mdb-tooltip-init
                                data-mdb-placement="bottom" data-mdb-trigger="hover" title="Add new entry"><i
                               class="fad fa-plus"></i></button>
                    </div>
                    <div class="card-body">
                        <table class="table table-sm table-bordered" id="invoiceItemsTable">
                            <thead class="table-dark">
                                <tr>
                                    <th>Service</th>
                                    <th>Notes</th>
                                    <th width="40">Fee</th>
                                    <th width="40">Qty</th>
                                    <th></th>
                                </tr>
                            </thead>
                            <tbody id="invoiceItems"></tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>

        <div class="row justify-content-end mt-n5">
            <div class="col-md-4">
                <div class="card">
                    <div class="card-body">
                        <div class="mb-2 d-flex justify-content-between align-items-center">
                            <label class="form-label mb-0">Subtotal (ex VAT)</label>
                            <input type="text" class="form-control form-control-sm text-end w-auto" id="invoiceTotal"
                                   readonly />
                        </div>
                        <div class="mb-2 d-flex justify-content-between align-items-center">
                            <label class="form-label mb-0">VAT</label>
                            <input type="text" class="form-control form-control-sm text-end w-auto" id="vatAmount"
                                   readonly />
                        </div>
                        <div class="mb-2 d-flex justify-content-between align-items-center">
                            <label class="form-label mb-0">Grand Total</label>
                            <input type="text" class="form-control form-control-sm text-end w-auto" id="grandTotal"
                                   readonly />
                        </div>
                        <div class="mb-2 justify-content-between align-items-center d-none" id="commissionBlock">
                            <label class="form-label mb-0">Broker Commission</label>
                            <input type="text" class="form-control form-control-sm text-end w-auto" id="commissionValue"
                                   readonly />
                        </div>
                        <div id="footerControls" class="mt-3 text-end">
                            <button id="commitBtn" class="btn btn-secondary" onclick="triggerUpdateValidation()"
                                    data-mdb-tooltip-init data-mdb-placement="top" data-mdb-trigger="hover"
                                    title="Update invoice">Update Invoice</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="row mt-4">
            <div class="col-md-12">
                <label for="invoiceNotes" class="form-label"><strong>Invoice Notes / Comments</strong></label>
                <textarea id="invoiceNotes" class="form-control" rows="3" placeholder="Optional notes..."></textarea>
            </div>
        </div>
    </div>
</div>

<script>
let invoiceHasUnsavedChanges = false;
let commissionData = null;
window.editClientId = 0;

const parseGBP = (v) => parseFloat(String(v).replace(/[^0-9.-]/g, '')) || 0;
const formatGBP = (v) => `${Number(v || 0).toLocaleString('en-GB', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;

let itemsEdited = false;
let currentVatRate = 0;

window.addEventListener('DOMContentLoaded', function() {
    const invNo = <?= (int)$invNo ?>;
    if (!invNo) {
        showResponse('danger', 'Missing invoice number.');
        return;
    }

    const url = `${ROOT_URL}/includes/finance/invoices/load_invoice_edit.php?tenant=${TENANT_URL}&invNo=${invNo}`;
    fetch(url)
        .then(r => r.json())
        .then(data => {
            if (!data || data.status !== 'success') {
                showResponse('danger', data?.message || 'Load failed');
                return;
            }

            // Show header blocks
            document.getElementById('invoiceNumberBlock').style.display = 'block';
            document.getElementById('invoiceDateBlock').style.display = 'block';
            document.getElementById('purchaseOrderBlock').style.display = 'block';

            // Core fields
            document.getElementById('invoiceNumber').value = data.invoicenumber || invNo;
            document.getElementById('invoiceDate').value = data.invoice_date_ddmmyyyy || '';
            document.getElementById('purchaseOrder').value = data.purchase_order || '';
            document.getElementById('invoiceNotes').value = data.notes || '';

            // Cards
            document.getElementById('billingInfo').innerHTML = data.billing || '';
            document.getElementById('accountInfo').innerHTML = data.account || '';

            // Items
            const tbody = document.getElementById('invoiceItems');
            tbody.innerHTML = '';
            (data.items || []).forEach(it => {
                const tr = document.createElement('tr');
                tr.innerHTML = `
          <td class="align-middle service" contenteditable="true" oninput="markItemsEditedAndRecalc()">${(it.service ?? '').toString().trim()}</td>
          <td class="align-middle notes"   contenteditable="true">${(it.notes ?? '').toString().trim()}</td>
          <td class="align-middle fee"     contenteditable="true" oninput="markItemsEditedAndRecalc()">${parseGBP(it.rate).toFixed(2)}</td>
          <td class="align-middle qty-controls">
            <div class="d-flex align-items-center">
              <button type="button" class="btn btn-sm btn-secondary me-1" onclick="adjustQty(this,-1)"><i class="fad fa-minus"></i></button>
              <span class="qty">${parseFloat(it.quantity ?? 1)}</span>
              <button type="button" class="btn btn-sm btn-secondary ms-1" onclick="adjustQty(this, 1)"><i class="fad fa-plus"></i></button>
            </div>
          </td>
          <td class="align-middle text-center">
            <button type="button" class="btn btn-sm btn-danger" onclick="confirmRemoveRow(this)" data-mdb-tooltip-init data-mdb-placement="bottom" data-mdb-trigger="hover" title="Remove entry">
              <i class="fad fa-trash"></i>
            </button>
          </td>`;
                tbody.appendChild(tr);
            });

            // Routing flags + client id
            window.editClientId = parseInt(data.clientnumber || 0, 10);
            window.brokerNumber = parseInt(data.broker_number || 0, 10);
            window.agentNumber = parseInt(data.agent_number || 0, 10);
            window.isBroker = data.is_broker === true;
            window.isAgent = data.is_agent === true;

            // Commission visibility
            const block = document.getElementById('commissionBlock');
            if (data.commission) {
                commissionData = data.commission;
                block.classList.remove('d-none');
                block.classList.add('d-flex');
            } else {
                commissionData = null;
                block.classList.remove('d-flex');
                block.classList.add('d-none');
            }

            // Show container and init datepicker
            document.getElementById('invoiceContainer').style.display = 'block';
            initDatepickerInline();

            // VAT rate + seed totals from DB
            currentVatRate = parseGBP(data && data.totals && data.totals.vatrate);
            const netFromDb = parseGBP(data && data.totals && data.totals.net);
            const vatFromDb = parseGBP(data && data.totals && data.totals.vat);
            document.getElementById('invoiceTotal').value = formatGBP(netFromDb);
            document.getElementById('vatAmount').value = formatGBP(vatFromDb);
            document.getElementById('grandTotal').value = formatGBP(netFromDb + vatFromDb);

            // Commission
            const comInput = document.getElementById('commissionValue');
            if (data.commission) {
                commissionData = data.commission;

                // 1) initially show stored invoice commission
                if (parseGBP(commissionData.initial_amount) > 0) {
                    comInput.value = `Existing Commission = ${formatGBP(parseGBP(commissionData.initial_amount))}`;
                    window.calculatedCommissionAmount = parseGBP(commissionData.initial_amount).toFixed(2);
                }

                // 2) now compute rule-based final on NET
                const val = parseGBP(commissionData.value);
                const final = commissionData.type === 0 ? netFromDb * (val / 100) : val;
                window.calculatedCommissionAmount = final.toFixed(2);
                comInput.value = `${commissionData.label} = ${formatGBP(final)}`;
            } else {
                commissionData = null;
                comInput.value = '';
                window.calculatedCommissionAmount = '0.00';
            }

            // Track changes (non-item fields)
            document.querySelectorAll('#invoiceApp input, #invoiceApp textarea').forEach(el => {
                el.addEventListener('input', () => {
                    invoiceHasUnsavedChanges = true;
                });
            });

            // Keep DB totals until first edit
            itemsEdited = false;
            renderBreadcrumbs(invNo);
        })
        .catch(err => {
            showResponse('danger', 'Failed to load invoice: ' + err.message);
        });
});

function markItemsEditedAndRecalc() {
    itemsEdited = true;
    calculateInvoiceTotal();
}

function renderBreadcrumbs(invNo) {
    const nav = document.getElementById('navBox');
    if (!nav) return;
    nav.innerHTML = '\
<li class="breadcrumb-item">Finance - Invoices <i class="fad fa-angle-double-right mx-2 mt-1"></i></li>\
<li class="breadcrumb-item"><a href="index.php?t=includes/finance&p=finance_unpaid.php">Outstanding</a> <i class="fad fa-angle-double-right mx-2 mt-1"></i></li>\
<li class="breadcrumb-item active">Edit #' + invNo + '</li>';
}

function initDatepickerInline() {
    const container = document.getElementById('invoiceApp');
    container.querySelectorAll('.date-picker').forEach((el) => {
        let existing = null;
        try {
            if (mdb.Datepicker && typeof mdb.Datepicker.getInstance === 'function') {
                existing = mdb.Datepicker.getInstance(el);
            }
        } catch (e) {}
        if (existing || el._invoiceEditDatepicker) return;

        const options = {
            confirmDateOnSelect: true,
            format: 'dd-mm-yyyy'
        };
        el._invoiceEditDatepicker = new mdb.Datepicker(el, options);
    });
    bindInvoiceDatepickerBackdropCleanup(container);
}

function bindInvoiceDatepickerBackdropCleanup(container) {
    if (container._invoiceDatepickerBackdropCleanupBound) return;
    container._invoiceDatepickerBackdropCleanupBound = true;

    const cleanup = () => {
        setTimeout(() => {
            document.querySelectorAll('.datepicker-backdrop').forEach((backdrop) => backdrop.remove());
        }, 150);
    };

    container.addEventListener('close.mdb.datepicker', cleanup);
    container.addEventListener('valueChanged.mdb.datepicker', cleanup);
    container.addEventListener('change', (ev) => {
        if (ev.target.closest('input[data-mdb-toggle="datepicker"]')) cleanup();
    });
    document.addEventListener('click', (ev) => {
        if (ev.target.closest('.datepicker-cancel-btn, .datepicker-ok-btn, .datepicker-cell')) cleanup();
    });
}

function convertDateToTimestamp(s) {
    const p = (s || '').split('-');
    const d = new Date(p[2], p[1] - 1, p[0]);
    return Math.floor(d.getTime() / 1000);
}

function openNewItemModal() {
    const cid = window.editClientId || 0;
    const dest = `${ROOT_URL}/includes/finance/invoices/new_item_modal.php?tenant=${TENANT_URL}&clientnumber=${cid}`;
    loadModalContent(dest, 'newItemModal', 'modal-lg', 1060, 'true', 'New Item', 'cancelConfirm', submitNewInvoiceItem);
}

function submitNewInvoiceItem() {
    const f = document.getElementById('newInvoiceItemForm');
    const service = f.service.value.trim();
    const notes = f.notes.value.trim();
    const fee = parseFloat(f.fee.value);
    const qty = parseInt(f.qty.value, 10);
    if (!notes || isNaN(fee) || isNaN(qty)) {
        showModalToast('Both Fee and Notes are required.');
        return;
    }
    const tr = document.createElement('tr');
    tr.innerHTML =
        `
    <td class="align-middle service" contenteditable="true" oninput="markItemsEditedAndRecalc()">${service}</td>
    <td class="align-middle notes" contenteditable="true">${notes}</td>
    <td class="align-middle fee" contenteditable="true" oninput="markItemsEditedAndRecalc()">${fee.toFixed(2)}</td>
    <td class="align-middle qty-controls"><div class="d-flex align-items-center">
      <button type="button" class="btn btn-sm btn-secondary me-1" onclick="adjustQty(this,-1)"><i class="fad fa-minus"></i></button>
      <span class="qty">${qty || 1}</span>
      <button type="button" class="btn btn-sm btn-secondary ms-1" onclick="adjustQty(this,1)"><i class="fad fa-plus"></i></button>
    </div></td>
    <td class="align-middle text-center"><button type="button" class="btn btn-sm btn-danger" onclick="confirmRemoveRow(this)" data-mdb-tooltip-init data-mdb-placement="bottom" data-mdb-trigger="hover" title="Remove entry"><i class="fad fa-trash"></i></button></td>`;
    document.getElementById('invoiceItems').appendChild(tr);
    itemsEdited = true;
    calculateInvoiceTotal();
    killModal('newItemModal');
}

function adjustQty(btn, delta) {
    const s = btn.parentElement.querySelector('.qty');
    let n = parseInt(s.textContent, 10);
    n += delta;
    if (n < 1) n = 1;
    s.textContent = n;
    itemsEdited = true;
    calculateInvoiceTotal();
}

function confirmRemoveRow(btn) {
    const row = btn.closest('tr');
    const svc = row.querySelector('.service')?.textContent || 'this item';
    loadModalContent(`<p>Remove entry: <strong>${svc}</strong>?</p>`, 'popupBox', 'modal-md', 1060, 'true', 'Confirm Removal', 'cancelConfirm', () => {
        row.remove();
        itemsEdited = true;
        calculateInvoiceTotal();
        killModal('popupBox');
    });
}

function calculateInvoiceTotal() {
    if (!itemsEdited) return;

    let subtotal = 0;
    document.querySelectorAll('#invoiceItems tr').forEach(r => {
        const fee = parseGBP(r.querySelector('.fee')?.textContent || '0');
        const qty = parseGBP(r.querySelector('.qty')?.textContent || '1') || 1;
        subtotal += fee * qty;
    });

    const vat = subtotal * (currentVatRate || 0);
    const grand = subtotal + vat;

    document.getElementById('invoiceTotal').value = formatGBP(subtotal);
    document.getElementById('vatAmount').value = formatGBP(vat);
    document.getElementById('grandTotal').value = formatGBP(grand);

    const comInput = document.getElementById('commissionValue');
    if (commissionData) {
        const val = parseGBP(commissionData.value);
        const comAmount = commissionData.type === 0 ? subtotal * (val / 100) : val; // NET base
        window.calculatedCommissionAmount = comAmount.toFixed(2);
        comInput.value = `${commissionData.label} = ${formatGBP(comAmount)}`;
    } else {
        comInput.value = '';
        window.calculatedCommissionAmount = '0.00';
    }
}

function triggerUpdateValidation() {
    if (document.querySelectorAll('#invoiceItems tr').length === 0) {
        loadModalContent('<p class="text-danger"><i class="fad fa-exclamation-triangle me-2"></i> Add at least one invoice item before updating.</p>', 'popupBox', 'modal-md', 1060, 'true', 'Validation Error', 'close');
        return;
    }
    loadModalContent('<p>Update this invoice now?</p>', 'popupBox', 'modal-md', 1060, 'true', 'Confirm Update', 'cancelConfirm', () => {
        killModal('popupBox');
        applyInvoiceUpdate();
    });
}

function applyInvoiceUpdate() {
    const clientId = window.editClientId || 0;
    const invoiceDate = document.getElementById('invoiceDate').value.trim();
    const dateTimestamp = convertDateToTimestamp(invoiceDate);
    const dueTimestamp = dateTimestamp + 30 * 24 * 60 * 60;
    const poNumber = document.getElementById('purchaseOrder')?.value.trim() || '';

    const subtotal = parseGBP(document.getElementById('invoiceTotal').value || '0');
    const vat = parseGBP(document.getElementById('vatAmount').value || '0');
    const vatRate = currentVatRate || 0;

    const invNo = parseInt((document.getElementById('invoiceNumber')?.value || '').trim(), 10) || <?= (int)$invNo ?>;
    if (!invNo) {
        showResponse('danger', 'Missing invoice number. Cannot update.');
        return;
    }

    const items = [];
    document.querySelectorAll('#invoiceItems tr').forEach(r => {
        const service = r.querySelector('.service')?.textContent.trim() || '';
        if (!service) return;
        const notes = r.querySelector('.notes')?.textContent.trim() || '';
        const rate = r.querySelector('.fee')?.textContent.trim() || '0';
        const qty = r.querySelector('.qty')?.textContent.trim() || '1';
        items.push({
            service,
            notes,
            rate,
            quantity: qty
        });
    });

    const invoiceNotes = document.getElementById('invoiceNotes')?.value || '';
    const aText = document.querySelector('#billingInfo')?.innerText || '';
    const addressData = {
        client_name: clientId,
        billing_name: (aText.match(/Name:\s+(.*)/) || [, ''])[1],
        billing1: (aText.match(/Billing1:\s+(.*)/) || [, ''])[1],
        billing2: (aText.match(/Billing2:\s+(.*)/) || [, ''])[1],
        billing_town: (aText.match(/Town:\s+(.*)/) || [, ''])[1],
        billing_county: (aText.match(/County:\s+(.*)/) || [, ''])[1],
        billing_postcode: (aText.match(/Postcode:\s+(.*)/) || [, ''])[1],
        email: '',
        contract_number: (document.querySelector('#accountInfo')?.innerText.match(/Contract:\s*([^\n]+)/) || [, ''])[1].trim(),
        commission: commissionData?.value?.toString() || '0.00'
    };

    const agentId = window.agentNumber || 0;
    const brokerId = window.brokerNumber || 0;
    let rtype = 'client',
        brokerCom = 0,
        agentCom = 0;
    if (window.isBroker) {
        rtype = 'broker';
        brokerCom = 1;
    } else if (window.isAgent) {
        rtype = 'agent';
        agentCom = 1;
    }

    const commissionAmount = (typeof window.calculatedCommissionAmount !== 'undefined') ?
        window.calculatedCommissionAmount :
        '0.00';

    const fd = new FormData();
    fd.append('invNo', invNo);
    fd.append('clientnumber', clientId);
    if (window.isBroker) fd.append('broker_number', brokerId);
    if (window.isAgent) fd.append('agent_number', agentId);
    fd.append('address', JSON.stringify(addressData));
    fd.append('items', JSON.stringify(items));
    fd.append('totals', `${subtotal}|${vat}`);
    fd.append('vatrate', vatRate);
    fd.append('date', dateTimestamp);
    fd.append('date_due', dueTimestamp);
    fd.append('commission', commissionAmount);
    fd.append('filter', 'Contract Renewal');
    fd.append('target', rtype);
    fd.append('invoiceNotes', invoiceNotes);
    fd.append('purchaseOrder', poNumber);
    fd.append('tenant', TENANT_URL);

    fetch(`${ROOT_URL}/includes/finance/invoices/update_invoice.php`, {
            method: 'POST',
            body: fd
        })
        .then(r => r.json())
        .then(j => {
            if (j.status !== 'success') throw new Error(j.message || 'Unknown error');
            showResponse('success', `Invoice #${invNo} updated successfully.`);
            invoiceHasUnsavedChanges = false;

            const post = new URLSearchParams();
            post.append('invNo', invNo);
            post.append('clientnumber', clientId);
            post.append('rtype', rtype);
            post.append('brokerCom', brokerCom);
            post.append('agentCom', agentCom);
            if (window.isBroker) post.append('broker_number', brokerId);
            if (window.isAgent) post.append('agent_number', agentId);
            post.append('tenant', TENANT_URL);

            return fetch(`${ROOT_URL}/includes/engines/invoice.php`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
                body: post.toString()
            });
        })
        .then(() => {
            // redirect after invoice saved and PDF generated
            setTimeout(() => {
                window.location.href = `index.php?t=includes/finance&p=finance_unpaid.php`;
            }, 600);
        })
        .catch(e => showResponse('danger', `Error updating invoice: ${e.message}`));

}
</script>
