/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/navigation/index.js
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
*/

// ======================================================
// 📦 Importação dos menus base por área
// ======================================================

import adminMenu from './menus/clinic.menu';
import therapistMenu from './menus/therapist.menu';
import supervisorMenu from './menus/supervisor.menu';
import editorMenu from './menus/editor.menu';
import portalMenu from './menus/portal.menu';
import saasMenu from './menus/saas.menu';

import { useSaasHealthStore } from '@/stores/saasHealthStore';
import { useTenantFeaturesStore } from '@/stores/tenantFeaturesStore';
import { useEntitlementsStore } from '@/stores/entitlementsStore';
import { countAtencao } from '@/composables/useDocsHealth';

// ======================================================
// 🎭 Mapeamento de role → menu base
// ======================================================

const MENUS = {
    clinic_admin: adminMenu,
    tenant_admin: adminMenu, // alias
    therapist: therapistMenu,
    supervisor: supervisorMenu,
    editor: editorMenu,
    patient: portalMenu,
    portal_user: portalMenu, // alias (globalRole do paciente)
    saas_admin: saasMenu
};

// ======================================================
// 🧠 Helpers
// ======================================================

function resolveMenu(builder, ctx) {
    if (!builder) return [];
    try {
        return typeof builder === 'function' ? builder(ctx) : builder;
    } catch (e) {
        // se um builder estourar, não derruba o app: cai no fallback
        console.warn('[NAV] menu builder error:', e);
        return [];
    }
}

// core menu anti-"sumir"
function coreMenu() {
    return [
        {
            label: 'Geral',
            items: [
                { label: 'Início', icon: 'pi pi-home', to: '/' },
                { label: 'Assinatura', icon: 'pi pi-credit-card', to: '/billing' },
                { label: 'Perfil', icon: 'pi pi-user', to: '/profile' }
            ]
        }
    ];
}

function safeHasFeature(fn, key) {
    try {
        return !!fn?.(key);
    } catch {
        return false;
    }
}

// ======================================================
// 🧩 Decorator do menu
// - NÃO remove itens
// - Apenas calcula badge PRO dinâmico (com base em entitlements)
// ======================================================

function decorateMenu(menu, hasFeature) {
    const arr = Array.isArray(menu) ? menu : [];
    return arr.map((group) => {
        if (group?.items && Array.isArray(group.items)) {
            return { ...group, items: decorateItems(group.items, hasFeature) };
        }
        return group;
    });
}

function decorateItems(items, hasFeature) {
    return (items || []).map((it) => {
        if (it?.items && Array.isArray(it.items)) {
            return { ...it, items: decorateItems(it.items, hasFeature) };
        }

        const featureKey = it?.feature ? String(it.feature) : null;
        const showPro = !!it?.proBadge && !!featureKey && !safeHasFeature(hasFeature, featureKey);

        return { ...it, __showProBadge: showPro };
    });
}

// ======================================================
// ✅ Normalização de role (evita menu vazio)
// ======================================================

function normalizeRole(role) {
    const r = String(role || '').trim();
    if (!r) return null;

    // aliases comuns (blindagem)
    if (r === 'tenant_admin') return 'clinic_admin';
    if (r === 'admin') return 'clinic_admin';
    if (r === 'clinic') return 'clinic_admin';

    return r;
}

// ======================================================
// ✅ hasFeature robusto
// - Prioriza sessionCtx (evita flicker)
// - Senão tenta deduzir do store com vários formatos comuns
// ======================================================

function buildHasFeature(sessionCtx, entitlementsStore) {
    // 1) se já veio pronto, usa
    if (typeof sessionCtx?.hasFeature === 'function') return sessionCtx.hasFeature;

    // 2) se veio entitlements como objeto { key: true }
    if (sessionCtx?.entitlements && typeof sessionCtx.entitlements === 'object') {
        const bag = sessionCtx.entitlements;
        return (k) => !!bag[String(k || '').trim()];
    }

    // 3) se veio allowedFeatures como array ou Set
    if (sessionCtx?.allowedFeatures) {
        const af = sessionCtx.allowedFeatures;
        if (Array.isArray(af)) {
            const s = new Set(af.map((x) => String(x).trim()).filter(Boolean));
            return (k) => s.has(String(k || '').trim());
        }
        if (af instanceof Set) {
            return (k) => af.has(String(k || '').trim());
        }
    }

    // 4) fallback no store
    return (featureKey) => {
        const k = String(featureKey || '').trim();
        if (!k) return false;

        try {
            if (typeof entitlementsStore?.hasFeature === 'function') return !!entitlementsStore.hasFeature(k);
            if (typeof entitlementsStore?.has === 'function') return !!entitlementsStore.has(k);

            // formatos comuns:
            // - entitlements: { key: true }
            // - entitlements: Set([...])
            // - entitlements: Array([...])
            // - byOwner: { [ownerId]: { key: true } }
            const bag = entitlementsStore?.entitlements || entitlementsStore?.features || entitlementsStore?.data || entitlementsStore?.state;

            if (bag instanceof Set) return bag.has(k);
            if (Array.isArray(bag)) return bag.includes(k);
            if (bag && typeof bag === 'object') {
                // tenta direto
                if (Object.prototype.hasOwnProperty.call(bag, k)) return !!bag[k];

                // tenta byOwner (caso exista)
                const ownerId = sessionCtx?.ownerId || sessionCtx?.activeTenantId || sessionCtx?.tenantId;
                if (ownerId && bag[ownerId] && typeof bag[ownerId] === 'object') {
                    return !!bag[ownerId][k];
                }
            }
        } catch {}

        return false;
    };
}

// ======================================================
// 🎯 getMenuByRole
// ======================================================

export function getMenuByRole(role, sessionCtx = {}) {
    const saasHealthStore = useSaasHealthStore();
    const mismatchCount = saasHealthStore?.mismatchCount || 0;

    const tenantFeaturesStore = useTenantFeaturesStore();
    const entitlementsStore = useEntitlementsStore();

    const isSaas = sessionCtx?.isSaasAdmin === true;

    const tenantFeatureEnabled =
        typeof sessionCtx?.tenantFeatureEnabled === 'function'
            ? sessionCtx.tenantFeatureEnabled
            : (key) => {
                  try {
                      return !!tenantFeaturesStore?.isEnabled?.(key);
                  } catch {
                      return false;
                  }
              };

    const tenantLoading = typeof sessionCtx?.tenantLoading === 'function' ? sessionCtx.tenantLoading : () => false;

    const tenantFeaturesLoading = typeof sessionCtx?.tenantFeaturesLoading === 'function' ? sessionCtx.tenantFeaturesLoading : () => false;

    const hasFeature = buildHasFeature(sessionCtx, entitlementsStore);

    const ctx = {
        ...sessionCtx,
        mismatchCount,
        tenantFeaturesStore,
        tenantFeatureEnabled,
        tenantLoading,
        tenantFeaturesLoading,
        entitlementsStore,
        hasFeature
    };

    // ✅ role normalizado
    const r = normalizeRole(role);

    const baseRaw = resolveMenu(MENUS[r], ctx);
    const base = decorateMenu(baseRaw, hasFeature);

    const saasRaw = typeof saasMenu === 'function' ? saasMenu(ctx, { mismatchCount, docsAtencaoCount: countAtencao.value }) : saasMenu;
    const saas = decorateMenu(saasRaw, hasFeature);

    // 🔒 SaaS master: somente área SaaS
    if (isSaas) {
        return saas.length ? saas : coreMenu();
    }

    // ✅ fallback: nunca retorna vazio
    if (!base || !base.length) {
        return coreMenu();
    }

    return [...base];
}
