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

import { useToast } from 'primevue/usetoast';

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

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

const events = ref([]);
const plans = ref([]);
const profiles = ref([]);

const q = ref('');

// filtro por tipo de owner (clinic/therapist/all)
const ownerType = ref('all'); // 'all' | 'clinic' | 'therapist'
const ownerTypeOptions = [
    { label: 'Todos', value: 'all' },
    { label: 'Clínica', value: 'clinic' },
    { label: 'Terapeuta', value: 'therapist' }
];

const isFocused = computed(() => {
    return typeof route.query?.q === 'string' && route.query.q.trim().length > 0;
});

// ---------- helpers: plano ----------
const planKeyById = computed(() => {
    const m = new Map();
    for (const p of plans.value) m.set(p.id, p.key);
    return m;
});

function planKey(planId) {
    if (!planId) return '—';
    return planKeyById.value.get(planId) || planId;
}

// ---------- helpers: datas ----------
function formatWhen(iso) {
    if (!iso) return '—';
    const d = new Date(iso);
    if (Number.isNaN(d.getTime())) return String(iso);
    return d.toLocaleString('pt-BR');
}

// ---------- helpers: owner ----------
function normalizeOwnerType(t) {
    const k = String(t || '').toLowerCase();
    if (k === 'clinic' || k === 'therapist') return k;
    return 'unknown';
}

function ownerKeyFromEvent(ev) {
    const t = normalizeOwnerType(ev.owner_type);
    const r = String(ev.owner_ref || '').trim();
    if ((t === 'clinic' || t === 'therapist') && r) return `${t}:${r}`;
    const legacy = String(ev.owner_id || '').trim();
    return legacy || 'unknown';
}

function parseOwnerKey(raw) {
    const s = String(raw || '').trim();
    if (!s) return { kind: 'unknown', id: null, raw: '' };

    const m = s.match(/^(clinic|therapist)\s*:\s*([0-9a-fA-F-]{8,})$/);
    if (m) return { kind: m[1].toLowerCase(), id: m[2], raw: s };

    return { kind: 'unknown', id: s, raw: s };
}

function ownerTagLabel(t) {
    if (t === 'clinic') return 'Clínica';
    if (t === 'therapist') return 'Terapeuta';
    return '—';
}

function ownerTagSeverity(t) {
    if (t === 'clinic') return 'info';
    if (t === 'therapist') return 'success';
    return 'secondary';
}

// ---------- helpers: profiles ----------
const profileById = computed(() => {
    const m = new Map();
    for (const p of profiles.value) m.set(p.id, p);
    return m;
});

function displayUser(userId) {
    if (!userId) return '—';
    const p = profileById.value.get(userId);
    if (!p) return userId;

    const name = p.nome || p.name || p.full_name || p.display_name || p.username || null;
    const email = p.email || p.email_principal || p.user_email || null;

    if (name && email) return `${name} <${email}>`;
    if (name) return name;
    if (email) return email;
    return userId;
}

function displayOwner(ev) {
    const t = normalizeOwnerType(ev.owner_type);
    const ref = String(ev.owner_ref || '').trim();
    if (t === 'therapist' && ref) return displayUser(ref);
    return ownerKeyFromEvent(ev);
}

// ---------- evento ----------
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 || '—';
}

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';
}

// ---------- navegação ----------
function goToSubscriptions(ev) {
    const key = ownerKeyFromEvent(ev);
    if (!key || key === 'unknown') return;
    router.push({ path: '/saas/subscriptions', query: { q: key } });
}

// ---------- fetch ----------
async function fetchAll() {
    if (isFetching.value) return;
    isFetching.value = true;
    loading.value = true;

    try {
        const [{ data: p, error: ep }, { data: e, error: ee }] = await Promise.all([
            supabase.from('plans').select('id,key').order('key', { ascending: true }),
            supabase.from('subscription_events').select('*').order('created_at', { ascending: false }).limit(500)
        ]);

        if (ep) throw ep;
        if (ee) throw ee;

        plans.value = p || [];
        events.value = e || [];

        // profiles: created_by e owners therapist
        const ids = new Set();
        for (const ev of events.value || []) {
            const createdBy = String(ev.created_by || '').trim();
            if (createdBy) ids.add(createdBy);

            const t = normalizeOwnerType(ev.owner_type);
            const ref = String(ev.owner_ref || '').trim();
            if (t === 'therapist' && ref) ids.add(ref);
        }

        if (ids.size) {
            const { data: pr, error: epr } = await supabase.from('profiles').select('id,nome,name,full_name,display_name,username,email,email_principal,user_email').in('id', Array.from(ids));

            profiles.value = epr ? [] : pr || [];
        } else {
            profiles.value = [];
        }
    } catch (err) {
        toast.add({ severity: 'error', summary: 'Erro', detail: err.message || String(err), life: 5000 });
    } finally {
        loading.value = false;
        isFetching.value = false;
    }
}

// ---------- filtro ----------
const filtered = computed(() => {
    const term = String(q.value || '')
        .trim()
        .toLowerCase();
    let list = events.value || [];

    if (ownerType.value !== 'all') {
        list = list.filter((ev) => normalizeOwnerType(ev.owner_type) === ownerType.value);
    }

    // foco por query (?q=clinic:... / therapist:...)
    const focus = String(route.query?.q || '').trim();
    if (focus) {
        const parsed = parseOwnerKey(focus);
        if (parsed.kind === 'clinic' || parsed.kind === 'therapist') {
            list = list.filter((ev) => normalizeOwnerType(ev.owner_type) === parsed.kind && String(ev.owner_ref || '') === String(parsed.id || ''));
        } else {
            const f = focus.toLowerCase();
            list = list.filter(
                (ev) =>
                    ownerKeyFromEvent(ev).toLowerCase().includes(f) ||
                    String(ev.owner_id || '')
                        .toLowerCase()
                        .includes(f)
            );
        }
    }

    if (!term) return list;

    return list.filter((ev) => {
        const oldKey = planKey(ev.old_plan_id);
        const newKey = planKey(ev.new_plan_id);

        const ok = ownerKeyFromEvent(ev);
        const ownerDisp = String(displayOwner(ev) || '');
        const subId = String(ev.subscription_id || '');
        const eventType = String(ev.event_type || '');
        const reason = String(ev.reason || '');

        const meta = ev.metadata ? JSON.stringify(ev.metadata) : '';

        const by = String(ev.created_by || '');
        const byDisp = String(displayUser(by) || '');

        return (
            ok.toLowerCase().includes(term) ||
            ownerDisp.toLowerCase().includes(term) ||
            subId.toLowerCase().includes(term) ||
            eventType.toLowerCase().includes(term) ||
            reason.toLowerCase().includes(term) ||
            meta.toLowerCase().includes(term) ||
            String(oldKey || '')
                .toLowerCase()
                .includes(term) ||
            String(newKey || '')
                .toLowerCase()
                .includes(term) ||
            by.toLowerCase().includes(term) ||
            byDisp.toLowerCase().includes(term)
        );
    });
});

const totalCount = computed(() => (filtered.value || []).length);
const changedCount = computed(() => (filtered.value || []).filter((x) => String(x?.event_type || '').toLowerCase() === 'plan_changed').length);

function clearFocus() {
    router.push({ path: route.path, query: {} });
}

// -------------------------
// Hero sticky
// -------------------------
const heroRef = ref(null);
const sentinelRef = ref(null);
const heroStuck = ref(false);
let heroObserver = null;
const mobileMenuRef = ref(null);

const heroMenuItems = computed(() => [
    {
        label: 'Voltar para assinaturas',
        icon: 'pi pi-arrow-left',
        command: () => router.push('/saas/subscriptions'),
        disabled: loading.value
    },
    {
        label: 'Recarregar',
        icon: 'pi pi-refresh',
        command: fetchAll,
        disabled: loading.value
    },
    { separator: true },
    {
        label: 'Filtros',
        items: ownerTypeOptions.map((o) => ({
            label: o.label,
            icon: ownerType.value === o.value ? 'pi pi-check' : 'pi pi-circle',
            command: () => {
                ownerType.value = o.value;
            }
        }))
    }
]);

onMounted(async () => {
    const initialQ = route.query?.q;
    if (typeof initialQ === 'string' && initialQ.trim()) {
        q.value = initialQ.trim();
        const parsed = parseOwnerKey(initialQ);
        if (parsed.kind === 'clinic') ownerType.value = 'clinic';
        if (parsed.kind === 'therapist') ownerType.value = 'therapist';
    }
    await fetchAll();

    if (sentinelRef.value) {
        heroObserver = new IntersectionObserver(
            ([entry]) => {
                heroStuck.value = !entry.isIntersecting;
            },
            { rootMargin: `${document.querySelector('.l2-main') ? '0px' : '-56px'} 0px 0px 0px`, threshold: 0 }
        );
        heroObserver.observe(sentinelRef.value);
    }
});

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

<template>
    <div class="flex flex-col gap-4 p-4">
        <!-- Header -->
        <div class="cfg-subheader">
            <div class="cfg-subheader__icon"><i class="pi pi-history" /></div>
            <div class="min-w-0 flex-1">
                <div class="cfg-subheader__title">Histórico de assinaturas</div>
                <div class="cfg-subheader__sub">Auditoria read-only das mudanças de plano e status.</div>
            </div>
            <div class="hidden xl:flex items-center gap-2 shrink-0">
                <Button label="Voltar para assinaturas" icon="pi pi-arrow-left" severity="secondary" outlined size="small" :disabled="loading" @click="router.push('/saas/subscriptions')" />
                <SelectButton v-model="ownerType" :options="ownerTypeOptions" optionLabel="label" optionValue="value" size="small" :disabled="loading" />
                <Button label="Recarregar" icon="pi pi-refresh" severity="secondary" outlined size="small" :loading="loading" @click="fetchAll" />
            </div>
            <div class="flex xl:hidden shrink-0">
                <Button label="Ações" icon="pi pi-ellipsis-v" severity="warn" size="small" @click="(e) => mobileMenuRef.toggle(e)" />
                <Menu ref="mobileMenuRef" :model="heroMenuItems" popup />
            </div>
        </div>
        <!-- Card foco -->
        <div v-if="isFocused" class="overflow-hidden rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)]">
            <div class="flex flex-wrap items-center justify-between gap-3 p-5">
                <div class="min-w-0">
                    <div class="text-[1rem] font-semibold leading-none text-[var(--text-color)]">Eventos em foco</div>
                    <div class="mt-1 flex flex-wrap items-center gap-2">
                        <Tag value="Filtro ativo" severity="warning" rounded />
                        <div class="text-[1rem] text-[var(--text-color-secondary)] break-all">
                            {{ route.query.q }}
                        </div>
                    </div>
                </div>

                <Button label="Limpar filtro" icon="pi pi-times" severity="danger" class="font-semibold" raised :disabled="loading" @click="clearFocus" />
            </div>
        </div>

        <!-- busca -->
        <div>
            <FloatLabel variant="on" class="w-full">
                <IconField class="w-full">
                    <InputIcon class="pi pi-search" />
                    <InputText v-model="q" id="events_search" class="w-full pr-10" variant="filled" :disabled="loading" />
                </IconField>
                <label for="events_search">Buscar owner, subscription, plano, tipo, usuário…</label>
            </FloatLabel>
        </div>

        <DataTable
            :value="filtered"
            dataKey="id"
            :loading="loading"
            stripedRows
            responsiveLayout="scroll"
            :rowHover="true"
            paginator
            :rows="15"
            :rowsPerPageOptions="[10, 15, 25, 50]"
            currentPageReportTemplate="{first}–{last} de {totalRecords}"
            paginatorTemplate="RowsPerPageDropdown FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport"
        >
            <Column header="Quando" style="min-width: 14rem">
                <template #body="{ data }">
                    {{ formatWhen(data.created_at) }}
                </template>
            </Column>

            <!-- Tipo = tipo do OWNER (clínica/terapeuta) -->
            <Column header="Owner tipo" style="width: 11rem">
                <template #body="{ data }">
                    <Tag :value="ownerTagLabel(normalizeOwnerType(data.owner_type))" :severity="ownerTagSeverity(normalizeOwnerType(data.owner_type))" rounded />
                </template>
            </Column>

            <Column header="Owner" style="min-width: 24rem">
                <template #body="{ data }">
                    <div class="flex flex-col">
                        <span class="font-medium">{{ ownerKeyFromEvent(data) }}</span>
                        <div class="text-[1rem] text-[var(--text-color-secondary)]">
                            {{ displayOwner(data) }}
                        </div>
                    </div>
                </template>
            </Column>

            <!-- Evento = event_type (plan_changed/canceled/reactivated) -->
            <Column header="Evento" style="min-width: 12rem">
                <template #body="{ data }">
                    <Tag :value="eventLabel(data.event_type)" :severity="eventSeverity(data.event_type)" />
                </template>
            </Column>

            <Column header="De → Para" style="min-width: 18rem">
                <template #body="{ data }">
                    <div class="flex items-center gap-2 flex-wrap">
                        <Tag :value="planKey(data.old_plan_id)" severity="secondary" />
                        <i class="pi pi-arrow-right text-color-secondary" />
                        <Tag :value="planKey(data.new_plan_id)" severity="success" />
                    </div>
                </template>
            </Column>

            <Column field="subscription_id" header="Subscription" style="min-width: 22rem">
                <template #body="{ data }">
                    <span class="font-mono text-[1rem]">{{ data.subscription_id }}</span>
                </template>
            </Column>

            <Column header="Alterado por" style="min-width: 22rem">
                <template #body="{ data }">
                    {{ displayUser(data.created_by) }}
                </template>
            </Column>

            <Column header="Ações" style="width: 12rem">
                <template #body="{ data }">
                    <Button label="Ver assinatura" icon="pi pi-external-link" size="small" severity="secondary" outlined class="w-full md:w-auto" :disabled="ownerKeyFromEvent(data) === 'unknown'" @click="goToSubscriptions(data)" />
                </template>
            </Column>

            <template #empty>
                <div class="p-4 text-[var(--text-color-secondary)]">Nenhum evento encontrado com os filtros atuais.</div>
            </template>
        </DataTable>

        <div class="text-[1rem] text-[var(--text-color-secondary)]">Mostrando até 500 eventos mais recentes.</div>
    </div>
</template>