/**
 * Confirmation for destructive actions.
 *
 * Destructive actions are always a POST/DELETE form — never a bare link — so
 * they cannot be triggered by a crawler, a prefetch or a stray GET. Any such
 * form opts into a confirmation dialog by declaring:
 *
 *     <form method="POST" action="..."
 *           data-ams-confirm="Delete AUM-LAP-0042? This cannot be undone."
 *           data-ams-confirm-title="Delete asset"
 *           data-ams-confirm-action="Delete">
 *
 * The same three attributes may instead sit on the *button* that submits the
 * form, and take priority over the form's own when present. This is what a
 * shared bulk-action form needs: one <form> serves an "Export Selected"
 * button (no confirmation) and a "Delete Selected" button (confirmation)
 * that lives outside the form entirely and points at it via `form="…"` — the
 * message belongs to the button's action, not to the form itself.
 *
 * One <x-confirm-modal /> instance in the layout serves every form on the page.
 * If JavaScript is unavailable the form still submits — the server-side policy
 * check is the real gate, not this dialog.
 */

import { Modal } from 'bootstrap';

const MODAL_SELECTOR = '#amsConfirmModal';

let pending = null;

document.addEventListener('submit', (event) => {
    const form = event.target;

    if (!(form instanceof HTMLFormElement)) {
        return;
    }

    // Set immediately before the programmatic re-submit below, so that exact
    // resubmission is let through without showing the dialog a second time.
    if (form.dataset.amsConfirmBypass === '1') {
        delete form.dataset.amsConfirmBypass;

        return;
    }

    const submitter = event.submitter instanceof HTMLElement ? event.submitter : null;
    const source = submitter?.dataset.amsConfirm ? submitter.dataset : form.dataset;
    const message = source.amsConfirm;

    if (!message) {
        return;
    }

    const modalElement = document.querySelector(MODAL_SELECTOR);

    // No modal on the page: fall back to the browser dialog rather than
    // letting a destructive action through unconfirmed.
    if (!modalElement) {
        if (!window.confirm(message)) {
            event.preventDefault();
        }

        return;
    }

    event.preventDefault();

    pending = { form, submitter };

    modalElement.querySelector('[data-ams-confirm-title]').textContent =
        source.amsConfirmTitle || 'Please confirm';

    modalElement.querySelector('[data-ams-confirm-message]').textContent = message;

    const acceptButton = modalElement.querySelector('[data-ams-confirm-accept]');
    acceptButton.textContent = source.amsConfirmAction || 'Confirm';

    Modal.getOrCreateInstance(modalElement).show();
});

document.addEventListener('DOMContentLoaded', () => {
    const modalElement = document.querySelector(MODAL_SELECTOR);

    if (!modalElement) {
        return;
    }

    modalElement
        .querySelector('[data-ams-confirm-accept]')
        .addEventListener('click', () => {
            if (!pending) {
                return;
            }

            const { form, submitter } = pending;
            pending = null;

            Modal.getOrCreateInstance(modalElement).hide();

            form.dataset.amsConfirmBypass = '1';

            // Clicking the original submitter — even one that lives outside
            // the form via form="…" — resubmits honouring its own
            // formaction/formmethod overrides, which a plain form.submit()
            // would silently discard.
            if (submitter instanceof HTMLElement && typeof submitter.click === 'function') {
                submitter.click();
            } else {
                HTMLFormElement.prototype.submit.call(form);
            }
        });

    // Dismissing the dialog must not leave a form armed for the next confirm.
    modalElement.addEventListener('hidden.bs.modal', () => {
        pending = null;
    });
});
