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

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

const mode = computed(() => route.meta?.mode || 'therapist');
const isClinic = computed(() => mode.value === 'clinic');
const tenantId = computed(() => tenantStore.activeTenantId || tenantStore.tenantId);

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

// ── Mobile ────────────────────────────────────────────────
const filtersDlgOpen = ref(false);

// ── state ──────────────────────────────────────────────────────────────────────
const loading = ref(false);
const userId = ref(null);
const rules = ref([]);
const exceptionsMap = ref({}); // ruleId → Exception[]
const sessionsMap = ref({}); // ruleId → AgendaEvento[]
const expandedId = ref(null);

const filterStatus = ref('ativo');
const filterOwner = ref(null);

const { staff, load: loadStaff } = useAgendaClinicStaff();

const staffOptions = computed(() =>
    (staff.value || []).map((s) => ({
        label: s.full_name || s.nome || s.name || 'Profissional',
        value: s.user_id
    }))
);
const staffMap = computed(() => {
    const m = {};
    for (const s of staff.value || []) m[s.user_id] = s.full_name || s.nome || s.name || 'Profissional';
    return m;
});

// ── auth / init ────────────────────────────────────────────────────────────────
async function init() {
    const { data } = await supabase.auth.getUser();
    userId.value = data?.user?.id || null;
    if (isClinic.value && tenantId.value) await loadStaff(tenantId.value);
    await load();
}

// ── data load ──────────────────────────────────────────────────────────────────
async function load() {
    if (!userId.value) return;
    loading.value = true;
    try {
        let q = tenantDb().from('recurrence_rules').select('*').order('start_date', { ascending: false });

        if (isClinic.value) {
            if (!tenantId.value) return;
            if (filterOwner.value) q = q.eq('owner_id', filterOwner.value);
        } else {
            q = q.eq('owner_id', userId.value);
        }
        if (filterStatus.value !== 'all') q = q.eq('status', filterStatus.value);

        const { data: rData, error: rErr } = await q;
        if (rErr) throw rErr;
        const rawRules = rData || [];

        // patient names
        const patientIds = [...new Set(rawRules.map((r) => r.patient_id).filter(Boolean))];
        const patientMap = {};
        if (patientIds.length) {
            const { data: pts } = await tenantDb().from('patients').select('id, nome_completo, avatar_url').in('id', patientIds);
            for (const p of pts || []) patientMap[p.id] = p;
        }
        for (const r of rawRules) r._patient = patientMap[r.patient_id] || null;

        rules.value = rawRules;

        const ruleIds = rawRules.map((r) => r.id);
        if (ruleIds.length) await reloadSessions(ruleIds);
    } catch (e) {
        toast.add({ severity: 'warn', summary: 'Erro ao carregar', detail: e?.message, life: 3500 });
    } finally {
        loading.value = false;
    }
}

async function reloadSessions(ruleIds) {
    const [exRes, sessRes] = await Promise.all([
        tenantDb().from('recurrence_exceptions').select('*').in('recurrence_id', ruleIds).order('original_date'),
        tenantDb().from('agenda_eventos').select('id, recurrence_id, recurrence_date, status, inicio_em, fim_em').in('recurrence_id', ruleIds).order('inicio_em')
    ]);
    const exm = {};
    for (const ex of exRes.data || []) {
        if (!exm[ex.recurrence_id]) exm[ex.recurrence_id] = [];
        exm[ex.recurrence_id].push(ex);
    }
    exceptionsMap.value = { ...exceptionsMap.value, ...exm, ...Object.fromEntries(ruleIds.filter((id) => !exm[id]).map((id) => [id, []])) };

    const sm = {};
    for (const s of sessRes.data || []) {
        if (!sm[s.recurrence_id]) sm[s.recurrence_id] = [];
        sm[s.recurrence_id].push(s);
    }
    sessionsMap.value = { ...sessionsMap.value, ...sm, ...Object.fromEntries(ruleIds.filter((id) => !sm[id]).map((id) => [id, []])) };
}

// ── date generation ────────────────────────────────────────────────────────────
function generateAllDates(rule) {
    const { type, interval = 1, weekdays = [], start_date, end_date, max_occurrences } = rule;
    if (!start_date || !Array.isArray(weekdays) || !weekdays.length) return [];
    const maxOcc = Math.min(max_occurrences || 500, 500);
    const endLimitISO = end_date || null;
    const dates = [];

    if (type === 'custom_weekdays') {
        const cursor = new Date(start_date + 'T12:00:00');
        let safety = 0;
        while (dates.length < maxOcc && safety < 3000) {
            safety++;
            const iso = cursor.toISOString().slice(0, 10);
            if (endLimitISO && iso > endLimitISO) break;
            if (weekdays.includes(cursor.getDay())) dates.push(iso);
            cursor.setDate(cursor.getDate() + 1);
        }
    } else {
        // weekly / biweekly
        const dow = weekdays[0];
        const cursor = new Date(start_date + 'T12:00:00');
        while (cursor.getDay() !== dow) cursor.setDate(cursor.getDate() + 1);
        while (dates.length < maxOcc) {
            const iso = cursor.toISOString().slice(0, 10);
            if (endLimitISO && iso > endLimitISO) break;
            dates.push(iso);
            cursor.setDate(cursor.getDate() + 7 * (interval || 1));
        }
    }
    return dates;
}

// ── sessions (merged) ──────────────────────────────────────────────────────────
const TODAY = new Date().toISOString().slice(0, 10);

function buildSessions(rule) {
    const exByDate = {};
    for (const ex of exceptionsMap.value[rule.id] || []) exByDate[ex.original_date] = ex;
    const sessByDate = {};
    for (const s of sessionsMap.value[rule.id] || []) sessByDate[s.recurrence_date] = s;

    return generateAllDates(rule).map((iso) => {
        const real = sessByDate[iso];
        const ex = exByDate[iso];
        let status = 'agendado';
        if (real) {
            status = real.status || 'agendado';
        } else if (ex) {
            if (ex.type === 'cancel_session' || ex.type === 'therapist_canceled') status = 'cancelado';
            else if (ex.type === 'patient_missed') status = 'faltou';
            else if (ex.type === 'reschedule_session') status = 'remarcado';
        }
        return { date: iso, status, real_id: real?.id || null };
    });
}

// ── stats ──────────────────────────────────────────────────────────────────────
const STATUS_DONE = new Set(['compareceu', 'veio', 'realizado', 'presente']);

function ruleStats(rule) {
    const sessions = buildSessions(rule);
    const total = sessions.length;
    const done = sessions.filter((s) => STATUS_DONE.has(s.status)).length;
    const faltou = sessions.filter((s) => s.status === 'faltou').length;
    const cancelado = sessions.filter((s) => s.status === 'cancelado').length;
    const pendentes = sessions.filter((s) => s.status === 'agendado' || s.status === 'remarcado').length;
    const progress = total ? Math.round((done / total) * 100) : 0;
    return { total, done, faltou, cancelado, pendentes, progress };
}

// ── formatters ─────────────────────────────────────────────────────────────────
const DIAS_SHORT = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'];

function fmtDate(iso) {
    if (!iso) return '';
    const [y, m, d] = iso.split('-');
    return `${d}/${m}/${y}`;
}
function fmtRuleDesc(rule) {
    const days = (rule.weekdays || []).map((d) => DIAS_SHORT[d]).join(', ');
    const time = rule.start_time ? rule.start_time.slice(0, 5) : '';
    const freq = rule.interval > 1 ? `a cada ${rule.interval} sem.` : '';
    return [days, time, freq].filter(Boolean).join(' · ');
}
function fmtPeriod(rule) {
    const s = fmtDate(rule.start_date);
    if (rule.end_date) return `${s} até ${fmtDate(rule.end_date)}`;
    if (rule.max_occurrences) return `${s} · ${rule.max_occurrences} sessões`;
    return `A partir de ${s}`;
}
function fmtPillDate(iso) {
    const [, m, d] = iso.split('-');
    const dow = DIAS_SHORT[new Date(iso + 'T12:00:00').getDay()];
    return `${dow} ${Number(d)}/${Number(m)}`;
}

// ── status UI ──────────────────────────────────────────────────────────────────
const STATUS_OPTS = [
    { label: 'Agendado', value: 'agendado' },
    { label: 'Compareceu', value: 'compareceu' },
    { label: 'Faltou', value: 'faltou' },
    { label: 'Cancelado', value: 'cancelado' },
    { label: 'Remarcado', value: 'remarcado' }
];

const PILL_CLASS = {
    agendado: 'pill--pending',
    compareceu: 'pill--done',
    veio: 'pill--done',
    realizado: 'pill--done',
    presente: 'pill--done',
    faltou: 'pill--missed',
    cancelado: 'pill--canceled',
    remarcado: 'pill--rescheduled'
};

// ── actions ────────────────────────────────────────────────────────────────────
async function onPillStatusChange(rule, s, newStatus) {
    try {
        if (s.real_id) {
            await tenantDb().from('agenda_eventos').update({ status: newStatus }).eq('id', s.real_id);
        } else {
            const { data: ex } = await tenantDb().from('agenda_eventos').select('id').eq('recurrence_id', rule.id).eq('recurrence_date', s.date).maybeSingle();
            if (ex?.id) {
                await tenantDb().from('agenda_eventos').update({ status: newStatus }).eq('id', ex.id);
            } else {
                await tenantDb().from('agenda_eventos').insert({
                    recurrence_id: rule.id,
                    recurrence_date: s.date,
                    owner_id: rule.owner_id,
                    tipo: 'sessao',
                    status: newStatus,
                    inicio_em: s.date + 'T' + (rule.start_time || '00:00') + ':00',
                    fim_em: s.date + 'T' + (rule.end_time || '01:00') + ':00',
                    visibility_scope: 'public',
                    titulo: 'Sessão',
                    paciente_id: rule.patient_id || null,
                    patient_id: rule.patient_id || null
                });
            }
        }
        toast.add({ severity: 'success', summary: 'Status atualizado', life: 1500 });
        await reloadSessions([rule.id]);
    } catch (e) {
        toast.add({ severity: 'warn', summary: 'Erro', detail: e?.message, life: 3500 });
    }
}

async function onCancelRule(rule) {
    const name = rule._patient?.nome_completo || 'paciente';
    if (!confirm(`Encerrar a série de "${name}"?\n\nSessões futuras deixarão de ser geradas. Sessões passadas já registradas são mantidas.`)) return;
    try {
        await tenantDb().from('recurrence_rules').update({ status: 'cancelado', updated_at: new Date().toISOString() }).eq('id', rule.id);
        toast.add({ severity: 'success', summary: 'Série encerrada', life: 2000 });
        await load();
    } catch (e) {
        toast.add({ severity: 'warn', summary: 'Erro', detail: e?.message, life: 3500 });
    }
}

async function onReactivateRule(rule) {
    try {
        await tenantDb().from('recurrence_rules').update({ status: 'ativo', updated_at: new Date().toISOString() }).eq('id', rule.id);
        toast.add({ severity: 'success', summary: 'Série reativada', life: 2000 });
        await load();
    } catch (e) {
        toast.add({ severity: 'warn', summary: 'Erro', detail: e?.message, life: 3500 });
    }
}

function toggleExpand(ruleId) {
    expandedId.value = expandedId.value === ruleId ? null : ruleId;
}

// ── navigation ─────────────────────────────────────────────────────────────────
function goBack() {
    if (isClinic.value) router.push({ name: 'admin-agenda-clinica' });
    else router.push({ name: 'therapist-agenda' });
}

onMounted(async () => {
    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);
    await init();
});

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

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

    <!-- ══════════════════════════════════════
       Hero sticky
  ═══════════════════════════════════════ -->
    <div
        ref="headerEl"
        class="sticky my-3 mx-3 md:mx-4 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 decorativos -->
        <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/9" />
        </div>

        <div class="relative z-1 flex items-center gap-3">
            <!-- Voltar + Brand -->
            <div class="flex items-center gap-2 shrink-0">
                <Button icon="pi pi-arrow-left" text severity="secondary" class="h-9 w-9 rounded-full shrink-0" v-tooltip.bottom="'Voltar à agenda'" @click="goBack" />
                <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-refresh text-base" />
                </div>
                <div class="min-w-0 hidden lg:block">
                    <div class="text-[1rem] font-bold tracking-tight text-[var(--text-color)]">Recorrências</div>
                    <div class="text-[0.75rem] text-[var(--text-color-secondary)]">
                        {{ isClinic ? 'Todas as séries da clínica' : 'Suas séries de sessões recorrentes' }}
                    </div>
                </div>
            </div>

            <!-- Filtros desktop -->
            <div class="hidden xl:flex items-center gap-2 flex-1 min-w-0 mx-2">
                <SelectButton
                    v-model="filterStatus"
                    :options="[
                        { label: 'Ativas', value: 'ativo' },
                        { label: 'Encerradas', value: 'cancelado' },
                        { label: 'Todas', value: 'all' }
                    ]"
                    optionLabel="label"
                    optionValue="value"
                    :allowEmpty="false"
                    size="small"
                    @change="load"
                />
                <Select
                    v-if="isClinic && staffOptions.length"
                    v-model="filterOwner"
                    :options="[{ label: 'Todos os terapeutas', value: null }, ...staffOptions]"
                    optionLabel="label"
                    optionValue="value"
                    placeholder="Todos os terapeutas"
                    class="w-[220px]"
                    @change="load"
                />
            </div>

            <!-- Ações -->
            <div class="flex items-center gap-1 shrink-0 ml-auto">
                <Button icon="pi pi-filter" severity="secondary" outlined class="xl:hidden h-9 w-9 rounded-full" v-tooltip.bottom="'Filtros'" @click="filtersDlgOpen = true" />
                <Button icon="pi pi-refresh" severity="secondary" outlined class="h-9 w-9 rounded-full" :loading="loading" v-tooltip.bottom="'Recarregar'" @click="load" />
            </div>
        </div>
    </div>

    <!-- Dialog filtros mobile -->
    <Dialog v-model:visible="filtersDlgOpen" modal :draggable="false" pt:mask:class="backdrop-blur-xs" header="Filtros" class="w-[94vw] max-w-sm">
        <div class="flex flex-col gap-3 pt-1">
            <div>
                <label class="block text-xs font-semibold text-[var(--text-color-secondary)] mb-1.5">Status</label>
                <SelectButton
                    v-model="filterStatus"
                    :options="[
                        { label: 'Ativas', value: 'ativo' },
                        { label: 'Encerradas', value: 'cancelado' },
                        { label: 'Todas', value: 'all' }
                    ]"
                    optionLabel="label"
                    optionValue="value"
                    :allowEmpty="false"
                    class="w-full"
                    @change="load"
                />
            </div>
            <div v-if="isClinic && staffOptions.length">
                <label class="block text-xs font-semibold text-[var(--text-color-secondary)] mb-1.5">Terapeuta</label>
                <Select v-model="filterOwner" :options="[{ label: 'Todos os terapeutas', value: null }, ...staffOptions]" optionLabel="label" optionValue="value" placeholder="Todos os terapeutas" class="w-full" @change="load" />
            </div>
        </div>
        <template #footer>
            <Button label="Fechar" severity="secondary" outlined class="rounded-full" @click="filtersDlgOpen = false" />
        </template>
    </Dialog>

    <!-- ══════════════════════════════════════
       Conteúdo principal
  ═══════════════════════════════════════ -->
    <div class="px-3 md:px-4 pb-8">
        <!-- ─── Loading ──────────────────────────────────────────────── -->
        <div v-if="loading" class="flex flex-col gap-3">
            <Skeleton v-for="i in 4" :key="i" height="130px" class="rounded-2xl" />
        </div>

        <!-- ─── Empty ────────────────────────────────────────────────── -->
        <div v-else-if="!rules.length" 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 min-w-0">
                    <i class="pi pi-list text-[var(--text-color-secondary)] opacity-60" />
                    <span class="font-semibold text-sm">Séries cadastradas</span>
                </div>
                <span class="inline-flex items-center justify-center min-w-[22px] h-[22px] px-1.5 rounded-full bg-[var(--surface-200,#e5e7eb)] text-[var(--text-color-secondary)] text-[0.72rem] font-bold">0</span>
            </div>
            <div class="py-10 px-6 text-center">
                <i class="pi pi-calendar-times text-2xl opacity-20 mb-2 block" />
                <div class="font-semibold text-sm">Nenhuma série encontrada</div>
                <div class="text-xs opacity-60 mt-1">
                    {{ filterStatus === 'ativo' ? 'Crie sessões recorrentes na agenda para vê-las aqui.' : 'Altere o filtro de status.' }}
                </div>
                <Button label="Voltar à agenda" icon="pi pi-calendar" outlined severity="secondary" size="small" class="rounded-full mt-3" @click="goBack" />
            </div>
        </div>

        <!-- ─── Rule cards ───────────────────────────────────────────── -->
        <div v-else class="flex flex-col gap-4">
            <div v-for="rule in rules" :key="rule.id" class="rr-card">
                <!-- Card head: patient info + status badge -->
                <div class="rr-card__head">
                    <div class="flex items-start gap-3 min-w-0 flex-1">
                        <Avatar :label="(rule._patient?.nome_completo || '?')[0].toUpperCase()" shape="circle" size="large" class="shrink-0" style="background: var(--primary-100, #e0e7ff); color: var(--primary-700, #3730a3); font-weight: 700" />
                        <div class="min-w-0 flex-1">
                            <div class="font-bold text-base truncate leading-tight">
                                {{ rule._patient?.nome_completo || 'Paciente não encontrado' }}
                            </div>
                            <div v-if="isClinic && staffMap[rule.owner_id]" class="text-xs opacity-55 mt-0.5 truncate"><i class="pi pi-user text-xs mr-1" />{{ staffMap[rule.owner_id] }}</div>
                            <div class="text-sm opacity-65 mt-1"><i class="pi pi-clock text-xs mr-1" />{{ fmtRuleDesc(rule) }}</div>
                            <div class="text-xs opacity-45 mt-0.5"><i class="pi pi-calendar text-xs mr-1" />{{ fmtPeriod(rule) }}</div>
                        </div>
                    </div>
                    <Tag :value="rule.status === 'ativo' ? 'Ativa' : 'Encerrada'" :severity="rule.status === 'ativo' ? 'success' : 'secondary'" class="shrink-0 self-start" />
                </div>

                <!-- Stats + progress -->
                <template v-for="stats in [ruleStats(rule)]" :key="'stats-' + rule.id">
                    <div class="rr-stats-row">
                        <span class="rr-stat rr-stat--done">{{ stats.done }} compareceu</span>
                        <span v-if="stats.faltou" class="rr-stat rr-stat--missed">{{ stats.faltou }} faltou</span>
                        <span v-if="stats.cancelado" class="rr-stat rr-stat--canceled">{{ stats.cancelado }} cancelada{{ stats.cancelado !== 1 ? 's' : '' }}</span>
                        <span class="rr-stat rr-stat--pending">{{ stats.pendentes }} pendente{{ stats.pendentes !== 1 ? 's' : '' }}</span>
                        <span class="rr-stat rr-stat--total ml-auto">{{ stats.total }} sessões</span>
                    </div>
                    <div class="px-4 pb-1">
                        <ProgressBar :value="stats.progress" class="h-1.5 rounded-full" />
                    </div>
                </template>

                <!-- Card footer: actions -->
                <div class="rr-card__foot">
                    <Button
                        :icon="expandedId === rule.id ? 'pi pi-chevron-up' : 'pi pi-list'"
                        :label="expandedId === rule.id ? 'Ocultar sessões' : `Ver sessões (${ruleStats(rule).total})`"
                        severity="secondary"
                        outlined
                        size="small"
                        class="rounded-full"
                        @click="toggleExpand(rule.id)"
                    />
                    <div class="flex gap-2 ml-auto">
                        <Button v-if="rule.status === 'ativo'" label="Encerrar série" icon="pi pi-times-circle" severity="danger" text size="small" class="rounded-full" @click="onCancelRule(rule)" />
                        <Button v-else label="Reativar" icon="pi pi-undo" severity="success" text size="small" class="rounded-full" @click="onReactivateRule(rule)" />
                    </div>
                </div>

                <!-- Sessions panel (expanded) -->
                <div v-if="expandedId === rule.id" class="rr-sessions">
                    <div class="rr-sessions__grid">
                        <div v-for="s in buildSessions(rule)" :key="s.date" class="rr-pill" :class="[PILL_CLASS[s.status] || 'pill--pending', s.date < TODAY ? 'rr-pill--past' : s.date === TODAY ? 'rr-pill--today' : 'rr-pill--future']">
                            <div class="rr-pill__date">{{ fmtPillDate(s.date) }}</div>
                            <Select :modelValue="s.status" :options="STATUS_OPTS" optionLabel="label" optionValue="value" class="rr-pill__sel" @change="(e) => onPillStatusChange(rule, s, e.value)" />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<style scoped>
/* ── Card ─────────────────────────────────────────────────────────── */
.rr-card {
    border-radius: 1.25rem;
    border: 1px solid var(--surface-border);
    background: var(--surface-card);
    overflow: hidden;
    transition: box-shadow 0.15s;
}
.rr-card:hover {
    box-shadow: 0 2px 16px color-mix(in srgb, var(--primary-400, #818cf8) 10%, transparent);
}

.rr-card__head {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 16px 16px 12px;
}

.rr-card__foot {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px 14px;
    border-top: 1px solid var(--surface-border);
}

/* ── Stats row ────────────────────────────────────────────────────── */
.rr-stats-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    padding: 4px 16px 8px;
}

.rr-stat {
    font-size: 0.72rem;
    font-weight: 600;
    border-radius: 999px;
    padding: 2px 8px;
}
.rr-stat--done {
    background: var(--green-100, #dcfce7);
    color: var(--green-700, #15803d);
}
.rr-stat--missed {
    background: var(--red-100, #fee2e2);
    color: var(--red-700, #b91c1c);
}
.rr-stat--canceled {
    background: var(--orange-100, #ffedd5);
    color: var(--orange-700, #c2410c);
}
.rr-stat--pending {
    background: var(--surface-200, #e5e7eb);
    color: var(--text-color-secondary);
}
.rr-stat--total {
    background: transparent;
    color: var(--text-color-secondary);
    font-weight: 400;
}

/* ── Sessions panel ───────────────────────────────────────────────── */
.rr-sessions {
    border-top: 1px solid var(--surface-border);
    background: color-mix(in srgb, var(--surface-ground) 60%, transparent);
    padding: 14px 16px;
    max-height: 420px;
    overflow-y: auto;
}

.rr-sessions__grid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* ── Pill ─────────────────────────────────────────────────────────── */
.rr-pill {
    display: flex;
    align-items: center;
    gap: 6px;
    border-radius: 999px;
    padding: 4px 4px 4px 10px;
    border: 1px solid transparent;
    min-width: 0;
}

.rr-pill--past {
    opacity: 0.7;
}
.rr-pill--today {
    box-shadow: 0 0 0 2px var(--primary-400, #818cf8);
    opacity: 1 !important;
}
.rr-pill--future {
}

.pill--pending {
    background: var(--surface-200, #e5e7eb);
    border-color: var(--surface-300, #d1d5db);
    color: var(--text-color-secondary);
}
.pill--done {
    background: var(--green-50, #f0fdf4);
    border-color: var(--green-200, #bbf7d0);
    color: var(--green-800, #166534);
}
.pill--missed {
    background: var(--red-50, #fff1f2);
    border-color: var(--red-200, #fecaca);
    color: var(--red-700, #b91c1c);
}
.pill--canceled {
    background: var(--orange-50, #fff7ed);
    border-color: var(--orange-200, #fed7aa);
    color: var(--orange-700, #c2410c);
}
.pill--rescheduled {
    background: var(--blue-50, #eff6ff);
    border-color: var(--blue-200, #bfdbfe);
    color: var(--blue-700, #1d4ed8);
}

.rr-pill__date {
    font-size: 0.72rem;
    font-weight: 700;
    white-space: nowrap;
    letter-spacing: -0.01em;
}

.rr-pill__sel {
    /* shrink the PrimeVue Select to pill size */
    --p-select-padding-x: 6px;
    --p-select-padding-y: 2px;
    font-size: 0.7rem;
    min-width: 0;
    border: none;
    background: transparent !important;
    box-shadow: none !important;
}
:deep(.rr-pill__sel .p-select-label) {
    font-size: 0.7rem;
    padding: 2px 4px;
    font-weight: 600;
}
:deep(.rr-pill__sel .p-select-dropdown) {
    width: 1.4rem;
}
</style>
