/**
 * Fichier  : assets/js/push-notifications.js
 * Auteur   : KREMER Régis
 * Version  : 2.6.10
 * Date     : 2026-02-21
 * Description : JS — Gestion des notifications Web Push côté client
 *
 * Changelog :
 *   v2.1.0 (2026-02-21) — Version initiale auditée et sécurisée
 *   v2.1.1 (2026-02-21) — Corrections sécurité, utils.js centralisé
 *   v2.2.0 (2026-02-21) — Permissions magasins, bons de commande, rapport d'écart,
 *                      import CSV, historique prix, bon de livraison multi-lignes
 *   v2.6.8 (2026-07-08) — Aide mobile/tablette : Android, iOS installé en PWA,
 *                      messages de permission et enregistrement SW fiabilisé
 *   v2.6.10 (2026-07-08) — URLs SW/API résolues via MageStockRuntime.
 */
// ================================================================
// push-notifications.js — Gestion des notifications push
// ================================================================

const PushManager = {
    swRegistration: null,
    isSubscribed: false,

    _isIOS() {
        return /iphone|ipad|ipod/i.test(navigator.userAgent || '') || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
    },

    _isStandalone() {
        return (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) || window.navigator.standalone === true;
    },

    _url(path) {
        const raw = String(path || '');
        if(/^(?:https?:)?\/\//i.test(raw) || raw.charAt(0) === '/') return raw;
        const runtime = window.MageStockRuntime || {};
        const base = String(runtime.basePath || '').replace(/\/+$/, '');
        return (base ? base : '') + '/' + raw.replace(/^\.\//, '').replace(/^\/+/, '');
    },

    _swUrl() {
        return this._url('sw.js');
    },

    getSupportInfo() {
        const secure = location.protocol === 'https:' || location.hostname === 'localhost' || location.hostname === '127.0.0.1';
        if (!secure) return { supported:false, code:'insecure', message:'Les notifications exigent HTTPS.' };
        if (!('serviceWorker' in navigator)) return { supported:false, code:'sw', message:'Service Worker non supporté par ce navigateur.' };
        if (!('Notification' in window)) return { supported:false, code:'notification', message:'Notifications non supportées par ce navigateur.' };
        if (!('PushManager' in window)) {
            if (this._isIOS() && !this._isStandalone()) {
                return { supported:false, code:'ios-install', message:'Sur iPhone/iPad, installez MageStock sur l’écran d’accueil puis ouvrez l’application installée pour activer les notifications.' };
            }
            return { supported:false, code:'push', message:'Push Web non supporté par ce navigateur.' };
        }
        if (this._isIOS() && !this._isStandalone()) {
            return { supported:false, code:'ios-install', message:'Sur iPhone/iPad, les notifications fonctionnent uniquement depuis MageStock installé sur l’écran d’accueil.' };
        }
        return { supported:true, code:'ok', message:'Notifications compatibles sur cet appareil.' };
    },
    
    /**
     * Initialise le système de notifications push
     */
    async init() {
        // Vérifier le support réel de l'appareil
        const support = this.getSupportInfo();
        if (!support.supported) {
            console.log('[Push] Non supporté:', support.message);
            this.updateUI(support);
            return false;
        }
        
        try {
            // Enregistrer le Service Worker
            this.swRegistration = await navigator.serviceWorker.register(this._swUrl());
            console.log('[Push] Service Worker enregistré:', this.swRegistration);
            
            // Attendre que le SW soit prêt
            await navigator.serviceWorker.ready;
            
            // Vérifier l'état actuel
            const subscription = await this.swRegistration.pushManager.getSubscription();
            this.isSubscribed = subscription !== null;
            
            console.log('[Push] Abonné:', this.isSubscribed);
            
            // Mettre à jour l'UI
            this.updateUI();
            
            return true;
        } catch (error) {
            console.error('[Push] Erreur initialisation:', error);
            return false;
        }
    },
    
    /**
     * Demande la permission et s'abonne aux notifications
     */
    async subscribe() {
        try {
            const support = this.getSupportInfo();
            if (!support.supported) {
                toast(support.message, 'warning');
                this.updateUI(support);
                return false;
            }

            if (!this.swRegistration) {
                await this.init();
            }
            if (!this.swRegistration) {
                toast('Service Worker non prêt. Rechargez la page puis réessayez.', 'warning');
                return false;
            }

            // Demander la permission depuis une action utilisateur
            const permission = await Notification.requestPermission();
            
            if (permission !== 'granted') {
                console.log('[Push] Permission refusée');
                toast('Permission refusée. Réactivez les notifications dans les réglages du navigateur ou du téléphone.', 'warning');
                return false;
            }
            
            // Obtenir la clé publique VAPID
            const response = await fetch(this._url('api/push.php'));
            const data = await response.json();
            const vapidPublicKey = data.publicKey;
            
            if (!vapidPublicKey) {
                console.error('[Push] Clé VAPID manquante');
                toast('Configuration des notifications incomplète', 'error');
                return false;
            }
            
            // Convertir la clé VAPID
            const applicationServerKey = this.urlBase64ToUint8Array(vapidPublicKey);
            
            // S'abonner
            const subscription = await this.swRegistration.pushManager.subscribe({
                userVisibleOnly: true,
                applicationServerKey: applicationServerKey
            });
            
            console.log('[Push] Subscription:', subscription);
            
            // Envoyer la subscription au serveur
            const saveResponse = await fetch(this._url('api/push.php'), {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-TOKEN': window.CSRF_TOKEN || ''
                },
                body: JSON.stringify({
                    action: 'subscribe',
                    subscription: subscription.toJSON()
                })
            });
            
            const saveData = await saveResponse.json();
            
            if (saveData.success) {
                this.isSubscribed = true;
                this.updateUI();
                toast('Notifications activées !', 'success');
                return true;
            } else {
                throw new Error(saveData.error || 'Erreur serveur');
            }
            
        } catch (error) {
            console.error('[Push] Erreur subscription:', error);
            toast('Erreur lors de l\'activation des notifications', 'error');
            return false;
        }
    },
    
    /**
     * Se désabonne des notifications
     */
    async unsubscribe() {
        try {
            const subscription = await this.swRegistration.pushManager.getSubscription();
            
            if (subscription) {
                // Supprimer côté serveur
                await fetch(this._url('api/push.php'), {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'X-CSRF-TOKEN': window.CSRF_TOKEN || ''
                    },
                    body: JSON.stringify({
                        action: 'unsubscribe',
                        endpoint: subscription.endpoint
                    })
                });
                
                // Désabonner côté client
                await subscription.unsubscribe();
            }
            
            this.isSubscribed = false;
            this.updateUI();
            toast('Notifications désactivées', 'info');
            return true;
            
        } catch (error) {
            console.error('[Push] Erreur unsubscribe:', error);
            toast('Erreur lors de la désactivation', 'error');
            return false;
        }
    },
    
    /**
     * Bascule l'état des notifications
     */
    async toggle() {
        if (this.isSubscribed) {
            return await this.unsubscribe();
        } else {
            return await this.subscribe();
        }
    },
    
    /**
     * Envoie une notification de test
     */
    async sendTest() {
        try {
            const response = await fetch(this._url('api/push.php'), {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-TOKEN': window.CSRF_TOKEN || ''
                },
                body: JSON.stringify({ action: 'test' })
            });

            const data = await response.json();
            console.log('[Push] Test result:', data);

            if (data.sent > 0) {
                toast(`Notification de test envoyée (${data.sent}/${data.total} appareil(s))`, 'success');
            } else if (data.total === 0) {
                toast('Aucun appareil abonné — cliquez "Activer" d\'abord sur cet appareil', 'warning');
            } else {
                // Afficher le debug
                const errs = (data.errors || []).map(e => e.debug || e).join(' | ');
                toast(`Envoi échoué (${data.total} sub) — ${errs}`, 'error');
                console.error('[Push] Errors:', data.errors);
            }

        } catch (error) {
            console.error('[Push] Erreur test:', error);
            toast('Erreur lors du test', 'error');
        }
    },
    
    /**
     * Met à jour l'interface utilisateur
     */
    updateUI(supportInfo) {
        const btn    = document.getElementById('pushToggleBtn');
        const status = document.getElementById('pushStatus');
        const support = supportInfo || this.getSupportInfo();

        if (!support.supported) {
            if (btn) {
                btn.disabled = true;
                btn.className = 'btn btn-secondary';
                btn.innerHTML = 'Notifications non disponibles';
            }
            if (status) {
                status.innerHTML = '<span class="badge badge-gray">Non disponible</span>';
            }
            const infoEl = document.getElementById('pushDeviceInfo');
            if (infoEl) {
                infoEl.style.display = 'flex';
                infoEl.innerHTML = '<span>' + this._escapeHtml(support.message) + '</span>';
            }
            return;
        }

        if (btn) {
            btn.innerHTML = this.isSubscribed
                ? `<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2">
                     <path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/>
                     <path d="M13.73 21a2 2 0 01-3.46 0"/>
                     <line x1="1" y1="1" x2="23" y2="23"/>
                   </svg> Désactiver les notifications`
                : `<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2">
                     <path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/>
                     <path d="M13.73 21a2 2 0 01-3.46 0"/>
                   </svg> Activer sur cet appareil`;
            btn.className = this.isSubscribed
                ? 'btn btn-secondary'
                : 'btn btn-success';
        }

        if (status) {
            status.innerHTML = this.isSubscribed
                ? '<span class="badge badge-green">Activées</span>'
                : '<span class="badge badge-gray">Désactivées</span>';
        }

        // Mettre à jour l'info appareil dans SetPage si disponible
        if (typeof SetPage !== 'undefined' && SetPage._refreshPushDeviceInfo) {
            SetPage._refreshPushDeviceInfo();
        }
    },
    
    /**
     * Convertit une clé base64url en Uint8Array
     */
    urlBase64ToUint8Array(base64String) {
        const padding = '='.repeat((4 - base64String.length % 4) % 4);
        const base64 = (base64String + padding)
            .replace(/-/g, '+')
            .replace(/_/g, '/');
        
        const rawData = window.atob(base64);
        const outputArray = new Uint8Array(rawData.length);
        
        for (let i = 0; i < rawData.length; ++i) {
            outputArray[i] = rawData.charCodeAt(i);
        }
        
        return outputArray;
    },
    
    /**
     * Vérifie si les notifications sont supportées
     */
    isSupported() {
        return this.getSupportInfo().supported;
    },

    _escapeHtml(value) {
        return String(value == null ? '' : value).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
    },
    
    /**
     * Obtient l'état de la permission
     */
    getPermissionState() {
        if (!('Notification' in window)) {
            return 'unsupported';
        }
        return Notification.permission; // 'default', 'granted', 'denied'
    }
};

// Auto-init si l'utilisateur est admin
document.addEventListener('DOMContentLoaded', () => {
    // Vérifier si l'utilisateur est admin (via variable globale ou data attribute)
    const isAdmin = document.body.dataset.userRole === 'admin' || window.USER_ROLE === 'admin';
    
    if (isAdmin && PushManager.isSupported()) {
        PushManager.init().then(success => {
            if (success) {
                console.log('[Push] Système initialisé avec succès');
            }
        });
    }
});

// Exposer globalement (PushManager = notre objet, SMPush = alias pour éviter conflit avec l'API native)
window.SMPush = PushManager;
window.PushManager = PushManager; // garde compat
