// Web Push helpers — Service Worker + PushManager
import { api } from './api';

const SW_URL = '/sw.js';

export function isPushSupported() {
    return typeof window !== 'undefined'
        && 'serviceWorker' in navigator
        && 'PushManager' in window
        && 'Notification' in window;
}

function urlBase64ToUint8Array(base64String) {
    const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
    const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
    const raw = atob(base64);
    const arr = new Uint8Array(raw.length);
    for (let i = 0; i < raw.length; i += 1) arr[i] = raw.charCodeAt(i);
    return arr;
}

async function registerSw() {
    if (!('serviceWorker' in navigator)) return null;
    // Reuse existing registration if any
    let reg = await navigator.serviceWorker.getRegistration(SW_URL);
    if (!reg) reg = await navigator.serviceWorker.register(SW_URL);
    await navigator.serviceWorker.ready;
    return reg;
}

export async function getPushStatus() {
    if (!isPushSupported()) return { supported: false };
    let permission = Notification.permission;
    let subscribed = false;
    try {
        const reg = await navigator.serviceWorker.getRegistration(SW_URL);
        if (reg) {
            const sub = await reg.pushManager.getSubscription();
            subscribed = !!sub;
        }
    } catch (_) {}
    return { supported: true, permission, subscribed };
}

export async function subscribePush() {
    if (!isPushSupported()) throw new Error('Notifications push non supportées sur ce navigateur');
    // 1) Permission
    let permission = Notification.permission;
    if (permission === 'default') {
        permission = await Notification.requestPermission();
    }
    if (permission !== 'granted') {
        throw new Error('Permission refusée — autorise les notifications dans ton navigateur');
    }
    // 2) Public VAPID key
    const r = await api.get('/push/public-key');
    const publicKey = r.data && r.data.key;
    if (!publicKey) throw new Error('Clé VAPID indisponible côté serveur');
    // 3) Register SW + subscribe
    const reg = await registerSw();
    if (!reg) throw new Error('Service Worker indisponible');
    let sub = await reg.pushManager.getSubscription();
    if (!sub) {
        sub = await reg.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: urlBase64ToUint8Array(publicKey),
        });
    }
    // 4) Persist on backend
    const json = sub.toJSON();
    await api.post('/push/subscribe', {
        endpoint: json.endpoint,
        p256dh: json.keys?.p256dh,
        auth: json.keys?.auth,
        user_agent: (navigator.userAgent || '').slice(0, 255),
    });
    return true;
}

export async function unsubscribePush() {
    if (!isPushSupported()) return false;
    try {
        const reg = await navigator.serviceWorker.getRegistration(SW_URL);
        if (!reg) return false;
        const sub = await reg.pushManager.getSubscription();
        if (!sub) return false;
        const endpoint = sub.endpoint;
        await sub.unsubscribe();
        await api.post('/push/unsubscribe', { endpoint });
        return true;
    } catch (_) {
        return false;
    }
}
