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

import { useToast } from 'primevue/usetoast';

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

/**
 * Token persistence (antes do login)
 * - sessionStorage: some ao fechar a aba (bom para convite)
 * - se você preferir cross-tab, use localStorage
 */
const PENDING_INVITE_TOKEN_KEY = 'pending_invite_token_v1';

function persistPendingToken(token) {
    try {
        sessionStorage.setItem(PENDING_INVITE_TOKEN_KEY, token);
    } catch (_) {}
}
function readPendingToken() {
    try {
        return sessionStorage.getItem(PENDING_INVITE_TOKEN_KEY);
    } catch (_) {
        return null;
    }
}
function clearPendingToken() {
    try {
        sessionStorage.removeItem(PENDING_INVITE_TOKEN_KEY);
    } catch (_) {}
}

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

const state = reactive({
    loading: true,
    success: false,
    error: '',
    debugDetails: '' // mantém vazio por padrão (pode ativar quando precisar)
});

const tokenFromQuery = computed(() => {
    const t = route.query?.token;
    return typeof t === 'string' ? t.trim() : '';
});

const tokenEffective = computed(() => tokenFromQuery.value || readPendingToken() || '');

const shortToken = computed(() => {
    const t = tokenEffective.value;
    if (!t) return '—';
    if (t.length <= 14) return t;
    return `${t.slice(0, 8)}…${t.slice(-4)}`;
});

function isUuid(v) {
    // UUID v1–v5 (aceita maiúsculas/minúsculas)
    return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(v);
}

function friendlyError(err) {
    const msg = (err?.message || err || '').toString();

    if (/expired|expirad/i.test(msg)) return 'Este convite expirou. Peça para a clínica reenviar o convite.';
    if (/invalid|inval/i.test(msg)) return 'Token inválido. Verifique se você copiou o link corretamente.';
    if (/not found|não encontrado|nao encontrado|used|utilizad/i.test(msg)) return 'Convite não encontrado ou já utilizado.';
    if (/email/i.test(msg) && /mismatch|diferent|different|bate|match/i.test(msg)) {
        return 'Você está logado com um e-mail diferente do convite. Faça login com o e-mail correto.';
    }
    if (/not_authenticated|not authenticated|jwt|auth/i.test(msg)) {
        return 'Você precisa estar logado para aceitar este convite.';
    }
    return 'Não foi possível concluir o aceite. Tente novamente ou peça para reenviar o convite.';
}

function safeRpcError(rpcError) {
    const raw = (rpcError?.message || '').toString().trim();
    // Por padrão: mensagem amigável. Se quiser ver a "real", coloque em debugDetails.
    const friendly = friendlyError(rpcError);
    return { friendly, raw };
}

async function goAdmin() {
    await router.replace('/admin');
}

async function goLogin() {
    const token = tokenEffective.value;
    if (token) persistPendingToken(token);

    // ✅ garante troca de conta (somente quando usuário clica)
    try {
        await supabase.auth.signOut();
    } catch (_) {}

    // ✅ volta para o accept com token (ou storage pendente)
    const returnTo = token ? `/accept-invite?token=${encodeURIComponent(token)}` : '/accept-invite';
    await router.replace({ path: '/auth/login', query: { redirect: returnTo } });
}

async function acceptInvite(token) {
    state.loading = true;
    state.error = '';
    state.success = false;
    state.debugDetails = '';

    // 1) sessão
    const { data: sessionData, error: sessionErr } = await supabase.auth.getSession();
    if (sessionErr) {
        state.loading = false;
        state.error = friendlyError(sessionErr);
        return;
    }

    const session = sessionData?.session;
    if (!session) {
        // não logado → salva token e vai pro login
        persistPendingToken(token);

        const returnTo = route.fullPath || `/accept-invite?token=${encodeURIComponent(token)}`;
        await router.replace({ path: '/auth/login', query: { redirect: returnTo } });

        state.loading = false;
        return;
    }

    // 2) chama RPC
    const { data, error } = await supabase.rpc('tenant_accept_invite', { p_token: token });

    if (error) {
        state.loading = false;

        const { friendly, raw } = safeRpcError(error);
        state.error = friendly;

        // Se você quiser ver a mensagem "crua" para debug, descomente a linha abaixo:
        // state.debugDetails = raw

        // Opcional: toast discreto
        toast.add({
            severity: 'error',
            summary: 'Falha no convite',
            detail: friendly,
            life: 4000
        });
        return;
    }

    // 3) sucesso → limpa token pendente
    clearPendingToken();

    // 4) atualiza tenantStore
    const acceptedTenantId = data?.tenant_id || data?.tenantId || null;
    try {
        await refreshTenantContextAfterInvite(acceptedTenantId);
    } catch (_) {
        // Silencioso: aceite ocorreu; não vamos quebrar o fluxo.
    }

    state.loading = false;
    state.success = true;

    // 5) redireciona
    await router.replace('/admin');
}

async function refreshTenantContextAfterInvite(acceptedTenantId) {
    if (typeof tenantStore.refreshMyTenantsAndMemberships === 'function') {
        await tenantStore.refreshMyTenantsAndMemberships();
    } else {
        if (typeof tenantStore.fetchMyTenants === 'function') await tenantStore.fetchMyTenants();
        if (typeof tenantStore.fetchMyMemberships === 'function') await tenantStore.fetchMyMemberships();
    }

    if (acceptedTenantId && typeof tenantStore.setActiveTenantId === 'function') {
        tenantStore.setActiveTenantId(acceptedTenantId);
    }

    if (typeof tenantStore.hydrateActiveTenantContext === 'function') {
        await tenantStore.hydrateActiveTenantContext();
    } else if (typeof tenantStore.refreshActiveTenant === 'function') {
        await tenantStore.refreshActiveTenant();
    }
}

async function run() {
    state.loading = true;
    state.error = '';
    state.success = false;
    state.debugDetails = '';

    const token = tokenEffective.value;

    if (!token) {
        state.loading = false;
        state.error = 'Token ausente. Abra novamente o link do convite.';
        return;
    }

    if (!isUuid(token)) {
        state.loading = false;
        state.error = 'Token inválido. Verifique se o link está completo.';
        return;
    }

    // Se veio da query, persiste (caso precise atravessar login)
    if (tokenFromQuery.value) persistPendingToken(token);

    await acceptInvite(token);
}

async function retry() {
    await run();
}

onMounted(run);
</script>

<template>
    <Toast />
    <div class="min-h-screen flex items-center justify-center p-6 bg-[var(--surface-ground)] text-[var(--text-color)]">
        <div class="w-full max-w-lg overflow-hidden rounded-[2rem] border border-[var(--surface-border)] bg-[var(--surface-card)] shadow-sm">
            <!-- Header / Hero -->
            <div class="relative p-6">
                <div class="pointer-events-none absolute inset-0 opacity-80">
                    <div class="absolute -top-16 -right-16 h-64 w-64 rounded-full bg-indigo-400/10 blur-3xl" />
                    <div class="absolute top-10 -left-20 h-64 w-64 rounded-full bg-emerald-400/10 blur-3xl" />
                    <div class="absolute -bottom-16 right-10 h-64 w-64 rounded-full bg-fuchsia-400/10 blur-3xl" />
                </div>

                <div class="relative">
                    <h1 class="text-xl font-semibold mb-2">Aceitar convite</h1>
                    <p class="text-sm opacity-80">Vamos validar seu convite e ativar seu acesso ao tenant.</p>

                    <div class="mt-3 flex flex-wrap items-center gap-2 text-xs opacity-80">
                        <span class="inline-flex items-center gap-2 rounded-full border border-[var(--surface-border)] px-3 py-1">
                            <i class="pi pi-ticket" />
                            Token:
                            <b class="font-mono">{{ shortToken }}</b>
                        </span>

                        <span v-if="state.loading" class="inline-flex items-center gap-2 rounded-full border border-[var(--surface-border)] px-3 py-1">
                            <i class="pi pi-spin pi-spinner" />
                            Processando…
                        </span>

                        <span v-else-if="state.success" class="inline-flex items-center gap-2 rounded-full border border-[var(--surface-border)] px-3 py-1">
                            <i class="pi pi-check" />
                            Confirmado
                        </span>
                    </div>
                </div>
            </div>

            <!-- Body -->
            <div class="p-6 border-t border-[var(--surface-border)]">
                <!-- Loading -->
                <div v-if="state.loading" class="text-sm">Processando convite…</div>

                <!-- Success -->
                <div v-else-if="state.success" class="space-y-3">
                    <div class="text-sm">✅ Convite aceito com sucesso. Redirecionando…</div>
                    <div class="text-xs opacity-70">Se você não for redirecionado, clique abaixo.</div>
                    <div class="flex gap-2">
                        <Button label="Ir para o painel" icon="pi pi-arrow-right" @click="goAdmin" />
                    </div>
                </div>

                <!-- Error -->
                <div v-else-if="state.error" class="space-y-4">
                    <div class="rounded-2xl border border-red-500/30 bg-red-500/10 p-4 text-sm">
                        <div class="font-semibold mb-1">Não foi possível aceitar o convite</div>
                        <div class="opacity-90">{{ state.error }}</div>

                        <div v-if="state.debugDetails" class="mt-3 text-xs opacity-70">
                            <div class="font-semibold mb-1">Detalhes (debug)</div>
                            <pre class="m-0 whitespace-pre-wrap break-words">{{ state.debugDetails }}</pre>
                        </div>
                    </div>

                    <div class="flex flex-wrap gap-2">
                        <Button label="Tentar novamente" icon="pi pi-refresh" severity="secondary" outlined @click="retry" />
                        <Button label="Ir para login" icon="pi pi-sign-in" @click="goLogin" />
                    </div>

                    <p class="text-xs opacity-70 leading-relaxed">Se você recebeu um convite, confirme se está logado com o mesmo e-mail do convite.</p>
                </div>

                <!-- Idle -->
                <div v-else class="text-sm opacity-80">Preparando…</div>
            </div>
        </div>
    </div>
</template>
