import { getToken } from '../Utils';

/** Převede base64url VAPID klíč na Uint8Array pro PushManager. */
function urlBase64ToUint8Array(base64String: string): Uint8Array {
    const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
    const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
    const rawData = atob(base64);
    const outputArray = new Uint8Array(rawData.length);
    for (let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
    }
    return outputArray;
}

/** Helper pro autorizované API volání na push endpointy. */
async function pushApiFetch(path: string, options: RequestInit = {}): Promise<Response> {
    const token = getToken();
    return fetch(`/api/notifications/push${path}`, {
        ...options,
        headers: {
            'Content-Type': 'application/json',
            ...(token ? { Authorization: `Bearer ${token}` } : {}),
            ...options.headers,
        },
    });
}

/**
 * Zaregistruje service worker, přihlásí se k push notifikacím
 * a odešle subscription na server.
 */
export async function subscribeToPush(reminderTime: string): Promise<boolean> {
    if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
        console.warn('Push notifikace nejsou v tomto prohlížeči podporovány');
        return false;
    }

    try {
        // Registrace service workeru
        const registration = await navigator.serviceWorker.register('/sw.js');
        await navigator.serviceWorker.ready;

        // Vyžádání oprávnění
        const permission = await Notification.requestPermission();
        if (permission !== 'granted') {
            console.warn('Push notifikace: oprávnění zamítnuto');
            return false;
        }

        // Získání VAPID veřejného klíče ze serveru
        const vapidResponse = await pushApiFetch('/vapidKey');
        if (!vapidResponse.ok) {
            console.error('Push notifikace: nepodařilo se získat VAPID klíč');
            return false;
        }
        const { key: vapidPublicKey } = await vapidResponse.json();

        // Přihlášení k push
        const subscription = await registration.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: urlBase64ToUint8Array(vapidPublicKey) as BufferSource,
        });

        // Odeslání subscription na server
        const response = await pushApiFetch('/subscribe', {
            method: 'POST',
            body: JSON.stringify({
                subscription: subscription.toJSON(),
                reminderTime,
            }),
        });

        if (!response.ok) {
            console.error('Push notifikace: nepodařilo se odeslat subscription na server');
            return false;
        }

        console.log('Push notifikace: úspěšně přihlášeno k připomínkám v', reminderTime);
        return true;
    } catch (error) {
        console.error('Push notifikace: chyba při registraci', error);
        return false;
    }
}

/**
 * Odhlásí se z push notifikací a informuje server.
 */
export async function unsubscribeFromPush(): Promise<void> {
    if (!('serviceWorker' in navigator)) {
        return;
    }

    try {
        const registration = await navigator.serviceWorker.getRegistration('/sw.js');
        if (registration) {
            const subscription = await registration.pushManager.getSubscription();
            if (subscription) {
                await subscription.unsubscribe();
            }
        }

        await pushApiFetch('/unsubscribe', { method: 'POST' });
        console.log('Push notifikace: úspěšně odhlášeno z připomínek');
    } catch (error) {
        console.error('Push notifikace: chyba při odhlášení', error);
    }
}
