<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/views/pages/billing/UpgradePage.vue
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
-->
<script setup>
import { computed, onMounted, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';

import { useToast } from 'primevue/usetoast';

import { supabase } from '@/lib/supabase/client';
import { useTenantStore } from '@/stores/tenantStore';
import { useEntitlementsStore } from '@/stores/entitlementsStore';

const toast = useToast();
const route = useRoute();
const router = useRouter();

const tenantStore = useTenantStore();
const entitlementsStore = useEntitlementsStore();

// ======================================================
// ✅ Detecta contexto: terapeuta (personal) ou clínica (tenant)
// O guard passa ?role=therapist ou ?role=clinic_admin na URL,
// mas também fazemos fallback pelo activeRole do tenantStore.
// ======================================================
const activeRole = computed(() => {
    const fromQuery = route.query.role || '';
    const fromStore = tenantStore.activeRole || '';
    const r = String(fromQuery || fromStore).trim();
    if (r === 'therapist') return 'therapist';
    if (r === 'clinic_admin' || r === 'tenant_admin') return 'clinic_admin';
    return 'clinic_admin'; // fallback seguro
});

const isTherapist = computed(() => activeRole.value === 'therapist');
const planTarget = computed(() => (isTherapist.value ? 'therapist' : 'clinic'));

// Feature que motivou o redirecionamento
const requestedFeature = computed(() => route.query.feature || null);

// ✅ nome vem do banco (features.name), sem hardcode
const featureNameMap = computed(() => {
    const m = new Map();
    for (const f of features.value) m.set(f.key, f.name || f.key);
    return m;
});

function friendlyFeatureLabel(key) {
    return featureNameMap.value.get(key) || key;
}

const requestedFeatureLabel = computed(() => {
    if (!requestedFeature.value) return null;
    return featureNameMap.value.get(requestedFeature.value) || requestedFeature.value;
});

const loading = ref(false);
const upgrading = ref(false);

const plans = ref([]);
const features = ref([]);
const planFeatures = ref([]);
const prices = ref([]);
const subscription = ref(null);

// IDs de contexto — dependem do role
const tenantId = computed(() => (isTherapist.value ? null : tenantStore.activeTenantId || null));
const userId = computed(() => (isTherapist.value ? tenantStore.user?.id || null : null));

const planById = computed(() => {
    const m = new Map();
    for (const p of plans.value) m.set(p.id, p);
    return m;
});

const enabledFeatureIdsByPlanId = computed(() => {
    const m = new Map();
    for (const row of planFeatures.value) {
        const set = m.get(row.plan_id) || new Set();
        set.add(row.feature_id);
        m.set(row.plan_id, set);
    }
    return m;
});

const currentPlanId = computed(() => subscription.value?.plan_id || null);
const currentPlanKey = computed(() => planById.value.get(currentPlanId.value)?.key || subscription.value?.plan_key || null);

function planKeyById(id) {
    return planById.value.get(id)?.key || null;
}

const billingInterval = ref('month');
const intervalOptions = [
    { label: 'Mensal', value: 'month' },
    { label: 'Anual', value: 'year' }
];

const q = ref('');

function intervalLabel(i) {
    return i === 'month' ? 'mês' : i === 'year' ? 'ano' : i || '-';
}

function money(currency, amountCents) {
    if (amountCents == null) return null;
    const value = Number(amountCents) / 100;
    try {
        return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: currency || 'BRL' }).format(value);
    } catch {
        return `${value.toFixed(2)} ${currency || ''}`.trim();
    }
}

function priceFor(planId, interval) {
    return (prices.value || []).find((p) => String(p.plan_id) === String(planId) && String(p.interval) === String(interval)) || null;
}

function priceLabelForPlan(planId) {
    const pp = priceFor(planId, billingInterval.value);
    if (!pp) return '—';
    return `${money(pp.currency, pp.amount_cents)} / ${intervalLabel(billingInterval.value)}`;
}

const sortedPlans = computed(() => {
    const term = String(q.value || '')
        .trim()
        .toLowerCase();
    let arr = [...plans.value];
    if (term) {
        arr = arr.filter((p) =>
            [p.key, p.name, p.description].some((s) =>
                String(s || '')
                    .toLowerCase()
                    .includes(term)
            )
        );
    }
    const rank = (k) => (String(k).toLowerCase() === 'pro' ? 0 : String(k).toLowerCase() === 'free' ? 5 : 10);
    arr.sort((a, b) => rank(a.key) - rank(b.key) || String(a.key).localeCompare(String(b.key)));
    return arr;
});

function planBenefits(planId) {
    const set = enabledFeatureIdsByPlanId.value.get(planId) || new Set();
    return features.value.map((f) => ({ ok: set.has(f.id), key: f.key, text: friendlyFeatureLabel(f.key) })).sort((a, b) => Number(b.ok) - Number(a.ok) || a.text.localeCompare(b.text));
}

function goBack() {
    router.back();
}
function goBilling() {
    router.push(isTherapist.value ? '/therapist/meu-plano' : '/admin/meu-plano');
}
function contactSupport() {
    goBilling();
}

async function revalidateCurrentRoute() {
    const redirectTo = route.query.redirectTo ? String(route.query.redirectTo) : null;
    if (redirectTo) {
        try {
            await router.replace(redirectTo);
            return;
        } catch {}
    }
    try {
        await router.replace(router.currentRoute.value.fullPath);
    } catch {}
}

async function fetchAll() {
    loading.value = true;
    try {
        if (!tenantStore.loaded) await tenantStore.loadSessionAndTenant();

        const nowIso = new Date().toISOString();

        // ✅ busca planos do target correto (therapist ou clinic)
        const pQuery = supabase.from('plans').select('*').eq('is_active', true).eq('target', planTarget.value).order('key', { ascending: true });

        // ✅ busca subscription do contexto correto
        let sQuery = supabase
            .from('subscriptions')
            .select(
                `id, tenant_id, user_id, plan_id, plan_key, interval, status,
               provider, source, started_at, current_period_start,
               current_period_end, created_at, updated_at`
            )
            .eq('status', 'active')
            .order('created_at', { ascending: false })
            .limit(1)
            .maybeSingle();

        if (isTherapist.value) {
            const uid = userId.value;
            if (!uid) throw new Error('Usuário não identificado.');
            sQuery = supabase
                .from('subscriptions')
                .select(
                    `id, tenant_id, user_id, plan_id, plan_key, interval, status,
                 provider, source, started_at, current_period_start,
                 current_period_end, created_at, updated_at`
                )
                .eq('user_id', uid)
                .is('tenant_id', null)
                .eq('status', 'active')
                .order('created_at', { ascending: false })
                .limit(1)
                .maybeSingle();
        } else {
            const tid = tenantId.value;
            if (!tid) throw new Error('Tenant ativo não encontrado.');
            sQuery = supabase
                .from('subscriptions')
                .select(
                    `id, tenant_id, user_id, plan_id, plan_key, interval, status,
                 provider, source, started_at, current_period_start,
                 current_period_end, created_at, updated_at`
                )
                .eq('tenant_id', tid)
                .eq('status', 'active')
                .order('created_at', { ascending: false })
                .limit(1)
                .maybeSingle();
        }

        const [pRes, fRes, pfRes, sRes, ppRes] = await Promise.all([
            pQuery,
            supabase.from('features').select('id, key, name, descricao').order('key', { ascending: true }),
            supabase.from('plan_features').select('plan_id, feature_id'),
            sQuery,
            supabase
                .from('plan_prices')
                .select('plan_id, currency, interval, amount_cents, is_active, active_from, active_to')
                .eq('is_active', true)
                .lte('active_from', nowIso)
                .or(`active_to.is.null,active_to.gte.${nowIso}`)
                .order('active_from', { ascending: false })
        ]);

        if (pRes.error) throw pRes.error;
        if (fRes.error) throw fRes.error;
        if (pfRes.error) throw pfRes.error;
        if (ppRes.error) throw ppRes.error;
        if (sRes.error) console.warn('[Upgrade] erro ao buscar subscription:', sRes.error);

        plans.value = pRes.data || [];
        features.value = fRes.data || [];
        planFeatures.value = pfRes.data || [];
        subscription.value = sRes.data || null;
        prices.value = ppRes.data || [];
    } catch (e) {
        console.error(e);
        toast.add({ severity: 'error', summary: 'Erro', detail: e.message || String(e), life: 5000 });
    } finally {
        loading.value = false;
    }
}

async function changePlan(targetPlanId) {
    if (!targetPlanId || upgrading.value) return;

    if (!subscription.value?.id) {
        toast.add({
            severity: 'warn',
            summary: 'Sem assinatura ativa',
            detail: 'Não encontrei uma assinatura ativa. Vá em "Assinatura" para ativar/criar um plano.',
            life: 5200
        });
        return;
    }

    upgrading.value = true;
    try {
        if (String(subscription.value.plan_id) === String(targetPlanId)) return;

        const { data, error } = await supabase.rpc('change_subscription_plan', {
            p_subscription_id: subscription.value.id,
            p_new_plan_id: targetPlanId
        });
        if (error) throw error;

        subscription.value.plan_id = data?.plan_id || targetPlanId;
        subscription.value.plan_key = data?.plan_key || planKeyById(subscription.value.plan_id) || subscription.value.plan_key;

        // ✅ recarrega entitlements do contexto correto
        if (isTherapist.value) {
            const uid = userId.value;
            if (uid && typeof entitlementsStore.loadForUser === 'function') {
                await entitlementsStore.loadForUser(uid, { force: true });
            }
        } else {
            const tid = tenantId.value;
            if (tid && typeof entitlementsStore.loadForTenant === 'function') {
                await entitlementsStore.loadForTenant(tid, { force: true });
            }
        }

        toast.add({
            severity: 'success',
            summary: 'Plano atualizado',
            detail: `Agora você está no plano ${planKeyById(subscription.value.plan_id) || subscription.value.plan_key || ''}`.trim(),
            life: 3000
        });

        await fetchAll();
        await revalidateCurrentRoute();
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e.message || String(e), life: 5000 });
    } finally {
        upgrading.value = false;
    }
}

onMounted(async () => {
    if (!tenantStore.loaded) await tenantStore.loadSessionAndTenant();
    await fetchAll();
});

watch(
    () => tenantStore.activeTenantId,
    () => {
        fetchAll();
    }
);
watch(
    () => tenantStore.user?.id,
    () => {
        fetchAll();
    }
);
</script>

<template>
    <!-- Sentinel -->
    <div class="h-px" />

    <!-- ══════════════════════════════════════════════════════
       HERO sticky
  ═══════════════════════════════════════════════════════ -->
    <section class="sticky mx-3 md:mx-4 my-3 z-20 overflow-hidden rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] px-3 py-2.5" :style="{ top: 'var(--layout-sticky-top, 56px)' }">
        <!-- Blobs -->
        <div class="absolute inset-0 pointer-events-none overflow-hidden" aria-hidden="true">
            <div class="absolute w-64 h-64 -top-16 -right-8 rounded-full blur-[60px] bg-indigo-500/10" />
            <div class="absolute w-72 h-72 top-0 -left-16 rounded-full blur-[60px] bg-emerald-400/[0.08]" />
            <div class="absolute w-56 h-56 -bottom-8 right-1/4 rounded-full blur-[55px] bg-fuchsia-400/[0.07]" />
        </div>

        <div class="relative z-1 flex flex-col gap-2.5">
            <!-- Linha 1: brand + busca + ações -->
            <div class="flex items-center gap-3 flex-wrap">
                <!-- Brand -->
                <div class="flex items-center gap-2 shrink-0">
                    <div class="grid place-items-center w-9 h-9 rounded-md shrink-0 bg-indigo-500/10 text-indigo-500">
                        <i class="pi pi-sparkles text-base" />
                    </div>
                    <div class="min-w-0 hidden sm:block">
                        <div class="text-[1rem] font-bold tracking-tight text-[var(--text-color)]">Atualize seu plano</div>
                        <div class="text-[1rem] text-[var(--text-color-secondary)]">
                            Contexto: <b>{{ isTherapist ? 'Terapeuta' : 'Clínica' }}</b>
                            <span class="mx-1.5 opacity-40">·</span>
                            Plano atual: <b>{{ currentPlanKey || '—' }}</b>
                        </div>
                    </div>
                </div>

                <!-- Busca desktop -->
                <div class="hidden md:flex flex-1 min-w-[180px] max-w-xs">
                    <IconField class="w-full">
                        <InputIcon class="pi pi-search" />
                        <InputText v-model="q" placeholder="Buscar plano..." class="w-full" autocomplete="off" :disabled="loading || upgrading" />
                    </IconField>
                </div>

                <!-- Ações -->
                <div class="flex items-center gap-1 shrink-0 ml-auto">
                    <Button icon="pi pi-refresh" severity="secondary" outlined class="h-9 w-9 rounded-full shrink-0" :loading="loading" :disabled="upgrading" title="Recarregar" @click="fetchAll" />
                    <Button label="Assinatura" icon="pi pi-credit-card" severity="secondary" outlined class="rounded-full hidden sm:inline-flex" :disabled="upgrading" @click="goBilling" />
                    <Button label="Voltar" icon="pi pi-arrow-left" severity="secondary" outlined class="rounded-full" :disabled="upgrading" @click="goBack" />
                </div>
            </div>

            <!-- Linha 2: busca mobile + chips de intervalo -->
            <div class="flex flex-wrap items-center gap-2">
                <!-- Busca mobile -->
                <div class="flex md:hidden flex-1 min-w-[160px]">
                    <IconField class="w-full">
                        <InputIcon class="pi pi-search" />
                        <InputText v-model="q" placeholder="Buscar plano..." class="w-full" autocomplete="off" :disabled="loading || upgrading" />
                    </IconField>
                </div>

                <!-- Intervalo chips -->
                <div class="flex items-center gap-1.5 shrink-0">
                    <span class="text-[1rem] text-[var(--text-color-secondary)] opacity-70 hidden sm:inline">Preço:</span>
                    <button
                        v-for="opt in intervalOptions"
                        :key="opt.value"
                        class="inline-flex items-center gap-1.5 px-3.5 py-1 rounded-full text-[1rem] font-semibold border-[1.5px] cursor-pointer transition-all duration-150 select-none"
                        :class="
                            billingInterval === opt.value
                                ? 'bg-[var(--primary-color,#6366f1)] border-[var(--primary-color,#6366f1)] text-white'
                                : 'border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-ground,#f8fafc)] text-[var(--text-color-secondary)] hover:border-indigo-300 hover:text-[var(--text-color)]'
                        "
                        :disabled="loading || upgrading"
                        @click="billingInterval = opt.value"
                    >
                        {{ opt.label }}
                    </button>
                </div>
            </div>
        </div>
    </section>

    <!-- ══════════════════════════════════════════════════════
       BANNER: recurso bloqueado
  ═══════════════════════════════════════════════════════ -->
    <Transition name="up-banner">
        <div v-if="requestedFeatureLabel && !loading" class="mx-3 md:mx-4 mb-3 flex items-center gap-3 px-4 py-3 rounded-md border border-amber-300/60 bg-amber-50">
            <div class="grid place-items-center w-8 h-8 rounded-md bg-amber-400/20 text-amber-600 shrink-0">
                <i class="pi pi-lock text-[0.95rem]" />
            </div>
            <div class="flex-1 min-w-0">
                <span class="font-semibold text-[1rem] text-amber-800">Recurso bloqueado: {{ requestedFeatureLabel }}</span>
                <span class="hidden sm:inline text-[1rem] text-amber-700 opacity-80 ml-1"
                    >Esse recurso depende da feature <b>{{ requestedFeature }}</b
                    >. Escolha um plano que a inclua.</span
                >
            </div>
            <Button
                label="Ver planos"
                icon="pi pi-arrow-down"
                severity="secondary"
                outlined
                size="small"
                class="rounded-full shrink-0"
                @click="() => document.getElementById('plans-grid')?.scrollIntoView({ behavior: 'smooth', block: 'start' })"
            />
        </div>
    </Transition>

    <!-- ══════════════════════════════════════════════════════
       QUICK-STATS
  ═══════════════════════════════════════════════════════ -->
    <div class="flex flex-wrap gap-2 px-3 md:px-4 mb-3">
        <div class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border flex-1 min-w-[80px] border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)]">
            <div class="text-[1.35rem] font-bold leading-none text-[var(--text-color)]">{{ sortedPlans.length }}</div>
            <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75">Planos disponíveis</div>
        </div>
        <div class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border flex-1 min-w-[80px] border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)]">
            <div class="text-[1.1rem] font-bold leading-none text-[var(--text-color)] truncate">{{ currentPlanKey || '—' }}</div>
            <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75">Plano atual</div>
        </div>
        <div class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border flex-1 min-w-[80px] border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)]">
            <div class="text-[1.1rem] font-bold leading-none text-[var(--text-color)]">{{ isTherapist ? 'Terapeuta' : 'Clínica' }}</div>
            <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75">Contexto</div>
        </div>
        <div class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border flex-1 min-w-[80px] border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)]">
            <div class="text-[1.35rem] font-bold leading-none text-[var(--text-color)]">{{ features.length }}</div>
            <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75">Features no sistema</div>
        </div>
    </div>

    <!-- ══════════════════════════════════════════════════════
       PLANOS
  ═══════════════════════════════════════════════════════ -->
    <div class="px-3 md:px-4 pb-8">
        <!-- Loading skeleton -->
        <div v-if="loading" class="grid grid-cols-1 lg:grid-cols-2 gap-3">
            <div v-for="n in 2" :key="n" class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] p-4">
                <div class="flex flex-col gap-3">
                    <div class="h-5 w-2/5 rounded-md bg-[var(--surface-border,#e2e8f0)] animate-pulse" />
                    <div class="h-3 w-3/5 rounded-md bg-[var(--surface-border,#e2e8f0)] animate-pulse" />
                    <div class="flex flex-col gap-2 mt-2">
                        <div v-for="i in 4" :key="i" class="h-3 w-4/5 rounded-md bg-[var(--surface-border,#e2e8f0)] animate-pulse" />
                    </div>
                </div>
            </div>
        </div>

        <!-- Empty state -->
        <div v-else-if="!sortedPlans.length" class="flex flex-col items-center justify-center gap-4 rounded-md border-2 border-dashed border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-ground,#f8fafc)] py-16 px-6 text-center">
            <div class="relative">
                <div class="grid place-items-center w-16 h-16 rounded-2xl bg-[var(--surface-card,#fff)] border border-[var(--surface-border,#e2e8f0)] shadow-sm text-[var(--text-color-secondary)]">
                    <i class="pi pi-box text-3xl opacity-30" />
                </div>
                <div class="absolute -top-2 -right-2 w-7 h-7 rounded-full bg-[var(--surface-card,#fff)] border border-[var(--surface-border,#e2e8f0)] shadow-sm grid place-items-center">
                    <i class="pi pi-times text-[0.65rem] text-[var(--text-color-secondary)] opacity-50" />
                </div>
            </div>
            <div>
                <div class="font-bold text-[1rem] text-[var(--text-color)] mb-1">Nenhum plano encontrado</div>
                <div class="text-[1rem] text-[var(--text-color-secondary)] max-w-xs leading-relaxed">Tente limpar o filtro de busca.</div>
            </div>
            <Button label="Limpar busca" icon="pi pi-filter-slash" severity="secondary" outlined class="rounded-full mt-1" @click="q = ''" />
        </div>

        <!-- Grid de planos -->
        <div v-else id="plans-grid" class="grid grid-cols-1 lg:grid-cols-2 gap-3">
            <div
                v-for="p in sortedPlans"
                :key="p.id"
                class="relative overflow-hidden rounded-md border bg-[var(--surface-card,#fff)] flex flex-col"
                :class="String(p.key).toLowerCase() === 'pro' ? 'border-[var(--primary-color,#6366f1)]/30' : 'border-[var(--surface-border,#e2e8f0)]'"
            >
                <!-- Blobs decorativos (plano PRO) -->
                <div v-if="String(p.key).toLowerCase() === 'pro'" class="pointer-events-none absolute inset-0 overflow-hidden" aria-hidden="true">
                    <div class="absolute -top-20 -right-16 w-72 h-72 rounded-full bg-[var(--primary-color,#6366f1)]/10 blur-[60px]" />
                    <div class="absolute -bottom-20 left-8 w-72 h-72 rounded-full bg-emerald-400/[0.08] blur-[60px]" />
                </div>

                <!-- Cabeçalho do card -->
                <div class="relative z-1 flex items-center justify-between px-4 py-3 border-b border-[var(--surface-border,#e2e8f0)]">
                    <div class="flex items-center gap-2">
                        <i class="text-[0.9rem]" :class="String(p.key).toLowerCase() === 'pro' ? 'pi pi-sparkles text-[var(--primary-color,#6366f1)]' : 'pi pi-leaf text-emerald-500 opacity-70'" />
                        <span class="font-bold text-[0.95rem] text-[var(--text-color)]">Plano {{ String(p.key || '').toUpperCase() }}</span>
                    </div>
                    <div class="flex items-center gap-2">
                        <Tag v-if="currentPlanId === p.id" value="Atual" severity="secondary" />
                        <Tag v-else-if="String(p.key).toLowerCase() === 'pro'" value="Recomendado" severity="success" />
                    </div>
                </div>

                <!-- Corpo do card -->
                <div class="relative z-1 p-4 flex flex-col gap-4 flex-1">
                    <!-- Descrição + preço -->
                    <div>
                        <div class="text-[1rem] text-[var(--text-color-secondary)] mb-2">
                            <template v-if="String(p.key).toLowerCase() === 'free'">O essencial para começar, sem travar seu fluxo.</template>
                            <template v-else-if="String(p.key).toLowerCase() === 'pro'">Para automatizar, reduzir ruído e ganhar previsibilidade.</template>
                            <template v-else>{{ p.description || p.key }}</template>
                        </div>
                        <div class="text-[1.6rem] font-bold leading-none text-[var(--text-color)]">{{ priceLabelForPlan(p.id) }}</div>
                    </div>

                    <!-- Benefits list -->
                    <div class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-ground,#f8fafc)] p-3">
                        <ul class="list-none p-0 m-0 flex flex-col gap-2.5">
                            <li v-for="(b, i) in planBenefits(p.id)" :key="i" class="flex items-start gap-2">
                                <i class="text-[1rem] mt-0.5 shrink-0" :class="b.ok ? 'pi pi-check-circle text-emerald-500' : 'pi pi-times-circle text-[var(--text-color-secondary)] opacity-40'" />
                                <span class="text-[1rem]" :class="b.ok ? 'text-[var(--text-color)]' : 'text-[var(--text-color-secondary)]'">{{ b.text }}</span>
                            </li>
                        </ul>

                        <div class="h-px bg-[var(--surface-border,#e2e8f0)] my-3" />

                        <!-- Ações -->
                        <div class="flex flex-col gap-2">
                            <Button
                                v-if="currentPlanId !== p.id"
                                :label="`Mudar para ${String(p.key || '').toUpperCase()}`"
                                icon="pi pi-arrow-up"
                                class="w-full rounded-full"
                                :loading="upgrading"
                                :disabled="upgrading || loading"
                                @click="changePlan(p.id)"
                            />
                            <Button v-else label="Você já está neste plano" icon="pi pi-check" severity="secondary" outlined class="w-full rounded-full" disabled />
                            <Button v-if="String(p.key).toLowerCase() !== 'free'" label="Falar com suporte" icon="pi pi-comments" severity="secondary" outlined class="w-full rounded-full" :disabled="upgrading" @click="contactSupport" />
                            <div class="text-center text-[1rem] text-[var(--text-color-secondary)] opacity-60">Cancele quando quiser. Sem burocracia.</div>
                            <div v-if="!subscription?.id" class="text-center text-[1rem] text-amber-500">⚠ Sem assinatura ativa — clique em <b>Assinatura</b> para ativar/criar.</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="mt-4 text-[1rem] text-[var(--text-color-secondary)] opacity-60">Alguns recursos PRO podem depender de configuração inicial (ex.: SMS exige provedor).</div>
    </div>
</template>

<style scoped>
.up-banner-enter-active,
.up-banner-leave-active {
    transition: all 0.25s ease;
    overflow: hidden;
}
.up-banner-enter-from,
.up-banner-leave-to {
    opacity: 0;
    max-height: 0;
    margin-bottom: 0;
}
.up-banner-enter-to,
.up-banner-leave-from {
    opacity: 1;
    max-height: 80px;
}
</style>
