/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/stores/notificationStore.js
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
*/
import { defineStore } from 'pinia';
import { supabase } from '@/lib/supabase/client';

import { tenantDb } from '@/lib/supabase/tenantClient';
import { useTenantStore } from '@/stores/tenantStore';
// ─── Browser Notification helpers ────────────────────────────
const BROWSER_NOTIF_PREF_KEY = 'agenciapsi.browser_notifications_enabled';

function browserNotifSupported() {
    return typeof window !== 'undefined' && 'Notification' in window;
}

function browserNotifAllowed() {
    return browserNotifSupported() && Notification.permission === 'granted';
}

function browserNotifEnabled() {
    if (!browserNotifAllowed()) return false;
    try {
        const v = localStorage.getItem(BROWSER_NOTIF_PREF_KEY);
        return v !== 'false'; // default: on quando permitido
    } catch {
        return true;
    }
}

export function fireBrowserNotification(item, onClick) {
    if (!browserNotifEnabled()) return;
    if (document.hasFocus() && document.visibilityState === 'visible') return; // não notifica se tab ativa
    try {
        const title = item?.payload?.title || 'Nova notificação';
        const body = item?.payload?.detail || '';
        const n = new Notification(title, {
            body,
            icon: '/favicon.ico',
            tag: `agenciapsi:${item.id}`,
            requireInteraction: false
        });
        n.onclick = () => {
            window.focus();
            if (typeof onClick === 'function') {
                try { onClick(item); } catch { /* ignore */ }
            } else if (item?.payload?.deeplink) {
                // fallback: navegação direta se ninguém registrou handler
                window.location.href = item.payload.deeplink;
            }
            n.close();
        };
    } catch {
        // browser sem suporte ou permissão revogada
    }
}

export async function requestBrowserNotificationPermission() {
    if (!browserNotifSupported()) return false;
    if (Notification.permission === 'granted') return true;
    if (Notification.permission === 'denied') return false;
    try {
        const res = await Notification.requestPermission();
        return res === 'granted';
    } catch {
        return false;
    }
}

export function setBrowserNotificationEnabled(enabled) {
    try {
        localStorage.setItem(BROWSER_NOTIF_PREF_KEY, enabled ? 'true' : 'false');
    } catch {
        // ignore
    }
}

export function getBrowserNotificationEnabled() {
    return browserNotifEnabled();
}

export const useNotificationStore = defineStore('notifications', {
    state: () => ({
        items: [],
        drawerOpen: false,
        _channel: null
    }),

    getters: {
        unreadCount: (state) => state.items.filter((n) => !n.read_at && !n.archived).length,

        unreadItems: (state) => state.items.filter((n) => !n.read_at && !n.archived),

        allItems: (state) => state.items.filter((n) => !n.archived)
    },

    actions: {
        // schema-per-tenant: notificações vêm de DUAS fontes —
        //  • tenant_<slug>.notifications (locais: agenda, conversas, pacientes)
        //  • public.notifications_sistema (cross-tenant: avisos do SaaS, suporte)
        // Cada item carrega _origem ('tenant' | 'sistema') p/ rotear markRead/archive.
        async load(ownerId) {
            const [localRes, sistemaRes] = await Promise.all([
                tenantDb().from('notifications').select('*').eq('owner_id', ownerId).eq('archived', false).order('created_at', { ascending: false }).limit(50),
                supabase.from('notifications_sistema').select('*').eq('owner_id', ownerId).eq('archived', false).order('created_at', { ascending: false }).limit(50)
            ]);

            if (localRes.error) console.error('[notificationStore] load tenant error:', localRes.error.message);
            if (sistemaRes.error) console.error('[notificationStore] load sistema error:', sistemaRes.error.message);

            const local = (localRes.data || []).map((n) => ({ ...n, _origem: 'tenant' }));
            const sistema = (sistemaRes.data || []).map((n) => ({ ...n, _origem: 'sistema' }));

            this.items = [...local, ...sistema]
                .sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
                .slice(0, 50);
        },

        subscribeRealtime(ownerId, onInsert = null) {
            if (this._channel) return;
            const tenantSchema = useTenantStore().activeTenantSchema;

            const onIns = (origem) => (payload) => {
                const item = { ...payload.new, _origem: origem };
                this.items.unshift(item);
                this.items.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
                if (typeof onInsert === 'function') {
                    try { onInsert(item); } catch { /* ignore */ }
                }
            };

            const channel = supabase.channel(`notifications:${ownerId}`);
            if (tenantSchema) {
                channel.on('postgres_changes',
                    { event: 'INSERT', schema: tenantSchema, table: 'notifications', filter: `owner_id=eq.${ownerId}` },
                    onIns('tenant'));
            }
            // canal cross-tenant (avisos do SaaS) — sempre escuta public
            channel.on('postgres_changes',
                { event: 'INSERT', schema: 'public', table: 'notifications_sistema', filter: `owner_id=eq.${ownerId}` },
                onIns('sistema'));

            channel.subscribe();
            this._channel = channel;
        },

        // roteia pra fonte certa conforme _origem do item
        _sourceFor(item) {
            return item?._origem === 'sistema'
                ? supabase.from('notifications_sistema')
                : tenantDb().from('notifications');
        },

        async markRead(id) {
            const item = this.items.find((n) => n.id === id);
            if (!item) return;
            const now = new Date().toISOString();
            const { error } = await this._sourceFor(item).update({ read_at: now }).eq('id', id);

            if (error) {
                console.error('[notificationStore] markRead error:', error.message);
                return;
            }
            item.read_at = now;
        },

        async markAllRead() {
            const unread = this.items.filter((n) => !n.read_at && !n.archived);
            if (!unread.length) return;
            const now = new Date().toISOString();

            const tenantIds = unread.filter((n) => n._origem !== 'sistema').map((n) => n.id);
            const sistemaIds = unread.filter((n) => n._origem === 'sistema').map((n) => n.id);

            const ops = [];
            if (tenantIds.length) ops.push(tenantDb().from('notifications').update({ read_at: now }).in('id', tenantIds));
            if (sistemaIds.length) ops.push(supabase.from('notifications_sistema').update({ read_at: now }).in('id', sistemaIds));
            const results = await Promise.all(ops);
            const err = results.find((r) => r.error);
            if (err) {
                console.error('[notificationStore] markAllRead error:', err.error.message);
                return;
            }
            this.items.forEach((n) => {
                if (!n.read_at && !n.archived) n.read_at = now;
            });
        },

        async archive(id) {
            const item = this.items.find((n) => n.id === id);
            if (!item) return;
            const { error } = await this._sourceFor(item).update({ archived: true }).eq('id', id);

            if (error) {
                console.error('[notificationStore] archive error:', error.message);
                return;
            }
            this.items = this.items.filter((n) => n.id !== id);
        },

        unsubscribe() {
            if (this._channel) {
                supabase.removeChannel(this._channel);
                this._channel = null;
            }
        },

        // ⚠️ Pegadinha #4: ao trocar de usuário (logout→login), o store é um
        // singleton Pinia — sem reset, items/_channel ficam stale e vazam
        // notificações entre usuários. Chamar no logout.
        reset() {
            this.unsubscribe();
            this.items = [];
            this.drawerOpen = false;
        }
    }
});
