<?php
/**
 * Reusable TPIN confirmation modal.
 *
 * Include once on screens that need step-up confirmation:
 *   <?= view('Modules\Tpin\Views\partials\verify_modal') ?>
 *
 * Mark forms/links:
 *   <form ... data-tpin-confirm data-confirm-message="Optional browser confirm">
 *   <a href="..." data-tpin-confirm>
 *
 * Or call from JS:
 *   EnterpriseTpin.confirm({ skipIfNotRequired: true }).then(ok => { ... });
 */
if (! empty($GLOBALS['__enterprise_tpin_modal'])) {
    return;
}
$GLOBALS['__enterprise_tpin_modal'] = true;

$csrfName = csrf_token();
$csrfHash = csrf_hash();
?>
<div class="modal fade" id="enterpriseTpinModal" tabindex="-1" aria-labelledby="enterpriseTpinModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered modal-sm">
        <div class="modal-content">
            <div class="modal-header">
                <h2 class="modal-title h6" id="enterpriseTpinModalLabel">Confirm with TPIN</h2>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <p class="small text-muted mb-3">Enter your transaction PIN to continue.</p>
                <div id="enterpriseTpinError" class="alert alert-danger py-2 small d-none"></div>
                <label for="enterpriseTpinInput" class="form-label">TPIN</label>
                <input type="password" inputmode="numeric" pattern="\d{4,6}" maxlength="6"
                       class="form-control" id="enterpriseTpinInput" autocomplete="off">
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-sm btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
                <button type="button" class="btn btn-sm btn-primary" id="enterpriseTpinSubmit">Confirm</button>
            </div>
        </div>
    </div>
</div>

<script>
window.EnterpriseTpin = (function () {
    const verifyUrl = <?= json_encode(base_url('tpin/verify')) ?>;
    const statusUrl = <?= json_encode(base_url('tpin/status')) ?>;
    const csrfName = <?= json_encode($csrfName) ?>;
    let csrfHash = <?= json_encode($csrfHash) ?>;

    function getModal() {
        return document.getElementById('enterpriseTpinModal');
    }

    function showError(msg) {
        const el = document.getElementById('enterpriseTpinError');
        if (!el) return;
        el.textContent = msg || 'Verification failed.';
        el.classList.remove('d-none');
    }

    function clearError() {
        const el = document.getElementById('enterpriseTpinError');
        if (!el) return;
        el.textContent = '';
        el.classList.add('d-none');
    }

    async function status() {
        const res = await fetch(statusUrl, {
            headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
            credentials: 'same-origin',
        });
        return res.json();
    }

    /**
     * Opens the modal and resolves true if TPIN verified, false if cancelled/failed.
     * If the user is not required to confirm, resolves true immediately when skipIfNotRequired is true.
     */
    function confirm(options) {
        const opts = Object.assign({ skipIfNotRequired: false }, options || {});

        return new Promise(async (resolve) => {
            if (opts.skipIfNotRequired) {
                try {
                    const s = await status();
                    if (!s.must_confirm) {
                        resolve(true);
                        return;
                    }
                } catch (e) {
                    // Fall through to modal if status check fails.
                }
            }

            const modalEl = getModal();
            if (!modalEl || typeof bootstrap === 'undefined') {
                resolve(false);
                return;
            }

            const input = document.getElementById('enterpriseTpinInput');
            const submitBtn = document.getElementById('enterpriseTpinSubmit');
            const modal = bootstrap.Modal.getOrCreateInstance(modalEl);
            let settled = false;

            function finish(ok) {
                if (settled) return;
                settled = true;
                modal.hide();
                resolve(ok);
            }

            clearError();
            if (input) input.value = '';

            const onHidden = function () {
                modalEl.removeEventListener('hidden.bs.modal', onHidden);
                if (!settled) finish(false);
            };
            modalEl.addEventListener('hidden.bs.modal', onHidden);

            const onSubmit = async function () {
                clearError();
                const tpin = (input && input.value) ? input.value.trim() : '';
                if (!tpin) {
                    showError('Enter your TPIN.');
                    return;
                }

                const body = new URLSearchParams();
                body.set('tpin', tpin);
                body.set(csrfName, csrfHash);

                try {
                    const res = await fetch(verifyUrl, {
                        method: 'POST',
                        headers: {
                            'Accept': 'application/json',
                            'Content-Type': 'application/x-www-form-urlencoded',
                            'X-Requested-With': 'XMLHttpRequest',
                        },
                        credentials: 'same-origin',
                        body: body.toString(),
                    });
                    const data = await res.json();
                    if (data.csrf_hash) csrfHash = data.csrf_hash;
                    if (data.success) {
                        finish(true);
                    } else {
                        showError(data.error || 'Incorrect TPIN.');
                    }
                } catch (e) {
                    showError('Could not verify TPIN. Try again.');
                }
            };

            if (submitBtn) {
                submitBtn.onclick = onSubmit;
            }
            if (input) {
                input.onkeydown = function (ev) {
                    if (ev.key === 'Enter') {
                        ev.preventDefault();
                        onSubmit();
                    }
                };
            }

            modal.show();
            setTimeout(function () { if (input) input.focus(); }, 300);
        });
    }

    function bind(root) {
        const scope = root || document;
        scope.querySelectorAll('[data-tpin-confirm]').forEach(function (el) {
            if (el.dataset.tpinBound === '1') return;
            el.dataset.tpinBound = '1';

            if (el.tagName === 'A') {
                el.addEventListener('click', async function (ev) {
                    if (ev.defaultPrevented) return;
                    ev.preventDefault();
                    const ok = await confirm({ skipIfNotRequired: true });
                    if (ok) {
                        window.location.href = el.href;
                    }
                });
                return;
            }

            if (el.tagName === 'FORM') {
                el.addEventListener('submit', async function (ev) {
                    if (el.dataset.tpinVerified === '1') {
                        el.dataset.tpinVerified = '0';
                        return;
                    }

                    ev.preventDefault();
                    ev.stopImmediatePropagation();

                    const msg = el.getAttribute('data-confirm-message');
                    if (msg && !window.confirm(msg)) {
                        return;
                    }

                    const ok = await confirm({ skipIfNotRequired: true });
                    if (ok) {
                        const csrfInput = el.querySelector('input[name="' + csrfName + '"]');
                        if (csrfInput) csrfInput.value = csrfHash;
                        const meta = document.querySelector('meta[name="csrf-token"]');
                        if (meta) meta.setAttribute('content', csrfHash);
                        el.dataset.tpinVerified = '1';
                        if (typeof el.requestSubmit === 'function') {
                            el.requestSubmit();
                        } else {
                            HTMLFormElement.prototype.submit.call(el);
                        }
                    }
                }, true);
            }
        });
    }

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

    return { status, confirm, bind, verifyUrl, statusUrl };
})();
</script>
