<!--
|--------------------------------------------------------------------------
| Agência PSI — MembersPage.vue
|--------------------------------------------------------------------------
| Gestão de membros e convites do tenant ativo. Usa services do tenantship
| (0.5.D scaffold). Cobre: listar membros ativos, mudar role, remover,
| listar convites pendentes, enviar novo convite, revogar.
|
| ⚠️ Aceitar convite ainda é STUB no repository (precisa RPC
|    `accept_tenant_invite(p_token uuid)`). Página de aceitar (via link
|    /aceitar-convite?token=...) fica pra sessão dedicada.
|
| Rota sugerida (registrar manualmente em routes.clinic.js ou routes.saas.js):
|   { path: 'members', name: 'AdminMembers', component: () => import('@/views/pages/admin/MembersPage.vue') }
|--------------------------------------------------------------------------
-->
<script setup>
import { ref, onMounted, computed } from 'vue';
import { useToast } from 'primevue/usetoast';
import { useTenantStore } from '@/stores/tenantStore';
import { useTenantMembers } from '@/features/tenantship/composables/useTenantMembers';
import { useTenantInvites } from '@/features/tenantship/composables/useTenantInvites';

const toast = useToast();
const tenantStore = useTenantStore();

const members = useTenantMembers();
const invites = useTenantInvites();

const tenantId = computed(() => tenantStore.activeTenantId || tenantStore.tenantId || null);

// ─── Estado UI ───────────────────────────────────────────────────────────

const inviteDialogOpen = ref(false);
const inviteForm = ref({ email: '', role: 'therapist' });
const inviteSaving = ref(false);

const roleEditDialogOpen = ref(false);
const roleEditTarget = ref(null);
const roleEditNewRole = ref('therapist');
const roleEditSaving = ref(false);

const removeConfirmOpen = ref(false);
const removeTarget = ref(null);
const removing = ref(false);

const ROLE_LABELS = {
    tenant_admin: 'Administrador',
    therapist: 'Terapeuta',
    secretary: 'Secretária'
};
const ROLE_OPTIONS = [
    { value: 'therapist', label: 'Terapeuta' },
    { value: 'secretary', label: 'Secretária' }
    // tenant_admin não é atribuível via UI — promoção manual.
];

const INVITE_ROLE_OPTIONS = [
    { value: 'therapist', label: 'Terapeuta' },
    { value: 'secretary', label: 'Secretária' }
];

// ─── Computeds ───────────────────────────────────────────────────────────

const activeMembers = computed(() => members.rows.value.filter((m) => m.status === 'active'));
const pendingInvites = computed(() => invites.rows.value.filter((i) => i.status === 'pending'));

// ─── Lifecycle ───────────────────────────────────────────────────────────

onMounted(async () => {
    if (!tenantId.value) {
        toast.add({ severity: 'warn', summary: 'Sem tenant ativo', detail: 'Selecione um tenant antes de gerenciar membros.', life: 4000 });
        return;
    }
    await refreshAll();
});

async function refreshAll() {
    await Promise.all([members.loadForTenant({ tenantId: tenantId.value }), invites.loadForTenant({ tenantId: tenantId.value })]);
}

// ─── Convites ────────────────────────────────────────────────────────────

function openInviteDialog() {
    inviteForm.value = { email: '', role: 'therapist' };
    inviteDialogOpen.value = true;
}

async function submitInvite() {
    const email = String(inviteForm.value.email || '').trim().toLowerCase();
    if (!email) {
        toast.add({ severity: 'warn', summary: 'E-mail obrigatório', life: 3000 });
        return;
    }
    inviteSaving.value = true;
    try {
        await invites.send({ email, role: inviteForm.value.role, tenantId: tenantId.value });
        toast.add({
            severity: 'success',
            summary: 'Convite enviado',
            detail: `Token gerado pra ${email}. (Envio de e-mail/WhatsApp pendente — Módulo 6.)`,
            life: 4500
        });
        inviteDialogOpen.value = false;
    } catch (e) {
        toast.add({
            severity: 'error',
            summary: 'Falha ao enviar convite',
            detail: e?.message || 'Erro desconhecido.',
            life: 4500
        });
    } finally {
        inviteSaving.value = false;
    }
}

async function revokeInvite(invite) {
    try {
        await invites.revoke(invite.id, { tenantId: tenantId.value });
        toast.add({ severity: 'success', summary: 'Convite revogado', life: 2500 });
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Falha ao revogar', detail: e?.message, life: 4500 });
    }
}

function copyInviteLink(invite) {
    const baseUrl = window.location.origin;
    const link = `${baseUrl}/aceitar-convite?token=${invite.token}`;
    navigator.clipboard
        .writeText(link)
        .then(() => toast.add({ severity: 'info', summary: 'Link copiado', detail: link, life: 3000 }))
        .catch(() => toast.add({ severity: 'error', summary: 'Falha ao copiar', life: 3000 }));
}

// ─── Members ─────────────────────────────────────────────────────────────

function openRoleEdit(member) {
    roleEditTarget.value = member;
    roleEditNewRole.value = member.role;
    roleEditDialogOpen.value = true;
}

async function submitRoleEdit() {
    if (!roleEditTarget.value) return;
    roleEditSaving.value = true;
    try {
        await members.updateRole(roleEditTarget.value.id, roleEditNewRole.value, { tenantId: tenantId.value });
        toast.add({ severity: 'success', summary: 'Papel atualizado', life: 2500 });
        roleEditDialogOpen.value = false;
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Falha ao atualizar papel', detail: e?.message, life: 4500 });
    } finally {
        roleEditSaving.value = false;
    }
}

function openRemoveConfirm(member) {
    removeTarget.value = member;
    removeConfirmOpen.value = true;
}

async function submitRemove() {
    if (!removeTarget.value) return;
    removing.value = true;
    try {
        await members.remove(removeTarget.value.id, { tenantId: tenantId.value });
        toast.add({ severity: 'success', summary: 'Membro removido', life: 2500 });
        removeConfirmOpen.value = false;
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Falha ao remover', detail: e?.message, life: 4500 });
    } finally {
        removing.value = false;
    }
}

function fmtDate(iso) {
    if (!iso) return '—';
    return new Date(iso).toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit', year: 'numeric' });
}
</script>

<template>
    <div class="p-4 max-w-[1100px] mx-auto">
        <!-- Header -->
        <div class="flex items-center justify-between mb-6">
            <div>
                <h1 class="text-2xl font-semibold">Membros & Convites</h1>
                <p class="text-sm text-[var(--text-color-secondary)]">Gestão de quem tem acesso à clínica.</p>
            </div>
            <Button label="Convidar membro" icon="pi pi-user-plus" @click="openInviteDialog" />
        </div>

        <!-- Aviso se sem tenant -->
        <div v-if="!tenantId" class="bg-yellow-50 border border-yellow-200 rounded-lg p-4 mb-4 text-yellow-800">
            Selecione um tenant ativo no menu pra gerenciar membros.
        </div>

        <!-- Loading state -->
        <div v-else-if="members.loading.value || invites.loading.value" class="text-center py-8 text-[var(--text-color-secondary)]">
            <i class="pi pi-spin pi-spinner mr-2" /> Carregando…
        </div>

        <template v-else>
            <!-- Membros ativos -->
            <section class="mb-8">
                <h2 class="text-lg font-medium mb-3 flex items-center gap-2">
                    <i class="pi pi-users text-blue-500" />
                    Membros ativos
                    <span class="text-sm text-[var(--text-color-secondary)] font-normal">({{ activeMembers.length }})</span>
                </h2>

                <div v-if="!activeMembers.length" class="text-center py-6 text-[var(--text-color-secondary)] border border-dashed border-[var(--surface-border)] rounded-lg">
                    Nenhum membro ativo.
                </div>

                <DataTable v-else :value="activeMembers" stripedRows class="text-sm">
                    <Column field="full_name" header="Nome">
                        <template #body="{ data }">
                            <div class="font-medium">{{ data.full_name || '—' }}</div>
                            <div class="text-xs text-[var(--text-color-secondary)]">{{ data.email }}</div>
                        </template>
                    </Column>
                    <Column field="role" header="Papel">
                        <template #body="{ data }">
                            <span class="px-2 py-0.5 rounded-full text-xs bg-blue-100 text-blue-700">
                                {{ ROLE_LABELS[data.role] || data.role }}
                            </span>
                        </template>
                    </Column>
                    <Column field="created_at" header="Desde">
                        <template #body="{ data }">{{ fmtDate(data.created_at) }}</template>
                    </Column>
                    <Column header="Ações" :style="{ width: '180px' }">
                        <template #body="{ data }">
                            <div class="flex gap-2">
                                <Button v-if="data.role !== 'tenant_admin'" icon="pi pi-pencil" severity="secondary" text rounded v-tooltip.top="'Alterar papel'" @click="openRoleEdit(data)" />
                                <Button v-if="data.role !== 'tenant_admin'" icon="pi pi-times" severity="danger" text rounded v-tooltip.top="'Remover'" @click="openRemoveConfirm(data)" />
                                <span v-else class="text-xs text-[var(--text-color-secondary)] italic">admin</span>
                            </div>
                        </template>
                    </Column>
                </DataTable>
            </section>

            <!-- Convites pendentes -->
            <section>
                <h2 class="text-lg font-medium mb-3 flex items-center gap-2">
                    <i class="pi pi-envelope text-amber-500" />
                    Convites pendentes
                    <span class="text-sm text-[var(--text-color-secondary)] font-normal">({{ pendingInvites.length }})</span>
                </h2>

                <div v-if="!pendingInvites.length" class="text-center py-6 text-[var(--text-color-secondary)] border border-dashed border-[var(--surface-border)] rounded-lg">
                    Nenhum convite pendente.
                </div>

                <DataTable v-else :value="pendingInvites" stripedRows class="text-sm">
                    <Column field="email" header="E-mail" />
                    <Column field="role" header="Papel convidado">
                        <template #body="{ data }">
                            <span class="px-2 py-0.5 rounded-full text-xs bg-blue-100 text-blue-700">
                                {{ ROLE_LABELS[data.role] || data.role }}
                            </span>
                        </template>
                    </Column>
                    <Column field="created_at" header="Enviado em">
                        <template #body="{ data }">{{ fmtDate(data.created_at) }}</template>
                    </Column>
                    <Column field="expires_at" header="Expira em">
                        <template #body="{ data }">{{ fmtDate(data.expires_at) }}</template>
                    </Column>
                    <Column header="Ações" :style="{ width: '200px' }">
                        <template #body="{ data }">
                            <div class="flex gap-2">
                                <Button icon="pi pi-link" severity="secondary" text rounded v-tooltip.top="'Copiar link'" @click="copyInviteLink(data)" />
                                <Button icon="pi pi-times" severity="danger" text rounded v-tooltip.top="'Revogar'" @click="revokeInvite(data)" />
                            </div>
                        </template>
                    </Column>
                </DataTable>
            </section>
        </template>

        <!-- Dialog: Convidar -->
        <Dialog v-model:visible="inviteDialogOpen" modal :draggable="false" header="Convidar membro" :style="{ width: '480px', maxWidth: '94vw' }">
            <div class="flex flex-col gap-4 pt-2">
                <FloatLabel variant="on">
                    <InputText id="inv-email" v-model="inviteForm.email" type="email" class="w-full" autofocus />
                    <label for="inv-email">E-mail *</label>
                </FloatLabel>
                <FloatLabel variant="on">
                    <Select id="inv-role" v-model="inviteForm.role" :options="INVITE_ROLE_OPTIONS" optionLabel="label" optionValue="value" class="w-full" />
                    <label for="inv-role">Papel</label>
                </FloatLabel>
                <div class="text-xs text-[var(--text-color-secondary)]">
                    O convite gera um link com token de 7 dias. Envio automático de e-mail/WhatsApp será adicionado no Módulo 6 — por enquanto copie o link manualmente.
                </div>
            </div>
            <template #footer>
                <Button label="Cancelar" severity="secondary" text @click="inviteDialogOpen = false" />
                <Button label="Enviar convite" icon="pi pi-send" :loading="inviteSaving" @click="submitInvite" />
            </template>
        </Dialog>

        <!-- Dialog: Editar papel -->
        <Dialog v-model:visible="roleEditDialogOpen" modal :draggable="false" header="Alterar papel" :style="{ width: '420px', maxWidth: '94vw' }">
            <div class="flex flex-col gap-3 pt-2">
                <div class="text-sm">Membro: <strong>{{ roleEditTarget?.full_name || roleEditTarget?.email }}</strong></div>
                <FloatLabel variant="on">
                    <Select id="role-new" v-model="roleEditNewRole" :options="ROLE_OPTIONS" optionLabel="label" optionValue="value" class="w-full" />
                    <label for="role-new">Novo papel</label>
                </FloatLabel>
            </div>
            <template #footer>
                <Button label="Cancelar" severity="secondary" text @click="roleEditDialogOpen = false" />
                <Button label="Salvar" :loading="roleEditSaving" @click="submitRoleEdit" />
            </template>
        </Dialog>

        <!-- Dialog: Confirmar remoção -->
        <Dialog v-model:visible="removeConfirmOpen" modal :draggable="false" header="Remover membro" :style="{ width: '420px', maxWidth: '94vw' }">
            <div class="pt-2">
                <p>
                    Tem certeza que quer remover
                    <strong>{{ removeTarget?.full_name || removeTarget?.email }}</strong>
                    do tenant?
                </p>
                <p class="text-xs text-[var(--text-color-secondary)] mt-2">Os dados criados por essa pessoa (pacientes, sessões, prontuários) permanecem — apenas o vínculo é desfeito.</p>
            </div>
            <template #footer>
                <Button label="Cancelar" severity="secondary" text @click="removeConfirmOpen = false" />
                <Button label="Remover" icon="pi pi-times" severity="danger" :loading="removing" @click="submitRemove" />
            </template>
        </Dialog>
    </div>
</template>
