<script setup>
import { ref, onMounted, computed } from 'vue';
import { usePage } from '@inertiajs/vue3';

const props = defineProps({
    autoSubscribe: {
        type: Boolean,
        default: false,
    },
});

const emit = defineEmits(['subscribed', 'unsubscribed', 'error']);

const isSupported = ref(false);
const permission = ref('default');
const isSubscribed = ref(false);
const isLoading = ref(false);
const error = ref(null);

const page = usePage();
const user = computed(() => page.props.auth?.user);

// Check browser support
const checkSupport = () => {
    isSupported.value = 'serviceWorker' in navigator && 'PushManager' in window;
    if ('Notification' in window) {
        permission.value = Notification.permission;
    }
};

// Request notification permission
const requestPermission = async () => {
    if (!('Notification' in window)) {
        error.value = 'Tu navegador no soporta notificaciones';
        return false;
    }

    try {
        const result = await Notification.requestPermission();
        permission.value = result;
        return result === 'granted';
    } catch (e) {
        error.value = 'Error al solicitar permisos: ' + e.message;
        return false;
    }
};

// Get VAPID public key from server
const getVapidPublicKey = async () => {
    try {
        const response = await window.axios.get('/api/push/vapid-public-key');
        return response.data.publicKey;
    } catch (e) {
        throw new Error('No se pudo obtener la clave VAPID del servidor');
    }
};

// Convert VAPID key to Uint8Array
const 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;
};

// Subscribe to push notifications
const subscribe = async () => {
    if (!user.value) {
        error.value = 'Debes iniciar sesión para activar las notificaciones';
        return;
    }

    if (!isSupported.value) {
        error.value = 'Tu navegador no soporta notificaciones push';
        return;
    }

    isLoading.value = true;
    error.value = null;

    try {
        // Request permission if needed
        if (permission.value !== 'granted') {
            const granted = await requestPermission();
            if (!granted) {
                error.value = 'Necesitas permitir las notificaciones para continuar';
                isLoading.value = false;
                return;
            }
        }

        // Get VAPID key
        const vapidPublicKey = await getVapidPublicKey();
        
        // Register service worker if not already
        const registration = await navigator.serviceWorker.ready;

        // Subscribe to push
        const subscription = await registration.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),
        });

        // Send subscription to server
        await window.axios.post('/api/push/subscribe', {
            endpoint: subscription.endpoint,
            keys: {
                p256dh: btoa(String.fromCharCode.apply(null, new Uint8Array(subscription.getKey('p256dh')))),
                auth: btoa(String.fromCharCode.apply(null, new Uint8Array(subscription.getKey('auth')))),
            },
        });

        isSubscribed.value = true;
        emit('subscribed');
    } catch (e) {
        error.value = 'Error al suscribirse: ' + e.message;
        emit('error', e);
    } finally {
        isLoading.value = false;
    }
};

// Unsubscribe from push notifications
const unsubscribe = async () => {
    isLoading.value = true;
    error.value = null;

    try {
        const registration = await navigator.serviceWorker.ready;
        const subscription = await registration.pushManager.getSubscription();

        if (subscription) {
            // Unsubscribe from push
            await subscription.unsubscribe();

            // Remove from server
            await window.axios.post('/api/push/unsubscribe', {
                endpoint: subscription.endpoint,
            });
        }

        isSubscribed.value = false;
        emit('unsubscribed');
    } catch (e) {
        error.value = 'Error al desuscribirse: ' + e.message;
        emit('error', e);
    } finally {
        isLoading.value = false;
    }
};

// Check current subscription status
const checkSubscription = async () => {
    if (!isSupported.value) return;

    try {
        const registration = await navigator.serviceWorker.ready;
        const subscription = await registration.pushManager.getSubscription();
        isSubscribed.value = !!subscription;
    } catch (e) {
    }
};

// Toggle subscription
const toggle = () => {
    if (isSubscribed.value) {
        unsubscribe();
    } else {
        subscribe();
    }
};

// Test notification
const testNotification = async () => {
    try {
        await window.axios.post('/api/push/test');
    } catch (e) {
        error.value = 'Error al enviar notificación de prueba';
    }
};

onMounted(() => {
    checkSupport();
    checkSubscription();
    
    if (props.autoSubscribe && !isSubscribed.value && permission.value === 'granted') {
        subscribe();
    }
});
</script>

<template>
    <div class="push-notifications">
        <!-- Not supported message -->
        <div v-if="!isSupported" class="text-sm text-gray-500 dark:text-gray-400">
            <slot name="not-supported">
                Tu navegador no soporta notificaciones push
            </slot>
        </div>

        <!-- Main content -->
        <div v-else>
            <slot 
                :is-subscribed="isSubscribed"
                :is-loading="isLoading"
                :permission="permission"
                :error="error"
                :subscribe="subscribe"
                :unsubscribe="unsubscribe"
                :toggle="toggle"
                :test="testNotification"
            >
                <!-- Default UI -->
                <div class="flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
                    <div class="flex items-center space-x-3">
                        <div class="flex-shrink-0">
                            <svg 
                                class="w-6 h-6" 
                                :class="isSubscribed ? 'text-green-500' : 'text-gray-400'"
                                fill="none" 
                                stroke="currentColor" 
                                viewBox="0 0 24 24"
                            >
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
                            </svg>
                        </div>
                        <div>
                            <p class="text-sm font-medium text-gray-900 dark:text-white">
                                Notificaciones Push
                            </p>
                            <p class="text-xs text-gray-500 dark:text-gray-400">
                                {{ isSubscribed ? 'Activadas' : 'Desactivadas' }}
                            </p>
                        </div>
                    </div>

                    <button
                        @click="toggle"
                        :disabled="isLoading"
                        class="relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50"
                        :class="isSubscribed ? 'bg-blue-600' : 'bg-gray-200 dark:bg-gray-700'"
                    >
                        <span
                            class="pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
                            :class="isSubscribed ? 'translate-x-5' : 'translate-x-0'"
                        />
                    </button>
                </div>

                <!-- Error message -->
                <p v-if="error" class="mt-2 text-sm text-red-600 dark:text-red-400">
                    {{ error }}
                </p>

                <!-- Permission denied message -->
                <p v-if="permission === 'denied'" class="mt-2 text-sm text-yellow-600 dark:text-yellow-400">
                    Has bloqueado las notificaciones. Debes habilitarlas desde la configuración del navegador.
                </p>
            </slot>
        </div>
    </div>
</template>
