<?php
// includes/finance/finance_preview.php

// Expect: TENANT_URL, ROOT_URL, $GLOBALS['con'] already defined in master config.

switch ($_REQUEST['type'] ?? '') {
    default:
        $label  = '';
        $script = '';
        break;
    case "outstanding":
        $label = 'Outstanding';
        $script = 'finance_unpaid';
        break;
    case "paid":
        $label = 'Paid';
        $script = 'finance_paid';
        break;
    case "archive":
        $label = 'Archived';
        $script = 'finance_archive';
        break;
}

//////////////////////////
/// PAYMENT STATUS     ///
/// 1 - Unpaid         ///
/// 2 - Reminder       ///
/// 3 - Paid           ///
/// 4 - Refund         ///
//////////////////////////

$invNo = (int)($_REQUEST['invNo'] ?? 0);

$stmt = $GLOBALS['con']->prepare("SELECT * FROM `invoices` WHERE `invNo`=?");
$stmt->bind_param('i', $invNo);
$stmt->execute();
$i = $stmt->get_result();
$stmt->close();
$id = mysqli_fetch_array($i);

if (!$id) {
    echo '<div class="alert alert-danger">Invoice not found.</div>';
    exit;
}

if ($id['target'] === "client" || $id['target'] === 'blank' || empty($id['target'])) {
    $id['target'] = "invoice";
}

switch ($id['status']) {
    default:
        $status = '<small><i>Status</i></small> <span class="badge badge-secondary">Unknown</span>';
        break;
    case "1":
        $status = '<small><i>Status</i></small> <span class="badge badge-danger">Unpaid</span>';
        break;
    case "2":
        $status = '<small><i>Status</i></small> <span class="badge badge-warning">Reminder Sent</span>';
        break;
    case "3":
        $status = '<small><i>Status</i></small> <span class="badge badge-success">Paid</span>';
        break;
    case "4":
        $status = '<small><i>Status</i></small> <span class="badge badge-dark">Refunded</span>';
        break;
}

$brokerNumber = (int)($id['broker'] ?? 0);
$agentNumber  = (int)($id['agent'] ?? 0);
echo "broker=".$brokerNumber;/*
    finance_preview does not currently have separate working values for brokerCom/agentCom
    like the edit page example. Use the stored invoice commission as fallback for both.
    If you later expose split values here, replace these two assignments only.
*/
$brokerCom = (string)($id['commission'] ?? '0');
$agentCom  = (string)($id['commission'] ?? '0');
?>
<div id="loadingObject" style="position: fixed; top:50%; width:100%; display:none;">
    <h1 class="text-center">
        <i class="fad fa-file-invoice fa-spin fa-3x fa-fw"
           style="--fa-primary-color: #0055A6; --fa-secondary-color: gray;"></i><br>
        Loading Invoice <br><small>Please wait</small>
    </h1>
</div>

<script>
document.getElementById('navBox').innerHTML =
    '<li class="breadcrumb-item"><a href="index.php?t=includes/finance&p=finance_invoices.php">Finance - Invoices</a> <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></li> <i class="fad fa-angle-double-right mx-2 mt-1"></i></li><li class="breadcrumb-item active">Preview</li>';
</script>

<style>
#wrapper {
    height: 70vh
}

#previewContainer {
    position: relative;
    display: block;
    height: 100% !important;
    width: 100%;
}

.pdfobject-container {
    height: 100%;
}

.pdfv-root {
    display: flex;
    flex-direction: column;
    min-height: 0;
    height: auto;
}

.pdfv-toolbar {
    display: flex;
    gap: .5rem;
    align-items: center;
    padding: .5rem .75rem;
    border-bottom: 1px solid var(--primary-color-muted);
    background: var(--primary-color);
    border-top-left-radius: 5px;
    border-top-right-radius: 5px;
}

.pdfv-btn {
    border: 1px solid #ddd;
    background: #fff;
    padding: .4rem .6rem;
    border-radius: .375rem;
    cursor: pointer;
}

.pdfv-counter {
    font: 500 14px/1 system-ui, Arial, sans-serif;
    color: #ffffff
}

.spacer {
    flex: 1;
}

.pdfv-body {
    flex: 1;
    min-height: 0;
    display: flex;
    overflow: hidden;
    background: #f2f2f2;
}

.pdfv-side {
    width: 200px;
    max-width: 50vw;
    min-width: 140px;
    border-right: 1px solid #e5e5e5;
    overflow: auto;
    background: #fff;
    display: none;
}

.pdfv-side.open {
    display: block;
}

.pdfv-thumbs {
    display: grid;
    grid-template-columns: 1fr;
    gap: .5rem;
    padding: .5rem;
}

.pdfv-thumb {
    border: 1px solid #ddd;
    border-radius: .25rem;
    overflow: hidden;
    background: #f9f9f9;
    cursor: pointer;
}

.pdfv-thumb img {
    display: block;
    width: 100%;
    height: auto;
}

.pdfv-thumb.active {
    outline: 2px solid #3b82f6;
}

.pdfv-stage {
    flex: 1;
    min-width: 0;
    overflow: auto;
    display: grid;
    place-items: start center;
    padding: 1rem;
}

.pdfv-page-wrap {
    background: #fff;
    box-shadow: 0 1px 6px rgba(0, 0, 0, .08);
    transform-origin: top center;
}

.pdfv-page {
    display: block;
    width: 100%;
    height: auto;
}

@media (max-width: 600px) {
    .pdfv-toolbar {
        flex-wrap: wrap;
    }
}
</style>

<div class="row">
    <div class="col-12 col-md-6">
        <h3>
            <span class="text-muted">Previewing Invoice</span>
            <strong>#<?php echo $invNo; ?></strong>: <?php echo $status; ?>
        </h3>
    </div>
    <div class="col-12 col-md-6">
        <div class="float-end">
            <?php if ($brokerNumber > 0) { ?>
            <a href="javascript:void(0)" class="btn btn-secondary noprint"
               data-mdb-tooltip-init data-mdb-placement="bottom" data-mdb-trigger="hover" title="Broker Invoice"
               onclick="invLoader('broker')">
                <i class="fad fa-file-pdf"></i> Broker Invoice
            </a>
            <?php } ?>

            <?php if ($agentNumber > 0) { ?>
            <a href="javascript:void(0)" class="btn btn-secondary noprint"
               data-mdb-tooltip-init data-mdb-placement="bottom" data-mdb-trigger="hover" title="Agent Invoice"
               onclick="invLoader('agent')">
                <i class="fad fa-file-pdf"></i> Agent Invoice
            </a>
            <?php } ?>

            <a href="javascript:void(0)" class="btn btn-secondary noprint"
               data-mdb-tooltip-init data-mdb-placement="bottom" data-mdb-trigger="hover" title="Client Invoice"
               onclick="invLoader('invoice')">
                <i class="fad fa-file-pdf"></i> Client Invoice
            </a>

            <a href="javascript:void(0)" class="btn btn-secondary noprint"
               data-mdb-tooltip-init data-mdb-placement="bottom" data-mdb-trigger="hover" title="Reminder"
               onclick="invLoader('remind')">
                <i class="fad fa-file-pdf"></i> Reminder
            </a>

            <a href="javascript:void(0)" class="btn btn-secondary noprint"
               data-mdb-tooltip-init data-mdb-placement="bottom" data-mdb-trigger="hover" title="Proforma"
               onclick="invLoader('proforma')">
                <i class="fad fa-file-pdf"></i> Proforma
            </a>

            <a href="javascript:void(0)" class="btn btn-secondary noprint"
               data-mdb-tooltip-init data-mdb-placement="bottom" data-mdb-trigger="hover" title="Remittance"
               onclick="invLoader('remit')">
                <i class="fad fa-file-pdf"></i> Remittance
            </a>
        </div>
    </div>
</div>

<div id="pdfv" class="pdfv-root mt-4"></div>

<script>
function sizePdfViewer() {
    const v = document.getElementById('pdfv');
    if (!v) return;
    const footer = document.querySelector('footer');
    const footerH = footer ? footer.offsetHeight : 0;
    const top = v.getBoundingClientRect().top;
    const avail = Math.max(300, window.innerHeight - top - footerH);
    v.style.height = avail + 'px';
}
window.addEventListener('resize', sizePdfViewer);
document.addEventListener('DOMContentLoaded', sizePdfViewer);

// preserve original if present
const _oldPdfImageViewer = window.pdfImageViewer;
window.pdfImageViewer = function(id, payload) {
    if (typeof _oldPdfImageViewer === 'function') _oldPdfImageViewer(id, payload);
    sizePdfViewer();
};

(function() {
    function ce(t, c) {
        const e = document.createElement(t);
        if (c) e.className = c;
        return e;
    }

    function mkBtn(t) {
        const b = ce('button', 'pdfv-btn');
        b.type = 'button';
        b.textContent = t;
        return b;
    }

    function guessName(u) {
        try {
            const p = new URL(u, location.href);
            return p.pathname.split('/').pop();
        } catch {
            return null;
        }
    }

    function pdfImageViewer(rootId, payload) {
        const root = document.getElementById(rootId);
        if (!root) return;
        const pages = payload.pages || [];
        const total = pages.length;

        if (!total) {
            root.textContent = 'No pages.';
            return;
        }

        const tb = ce('div', 'pdfv-toolbar');
        const btnIndex = mkBtn('Index'),
            btnOut = mkBtn('−'),
            btnIn = mkBtn('+');
        const counter = ce('div', 'pdfv-counter');
        counter.textContent = `Page 1 / ${total}`;
        const spacer = ce('div', 'spacer');
        const btnFull  = mkBtn('Fullscreen');
        const btnPrint = mkBtn('Print');
        const btnDL    = mkBtn('Download');

        btnPrint.setAttribute('data-mdb-tooltip-init', '');
        btnPrint.setAttribute('data-mdb-placement', 'top');
        btnPrint.setAttribute('data-mdb-trigger', 'hover');
        btnPrint.setAttribute('title', 'Print');

        btnDL.setAttribute('data-mdb-tooltip-init', '');
        btnDL.setAttribute('data-mdb-placement', 'top');
        btnDL.setAttribute('data-mdb-trigger', 'hover');
        btnDL.setAttribute('title', 'Download');

        tb.append(btnIndex, btnOut, btnIn, counter, spacer, btnFull, btnPrint, btnDL);

        const body = ce('div', 'pdfv-body');
        const side = ce('aside', 'pdfv-side');
        const thumbs = ce('div', 'pdfv-thumbs');
        side.appendChild(thumbs);

        const stage = ce('div', 'pdfv-stage');
        const wrap = ce('div', 'pdfv-page-wrap');
        const img = new Image();
        img.className = 'pdfv-page';
        wrap.appendChild(img);
        stage.appendChild(wrap);
        body.append(side, stage);

        root.innerHTML = '';
        root.append(tb, body);

        const st = {
            i: 1,
            scale: 1,
            min: 0.4,
            max: 3
        };

        function goto(n) {
            if (n < 1 || n > total) return;
            st.i = n;
            img.src = pages[n - 1];
            counter.textContent = `Page ${st.i} / ${total}`;
            hilite();
        }

        function hilite() {
            [...thumbs.children].forEach((t, idx) => t.classList.toggle('active', idx === st.i - 1));
        }

        function setScale(s) {
            st.scale = Math.max(st.min, Math.min(st.max, s));
            wrap.style.transform = `scale(${st.scale})`;
        }

        btnIndex.onclick = () => side.classList.toggle('open');
        btnIn.onclick = () => setScale(st.scale * 1.15);
        btnOut.onclick = () => setScale(st.scale / 1.15);
        btnFull.onclick = () => toggleFS(root);

        btnDL.onclick = () => {
            const a = document.createElement('a');
            a.href = payload.downloadUrl || pages[0];
            a.download = payload.filename || guessName(payload.downloadUrl) || 'document.pdf';
            document.body.appendChild(a);
            a.click();
            a.remove();
        };

        btnPrint.onclick = () => {
            const pdfUrl = payload.downloadUrl;

            if (!pdfUrl) {
                if (typeof showResponse === 'function') {
                    showResponse('warning', 'Print is not available (PDF URL missing).');
                }
                return;
            }

            const existing = document.getElementById('pdfPrintFrame');
            if (existing) existing.remove();

            const iframe = document.createElement('iframe');
            iframe.id = 'pdfPrintFrame';
            iframe.style.position = 'fixed';
            iframe.style.right = '0';
            iframe.style.bottom = '0';
            iframe.style.width = '0';
            iframe.style.height = '0';
            iframe.style.border = '0';
            iframe.style.visibility = 'hidden';

            const bust = (pdfUrl.indexOf('?') === -1 ? '?' : '&') + 't=' + Date.now();
            iframe.src = pdfUrl + bust;

            iframe.onload = () => {
                try {
                    iframe.contentWindow.focus();
                    iframe.contentWindow.print();
                } catch (e) {
                    if (typeof showResponse === 'function') {
                        showResponse('warning', 'Unable to invoke print for this PDF in this browser.');
                    }
                }

                setTimeout(() => {
                    try {
                        iframe.remove();
                    } catch (e) {}
                }, 1500);
            };

            document.body.appendChild(iframe);
        };

        window.addEventListener('keydown', (e) => {
            if (/input|textarea|select/i.test(e.target.tagName)) return;

            if (e.key === 'ArrowRight' || e.key === 'PageDown') {
                e.preventDefault();
                goto(st.i + 1);
            }

            if (e.key === 'ArrowLeft' || e.key === 'PageUp') {
                e.preventDefault();
                goto(st.i - 1);
            }

            if (e.key === '+') setScale(st.scale * 1.15);
            if (e.key === '-') setScale(st.scale / 1.15);
        });

        pages.forEach((src, idx) => {
            const th = ce('div', 'pdfv-thumb' + (idx === 0 ? ' active' : ''));
            const ti = new Image();
            ti.loading = 'lazy';
            ti.src = src;
            th.appendChild(ti);
            th.onclick = () => goto(idx + 1);
            thumbs.appendChild(th);
        });

        goto(1);
    }

    function toggleFS(el) {
        const d = document;
        if (!d.fullscreenElement && !d.webkitFullscreenElement) {
            (el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen)?.call(el);
        } else {
            (d.exitFullscreen || d.webkitExitFullscreen || d.msExitFullscreen)?.call(d);
        }
    }

    window.pdfImageViewer = pdfImageViewer;
})();
</script>

<script>
(() => {
    const INV_NO = <?= (int)$invNo ?>;
    const CLIENT_ID = <?= (int)($id['client'] ?? 0) ?>;
    const BROKER_NUMBER = <?= json_encode($brokerNumber ?? null) ?>;
    const AGENT_NUMBER = <?= json_encode($agentNumber ?? null) ?>;
    
    const BROKER_COM = (BROKER_NUMBER !== null && String(BROKER_NUMBER) !== '' && String(BROKER_NUMBER) !== '0') ? 1 : 0;
    const AGENT_COM = (AGENT_NUMBER !== null && String(AGENT_NUMBER) !== '' && String(AGENT_NUMBER) !== '0') ? 1 : 0;
    const TENANT = TENANT_URL;
    const API = `${ROOT_URL}/functions/pdf_rasterise.php`;
    const GENERATOR = `${ROOT_URL}/includes/engines/invoice.php`;
    const VIEWER_ID = 'pdfv';

    let inflight = null;
    let currentType = <?= json_encode($id['target']) ?>;
    let isGenerating = false;

    markActive(currentType);
    loadPdf(currentType);

    window.invLoader = (type) => {
        if (isGenerating) {
            return;
        }
        currentType = type;
        markActive(type);
        loadPdf(type);
    };

    function buildPdfUrl(type) {
        return `/invoices/${INV_NO}_${type}.pdf`;
    }

    function buildRasterUrl(type, extra = '') {
        const pdfUrl = buildPdfUrl(type);
        const qs = `tenant=${encodeURIComponent(TENANT)}&pdf=${encodeURIComponent(pdfUrl)}&t=${Date.now()}${extra}`;
        return `${API}?${qs}`;
    }

    async function fetchRasterData(type, signal, extra = '') {
        const res = await fetch(buildRasterUrl(type, extra), {
            signal,
            cache: 'no-store'
        });

        let data = {};
        try {
            data = await res.json();
        } catch (err) {
            data = {};
        }

        return data;
    }

    function hasPages(data) {
        return !!(data && Array.isArray(data.pages) && data.pages.length > 0);
    }

    function shouldAttemptRebuild(data) {
        const msg = String(data?.error || data?.message || '').toLowerCase();

        return (
            msg.includes('not found') ||
            msg.includes('missing') ||
            msg.includes('unable to open')
        );
    }

    function setBusy(state) {
        isGenerating = state;

        document.querySelectorAll('[onclick^="invLoader("]').forEach((btn) => {
            if (state) {
                btn.classList.add('disabled');
                btn.style.pointerEvents = 'none';
                btn.style.opacity = '0.65';
            } else {
                btn.classList.remove('disabled');
                btn.style.pointerEvents = '';
                btn.style.opacity = '';
            }
        });
    }

    async function rebuildPdf(type, signal) {
        const post = new URLSearchParams();
        post.append('invNo', String(INV_NO));
        post.append('clientnumber', String(CLIENT_ID));
        post.append('rtype', type);
        post.append('brokerCom', String(BROKER_COM || 0));
        post.append('agentCom', String(AGENT_COM || 0));
        post.append('tenant', TENANT);

        if (BROKER_NUMBER !== null && BROKER_NUMBER !== '' && String(BROKER_NUMBER) !== '0') {
            post.append('broker_number', String(BROKER_NUMBER));
        }

        if (AGENT_NUMBER !== null && AGENT_NUMBER !== '' && String(AGENT_NUMBER) !== '0') {
            post.append('agent_number', String(AGENT_NUMBER));
        }

        const res = await fetch(GENERATOR, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: post.toString(),
            cache: 'no-store',
            signal
        });

        const text = await res.text();

        if (!res.ok) {
            throw new Error('Unable to rebuild invoice PDF.');
        }

        return text.trim();
    }

    async function retryRasterAfterBuild(type, signal) {
        let data = {};

        for (let i = 0; i < 8; i++) {
            await new Promise((resolve) => setTimeout(resolve, 400));
            data = await fetchRasterData(type, signal, `&retry=${i}&r=${Math.random()}`);

            if (hasPages(data)) {
                return data;
            }
        }

        return data;
    }

    async function loadPdf(type) {
        if (inflight) {
            inflight.abort();
        }

        inflight = new AbortController();
        const signal = inflight.signal;

        const viewer = document.getElementById(VIEWER_ID);

        showLoadingIndicator('Generating Preview', 'fa-spinner fa-spin-reverse', null);
        if (viewer) {
            viewer.style.opacity = '0.2';
        }

        try {
            let data = await fetchRasterData(type, signal);

            if (!hasPages(data) && shouldAttemptRebuild(data)) {
                setBusy(true);
                removeLoadingIndicator();
                showLoadingIndicator('Generating Invoice PDF', 'fa-file-invoice', null);

                await rebuildPdf(type, signal);

                removeLoadingIndicator();
                showLoadingIndicator('Generating Preview', 'fa-spinner fa-spin-reverse', null);

                data = await retryRasterAfterBuild(type, signal);
            } else if (!hasPages(data)) {
                await new Promise((resolve) => setTimeout(resolve, 300));
                data = await fetchRasterData(type, signal, `&r=${Math.random()}`);
            }

            if (!hasPages(data)) {
                throw new Error(data?.error || 'No pages returned for this invoice preview.');
            }

            pdfImageViewer(VIEWER_ID, data);
        } catch (e) {
            if (e.name !== 'AbortError') {
                if (typeof showResponse === 'function') {
                    showResponse('danger', e.message || 'Unable to load invoice preview.');
                } else {
                    console.error(e);
                }
            }
        } finally {
            setBusy(false);
            removeLoadingIndicator();

            if (viewer) {
                viewer.style.opacity = '1';
            }

            sizePdfViewer();
        }
    }

    function markActive(type) {
        document.querySelectorAll('[onclick^="invLoader("]').forEach((a) => {
            a.classList.remove('active');
        });

        let btn = null;

        try {
            btn = document.querySelector(`[onclick="invLoader('${CSS.escape(type)}')"]`);
        } catch (e) {
            btn = document.querySelector(`[onclick="invLoader('${String(type).replace(/'/g, "\\'")}')"]`);
        }

        if (btn) {
            btn.classList.add('active');
        }
    }
})();
</script>