import { Controller } from '@hotwired/stimulus';

/*
 * Progression des imports de la page Paramètres (référentiel des concessions,
 * photo du stock). Intercepte la soumission du formulaire, téléverse en XHR
 * (pour suivre l'upload en %), puis interroge /param/import/progress/<token>
 * pendant le traitement serveur (lecture du fichier, enregistrement…).
 * À la fin, recharge la page : les messages flash habituels s'affichent.
 * Sans JavaScript, le formulaire garde sa soumission native.
 */
export default class extends Controller {
    static targets = ['panel', 'bar', 'label', 'submit'];
    static values = { progressUrl: String };

    disconnect() {
        this.stopPolling();
    }

    submit(event) {
        event.preventDefault();
        if (this.running) return;
        this.running = true;

        const token = this.makeToken();
        const data = new FormData(this.element);
        data.append('progress_token', token);

        this.panelTarget.classList.remove('hidden');
        this.submitTargets.forEach((b) => {
            b.disabled = true;
            b.classList.add('opacity-50', 'pointer-events-none');
        });
        this.setBar('Téléversement du fichier…', 0, 100);

        const xhr = new XMLHttpRequest();
        xhr.open('POST', this.element.action);
        xhr.responseType = 'json';
        xhr.upload.addEventListener('progress', (e) => {
            if (e.lengthComputable) {
                const pct = Math.round((e.loaded / e.total) * 100);
                this.setBar(`Téléversement du fichier… ${pct} %`, e.loaded, e.total);
            }
        });
        xhr.upload.addEventListener('load', () => {
            this.setIndeterminate('Analyse du fichier…');
            this.startPolling(token);
        });
        xhr.addEventListener('load', () => this.finish(xhr));
        xhr.addEventListener('error', () => this.fail('Erreur réseau pendant l’import. Vérifiez la connexion et réessayez.'));
        xhr.addEventListener('timeout', () => this.fail('Le serveur ne répond pas. Réessayez.'));
        xhr.send(data);
    }

    startPolling(token) {
        if (this.pollTimer) return;
        const url = this.progressUrlValue.replace('PROGRESS-TOKEN', token);
        this.pollTimer = setInterval(async () => {
            try {
                const res = await fetch(url, { headers: { Accept: 'application/json' } });
                if (!res.ok) return;
                const p = await res.json();
                if (p.done) this.stopPolling();
                if (p.error) {
                    this.setIndeterminate(p.label || 'Erreur pendant l’import.');
                } else if (p.total) {
                    this.setBar(`${p.label} ${p.current ?? 0} / ${p.total}`, p.current ?? 0, p.total);
                } else if (p.current) {
                    this.setIndeterminate(`${p.label} ${p.current} ligne(s) lue(s)`);
                } else {
                    this.setIndeterminate(p.label || 'Traitement en cours…');
                }
            } catch (e) {
                /* suivi best-effort : on retentera au prochain tick */
            }
        }, 600);
    }

    stopPolling() {
        if (this.pollTimer) {
            clearInterval(this.pollTimer);
            this.pollTimer = null;
        }
    }

    finish(xhr) {
        this.stopPolling();
        // Réponse JSON {ok} du flux JS, ou HTML de /param si le serveur a redirigé
        // (jeton CSRF invalide…) : dans les deux cas le flash explique le résultat.
        if (xhr.status >= 200 && xhr.status < 300) {
            this.setBar('Terminé — actualisation de la page…', 1, 1);
            window.location.reload();
        } else {
            this.fail(`Échec de l'import (HTTP ${xhr.status}). Réessayez.`);
        }
    }

    fail(message) {
        this.stopPolling();
        this.running = false;
        this.barTarget.classList.remove('animate-pulse');
        this.barTarget.classList.add('bg-red-600');
        this.barTarget.style.width = '100%';
        this.labelTarget.textContent = message;
        this.labelTarget.classList.add('text-red-600');
        this.submitTargets.forEach((b) => {
            b.disabled = false;
            b.classList.remove('opacity-50', 'pointer-events-none');
        });
    }

    setBar(text, current, total) {
        this.barTarget.classList.remove('animate-pulse');
        this.barTarget.style.width = total > 0 ? `${Math.min(100, Math.round((current / total) * 100))}%` : '0%';
        this.labelTarget.textContent = text;
    }

    /* Phase sans total connu : barre pleine en pulsation. */
    setIndeterminate(text) {
        this.barTarget.classList.add('animate-pulse');
        this.barTarget.style.width = '100%';
        this.labelTarget.textContent = text;
    }

    makeToken() {
        if (window.crypto && window.crypto.randomUUID) {
            return window.crypto.randomUUID();
        }
        return `t${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
    }
}
