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

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

const loading = ref(false);
const hasLoaded = ref(false);
const subscription = ref(null);
const plan = ref(null);
const price = ref(null);
const features = ref([]);
const events = ref([]);
const plans = ref([]);
const profiles = ref([]);

// ── Hero sticky ────────────────────────────────────────────
const headerEl = ref(null);
const headerSentinelRef = ref(null);
const headerStuck = ref(false);
let _observer = null;

// ── Formatters ─────────────────────────────────────────────
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 fmtDate(iso) {
    if (!iso) return '—';
    const d = new Date(iso);
    if (Number.isNaN(d.getTime())) return String(iso);
    return d.toLocaleString('pt-BR');
}

function prettyMeta(meta) {
    if (!meta) return null;
    try {
        if (typeof meta === 'string') return meta;
        return JSON.stringify(meta, null, 2);
    } catch (_) {
        return String(meta);
    }
}

function statusSeverity(st) {
    const s = String(st || '').toLowerCase();
    if (s === 'active') return 'success';
    if (s === 'trialing') return 'info';
    if (s === 'past_due') return 'warning';
    if (s === 'canceled' || s === 'cancelled') return 'danger';
    return 'secondary';
}

function statusLabel(st) {
    const s = String(st || '').toLowerCase();
    if (s === 'active') return 'Ativo';
    if (s === 'trialing') return 'Trial';
    if (s === 'past_due') return 'Atrasado';
    if (s === 'canceled' || s === 'cancelled') return 'Cancelado';
    return st || '—';
}

function eventSeverity(t) {
    const k = String(t || '').toLowerCase();
    if (k === 'plan_changed') return 'info';
    if (k === 'canceled') return 'danger';
    if (k === 'reactivated') return 'success';
    return 'secondary';
}

function eventLabel(t) {
    const k = String(t || '').toLowerCase();
    if (k === 'plan_changed') return 'Plano alterado';
    if (k === 'canceled') return 'Cancelada';
    if (k === 'reactivated') return 'Reativada';
    return t || '—';
}

// ── Computed ────────────────────────────────────────────────
const planName = computed(() => plan.value?.name || subscription.value?.plan_key || '—');

const intervalLabel = computed(() => {
    const i = subscription.value?.interval;
    if (i === 'month') return 'mês';
    if (i === 'year') return 'ano';
    return i || '—';
});

const priceLabel = computed(() => {
    if (!price.value) return null;
    return `${money(price.value.currency, price.value.amount_cents)} / ${intervalLabel.value}`;
});

const periodLabel = computed(() => {
    const s = subscription.value;
    if (!s?.current_period_start || !s?.current_period_end) return '—';
    return `${fmtDate(s.current_period_start)} → ${fmtDate(s.current_period_end)}`;
});

// ── Features agrupadas ──────────────────────────────────────
function moduleFromKey(key) {
    const k = String(key || '').trim();
    if (!k) return 'Outros';
    if (k.includes('.')) return k.split('.')[0] || 'Outros';
    if (k.includes('_')) return k.split('_')[0] || 'Outros';
    return 'Outros';
}

function moduleLabel(m) {
    const s = String(m || '').trim();
    if (!s) return 'Outros';
    return s.charAt(0).toUpperCase() + s.slice(1);
}

const groupedFeatures = computed(() => {
    const list = features.value || [];
    const map = new Map();
    for (const f of list) {
        const mod = moduleFromKey(f.key);
        if (!map.has(mod)) map.set(mod, []);
        map.get(mod).push(f);
    }
    const modules = Array.from(map.keys()).sort((a, b) => {
        if (a === 'Outros') return 1;
        if (b === 'Outros') return -1;
        return a.localeCompare(b);
    });
    return modules.map((mod) => {
        const items = map.get(mod) || [];
        items.sort((a, b) => String(a.key || '').localeCompare(String(b.key || '')));
        return { module: mod, items };
    });
});

// ── Histórico ───────────────────────────────────────────────
const planById = computed(() => {
    const m = new Map();
    for (const p of plans.value || []) m.set(String(p.id), p);
    return m;
});

function planKeyOrName(planId) {
    if (!planId) return '—';
    const p = planById.value.get(String(planId));
    return p?.key || p?.name || String(planId);
}

const profileById = computed(() => {
    const m = new Map();
    for (const p of profiles.value || []) m.set(String(p.id), p);
    return m;
});

function displayUser(userId) {
    if (!userId) return '—';
    const p = profileById.value.get(String(userId));
    if (!p) return String(userId);
    const name = p.nome || p.name || p.full_name || p.display_name || null;
    const email = p.email || p.email_principal || null;
    if (name && email) return `${name} <${email}>`;
    return name || email || String(userId);
}

// ── Actions ─────────────────────────────────────────────────
function goUpgrade() {
    router.push('/therapist/upgrade?redirectTo=/therapist/meu-plano');
}

// ── Fetch ───────────────────────────────────────────────────
async function fetchMeuPlanoTherapist() {
    loading.value = true;
    try {
        const { data: authData, error: authError } = await supabase.auth.getUser();
        if (authError) throw authError;
        const uid = authData?.user?.id;
        if (!uid) throw new Error('Sessão não encontrada.');

        const sRes = await supabase.from('subscriptions').select('*').eq('user_id', uid).order('created_at', { ascending: false }).limit(10);

        if (sRes.error) throw sRes.error;

        const subList = sRes.data || [];
        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;
        };
        subscription.value = subList.length
            ? subList.slice().sort((a, b) => {
                  const pa = priority(a?.status);
                  const pb = priority(b?.status);
                  if (pa !== pb) return pa - pb;
                  return new Date(b?.created_at || 0) - new Date(a?.created_at || 0);
              })[0]
            : null;

        if (!subscription.value) {
            plan.value = null;
            price.value = null;
            features.value = [];
            events.value = [];
            plans.value = [];
            profiles.value = [];
            return;
        }

        const pRes = await supabase.from('plans').select('id, key, name, description').eq('id', subscription.value.plan_id).maybeSingle();
        if (pRes.error) throw pRes.error;
        plan.value = pRes.data || null;

        const nowIso = new Date().toISOString();
        const ppRes = await supabase
            .from('plan_prices')
            .select('currency, interval, amount_cents, is_active, active_from, active_to')
            .eq('plan_id', subscription.value.plan_id)
            .eq('interval', subscription.value.interval)
            .eq('is_active', true)
            .lte('active_from', nowIso)
            .or(`active_to.is.null,active_to.gte.${nowIso}`)
            .order('active_from', { ascending: false })
            .limit(1)
            .maybeSingle();
        if (ppRes.error) throw ppRes.error;
        price.value = ppRes.data || null;

        const pfRes = await supabase.from('plan_features').select('feature_id').eq('plan_id', subscription.value.plan_id);
        if (pfRes.error) throw pfRes.error;
        const featureIds = (pfRes.data || []).map((r) => r.feature_id).filter(Boolean);

        if (featureIds.length) {
            const fRes = await supabase.from('features').select('id, key, description, descricao').in('id', featureIds).order('key', { ascending: true });
            if (fRes.error) throw fRes.error;
            features.value = (fRes.data || []).map((f) => ({ key: f.key, description: (f.descricao || f.description || '').trim() }));
        } else {
            features.value = [];
        }

        const eRes = await supabase.from('subscription_events').select('*').eq('subscription_id', subscription.value.id).order('created_at', { ascending: false }).limit(50);
        if (eRes.error) throw eRes.error;
        events.value = eRes.data || [];

        const planIds = new Set();
        if (subscription.value?.plan_id) planIds.add(String(subscription.value.plan_id));
        for (const ev of events.value) {
            if (ev?.old_plan_id) planIds.add(String(ev.old_plan_id));
            if (ev?.new_plan_id) planIds.add(String(ev.new_plan_id));
        }
        if (planIds.size) {
            const { data: pAll, error: epAll } = await supabase.from('plans').select('id,key,name').in('id', Array.from(planIds));
            plans.value = epAll ? [] : pAll || [];
        } else {
            plans.value = [];
        }

        const userIds = new Set();
        for (const ev of events.value) {
            const by = String(ev.created_by || '').trim();
            if (by) userIds.add(by);
        }
        if (userIds.size) {
            const { data: pr, error: epr } = await supabase.from('profiles').select('*').in('id', Array.from(userIds));
            profiles.value = epr ? [] : pr || [];
        } else {
            profiles.value = [];
        }
    } catch (e) {
        console.error(e);
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || String(e), life: 5000 });
    } finally {
        loading.value = false;
        hasLoaded.value = true;
    }
}

onMounted(() => {
    const rootMargin = `${document.querySelector('.l2-main') ? '0px' : '-56px'} 0px 0px 0px`;
    _observer = new IntersectionObserver(
        ([entry]) => {
            headerStuck.value = !entry.isIntersecting;
        },
        { threshold: 0, rootMargin }
    );
    if (headerSentinelRef.value) _observer.observe(headerSentinelRef.value);
    fetchMeuPlanoTherapist();
});

onBeforeUnmount(() => {
    _observer?.disconnect();
});
</script>

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

    <!-- ══════════════════════════════════════════════════════
       HERO sticky
  ═══════════════════════════════════════════════════════ -->
    <section
        ref="headerEl"
        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 transition-[border-radius] duration-200"
        :class="{ 'rounded-tl-none rounded-tr-none': headerStuck }"
        :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>

        <div class="relative z-1 flex items-center gap-3">
            <!-- 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-credit-card text-base" />
                </div>
                <div class="min-w-0 hidden sm:block">
                    <div class="flex items-center gap-2 flex-wrap">
                        <div class="text-[1rem] font-bold tracking-tight text-[var(--text-color)]">Meu Plano</div>
                        <Tag v-if="subscription" :value="statusLabel(subscription.status)" :severity="statusSeverity(subscription.status)" />
                    </div>
                    <div class="text-[1rem] text-[var(--text-color-secondary)]">Plano pessoal do terapeuta — gerencie sua assinatura</div>
                </div>
            </div>

            <!-- Ações desktop (≥ xl) -->
            <div class="hidden xl:flex items-center gap-1 shrink-0 ml-auto">
                <Button icon="pi pi-refresh" severity="secondary" outlined class="h-9 w-9 rounded-full" :loading="loading" title="Atualizar" @click="fetchMeuPlanoTherapist" />
                <Button label="Alterar plano" icon="pi pi-arrow-up-right" class="rounded-full" @click="goUpgrade" />
            </div>

            <!-- Ações mobile (< xl) -->
            <div class="flex xl:hidden items-center gap-1 shrink-0 ml-auto">
                <Button icon="pi pi-refresh" severity="secondary" outlined class="h-9 w-9 rounded-full" :loading="loading" @click="fetchMeuPlanoTherapist" />
                <Button label="Alterar plano" icon="pi pi-arrow-up-right" size="small" class="rounded-full" @click="goUpgrade" />
            </div>
        </div>
    </section>

    <!-- ══════════════════════════════════════════════════════
       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.1rem] font-bold leading-none text-[var(--text-color)] truncate">{{ planName }}</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] transition-colors duration-150"
            :class="subscription?.status === 'active' ? 'border-green-500/25 bg-green-500/5' : 'border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)]'"
        >
            <div class="text-[1.1rem] font-bold leading-none truncate" :class="subscription?.status === 'active' ? 'text-green-500' : 'text-[var(--text-color)]'">{{ subscription ? statusLabel(subscription.status) : '—' }}</div>
            <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75">Status</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">Recursos</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)]">{{ events.length }}</div>
            <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75">Eventos</div>
        </div>
    </div>

    <!-- ══════════════════════════════════════════════════════
       CONTEÚDO
  ═══════════════════════════════════════════════════════ -->
    <div class="px-3 md:px-4 pb-8 flex flex-col gap-3">
        <!-- Loading skeleton -->
        <div v-if="loading" class="flex flex-col gap-3">
            <div v-for="n in 3" :key="n" class="flex items-center gap-4 p-4 rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)]">
                <div class="w-10 h-10 rounded-full shrink-0 bg-[var(--surface-border,#e2e8f0)] animate-pulse" />
                <div class="flex flex-col gap-2 flex-1">
                    <div class="h-3.5 w-3/5 rounded-md bg-[var(--surface-border,#e2e8f0)] animate-pulse" />
                    <div class="h-2.5 w-2/5 rounded-md bg-[var(--surface-border,#e2e8f0)] animate-pulse" />
                </div>
            </div>
        </div>

        <!-- Sem assinatura -->
        <div v-else-if="!subscription" 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-credit-card 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">Nenhuma assinatura encontrada</div>
                <div class="text-[1rem] text-[var(--text-color-secondary)] max-w-xs leading-relaxed">Escolha um plano para começar a usar todos os recursos.</div>
            </div>
            <Button label="Ver planos" icon="pi pi-arrow-up-right" class="rounded-full mt-1" @click="goUpgrade" />
        </div>

        <template v-else>
            <!-- ── Assinatura atual ──────────────────────────── -->
            <div class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] overflow-hidden">
                <div class="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="pi pi-credit-card text-[var(--text-color-secondary)] opacity-60" />
                        <span class="font-semibold text-[1rem]">Assinatura atual</span>
                    </div>
                    <div class="flex items-center gap-2">
                        <Tag :value="statusLabel(subscription.status)" :severity="statusSeverity(subscription.status)" />
                        <Tag v-if="subscription.cancel_at_period_end" severity="warning" value="Cancelamento agendado" />
                        <Tag v-else severity="success" value="Renovação automática" />
                    </div>
                </div>
                <div class="px-4 py-3 flex flex-wrap gap-x-8 gap-y-3">
                    <div class="flex flex-col gap-0.5">
                        <span class="text-[0.68rem] font-bold uppercase tracking-[0.06em] text-[var(--text-color-secondary)] opacity-60">Plano</span>
                        <span class="text-[0.9rem] font-semibold text-[var(--text-color)]">{{ planName }}</span>
                    </div>
                    <div class="flex flex-col gap-0.5">
                        <span class="text-[0.68rem] font-bold uppercase tracking-[0.06em] text-[var(--text-color-secondary)] opacity-60">Valor</span>
                        <span class="text-[1rem] text-[var(--text-color)]">{{ priceLabel || 'Preço não encontrado para este intervalo.' }}</span>
                    </div>
                    <div class="flex flex-col gap-0.5">
                        <span class="text-[0.68rem] font-bold uppercase tracking-[0.06em] text-[var(--text-color-secondary)] opacity-60">Período</span>
                        <span class="text-[1rem] text-[var(--text-color)]">{{ periodLabel }}</span>
                    </div>
                    <div v-if="plan?.description" class="flex flex-col gap-0.5 w-full">
                        <span class="text-[0.68rem] font-bold uppercase tracking-[0.06em] text-[var(--text-color-secondary)] opacity-60">Descrição</span>
                        <span class="text-[1rem] text-[var(--text-color-secondary)]">{{ plan.description }}</span>
                    </div>
                    <div class="flex flex-col gap-0.5">
                        <span class="text-[0.68rem] font-bold uppercase tracking-[0.06em] text-[var(--text-color-secondary)] opacity-60">ID da assinatura</span>
                        <code class="text-[0.75rem] text-[var(--text-color-secondary)] break-all font-mono select-all">{{ subscription.id }}</code>
                    </div>
                </div>
            </div>

            <div class="grid grid-cols-1 lg:grid-cols-2 gap-3">
                <!-- ── Seu plano inclui ───────────────────────── -->
                <div class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] overflow-hidden">
                    <div class="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="pi pi-check-circle text-[var(--text-color-secondary)] opacity-60" />
                            <span class="font-semibold text-[1rem]">Seu plano inclui</span>
                        </div>
                        <span v-if="features.length" class="inline-flex items-center justify-center min-w-[22px] h-[22px] px-1.5 rounded-full bg-[var(--primary-color,#6366f1)] text-white text-[1rem] font-bold">{{ features.length }}</span>
                    </div>

                    <div class="p-4">
                        <div v-if="!features.length" class="text-[1rem] text-[var(--text-color-secondary)]">Nenhuma feature vinculada a este plano.</div>

                        <div v-else class="flex flex-col gap-5">
                            <div v-for="g in groupedFeatures" :key="g.module">
                                <div class="flex items-center gap-2 mb-2">
                                    <span class="text-[0.68rem] font-bold uppercase tracking-[0.07em] text-[var(--text-color-secondary)] opacity-50">{{ moduleLabel(g.module) }}</span>
                                    <div class="flex-1 h-px bg-[var(--surface-border,#e2e8f0)]" />
                                    <span class="text-[1rem] text-[var(--text-color-secondary)]">{{ g.items.length }}</span>
                                </div>
                                <div class="grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-1">
                                    <div v-for="f in g.items" :key="f.key" class="flex items-start gap-2 py-1 px-2 rounded-md hover:bg-[var(--surface-ground,#f8fafc)] transition-colors" :title="f.description || f.key">
                                        <i class="pi pi-check-circle text-emerald-500 text-[1rem] mt-0.5 shrink-0" />
                                        <div class="min-w-0">
                                            <div class="text-[1rem] font-medium truncate text-[var(--text-color)]">{{ f.key }}</div>
                                            <div v-if="f.description" class="text-[1rem] text-[var(--text-color-secondary)] leading-snug truncate">{{ f.description }}</div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- ── Histórico ──────────────────────────────── -->
                <div class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] overflow-hidden">
                    <div class="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="pi pi-history text-[var(--text-color-secondary)] opacity-60" />
                            <span class="font-semibold text-[1rem]">Histórico</span>
                        </div>
                        <span v-if="events.length" class="inline-flex items-center justify-center min-w-[22px] h-[22px] px-1.5 rounded-full bg-[var(--primary-color,#6366f1)] text-white text-[1rem] font-bold">{{ events.length }}</span>
                    </div>

                    <div class="p-4">
                        <div v-if="!events.length" class="py-8 text-center">
                            <i class="pi pi-history text-2xl text-[var(--text-color-secondary)] opacity-20 mb-2 block" />
                            <div class="text-[1rem] text-[var(--text-color-secondary)]">Sem eventos registrados.</div>
                        </div>

                        <div v-else class="flex flex-col gap-2">
                            <div v-for="ev in events" :key="ev.id" class="rounded-md border border-[var(--surface-border,#e2e8f0)] p-3 hover:bg-[var(--surface-ground,#f8fafc)] transition-colors duration-100">
                                <div class="flex items-start justify-between gap-3 flex-wrap">
                                    <div class="min-w-0 flex-1">
                                        <div class="flex items-center gap-2 flex-wrap">
                                            <Tag :value="eventLabel(ev.event_type)" :severity="eventSeverity(ev.event_type)" />
                                            <span class="text-[1rem] text-[var(--text-color-secondary)]">
                                                por <b>{{ displayUser(ev.created_by) }}</b>
                                            </span>
                                        </div>
                                        <div v-if="ev.old_plan_id || ev.new_plan_id" class="mt-1.5 text-[1rem] text-[var(--text-color-secondary)] flex items-center gap-1.5 flex-wrap">
                                            <span class="font-medium text-[var(--text-color)]">{{ planKeyOrName(ev.old_plan_id) }}</span>
                                            <i class="pi pi-arrow-right text-[1rem] opacity-50" />
                                            <span class="font-medium text-[var(--text-color)]">{{ planKeyOrName(ev.new_plan_id) }}</span>
                                        </div>
                                        <div v-if="ev.reason" class="mt-1 text-[1rem] text-[var(--text-color-secondary)] opacity-70">{{ ev.reason }}</div>
                                        <div v-if="ev.metadata" class="mt-1.5">
                                            <pre class="m-0 text-[1rem] text-[var(--text-color-secondary)] whitespace-pre-wrap break-words opacity-60">{{ prettyMeta(ev.metadata) }}</pre>
                                        </div>
                                    </div>
                                    <div class="text-[1rem] text-[var(--text-color-secondary)] shrink-0">{{ fmtDate(ev.created_at) }}</div>
                                </div>
                            </div>
                            <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-60 mt-1">Mostrando até 50 eventos (mais recentes).</div>
                        </div>
                    </div>
                </div>
            </div>

            <LoadedPhraseBlock v-if="hasLoaded" />
        </template>
    </div>
</template>
