<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/views/pages/therapist/RelatoriosPage.vue
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
-->
<script setup>
import { ref, computed, watch, onMounted } from 'vue';
import { useToast } from 'primevue/usetoast';
import { supabase } from '@/lib/supabase/client';
import { tenantDb } from '@/lib/supabase/tenantClient';
import { useTenantStore } from '@/stores/tenantStore';
import { useLayout } from '@/layout/composables/layout';
import { exportSessionsToPDF, exportSessionsToXLSX, exportSessionsToCSV } from '@/services/reportExport.service';

const toast = useToast();

const { layoutConfig, isDarkTheme } = useLayout();
const tenantStore = useTenantStore();

// ── Período ───────────────────────────────────────────────
const PERIODS = [
    { label: 'Esta semana', value: 'week' },
    { label: 'Este mês', value: 'month' },
    { label: 'Últimos 3 meses', value: '3months' },
    { label: 'Últimos 6 meses', value: '6months' }
];

const selectedPeriod = ref('month');

function periodRange(period) {
    const now = new Date();
    let start, end;
    if (period === 'week') {
        start = new Date(now);
        start.setDate(now.getDate() - now.getDay());
        start.setHours(0, 0, 0, 0);
        end = new Date(now);
        end.setHours(23, 59, 59, 999);
    } else if (period === 'month') {
        start = new Date(now.getFullYear(), now.getMonth(), 1, 0, 0, 0, 0);
        end = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
    } else if (period === '3months') {
        start = new Date(now.getFullYear(), now.getMonth() - 2, 1, 0, 0, 0, 0);
        end = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
    } else if (period === '6months') {
        start = new Date(now.getFullYear(), now.getMonth() - 5, 1, 0, 0, 0, 0);
        end = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
    }
    return { start, end };
}

// ── Dados ─────────────────────────────────────────────────
const loading = ref(false);
const hasLoaded = ref(false);
const sessions = ref([]);
const loadError = ref('');

async function loadSessions() {
    const uid = tenantStore.user?.id || null;
    const tenantId = tenantStore.activeTenantId || null;
    if (!uid || !tenantId) return;

    const { start, end } = periodRange(selectedPeriod.value);
    loading.value = true;
    loadError.value = '';
    sessions.value = [];

    try {
        const { data, error } = await tenantDb().from('agenda_eventos')
            .select('id, inicio_em, fim_em, status, modalidade, tipo, titulo, titulo_custom, patient_id, patients(nome_completo)')
            
            .eq('owner_id', uid)
            .gte('inicio_em', start.toISOString())
            .lte('inicio_em', end.toISOString())
            .order('inicio_em', { ascending: false })
            .limit(500);
        if (error) throw error;
        sessions.value = data || [];
    } catch (e) {
        loadError.value = e?.message || 'Falha ao carregar relatório.';
    } finally {
        loading.value = false;
        hasLoaded.value = true;
    }
}

// ── Métricas ──────────────────────────────────────────────
const total = computed(() => sessions.value.length);
const realizadas = computed(() => sessions.value.filter((s) => s.status === 'realizado').length);
const faltas = computed(() => sessions.value.filter((s) => s.status === 'faltou').length);
const canceladas = computed(() => sessions.value.filter((s) => s.status === 'cancelado').length);
const agendadas = computed(() => sessions.value.filter((s) => !s.status || s.status === 'agendado').length);
const remarcadas = computed(() => sessions.value.filter((s) => s.status === 'remarcado').length);
const taxaRealizacao = computed(() => {
    const denom = realizadas.value + faltas.value + canceladas.value;
    if (!denom) return null;
    return Math.round((realizadas.value / denom) * 100);
});

// ── Filtro de status na tabela ────────────────────────────
const filtroTabela = ref(null); // null = todos

const sessionsFiltradas = computed(() => {
    if (!filtroTabela.value) return sessions.value;
    if (filtroTabela.value === 'agendado') return sessions.value.filter((s) => !s.status || s.status === 'agendado');
    return sessions.value.filter((s) => s.status === filtroTabela.value);
});

function toggleFiltroTabela(val) {
    filtroTabela.value = filtroTabela.value === val ? null : val;
}

// ── Quick-stats config ────────────────────────────────────
const quickStats = computed(() => [
    { label: 'Total', value: total.value, filter: null, cls: '', valCls: 'text-[var(--text-color)]' },
    { label: 'Realizadas', value: realizadas.value, filter: 'realizado', cls: 'qs-ok', valCls: 'text-green-500' },
    { label: 'Faltas', value: faltas.value, filter: 'faltou', cls: 'qs-danger', valCls: 'text-red-500' },
    { label: 'Canceladas', value: canceladas.value, filter: 'cancelado', cls: 'qs-warn', valCls: 'text-orange-500' },
    { label: 'Agendadas', value: agendadas.value, filter: 'agendado', cls: 'qs-info', valCls: 'text-sky-500' },
    {
        label: 'Taxa realização',
        value: taxaRealizacao.value != null ? `${taxaRealizacao.value}%` : '—',
        filter: null,
        cls: taxaRealizacao.value != null && taxaRealizacao.value >= 85 ? 'qs-ok' : '',
        valCls: taxaRealizacao.value != null && taxaRealizacao.value >= 85 ? 'text-green-500' : 'text-[var(--text-color)]'
    }
]);

// ── Gráfico ───────────────────────────────────────────────
function isoWeek(d) {
    const dt = new Date(d);
    const day = dt.getDay() || 7;
    dt.setDate(dt.getDate() + 4 - day);
    const yearStart = new Date(dt.getFullYear(), 0, 1);
    const wk = Math.ceil(((dt - yearStart) / 86400000 + 1) / 7);
    return `${dt.getFullYear()}-S${String(wk).padStart(2, '0')}`;
}
function isoMonth(d) {
    const dt = new Date(d);
    return `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, '0')}`;
}
function monthLabel(key) {
    const [y, m] = key.split('-');
    const names = ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'];
    return `${names[Number(m) - 1]}/${y}`;
}

const chartData = computed(() => {
    const groupBy = selectedPeriod.value === 'week' ? isoWeek : isoMonth;
    const labelFn = selectedPeriod.value === 'week' ? (k) => k : monthLabel;
    const buckets = {};
    for (const s of sessions.value) {
        const key = groupBy(s.inicio_em);
        if (!buckets[key]) buckets[key] = { realizado: 0, faltou: 0, cancelado: 0, outros: 0 };
        const st = s.status || 'agendado';
        if (st === 'realizado') buckets[key].realizado++;
        else if (st === 'faltou') buckets[key].faltou++;
        else if (st === 'cancelado') buckets[key].cancelado++;
        else buckets[key].outros++;
    }
    const keys = Object.keys(buckets).sort();
    return {
        labels: keys.map(labelFn),
        datasets: [
            { label: 'Realizadas', backgroundColor: '#22c55e', data: keys.map((k) => buckets[k].realizado), barThickness: 20 },
            { label: 'Faltas', backgroundColor: '#ef4444', data: keys.map((k) => buckets[k].faltou), barThickness: 20 },
            { label: 'Canceladas', backgroundColor: '#f97316', data: keys.map((k) => buckets[k].cancelado), barThickness: 20 },
            { label: 'Outros', backgroundColor: '#93c5fd', data: keys.map((k) => buckets[k].outros), barThickness: 20 }
        ]
    };
});

const chartOptions = computed(() => {
    const ds = getComputedStyle(document.documentElement);
    const borderColor = ds.getPropertyValue('--surface-border') || '#e2e8f0';
    const textMutedColor = ds.getPropertyValue('--text-color-secondary') || '#64748b';
    return {
        maintainAspectRatio: false,
        plugins: { legend: { labels: { color: textMutedColor } } },
        scales: {
            x: { stacked: true, ticks: { color: textMutedColor }, grid: { color: 'transparent' } },
            y: { stacked: true, ticks: { color: textMutedColor, precision: 0 }, grid: { color: borderColor, drawTicks: false } }
        }
    };
});

// ── Tabela helpers ────────────────────────────────────────
const STATUS_LABEL = {
    agendado: 'Agendado',
    realizado: 'Realizado',
    faltou: 'Faltou',
    cancelado: 'Cancelado',
    remarcado: 'Remarcado',
    bloqueado: 'Bloqueado'
};
const STATUS_SEVERITY = {
    agendado: 'info',
    realizado: 'success',
    faltou: 'danger',
    cancelado: 'warn',
    remarcado: 'secondary',
    bloqueado: 'secondary'
};

function fmtDateTimeBR(iso) {
    if (!iso) return '—';
    const d = new Date(iso);
    if (Number.isNaN(d.getTime())) return iso;
    const dd = String(d.getDate()).padStart(2, '0');
    const mm = String(d.getMonth() + 1).padStart(2, '0');
    const yy = d.getFullYear();
    const hh = String(d.getHours()).padStart(2, '0');
    const mi = String(d.getMinutes()).padStart(2, '0');
    return `${dd}/${mm}/${yy} ${hh}:${mi}`;
}
function sessionTitle(s) {
    return s.titulo_custom || s.titulo || (s.tipo ? s.tipo : 'Sessão');
}
function patientName(s) {
    return s.patients?.nome_completo || '—';
}

// ── Export PDF / Excel / CSV ──────────────────────────────
const exportingPdf = ref(false);
const exportingXlsx = ref(false);

function buildExportParams() {
    const period = PERIODS.find(p => p.value === selectedPeriod.value)?.label || '';
    // Normaliza patients.nome_completo pra paciente_nome (RelatoriosPage usa nested patients(...))
    const normalized = sessionsFiltradas.value.map(s => ({
        ...s,
        paciente_nome: s.patients?.nome_completo || '—'
    }));
    return {
        title: 'Relatório de Sessões',
        subtitle: period,
        sessions: normalized,
        kpis: [
            { label: 'Total', value: total.value },
            { label: 'Realizadas', value: realizadas.value },
            { label: 'Faltas', value: faltas.value },
            { label: 'Canceladas', value: canceladas.value },
            { label: 'Taxa', value: taxaRealizacao.value != null ? `${taxaRealizacao.value}%` : '—' }
        ],
        tenantName: tenantStore.activeTenantName || tenantStore.tenant?.name || '',
        terapeutaNome: tenantStore.user?.full_name || tenantStore.user?.email || ''
    };
}

async function exportPdf() {
    if (exportingPdf.value) return;
    exportingPdf.value = true;
    try {
        const file = await exportSessionsToPDF(buildExportParams());
        toast.add({ severity: 'success', summary: 'PDF gerado', detail: file, life: 2500 });
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro ao gerar PDF', detail: e?.message || '', life: 4500 });
    } finally {
        exportingPdf.value = false;
    }
}

async function exportXlsx() {
    if (exportingXlsx.value) return;
    exportingXlsx.value = true;
    try {
        const file = await exportSessionsToXLSX(buildExportParams());
        toast.add({ severity: 'success', summary: 'Excel gerado', detail: file, life: 2500 });
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro ao gerar Excel', detail: e?.message || '', life: 4500 });
    } finally {
        exportingXlsx.value = false;
    }
}

function exportCsv() {
    try {
        const file = exportSessionsToCSV(buildExportParams());
        toast.add({ severity: 'success', summary: 'CSV gerado', detail: file, life: 2500 });
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro ao gerar CSV', detail: e?.message || '', life: 4500 });
    }
}

// ── Watch & mount ─────────────────────────────────────────
watch(selectedPeriod, () => {
    filtroTabela.value = null;
    loadSessions();
});
watch([() => layoutConfig.primary, () => layoutConfig.surface, isDarkTheme], () => {});
onMounted(loadSessions);
</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 transition-[border-radius] duration-200"
        :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 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-chart-bar text-base" />
                </div>
                <div class="min-w-0 hidden lg:block">
                    <div class="text-[1rem] font-bold tracking-tight text-[var(--text-color)]">Relatórios</div>
                    <div class="text-[1rem] text-[var(--text-color-secondary)]">Visão geral das suas sessões</div>
                </div>
            </div>

            <!-- Seletor de período -->
            <div class="flex-1 min-w-0 hidden xl:flex items-center mx-2">
                <SelectButton v-model="selectedPeriod" :options="PERIODS" option-label="label" option-value="value" :allow-empty="false" size="small" />
            </div>

            <!-- Refresh + Exports -->
            <div class="flex items-center gap-1.5 shrink-0 ml-auto">
                <Button
                    icon="pi pi-file-pdf"
                    severity="secondary"
                    outlined
                    class="h-9 w-9 rounded-full"
                    :loading="exportingPdf"
                    :disabled="!hasLoaded || loading || total === 0"
                    v-tooltip.bottom="'Exportar PDF'"
                    @click="exportPdf"
                />
                <Button
                    icon="pi pi-file-excel"
                    severity="secondary"
                    outlined
                    class="h-9 w-9 rounded-full"
                    :loading="exportingXlsx"
                    :disabled="!hasLoaded || loading || total === 0"
                    v-tooltip.bottom="'Exportar Excel (.xlsx)'"
                    @click="exportXlsx"
                />
                <Button
                    icon="pi pi-table"
                    severity="secondary"
                    outlined
                    class="h-9 w-9 rounded-full"
                    :disabled="!hasLoaded || loading || total === 0"
                    v-tooltip.bottom="'Exportar CSV'"
                    @click="exportCsv"
                />
                <Button icon="pi pi-refresh" severity="secondary" outlined class="h-9 w-9 rounded-full" :loading="loading" title="Recarregar" @click="loadSessions" />
            </div>
        </div>

        <!-- Seletor de período — mobile (abaixo da linha principal) -->
        <div class="xl:hidden relative z-1 mt-2.5 flex flex-wrap gap-1.5">
            <button
                v-for="p in PERIODS"
                :key="p.value"
                class="inline-flex items-center px-3 py-1 rounded-full text-[1rem] font-semibold border-[1.5px] cursor-pointer transition-all duration-150 select-none"
                :class="
                    selectedPeriod === p.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)]'
                "
                @click="selectedPeriod = p.value"
            >
                {{ p.label }}
            </button>
        </div>
    </section>

    <!-- ══════════════════════════════════════════════════════
       CONTEÚDO
  ═══════════════════════════════════════════════════════ -->
    <div class="px-3 md:px-4 pb-8 flex flex-col gap-3">
        <!-- Erro -->
        <Message v-if="loadError" severity="error">{{ loadError }}</Message>

        <!-- Loading skeleton -->
        <div v-if="loading" class="flex flex-col gap-3">
            <!-- Stats skeleton -->
            <div class="flex flex-wrap gap-2">
                <div v-for="n in 6" :key="n" class="flex-1 min-w-[80px] h-[72px] rounded-md bg-[var(--surface-border,#e2e8f0)] animate-pulse" />
            </div>
            <!-- Chart skeleton -->
            <div class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] h-[280px] animate-pulse" />
        </div>

        <template v-else>
            <!-- ── QUICK-STATS clicáveis ────────────────────── -->
            <div class="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-6 gap-2">
                <div
                    v-for="s in quickStats"
                    :key="s.label"
                    class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border flex-1 min-w-[80px] transition-[border-color,box-shadow,background] duration-150"
                    :class="[
                        s.filter !== null ? 'cursor-pointer select-none' : '',
                        s.filter !== null && filtroTabela === s.filter
                            ? 'border-[var(--primary-color,#6366f1)] shadow-[0_0_0_3px_rgba(99,102,241,0.15)] bg-[var(--surface-card,#fff)]'
                            : s.cls === 'qs-ok'
                              ? 'border-green-500/25 bg-green-500/5 hover:border-green-500/40'
                              : s.cls === 'qs-danger'
                                ? 'border-red-500/25 bg-red-500/5 hover:border-red-500/40'
                                : s.cls === 'qs-warn'
                                  ? 'border-orange-500/25 bg-orange-500/5 hover:border-orange-500/40'
                                  : s.cls === 'qs-info'
                                    ? 'border-sky-500/25 bg-sky-500/5 hover:border-sky-500/40'
                                    : 'border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] hover:border-indigo-300/50'
                    ]"
                    @click="s.filter !== null ? toggleFiltroTabela(s.filter) : null"
                >
                    <div class="text-[1.35rem] font-bold leading-none" :class="s.valCls">{{ s.value }}</div>
                    <div class="text-[1rem] text-[var(--text-color-secondary)] opacity-75 truncate">{{ s.label }}</div>
                </div>
            </div>

            <!-- Chip de filtro ativo na tabela -->
            <div v-if="filtroTabela" class="flex items-center gap-2">
                <span class="text-[1rem] text-[var(--text-color-secondary)]">Filtrando por:</span>
                <span class="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[0.75rem] font-semibold bg-[var(--primary-color,#6366f1)] text-white">
                    {{ STATUS_LABEL[filtroTabela] || filtroTabela }}
                    <button class="ml-0.5 opacity-70 hover:opacity-100" @click="filtroTabela = null">
                        <i class="pi pi-times text-[0.6rem]" />
                    </button>
                </span>
            </div>

            <!-- ── GRÁFICO ──────────────────────────────────── -->
            <div v-if="total > 0" 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-chart-bar text-[var(--text-color-secondary)] opacity-60" />
                        <span class="font-semibold text-[1rem] text-[var(--text-color)]"> Sessões por {{ selectedPeriod === 'week' ? 'semana' : 'mês' }} </span>
                    </div>
                    <span class="text-[0.72rem] text-[var(--text-color-secondary)] opacity-60">{{ total }} sessão{{ total !== 1 ? 'ões' : '' }}</span>
                </div>
                <div class="p-4">
                    <Chart type="bar" :data="chartData" :options="chartOptions" class="h-64" />
                </div>
            </div>

            <!-- ── TABELA ───────────────────────────────────── -->
            <div class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] overflow-hidden">
                <!-- Cabeçalho da seção -->
                <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-table text-[var(--text-color-secondary)] opacity-60" />
                        <span class="font-semibold text-[1rem] text-[var(--text-color)]">Sessões no período</span>
                        <span v-if="filtroTabela" class="text-[0.72rem] text-[var(--text-color-secondary)] opacity-70">(filtrado)</span>
                    </div>
                    <span 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">
                        {{ sessionsFiltradas.length }}
                    </span>
                </div>

                <!-- Empty state (sem dados no período) -->
                <div v-if="!sessions.length" class="flex flex-col items-center justify-center gap-3 py-14 px-6 text-center border-2 border-dashed border-[var(--surface-border,#e2e8f0)] mx-4 my-4 rounded-md bg-[var(--surface-ground,#f8fafc)]">
                    <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-chart-bar text-3xl opacity-25" />
                        </div>
                        <div class="absolute -top-1.5 -right-1.5 w-6 h-6 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.58rem] text-[var(--text-color-secondary)] opacity-50" />
                        </div>
                    </div>
                    <div>
                        <div class="font-bold text-[0.9rem] text-[var(--text-color)] mb-0.5">Nenhuma sessão no período</div>
                        <div class="text-[1rem] text-[var(--text-color-secondary)] max-w-xs">Tente selecionar um período diferente.</div>
                    </div>
                    <div class="flex flex-wrap gap-2 mt-1 justify-center">
                        <button
                            v-for="p in PERIODS"
                            :key="p.value"
                            class="inline-flex items-center px-3 py-1 rounded-full text-[0.75rem] font-semibold border cursor-pointer transition-colors duration-150"
                            :class="
                                selectedPeriod === p.value ? 'bg-[var(--primary-color,#6366f1)] border-[var(--primary-color,#6366f1)] text-white' : 'border-[var(--surface-border,#e2e8f0)] text-[var(--text-color-secondary)] hover:border-indigo-300'
                            "
                            @click="selectedPeriod = p.value"
                        >
                            {{ p.label }}
                        </button>
                    </div>
                </div>

                <!-- Empty state (filtro sem resultado) -->
                <div v-else-if="!sessionsFiltradas.length" class="flex flex-col items-center gap-2 py-10 text-center text-[var(--text-color-secondary)]">
                    <i class="pi pi-filter-slash text-2xl opacity-30" />
                    <div class="font-semibold text-[0.88rem]">Nenhuma sessão com este status</div>
                    <Button label="Limpar filtro" icon="pi pi-times" severity="secondary" outlined size="small" class="rounded-full mt-1" @click="filtroTabela = null" />
                </div>

                <!-- DataTable -->
                <DataTable v-else :value="sessionsFiltradas" :rows="20" paginator :rows-per-page-options="[10, 20, 50]" scrollable scroll-height="480px" class="rel-datatable">
                    <Column field="inicio_em" header="Data / Hora" :sortable="true" style="min-width: 140px">
                        <template #body="{ data }">
                            <span class="font-medium">{{ fmtDateTimeBR(data.inicio_em) }}</span>
                        </template>
                    </Column>

                    <Column header="Paciente" style="min-width: 160px">
                        <template #body="{ data }">{{ patientName(data) }}</template>
                    </Column>

                    <Column header="Sessão" style="min-width: 160px">
                        <template #body="{ data }">{{ sessionTitle(data) }}</template>
                    </Column>

                    <Column field="modalidade" header="Modalidade" style="min-width: 110px">
                        <template #body="{ data }">
                            {{ data.modalidade === 'online' ? 'Online' : data.modalidade === 'presencial' ? 'Presencial' : data.modalidade || '—' }}
                        </template>
                    </Column>

                    <Column field="status" header="Status" style="min-width: 110px">
                        <template #body="{ data }">
                            <Tag :value="STATUS_LABEL[data.status] || data.status || 'Agendado'" :severity="STATUS_SEVERITY[data.status] || 'info'" />
                        </template>
                    </Column>
                </DataTable>
            </div>

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

<style scoped>
.rel-datatable :deep(.p-datatable-table-container) {
    border-radius: 0;
}
.rel-datatable :deep(th) {
    background: var(--surface-ground) !important;
    font-size: 0.82rem;
}
.rel-datatable :deep(td) {
    font-size: 0.85rem;
}
</style>
