document.addEventListener('DOMContentLoaded', () => {
    const forms = document.querySelectorAll(
        '.darlink-install-form'
    );

    forms.forEach((form) => {
        form.addEventListener('submit', () => {
            const submitButton = form.querySelector(
                'button[type="submit"]'
            );

            if (!submitButton) {
                return;
            }

            submitButton.disabled = true;
            submitButton.dataset.originalText =
                submitButton.innerHTML;
            submitButton.innerHTML =
                '<span class="spinner-border spinner-border-sm me-2"></span>Test en cours...';
        });
    });

    const toggles = document.querySelectorAll(
        '[data-password-toggle]'
    );

    toggles.forEach((button) => {
        button.addEventListener('click', () => {
            const targetId = button.getAttribute(
                'data-password-toggle'
            );

            const input = document.getElementById(
                targetId
            );

            if (!input) {
                return;
            }

            const isPassword =
                input.getAttribute('type') === 'password';

            input.setAttribute(
                'type',
                isPassword ? 'text' : 'password'
            );

            const icon = button.querySelector('i');

            if (icon) {
                icon.className = isPassword
                    ? 'bi bi-eye-slash'
                    : 'bi bi-eye';
            }
        });
    });
});


document.addEventListener('DOMContentLoaded', () => {
    const runner = document.querySelector(
        '[data-installation-runner]'
    );

    if (!runner) {
        return;
    }

    const apiUrl = runner.dataset.apiUrl;
    const csrfToken = runner.dataset.csrfToken;
    const alreadyComplete =
        runner.dataset.alreadyComplete === '1';

    const startButton = runner.querySelector(
        '[data-start-installation]'
    );

    const continueButton = runner.querySelector(
        '[data-continue-button]'
    );

    const backButton = runner.querySelector(
        '[data-back-button]'
    );

    const progressBar = runner.querySelector(
        '[data-progress-bar]'
    );

    const progressLabel = runner.querySelector(
        '[data-progress-label]'
    );

    const currentOperation = runner.querySelector(
        '[data-current-operation]'
    );

    const logContainer = runner.querySelector(
        '[data-install-log]'
    );

    const statusBox = runner.querySelector(
        '[data-execution-status]'
    );

    const statusTitle = runner.querySelector(
        '[data-status-title]'
    );

    const statusMessage = runner.querySelector(
        '[data-status-message]'
    );

    const summaryBox = runner.querySelector(
        '[data-execution-summary]'
    );

    if (alreadyComplete || !startButton) {
        return;
    }

    const appendLog = (message, type = 'info') => {
        const placeholder = logContainer.querySelector(
            '.is-muted'
        );

        if (placeholder) {
            placeholder.remove();
        }

        const line = document.createElement('div');
        line.className = `darlink-log-line is-${type}`;
        line.textContent = message;
        logContainer.appendChild(line);
        logContainer.scrollTop =
            logContainer.scrollHeight;
    };

    const updateProgress = (progress) => {
        const percent = Number(
            progress?.percent ?? 0
        );

        progressBar.style.width = `${percent}%`;
        progressBar.setAttribute(
            'aria-valuenow',
            String(percent)
        );
        progressLabel.textContent = `${percent} %`;

        if (progress?.message) {
            currentOperation.textContent =
                progress.message;
        }

        const entries = Array.isArray(progress?.log)
            ? progress.log
            : [];

        if (entries.length > 0) {
            const latest = entries[entries.length - 1];

            appendLog(
                `${latest.time} — ${latest.message}`,
                percent >= 100 ? 'success' : 'info'
            );
        }
    };

    const displaySummary = (summary) => {
        if (!summary) {
            return;
        }

        runner.querySelector(
            '[data-summary-successes]'
        ).textContent =
            summary.successes ?? 0;

        runner.querySelector(
            '[data-summary-baselines]'
        ).textContent =
            summary.baselines ?? 0;

        runner.querySelector(
            '[data-summary-statements]'
        ).textContent =
            summary.statements ?? 0;

        runner.querySelector(
            '[data-summary-duration]'
        ).textContent =
            `${((summary.duration_ms ?? 0) / 1000)
                .toFixed(2)
                .replace('.', ',')} s`;

        summaryBox.classList.remove('d-none');
    };

    const request = async (action) => {
        const body = new URLSearchParams();
        body.set('action', action);
        body.set('csrf_token', csrfToken);

        const response = await fetch(apiUrl, {
            method: 'POST',
            headers: {
                'Content-Type':
                    'application/x-www-form-urlencoded;charset=UTF-8',
                'X-Requested-With': 'XMLHttpRequest',
            },
            body: body.toString(),
        });

        const rawResponse = await response.text();
        let payload;

        try {
            payload = JSON.parse(rawResponse);
        } catch (parseError) {
            const preview = rawResponse
                .replace(/<[^>]*>/g, ' ')
                .replace(/\s+/g, ' ')
                .trim()
                .slice(0, 240);

            throw new Error(
                'Réponse invalide du serveur'
                + (preview ? ` : ${preview}` : '.')
            );
        }

        if (!response.ok || !payload.success) {
            throw new Error(
                payload.message
                || 'Erreur pendant l’installation.'
            );
        }

        return payload;
    };

    const finish = (payload) => {
        updateProgress(payload.progress);
        displaySummary(payload.summary);

        statusBox.classList.remove(
            'has-errors'
        );
        statusBox.classList.add('is-ready');

        const icon = statusBox.querySelector('i');

        if (icon) {
            icon.className =
                'bi bi-check-circle-fill';
        }

        statusTitle.textContent =
            'Installation terminée';

        statusMessage.textContent =
            payload.message
            || 'La base de données est opérationnelle.';

        startButton.classList.add('d-none');
        continueButton.classList.remove('d-none');
        backButton.classList.add('disabled');
        backButton.setAttribute(
            'aria-disabled',
            'true'
        );
    };

    const runNext = async () => {
        const payload = await request('next');
        updateProgress(payload.progress);

        if (payload.migration?.name) {
            appendLog(
                `${payload.migration.name} — `
                + `${payload.migration.statements} instruction(s)`,
                'success'
            );
        }

        if (payload.complete) {
            finish(payload);
            return;
        }

        await runNext();
    };

    startButton.addEventListener(
        'click',
        async () => {
            startButton.disabled = true;
            backButton.classList.add('disabled');

            startButton.innerHTML =
                '<span class="spinner-border spinner-border-sm me-2"></span>Installation...';

            statusTitle.textContent =
                'Installation en cours';

            statusMessage.textContent =
                'Ne fermez pas cette page.';

            appendLog(
                'Initialisation du moteur de migrations.'
            );

            try {
                const initialization =
                    await request('initialize');

                updateProgress(
                    initialization.progress
                );

                if (initialization.message) {
                    appendLog(
                        initialization.message,
                        initialization.complete
                            ? 'success'
                            : 'info'
                    );
                }

                if (initialization.complete) {
                    finish(initialization);
                    return;
                }

                await runNext();
            } catch (error) {
                startButton.disabled = false;
                startButton.innerHTML =
                    '<i class="bi bi-arrow-clockwise me-2"></i>Réessayer';

                backButton.classList.remove(
                    'disabled'
                );

                statusTitle.textContent =
                    'Installation interrompue';

                statusMessage.textContent =
                    error.message;

                currentOperation.textContent =
                    error.message;

                appendLog(
                    error.message,
                    'error'
                );
            }
        }
    );
});


document.addEventListener('DOMContentLoaded', () => {
    const password = document.querySelector(
        '[data-password-strength-source]'
    );

    const bar = document.querySelector(
        '[data-password-strength-bar]'
    );

    const label = document.querySelector(
        '[data-password-strength-label]'
    );

    if (!password || !bar || !label) {
        return;
    }

    const evaluate = () => {
        const value = password.value;
        let score = 0;

        if (value.length >= 10) score++;
        if (/[a-z]/.test(value)) score++;
        if (/[A-Z]/.test(value)) score++;
        if (/\d/.test(value)) score++;
        if (/[^A-Za-z0-9]/.test(value)) score++;

        const states = [
            {
                width: 0,
                label: 'Mot de passe non évalué',
                className: '',
            },
            {
                width: 20,
                label: 'Très faible',
                className: 'is-danger',
            },
            {
                width: 40,
                label: 'Faible',
                className: 'is-danger',
            },
            {
                width: 60,
                label: 'Moyen',
                className: 'is-warning',
            },
            {
                width: 80,
                label: 'Bon',
                className: 'is-good',
            },
            {
                width: 100,
                label: 'Excellent',
                className: 'is-strong',
            },
        ];

        const state = value === ''
            ? states[0]
            : states[score];

        bar.style.width = `${state.width}%`;
        bar.className = state.className;
        label.textContent = state.label;
    };

    password.addEventListener('input', evaluate);
    evaluate();
});
