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

const toast = useToast();

const inviteToken = ref('');
const rotating = ref(false);

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

// ── Mobile menu ───────────────────────────────────────────
const mobileMenuRef = ref(null);

const mobileMenuItems = computed(() => [
    { label: 'Copiar link', icon: 'pi pi-copy', command: () => copyLink(), disabled: !inviteToken.value },
    { label: 'Copiar mensagem', icon: 'pi pi-comment', command: () => copyInviteMessage(), disabled: !inviteToken.value },
    { label: 'Abrir no navegador', icon: 'pi pi-external-link', command: () => openLink(), disabled: !inviteToken.value },
    { separator: true },
    { label: 'Gerar novo link', icon: 'pi pi-refresh', command: () => rotateLink() }
]);

// ── Conteúdo estático ─────────────────────────────────────
const howItWorks = [
    { n: 1, title: 'Você envia o link', desc: 'Por WhatsApp, e-mail ou mensagem direta.' },
    { n: 2, title: 'O paciente preenche', desc: 'Campos opcionais podem ficar em branco. Menos fricção, mais adesão.' },
    { n: 3, title: 'Você recebe e converte', desc: 'O cadastro aparece em "Cadastros recebidos". Revise e converta em paciente quando quiser.' }
];

const goodPractices = ['Gere um novo link se suspeitar que ele foi repassado indevidamente.', 'Informe o paciente que campos opcionais podem ficar em branco.', 'Evite divulgar em público; é um link para compartilhamento individual.'];

// ── URL base ──────────────────────────────────────────────
const PUBLIC_BASE_URL = '';

const origin = computed(() => {
    if (PUBLIC_BASE_URL) return PUBLIC_BASE_URL;
    return typeof window !== 'undefined' ? window.location.origin : '';
});

const publicUrl = computed(() => {
    if (!inviteToken.value) return '';
    return `${origin.value}/cadastro/paciente?t=${encodeURIComponent(inviteToken.value)}`;
});

// ── Token helpers ─────────────────────────────────────────
// A#18 + A#23: tokens são gerados NO SERVIDOR via gen_random_uuid(). O cliente
// NUNCA gera tokens — elimina fallback inseguro com Math.random().

async function loadOrCreateInvite() {
    // RPC issue_patient_invite retorna o token ativo existente ou cria um novo
    // (servidor resolve uid via auth.uid() + tenant_id via tenant_members).
    const { data, error } = await supabase.rpc('issue_patient_invite');
    if (error) throw error;
    inviteToken.value = data;
}

async function rotateLink() {
    rotating.value = true;
    try {
        const { data, error } = await supabase.rpc('rotate_patient_invite_token_v2');
        if (error) throw error;
        inviteToken.value = data;
        toast.add({ severity: 'success', summary: 'Pronto', detail: 'Novo link gerado. O anterior foi revogado.', life: 2500 });
    } catch (err) {
        toast.add({ severity: 'error', summary: 'Erro', detail: err?.message || 'Falha ao gerar novo link.', life: 3500 });
    } finally {
        rotating.value = false;
    }
}

async function copyLink() {
    try {
        if (!publicUrl.value) return;
        await navigator.clipboard.writeText(publicUrl.value);
        toast.add({ severity: 'success', summary: 'Copiado', detail: 'Link copiado para a área de transferência.', life: 1500 });
    } catch {
        window.prompt('Copie o link:', publicUrl.value);
    }
}

function openLink() {
    if (!publicUrl.value) return;
    window.open(publicUrl.value, '_blank', 'noopener');
}

async function copyInviteMessage() {
    try {
        if (!publicUrl.value) return;
        const msg = `Olá! Segue o link para seu pré-cadastro. Preencha com calma — campos opcionais podem ficar em branco:\n${publicUrl.value}`;
        await navigator.clipboard.writeText(msg);
        toast.add({ severity: 'success', summary: 'Copiado', detail: 'Mensagem copiada para a área de transferência.', life: 1500 });
    } catch {
        toast.add({ severity: 'warn', summary: 'Atenção', detail: 'Não foi possível copiar automaticamente.', life: 2500 });
    }
}

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);

    try {
        await loadOrCreateInvite();
    } catch (err) {
        toast.add({ severity: 'error', summary: 'Erro', detail: err?.message || 'Falha ao carregar link.', life: 3500 });
    }
});

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-link text-base" />
                </div>
                <div class="min-w-0 hidden lg:block">
                    <div class="text-[1rem] font-bold tracking-tight text-[var(--text-color)]">Link de Cadastro</div>
                    <div class="text-[1rem] text-[var(--text-color-secondary)]">Compartilhe com o paciente para preencher o pré-cadastro</div>
                </div>
            </div>

            <!-- Status + link rápido — desktop -->
            <div class="hidden xl:flex flex-1 min-w-0 mx-2 items-center gap-3">
                <!-- Badge de status -->
                <span
                    class="inline-flex items-center gap-1.5 text-[0.75rem] px-2.5 py-1 rounded-full border shrink-0 transition-colors"
                    :class="inviteToken ? 'border-emerald-200 text-emerald-700 bg-emerald-50' : 'border-[var(--surface-border)] text-[var(--text-color-secondary)] bg-[var(--surface-ground)]'"
                >
                    <span class="h-1.5 w-1.5 rounded-full" :class="inviteToken ? 'bg-emerald-500 animate-pulse' : 'bg-[var(--text-color-secondary)]'" />
                    {{ inviteToken ? 'Link ativo' : 'Gerando…' }}
                </span>

                <!-- Link inline -->
                <div v-if="!inviteToken" class="flex items-center gap-2 text-[1rem] text-[var(--text-color-secondary)]"><i class="pi pi-spin pi-spinner" /> Gerando link…</div>
                <InputGroup v-else class="max-w-xl">
                    <InputGroupAddon><i class="pi pi-link" /></InputGroupAddon>
                    <InputText readonly :value="publicUrl" class="font-mono text-[0.75rem]" />
                    <Button icon="pi pi-copy" severity="secondary" title="Copiar link" @click="copyLink" />
                    <Button icon="pi pi-external-link" severity="secondary" title="Abrir no navegador" @click="openLink" />
                </InputGroup>
            </div>

            <!-- Ações desktop -->
            <div class="hidden xl:flex items-center gap-1 shrink-0">
                <Button label="Gerar novo link" icon="pi pi-refresh" severity="secondary" outlined class="rounded-full" :loading="rotating" @click="rotateLink" />
            </div>

            <!-- Mobile -->
            <div class="flex xl:hidden items-center gap-1 shrink-0 ml-auto">
                <Button label="Ações" icon="pi pi-ellipsis-v" severity="secondary" size="small" class="rounded-full" @click="(e) => mobileMenuRef.toggle(e)" />
                <Menu ref="mobileMenuRef" :model="mobileMenuItems" :popup="true" />
            </div>
        </div>
    </section>

    <!-- ══════════════════════════════════════════════════════
       CONTEÚDO
  ═══════════════════════════════════════════════════════ -->
    <div class="flex flex-col lg:flex-row gap-3 px-3 md:px-4 pb-5">
        <!-- ── ESQUERDA: link + mensagem ──────────────────── -->
        <div class="flex-1 min-w-0 flex flex-col gap-3">
            <!-- Card principal: link -->
            <div class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] overflow-hidden">
                <!-- Header da seção -->
                <div class="flex items-center justify-between gap-3 flex-wrap px-4 pt-3.5 pb-3 border-b border-[var(--surface-border,#e2e8f0)]">
                    <div>
                        <div class="font-semibold text-[var(--text-color)]">Seu link público</div>
                        <div class="text-[1rem] text-[var(--text-color-secondary)] mt-0.5">Envie ao paciente por WhatsApp, e-mail ou mensagem direta</div>
                    </div>
                    <span
                        class="inline-flex items-center gap-1.5 text-[0.75rem] px-2.5 py-1 rounded-full border shrink-0"
                        :class="inviteToken ? 'border-emerald-200 text-emerald-700 bg-emerald-50' : 'border-[var(--surface-border)] text-[var(--text-color-secondary)] bg-[var(--surface-ground)]'"
                    >
                        <span class="h-1.5 w-1.5 rounded-full" :class="inviteToken ? 'bg-emerald-500 animate-pulse' : 'bg-[var(--text-color-secondary)]'" />
                        {{ inviteToken ? 'Ativo' : 'Gerando…' }}
                    </span>
                </div>

                <div class="p-4 flex flex-col gap-4">
                    <!-- Skeleton -->
                    <div v-if="!inviteToken" class="flex flex-col gap-3">
                        <div class="h-10 rounded-md bg-[var(--surface-ground,#f8fafc)] animate-pulse" />
                        <div class="h-10 rounded-md bg-[var(--surface-ground,#f8fafc)] animate-pulse" />
                    </div>

                    <div v-else class="flex flex-col gap-4">
                        <!-- InputGroup do link -->
                        <InputGroup>
                            <InputGroupAddon><i class="pi pi-link" /></InputGroupAddon>
                            <InputText readonly :value="publicUrl" class="font-mono text-[0.75rem]" />
                            <Button icon="pi pi-copy" severity="secondary" title="Copiar" @click="copyLink" />
                            <Button icon="pi pi-external-link" severity="secondary" title="Abrir" @click="openLink" />
                        </InputGroup>

                        <div class="text-[0.75rem] text-[var(--text-color-secondary)]">
                            Token: <span class="font-mono select-all opacity-60">{{ inviteToken }}</span>
                        </div>

                        <!-- CTAs rápidas -->
                        <div class="grid grid-cols-1 sm:grid-cols-2 gap-2.5">
                            <!-- Copiar link -->
                            <button
                                class="flex items-center gap-3 px-3.5 py-3 rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-ground,#f8fafc)] cursor-pointer text-left transition-[background,box-shadow,transform] duration-150 hover:bg-[var(--surface-hover,#f1f5f9)] hover:shadow-[0_2px_12px_rgba(0,0,0,0.06)] hover:-translate-y-px active:translate-y-0"
                                @click="copyLink"
                            >
                                <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-copy" />
                                </div>
                                <div class="min-w-0">
                                    <div class="font-semibold text-[1rem] text-[var(--text-color)]">Copiar link</div>
                                    <div class="text-[0.75rem] text-[var(--text-color-secondary)]">Cole no WhatsApp ou e-mail</div>
                                </div>
                            </button>

                            <!-- Copiar mensagem pronta -->
                            <button
                                class="flex items-center gap-3 px-3.5 py-3 rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-ground,#f8fafc)] cursor-pointer text-left transition-[background,box-shadow,transform] duration-150 hover:bg-[var(--surface-hover,#f1f5f9)] hover:shadow-[0_2px_12px_rgba(0,0,0,0.06)] hover:-translate-y-px active:translate-y-0"
                                @click="copyInviteMessage"
                            >
                                <div class="grid place-items-center w-9 h-9 rounded-md shrink-0 bg-emerald-500/10 text-emerald-600">
                                    <i class="pi pi-comment" />
                                </div>
                                <div class="min-w-0">
                                    <div class="font-semibold text-[1rem] text-[var(--text-color)]">Copiar mensagem pronta</div>
                                    <div class="text-[0.75rem] text-[var(--text-color-secondary)]">Texto formatado com o link incluso</div>
                                </div>
                            </button>
                        </div>

                        <!-- Aviso -->
                        <Message severity="warn" :closable="false"> <b>Dica:</b> ao gerar um novo link, o anterior é revogado. Use isso quando quiser invalidar um link já compartilhado. </Message>
                    </div>
                </div>
            </div>

            <!-- Mensagem pronta -->
            <div class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] p-4">
                <div class="font-semibold text-[var(--text-color)] flex items-center gap-2 mb-1">
                    <i class="pi pi-comment text-[1rem] text-[var(--text-color-secondary)]" />
                    Mensagem pronta para envio
                </div>
                <div class="text-[1rem] text-[var(--text-color-secondary)] mb-3">Copie e cole ao enviar o link ao paciente:</div>
                <div class="rounded-md bg-[var(--surface-ground,#f8fafc)] border border-[var(--surface-border,#e2e8f0)] p-4 text-[1rem] text-[var(--text-color)] leading-relaxed">
                    Olá! Segue o link para seu pré-cadastro. Preencha com calma — campos opcionais podem ficar em branco:
                    <span class="block mt-2 font-mono text-[0.72rem] break-all text-[var(--text-color-secondary)]">{{ publicUrl || '…aguardando link…' }}</span>
                </div>
                <div class="mt-3">
                    <Button icon="pi pi-copy" label="Copiar mensagem" severity="secondary" outlined class="rounded-full" :disabled="!publicUrl" @click="copyInviteMessage" />
                </div>
            </div>

            <LoadedPhraseBlock v-if="inviteToken" />
        </div>

        <!-- ── DIREITA: instruções ────────────────────────── -->
        <div class="w-full lg:w-[272px] lg:shrink-0 flex flex-col gap-3">
            <!-- Como funciona -->
            <div class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] overflow-hidden">
                <div class="flex items-center gap-2.5 px-3.5 pt-3 pb-2.5 border-b border-[var(--surface-border,#f1f5f9)]">
                    <div class="w-8 h-8 rounded-md flex items-center justify-center shrink-0 bg-indigo-500/10 text-indigo-500">
                        <i class="pi pi-list-check text-[0.9rem]" />
                    </div>
                    <div class="min-w-0">
                        <span class="block text-[1rem] font-bold text-[var(--text-color)]">Como funciona</span>
                        <span class="block text-[0.72rem] text-[var(--text-color-secondary)]">Simples e sem fricção para o paciente</span>
                    </div>
                </div>

                <ol class="flex flex-col divide-y divide-[var(--surface-border,#f1f5f9)]">
                    <li v-for="step in howItWorks" :key="step.n" class="flex items-start gap-3 px-3.5 py-3">
                        <div class="grid place-items-center w-7 h-7 rounded-md shrink-0 bg-indigo-500/10 text-indigo-500 text-[0.75rem] font-bold mt-px">
                            {{ step.n }}
                        </div>
                        <div class="min-w-0">
                            <div class="font-semibold text-[1rem] text-[var(--text-color)]">{{ step.title }}</div>
                            <div class="text-[0.75rem] text-[var(--text-color-secondary)] mt-0.5 leading-relaxed">{{ step.desc }}</div>
                        </div>
                    </li>
                </ol>
            </div>

            <!-- Boas práticas -->
            <div class="rounded-md border border-[var(--surface-border,#e2e8f0)] bg-[var(--surface-card,#fff)] overflow-hidden">
                <div class="flex items-center gap-2.5 px-3.5 pt-3 pb-2.5 border-b border-[var(--surface-border,#f1f5f9)]">
                    <div class="w-8 h-8 rounded-md flex items-center justify-center shrink-0 bg-emerald-500/10 text-emerald-600">
                        <i class="pi pi-shield text-[0.9rem]" />
                    </div>
                    <div class="min-w-0">
                        <span class="block text-[1rem] font-bold text-[var(--text-color)]">Boas práticas</span>
                        <span class="block text-[0.72rem] text-[var(--text-color-secondary)]">Segurança e privacidade</span>
                    </div>
                </div>

                <ul class="flex flex-col divide-y divide-[var(--surface-border,#f1f5f9)]">
                    <li v-for="tip in goodPractices" :key="tip" class="flex items-start gap-2.5 px-3.5 py-2.5">
                        <i class="pi pi-check text-emerald-500 mt-0.5 shrink-0 text-[1rem]" />
                        <span class="text-[1rem] text-[var(--text-color-secondary)] leading-relaxed">{{ tip }}</span>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</template>
