(() => {
    'use strict';

    const monitor = document.getElementById('live-pipeline-monitor');
    if (!monitor) return;

    const csrfInput = document.querySelector('input[name="_csrf"]');
    const csrf = csrfInput ? csrfInput.value : '';
    const title = document.getElementById('live-title');
    const subtitle = document.getElementById('live-subtitle');
    const decision = document.getElementById('live-decision');
    const score = document.getElementById('live-score');
    const progressBar = document.getElementById('live-progress-bar');
    const progressText = document.getElementById('live-progress-text');
    const elapsed = document.getElementById('live-elapsed');
    const stepsContainer = document.getElementById('live-steps');
    const errorBox = document.getElementById('live-error');
    const closeButton = document.getElementById('live-close');

    let activeRunId = 0;
    let running = false;

    const escapeHtml = (value) => String(value ?? '')
        .replaceAll('&', '&amp;')
        .replaceAll('<', '&lt;')
        .replaceAll('>', '&gt;')
        .replaceAll('"', '&quot;')
        .replaceAll("'", '&#039;');

    const badgeClass = (value) => {
        if (['ALLOWED', 'PASSED', 'COMPATIBLE', 'CERTIFIED', 'RESOLVED'].includes(value)) return 'good';
        if (['WARNING', 'DEFERRED', 'NOT_CERTIFIED', 'PENDING'].includes(value)) return 'warn';
        return 'bad';
    };

    async function request(url, body = null) {
        const options = {
            method: body === null ? 'GET' : 'POST',
            credentials: 'same-origin',
            headers: {'X-Requested-With': 'XMLHttpRequest'}
        };

        if (body !== null) {
            options.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
            options.body = new URLSearchParams(body).toString();
        }

        const response = await fetch(url, options);
        const payload = await response.json();

        if (!response.ok || payload.ok === false) {
            throw new Error(payload.error || 'Erreur du Live Pipeline Monitor.');
        }

        return payload;
    }

    function render(payload) {
        const run = payload.run || {};
        const steps = payload.steps || [];

        title.textContent = run.package_name || 'Exécution en direct';
        subtitle.textContent = payload.finished
            ? `Exécution #${run.id} terminée`
            : `Étape suivante : ${payload.next_step?.label || 'Finalisation'}`;

        decision.textContent = run.decision || 'PENDING';
        decision.className = `badge ${badgeClass(run.decision || 'PENDING')}`;
        score.textContent = `${Number(run.score || 0)}/100`;
        progressBar.style.width = `${Number(payload.progress || 0)}%`;
        progressText.textContent = `${Number(payload.progress || 0)} %`;
        elapsed.textContent = `${Number(run.duration_ms || 0)} ms`;

        const expected = [
            ['native_preflight', 'Préflight natif'],
            ['trust', 'Trust Engine'],
            ['compatibility', 'Compatibility Engine'],
            ['policy', 'Package Policy Engine'],
            ['dependencies', 'Dépendances']
        ];

        const byCode = new Map(steps.map(step => [step.step_code, step]));

        stepsContainer.innerHTML = expected.map(([code, label]) => {
            const step = byCode.get(code);
            if (!step) {
                const isNext = payload.next_step?.code === code;
                return `<article class="report-step">
                    <header>
                        <div><strong>${escapeHtml(label)}</strong><small> · ${escapeHtml(code)}</small></div>
                        <span class="badge warn">${isNext ? 'EN COURS' : 'EN ATTENTE'}</span>
                    </header>
                </article>`;
            }

            const issues = (step.issues || []).map(item =>
                `<li>${escapeHtml(typeof item === 'string' ? item : JSON.stringify(item))}</li>`
            ).join('');
            const warnings = (step.warnings || []).map(item =>
                `<li>${escapeHtml(typeof item === 'string' ? item : JSON.stringify(item))}</li>`
            ).join('');

            return `<article class="report-step">
                <header>
                    <div><strong>${escapeHtml(step.step_label)}</strong><small> · ${escapeHtml(step.step_code)}</small></div>
                    <div>
                        <span class="badge ${badgeClass(step.decision)}">${escapeHtml(step.decision)}</span>
                        <strong>${Number(step.score || 0)}/100</strong>
                        · ${Number(step.duration_ms || 0)} ms
                    </div>
                </header>
                ${step.message ? `<p>${escapeHtml(step.message)}</p>` : ''}
                ${issues ? `<ul class="issues">${issues}</ul>` : ''}
                ${warnings ? `<ul class="warnings">${warnings}</ul>` : ''}
            </article>`;
        }).join('');
    }

    async function advanceLoop() {
        if (!running || activeRunId <= 0) return;

        try {
            const payload = await request(
                '/public/administration/plateforme/validation/live/avancer',
                {_csrf: csrf, run_id: activeRunId}
            );

            render(payload);

            if (payload.finished) {
                running = false;
                setTimeout(() => window.location.reload(), 1200);
                return;
            }

            setTimeout(advanceLoop, 350);
        } catch (error) {
            running = false;
            errorBox.hidden = false;
            errorBox.textContent = error.message;
        }
    }

    document.querySelectorAll('[data-live-pipeline]').forEach(button => {
        button.addEventListener('click', async () => {
            if (running) return;

            errorBox.hidden = true;
            errorBox.textContent = '';
            monitor.hidden = false;
            monitor.scrollIntoView({behavior: 'smooth', block: 'start'});
            title.textContent = button.dataset.packageName || 'Pipeline';
            subtitle.textContent = 'Création de l’exécution sécurisée…';
            stepsContainer.innerHTML = '';
            progressBar.style.width = '0%';
            progressText.textContent = '0 %';

            try {
                const payload = await request(
                    '/public/administration/plateforme/validation/live/demarrer',
                    {_csrf: csrf, package_id: button.dataset.packageId}
                );

                activeRunId = Number(payload.run?.id || 0);
                running = true;
                render(payload);
                setTimeout(advanceLoop, 250);
            } catch (error) {
                errorBox.hidden = false;
                errorBox.textContent = error.message;
            }
        });
    });

    closeButton.addEventListener('click', () => {
        if (running && !window.confirm('Le pipeline est encore en cours. Masquer seulement le suivi ?')) {
            return;
        }
        monitor.hidden = true;
    });
})();
