/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/stores/noticeStore.js
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
*/
// Store Pinia — lógica de prioridade, filtragem, dismiss e regras de exibição

import { defineStore } from 'pinia';
import { fetchActiveNotices, loadUserDismissals, saveDismissal, trackView, trackClick as svcTrackClick } from '@/features/notices/noticeService';

// ── Storage helpers ────────────────────────────────────────────

function dismissKey(id, version) {
    return `notice_dismissed_${id}_v${version}`;
}

function viewKey(id) {
    return `notice_views_${id}`;
}

function lastSeenKey(id) {
    return `notice_last_seen_${id}`;
}

function isDismissedLocally(id, version, scope) {
    const store = scope === 'session' ? sessionStorage : localStorage;
    return store.getItem(dismissKey(id, version)) === '1';
}

function setDismissedLocally(id, version, scope) {
    const store = scope === 'session' ? sessionStorage : localStorage;
    store.setItem(dismissKey(id, version), '1');
}

function getViewCount(id) {
    return parseInt(localStorage.getItem(viewKey(id)) || '0', 10);
}

function incrementViewCount(id) {
    const count = getViewCount(id) + 1;
    localStorage.setItem(viewKey(id), String(count));
    return count;
}

function getLastSeen(id) {
    const v = localStorage.getItem(lastSeenKey(id));
    return v ? new Date(v) : null;
}

function setLastSeen(id) {
    localStorage.setItem(lastSeenKey(id), new Date().toISOString());
}

// ── Contexto da rota → string de contexto ─────────────────────

export function routeToContext(path = '') {
    if (path.startsWith('/saas')) return 'saas';
    if (path.startsWith('/admin')) return 'clinic';
    if (path.startsWith('/therapist')) return 'therapist';
    if (path.startsWith('/supervisor')) return 'supervisor';
    if (path.startsWith('/editor')) return 'editor';
    if (path.startsWith('/portal')) return 'portal';
    return 'public';
}

// ── Store ──────────────────────────────────────────────────────

export const useNoticeStore = defineStore('noticeStore', {
    state: () => ({
        notices: [], // todos os notices ativos buscados
        activeNotice: null, // o notice sendo exibido agora
        userDismissals: [], // dismissals do banco (scope = 'user')
        loading: false,
        lastFetch: null, // timestamp da última busca
        currentRole: null, // role do usuário atual
        currentContext: null // contexto da rota atual
    }),

    actions: {
        // ── Inicialização ──────────────────────────────────────────

        async init(role, routePath) {
            this.currentRole = role || null;
            this.currentContext = routeToContext(routePath);

            // Não rebusca se buscou há menos de 5 minutos
            const CACHE_MS = 5 * 60 * 1000;
            if (this.lastFetch && Date.now() - this.lastFetch < CACHE_MS) {
                this._recalcActive();
                return;
            }

            await this._fetchAndApply();
        },

        async _fetchAndApply() {
            this.loading = true;
            try {
                const [notices, dismissals] = await Promise.all([fetchActiveNotices(), loadUserDismissals()]);
                this.notices = notices;
                this.userDismissals = dismissals;
                this.lastFetch = Date.now();
                this._recalcActive();
            } catch (e) {
                console.warn('[NoticeStore] falha ao buscar avisos:', e?.message || e);
            } finally {
                this.loading = false;
            }
        },

        // ── Filtragem + prioridade ─────────────────────────────────

        _recalcActive() {
            const role = this.currentRole;
            const context = this.currentContext;

            const candidates = this.notices.filter((n) => {
                // 1. Segmentação por role (array vazio = todos)
                if (n.roles?.length && role && !n.roles.includes(role)) return false;

                // 2. Segmentação por context (array vazio = todos)
                if (n.contexts?.length && context && !n.contexts.includes(context)) return false;

                // 3. Dismiss check
                if (this._isDismissed(n)) return false;

                // 4. show_once
                if (n.show_once && getViewCount(n.id) > 0) return false;

                // 5. max_views
                if (n.max_views != null && getViewCount(n.id) >= n.max_views) return false;

                // 6. cooldown
                if (n.cooldown_minutes) {
                    const last = getLastSeen(n.id);
                    if (last) {
                        const diffMin = (Date.now() - last.getTime()) / 60_000;
                        if (diffMin < n.cooldown_minutes) return false;
                    }
                }

                return true;
            });

            // Ordena por priority desc (já vem ordenado do server, mas garante)
            candidates.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));

            this.activeNotice = candidates[0] || null;
        },

        _isDismissed(notice) {
            const { id, version, dismiss_scope: scope } = notice;

            if (scope === 'user') {
                const entry = this.userDismissals.find((d) => d.notice_id === id);
                return !!entry && entry.version >= version;
            }

            return isDismissedLocally(id, version, scope || 'device');
        },

        // ── Dismiss ────────────────────────────────────────────────

        async dismiss(notice) {
            if (!notice?.dismissible) return;

            const { id, version, dismiss_scope: scope, persist_dismiss: persist } = notice;

            if (scope === 'user' && persist) {
                await saveDismissal(id, version);
                this.userDismissals = [...this.userDismissals.filter((d) => d.notice_id !== id), { notice_id: id, version }];
            } else if (persist) {
                setDismissedLocally(id, version, scope || 'device');
            } else {
                // sem persistência: usa session como temporário
                setDismissedLocally(id, version, 'session');
            }

            this._recalcActive();
        },

        // ── Tracking ───────────────────────────────────────────────

        onView(notice) {
            if (!notice?.id) return;
            incrementViewCount(notice.id);
            setLastSeen(notice.id);
            trackView(notice.id);
        },

        async onCtaClick(notice) {
            if (!notice?.id) return;
            await svcTrackClick(notice.id);
        },

        // ── Atualiza contexto quando rota muda ─────────────────────

        updateContext(routePath, role) {
            const newCtx = routeToContext(routePath);
            const newRole = role || this.currentRole;

            if (newCtx !== this.currentContext || newRole !== this.currentRole) {
                this.currentContext = newCtx;
                this.currentRole = newRole;
                this._recalcActive();
            }
        },

        // ── Força re-busca ─────────────────────────────────────────

        async refresh() {
            this.lastFetch = null;
            await this._fetchAndApply();
        }
    }
});
