/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/composables/useNotifications.js
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
*/
import { onMounted, onUnmounted } from 'vue';
import { useRouter } from 'vue-router';
import { useToast } from 'primevue/usetoast';
import { supabase } from '@/lib/supabase/client';
import { tenantDb } from '@/lib/supabase/tenantClient';
import { useNotificationStore, fireBrowserNotification } from '@/stores/notificationStore';
import { useConversationDrawerStore } from '@/stores/conversationDrawerStore';
import { useTenantStore } from '@/stores/tenantStore';

// Alertas de sistema ficam fixos em vermelho até o usuário fechar manualmente.
// 24h em ms — na prática "sticky" (PrimeVue Toast não aceita Infinity).
const STICKY_TOAST_LIFE_MS = 24 * 60 * 60 * 1000;

// Fallback polling — garante catch-up mesmo se Realtime perder eventos.
const POLLING_INTERVAL_MS = 60_000;

// Aliases semânticos do deeplink → rota real por role. Mesmo map do AppLayout.
const DEEPLINK_ALIASES = {
    '/crm/conversas': { therapist: '/therapist/conversas', clinic_admin: '/admin/conversas' },
    '/conversas': { therapist: '/therapist/conversas', clinic_admin: '/admin/conversas' }
};

function resolveDeeplink(link, role) {
    if (!link || typeof link !== 'string') return link;
    const alias = DEEPLINK_ALIASES[link];
    if (!alias) return link;
    return alias[role] || alias.therapist;
}

export function useNotifications() {
    const store = useNotificationStore();
    const toast = useToast();
    const router = useRouter();
    const conversationDrawer = useConversationDrawerStore();
    const tenantStore = useTenantStore();
    const alertedIds = new Set();   // ids que já dispararam toast nesta sessão
    let ownerId = null;
    let pollTimer = null;

    // Label curto do botão do toast baseado no deeplink
    function defaultActionLabel(deeplink) {
        if (!deeplink) return null;
        if (deeplink.includes('creditos-whatsapp')) return 'Ir pra loja';
        if (deeplink.includes('whatsapp-pessoal')) return 'Ver conexão';
        if (deeplink.includes('whatsapp-oficial')) return 'Ver canal oficial';
        return 'Abrir';
    }

    function showToastFor(item) {
        if (item?.type !== 'system_alert') return;
        if (alertedIds.has(item.id)) return;
        alertedIds.add(item.id);
        const payload = item.payload || {};
        toast.add({
            severity: 'error',
            summary: payload.title || 'Alerta do sistema',
            detail: payload.detail || '',
            life: STICKY_TOAST_LIFE_MS,
            closable: true,
            group: 'system-alerts',
            data: {
                deeplink: payload.deeplink,
                actionLabel: payload.actionLabel || defaultActionLabel(payload.deeplink),
                thread_key: payload.thread_key || null
            }
        });
    }

    // Ação principal ao clicar numa notificação (seja do toast, sino ou OS):
    // 1. Se tem thread_key, abre o drawer global na thread
    // 2. Senão, resolve alias e navega via router
    async function handleNotificationAction(item) {
        if (!item) return;
        const payload = item.payload || {};

        if (payload.thread_key) {
            try {
                const tenantId = tenantStore.activeTenantId;
                const { data } = await tenantDb().from('conversation_threads')
                    .select('*')
                    
                    .eq('thread_key', payload.thread_key)
                    .maybeSingle();
                if (data) {
                    await conversationDrawer.openForThread(data);
                    return;
                }
            } catch {
                // cai no fallback abaixo
            }
        }

        const role = tenantStore?.activeRole || 'therapist';
        const link = resolveDeeplink(payload.deeplink, role);
        if (link) {
            if (typeof link === 'string' && link.startsWith('/')) router.push(link);
            else window.location.href = link;
        }
    }

    function onRealtimeNotification(item) {
        showToastFor(item);
        // Dispara a notificação nativa do browser com handler de click que
        // aplica a mesma lógica (drawer / alias) do toast e do sininho.
        fireBrowserNotification(item, handleNotificationAction);
    }

    // Re-carrega notifs do DB e dispara toast AGREGADO pras system_alert
    // não-lidas ainda não vistas nesta sessão. Se tiver várias, mostra só
    // a mais recente com sufixo "(+N outros alertas)" no detail pra evitar
    // enxurrada de toasts ao voltar pra aba / recarregar. Eventos novos via
    // Realtime continuam aparecendo individualmente (showToastFor direto).
    async function refreshAndMaybeAlert() {
        if (!ownerId) return;
        await store.load(ownerId);

        const pending = (store.items || [])
            .filter((i) => i.type === 'system_alert' && !i.read_at && !i.archived && !alertedIds.has(i.id));

        if (pending.length === 0) return;

        // Marca os demais como já "alertados" nesta sessão pra não redisparar
        // nos próximos ticks de polling/visibility — eles continuam no sininho.
        const newest = pending[0];  // store.items já vem ordenado por created_at DESC
        for (let i = 1; i < pending.length; i++) {
            alertedIds.add(pending[i].id);
        }

        if (pending.length > 1) {
            const extra = pending.length - 1;
            const suffix = `  •  +${extra} outro${extra === 1 ? '' : 's'} alerta${extra === 1 ? '' : 's'} no sino`;
            const patched = {
                ...newest,
                payload: {
                    ...(newest.payload || {}),
                    detail: `${newest.payload?.detail || ''}${suffix}`
                }
            };
            showToastFor(patched);
        } else {
            showToastFor(newest);
        }
    }

    function onVisibilityChange() {
        if (document.visibilityState === 'visible') {
            refreshAndMaybeAlert();
        }
    }

    onMounted(async () => {
        const { data, error } = await supabase.auth.getUser();
        if (error || !data?.user?.id) return;

        ownerId = data.user.id;
        await store.load(ownerId);

        // Seed: marca TODAS as system_alert existentes como "já vistas" pra
        // não redisparar toast em F5/reload. Alertas antigos aparecem no
        // sino/drawer normalmente; toast só dispara pra alertas que chegarem
        // depois do mount (via Realtime ou catch-up detectando ids novos).
        for (const item of store.items || []) {
            if (item.type === 'system_alert') {
                alertedIds.add(item.id);
            }
        }

        store.subscribeRealtime(ownerId, onRealtimeNotification);

        document.addEventListener('visibilitychange', onVisibilityChange);
        pollTimer = setInterval(refreshAndMaybeAlert, POLLING_INTERVAL_MS);
    });

    onUnmounted(() => {
        document.removeEventListener('visibilitychange', onVisibilityChange);
        if (pollTimer) clearInterval(pollTimer);
        pollTimer = null;
        store.unsubscribe();
    });

    return store;
}

