/*
 * useTopbarPlanMenu — DEV-only switcher de subscription_plan no topbar.
 *
 * Extraído do AppTopbar.vue pra ser reusado pelo Melissa (e qualquer
 * topbar futuro). Encapsula toda a máquina de estados:
 *   - resolve subscription ativa do contexto (clinic vs therapist)
 *   - lista plans ativos do target
 *   - ordena (free primeiro)
 *   - troca via RPC `change_subscription_plan` + invalida entitlements
 *
 * Visibilidade controlada por `showPlanDevMenu` (DEV mode + feature flag
 * `VITE_ENABLE_PLAN_TOGGLE` + permissão settings.view).
 *
 * Uso:
 *   const { planBtn, planMenu, planMenuModel, planMenuLoading,
 *           trocandoPlano, showPlanDevMenu, openPlanMenu } = useTopbarPlanMenu();
 *
 *   <Button v-if="showPlanDevMenu" ref="planBtn" :loading="planMenuLoading || trocandoPlano" @click="openPlanMenu">…</Button>
 *   <Menu ref="planMenu" :model="planMenuModel" popup appendTo="body" />
 */
import { ref, computed } from 'vue';
import { useRoute } from 'vue-router';
import { useToast } from 'primevue/usetoast';
import { supabase } from '@/lib/supabase/client';
import { useTenantStore } from '@/stores/tenantStore';
import { useEntitlementsStore } from '@/stores/entitlementsStore';
import { useRoleGuard } from '@/composables/useRoleGuard';

export function useTopbarPlanMenu() {
    const route = useRoute();
    const toast = useToast();
    const tenantStore = useTenantStore();
    const entitlementsStore = useEntitlementsStore();
    const { canSee } = useRoleGuard();

    const tenantId = computed(() => tenantStore.activeTenantId || null);

    const planBtn = ref(null);
    const planMenu = ref(null);
    const planMenuLoading = ref(false);
    const planMenuTarget = ref(null);   // 'therapist' | 'clinic' | null
    const planMenuSub = ref(null);      // subscription ativa
    const planMenuPlans = ref([]);      // plans ativos do target
    const trocandoPlano = ref(false);

    const enablePlanToggle = computed(() => {
        const flag = String(import.meta.env?.VITE_ENABLE_PLAN_TOGGLE || '').toLowerCase();
        return Boolean(import.meta.env?.DEV) || flag === 'true';
    });

    const showPlanDevMenu = computed(() => canSee('settings.view') && enablePlanToggle.value);

    async function getMyUserId() {
        const { data, error } = await supabase.auth.getUser();
        if (error) throw error;
        const uid = data?.user?.id;
        if (!uid) throw new Error('Sessão inválida (sem user).');
        return uid;
    }

    async function getActiveTherapistSubscription() {
        const uid = await getMyUserId();
        const { data, error } = await supabase
            .from('subscriptions')
            .select('id, tenant_id, user_id, plan_id, status, updated_at')
            .eq('user_id', uid)
            .order('updated_at', { ascending: false })
            .limit(10);
        if (error) throw error;
        const list = data || [];
        if (!list.length) return null;
        const priority = (st) => {
            const s = String(st || '').toLowerCase();
            if (s === 'active') return 1;
            if (s === 'trialing') return 2;
            if (s === 'past_due') return 3;
            if (s === 'unpaid') return 4;
            if (s === 'incomplete') return 5;
            if (s === 'canceled' || s === 'cancelled') return 9;
            return 8;
        };
        return list.slice().sort((a, b) => {
            const pa = priority(a?.status);
            const pb = priority(b?.status);
            if (pa !== pb) return pa - pb;
            return new Date(b?.updated_at || 0) - new Date(a?.updated_at || 0);
        })[0];
    }

    async function getActiveClinicSubscription() {
        const tid = tenantId.value;
        if (!tid) return null;
        const { data, error } = await supabase
            .from('subscriptions')
            .select('id, tenant_id, user_id, plan_id, status, updated_at')
            .eq('tenant_id', tid)
            .eq('status', 'active')
            .order('updated_at', { ascending: false })
            .limit(1)
            .maybeSingle();
        if (error) throw error;
        return data || null;
    }

    async function listActivePlansByTarget(target) {
        const { data, error } = await supabase
            .from('plans')
            .select('id, key, target, is_active')
            .eq('target', target)
            .eq('is_active', true)
            .order('key', { ascending: true });
        if (error) throw error;
        return data || [];
    }

    async function refreshEntitlementsAfterToggle(target) {
        if (target === 'clinic') {
            const tid = tenantId.value;
            if (!tid) return;
            await entitlementsStore.loadForTenant(tid, { force: true });
            return;
        }
        const uid = await getMyUserId();
        await entitlementsStore.loadForUser(uid, { force: true });
    }

    // Áreas de clínica (/admin, /supervisor) → contexto tenant_id (clinic).
    // Demais áreas (/therapist, /editor, /portal, etc.) → contexto user_id.
    // Em /melissa não há um caminho semântico de área, então cai no fallback
    // therapist (que é o role mais comum do user que escolhe Melissa).
    async function resolveActiveSubscriptionContext() {
        const path = route.path || '';
        const isClinicContext = path.startsWith('/admin') || path.startsWith('/supervisor');

        if (isClinicContext && tenantId.value) {
            const clinicSub = await getActiveClinicSubscription();
            if (clinicSub) return { sub: clinicSub, target: 'clinic' };
        }

        const therapistSub = await getActiveTherapistSubscription();
        if (therapistSub) return { sub: therapistSub, target: 'therapist' };

        if (tenantId.value) {
            const clinicSub = await getActiveClinicSubscription();
            return { sub: clinicSub || null, target: clinicSub ? 'clinic' : null };
        }
        return { sub: null, target: null };
    }

    function normalizeKey(k) {
        return String(k || '').trim();
    }

    // free primeiro, depois o resto por key
    function sortPlansSmart(plans) {
        const arr = [...(plans || [])];
        arr.sort((a, b) => {
            const ak = normalizeKey(a?.key).toLowerCase();
            const bk = normalizeKey(b?.key).toLowerCase();
            const aIsFree = ak.endsWith('_free') || ak === 'free';
            const bIsFree = bk.endsWith('_free') || bk === 'free';
            if (aIsFree && !bIsFree) return -1;
            if (!aIsFree && bIsFree) return 1;
            return ak.localeCompare(bk);
        });
        return arr;
    }

    async function loadPlanMenuData() {
        planMenuLoading.value = true;
        try {
            const { sub, target } = await resolveActiveSubscriptionContext();
            planMenuSub.value = sub;
            planMenuTarget.value = target;
            if (!sub?.id || !target) {
                planMenuPlans.value = [];
                return;
            }
            const plans = await listActivePlansByTarget(target);
            planMenuPlans.value = sortPlansSmart(plans);
        } finally {
            planMenuLoading.value = false;
        }
    }

    const planMenuModel = computed(() => {
        const sub = planMenuSub.value;
        const target = planMenuTarget.value;
        const plans = planMenuPlans.value || [];

        if (!sub?.id || !target) {
            return [
                { label: 'Sem assinatura ativa', icon: 'pi pi-exclamation-triangle', disabled: true },
                { label: 'Não encontrei subscription ativa nem para therapist (user_id) nem para clinic (tenant_id).', disabled: true }
            ];
        }

        const currentPlanId = String(sub.plan_id || '');

        const header = {
            label: `Planos (${target})`,
            icon: target === 'therapist' ? 'pi pi-user' : 'pi pi-building',
            disabled: true
        };

        const subInfo = {
            label: `Sub: ${String(sub.id).slice(0, 8)}…  •  Atual: ${String(currentPlanId).slice(0, 8)}…`,
            icon: 'pi pi-info-circle',
            disabled: true
        };

        const items = [];
        let insertedSeparator = false;

        plans.forEach((p) => {
            const isCurrent = String(p.id) === currentPlanId;
            const keyLower = String(p.key || '').toLowerCase();
            const isFree = keyLower.endsWith('_free') || keyLower === 'free';

            items.push({
                label: isCurrent ? `${p.key} (atual)` : p.key,
                icon: isCurrent ? 'pi pi-check' : isFree ? 'pi pi-star' : 'pi pi-circle',
                disabled: isCurrent || planMenuLoading.value || trocandoPlano.value,
                command: async () => {
                    await changePlanTo(p.id, p.key, target);
                }
            });

            if (!insertedSeparator && isFree) {
                items.push({ separator: true });
                insertedSeparator = true;
            }
        });

        if (items.length && items[items.length - 1]?.separator) items.pop();

        if (!plans.length) {
            return [header, subInfo, { separator: true }, { label: 'Nenhum plano ativo encontrado', icon: 'pi pi-info-circle', disabled: true }];
        }

        return [header, subInfo, { separator: true }, ...items];
    });

    async function openPlanMenu(event) {
        if (!showPlanDevMenu.value) return;

        // Captura a âncora ANTES do await — `event.currentTarget` é null
        // depois que a microtask resume (DOM behavior). Suporta tanto
        // PrimeVue <Button> (expõe `$el`) quanto <button> HTML cru
        // (planBtn.value já é o DOM element).
        const anchorEl =
            planBtn.value?.$el ||
            planBtn.value ||
            event?.currentTarget ||
            event?.target;

        try {
            await loadPlanMenuData();
        } catch (err) {
            // eslint-disable-next-line no-console
            console.error('[PLANO][DEV menu] erro:', err?.message || err);
            toast.add({
                severity: 'error',
                summary: 'Erro ao carregar planos',
                detail: err?.message || 'Falha desconhecida.',
                life: 5200
            });
        }

        if (!anchorEl) {
            planMenu.value?.toggle?.(event);
            return;
        }
        planMenu.value?.show?.({ currentTarget: anchorEl });
    }

    async function changePlanTo(newPlanId, newPlanKey, target) {
        if (trocandoPlano.value) return;
        trocandoPlano.value = true;
        try {
            const sub = planMenuSub.value;
            if (!sub?.id) throw new Error('Subscription inválida.');
            const { error: rpcError } = await supabase.rpc('change_subscription_plan', {
                p_subscription_id: sub.id,
                p_new_plan_id: newPlanId
            });
            if (rpcError) throw rpcError;
            planMenuSub.value = { ...sub, plan_id: newPlanId };
            await refreshEntitlementsAfterToggle(target);
            toast.add({
                severity: 'success',
                summary: 'Plano alterado (DEV)',
                detail: `${String(newPlanKey).toUpperCase()} aplicado (${target})`,
                life: 3200
            });
        } catch (err) {
            // eslint-disable-next-line no-console
            console.error('[PLANO] Erro ao trocar:', err?.message || err);
            toast.add({
                severity: 'error',
                summary: 'Erro ao trocar plano',
                detail: err?.message || 'Falha desconhecida.',
                life: 6000
            });
        } finally {
            trocandoPlano.value = false;
        }
    }

    return {
        planBtn,
        planMenu,
        planMenuModel,
        planMenuLoading,
        trocandoPlano,
        showPlanDevMenu,
        openPlanMenu
    };
}
