/**
 * Mini form for downloading a bundle from prod.
 *
 * @package EaLab\WP_Deployer
 */

(() => {
    const disableAllButtons = () => {
        const currentButtonElements = document.querySelectorAll('deploy-sync-content--download-prod-bundle');
        currentButtonElements.forEach((toDisable) => {
            const toDisableButton = toDisable.querySelector('button');
            toDisableButton.dataset.inProgress = 'true';
            toDisableButton.classList.add('disabled');
        });
    };

    const enableAllButtons = () => {
        const currentButtonElements = document.querySelectorAll('deploy-sync-content--download-prod-bundle');
        currentButtonElements.forEach((toEnable) => {
            const toDisableButton = toEnable.querySelector('button');
            delete toDisableButton.dataset.inProgress;
            toDisableButton.classList.remove('disabled');
        });
    }

    const handle = () => {
        // Retrieve all components.
        const components = document.querySelectorAll('deploy-sync-content--download-prod-bundle');

        components.forEach((component) => {
            if (component.getAttribute('data-initialized') === 'true') {
                // The component is already initialized.
                return;
            }

            // Mark the component as initialized.
            component.setAttribute('data-initialized', 'true');

            const button = component.querySelector('button');
            const statusText = component.querySelector('.status-text');
            const sinceInput = component.querySelector('input[name="since"]');
            const bundleLabelInput = component.querySelector('input[name="bundle_label"]');

            // Append the action on click on the button.
            button.addEventListener('click', () => {
                if (button.dataset.inProgress) {
                    // A request is already in progress.
                    // Wait for it to finish.
                    return;
                }

                // Disable all buttons.
                disableAllButtons();

                statusText.classList.add('in-progress');
                statusText.classList.remove('ok', 'not-ok');
                statusText.textContent = deploy_sync_content__component_settings?.text?.inProgress ?? 'In progress…';

                // Add the nonce header to the request.
                const headers = new Headers();
                headers.append('X-WP-Nonce', deploy_sync_content__component_settings?.rest?.nonce ?? '');

                const url = component.dataset.url ?? '';

                if (!url) {
                    return;
                }

                const urlObj = new URL(url);

                const params = {
                    since: sinceInput.value,
                    bundle_label: bundleLabelInput.value,
                }

                urlObj.search = new URLSearchParams(params);

                const setErrorStatusText = (additionalMessage) => {
                    let fullReason = (deploy_sync_content__component_settings?.text?.requestError ?? 'The request failed.');

                    if (additionalMessage.length > 0) {
                        fullReason += ' ' + additionalMessage;
                    }

                    statusText.innerHTML = fullReason;

                    statusText.classList.add('not-ok');
                };

                fetch(urlObj, {method: 'POST', headers: headers})
                    .then((response) => {
                        response.json()
                            .then((json) => {
                                if (!response.ok) {
                                    const defaultMessage = deploy_sync_content__component_settings?.text?.error ?? 'An error occurred. Please check your network status or the basic Deploy & Sync Content settings, or try again later.';

                                    let errorDetailsMessage = '';

                                    if ([401, 403, 405].includes(response.status)) {
                                        // Forbidden. Not allowed.
                                        errorDetailsMessage = deploy_sync_content__component_settings?.text?.error_notAllowed ?? 'Please tick the checkbox on the settings page of the remote instance to allow the request, then return to this form to retry.';
                                    }

                                    if (errorDetailsMessage.length === 0) {
                                        // Fetch any message that is in the response object.
                                        errorDetailsMessage = json?.message?.length > 0
                                            ? json.message
                                            : defaultMessage;
                                    }

                                    setErrorStatusText(errorDetailsMessage);

                                    return;
                                }

                                statusText.textContent = deploy_sync_content__component_settings?.text?.requestSuccessful ?? 'Done.';

                                statusText.classList.add('ok');

                                if (json.bundleImportPageUrl) {
                                    // Redirect to the bundle page.
                                    window.location.href = json.bundleImportPageUrl;
                                }
                            })
                            .finally(() => {
                                statusText.classList.remove('in-progress');

                                // Reenable all buttons.
                                enableAllButtons();
                            });
                    })
                    .catch(() => {
                        statusText.textContent = (deploy_sync_content__component_settings?.text?.requestError ?? 'The request failed.');

                        statusText.classList.add('not-ok');

                        statusText.classList.remove('in-progress');

                        // Reenable all buttons.
                        enableAllButtons();
                    })
            });
        });
    };

    handle();
})();
