<!--
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/views/pages/auth/Login.vue
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
-->
<script setup>
import { useTenantStore } from '@/stores/tenantStore';

import { ref, onMounted, onBeforeUnmount, computed } from 'vue';
import { useRouter } from 'vue-router';
import { supabase } from '../../../lib/supabase/client';

import Password from 'primevue/password';
import Checkbox from 'primevue/checkbox';
import { useToast } from 'primevue/usetoast';

// ✅ sessão (fonte de verdade p/ saas admin)
import { initSession, sessionIsSaasAdmin } from '@/app/session';

const tenant = useTenantStore();
const toast = useToast();
const router = useRouter();

const email = ref('');
const password = ref('');
const checked = ref(false);

const loading = ref(false);
const authError = ref('');

// recovery
const openRecovery = ref(false);
const recoveryEmail = ref('');
const loadingRecovery = ref(false);
const recoverySent = ref(false);

// Freemium F3d: "esqueci meu e-mail" — recupera por slug (identificador)
const openRecoverEmail = ref(false);
const recoverSlug = ref('');
const recoverHint = ref('');
const recoverDone = ref(false);
const loadingRecoverEmail = ref(false);

// carrossel
const SLIDES_FALLBACK = [
    {
        title: 'Gestão clínica simplificada',
        body: 'Agendamentos, prontuários e sessões em um único painel. Foco no que importa: seus pacientes.',
        icon: 'pi-calendar-clock'
    },
    {
        title: 'Múltiplos profissionais',
        body: 'Adicione terapeutas, gerencie vínculos e mantenha tudo organizado por clínica.',
        icon: 'pi-users'
    },
    {
        title: 'Agendamento online',
        body: 'Seus pacientes marcam sessões diretamente pelo portal, com confirmação automática.',
        icon: 'pi-globe'
    },
    {
        title: 'Seguro e privado',
        body: 'Dados protegidos com autenticação robusta e controle de acesso por perfil.',
        icon: 'pi-shield'
    }
];

const slides = ref(SLIDES_FALLBACK);

const currentSlide = ref(0);
let slideInterval = null;

function goToSlide(i) {
    currentSlide.value = i;
}

function startCarousel() {
    slideInterval = setInterval(() => {
        currentSlide.value = (currentSlide.value + 1) % slides.value.length;
    }, 4500);
}

function stopCarousel() {
    if (slideInterval) clearInterval(slideInterval);
}

async function loadCarouselSlides() {
    try {
        const { data, error } = await supabase.from('login_carousel_slides').select('title, body, icon').eq('ativo', true).order('ordem', { ascending: true });
        if (!error && data && data.length > 0) {
            slides.value = data;
        }
    } catch {
        // mantém fallback
    }
}

const canSubmit = computed(() => {
    return !!email.value?.trim() && !!password.value && !loading.value && !loadingRecovery.value;
});

function isEmail(v) {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(v || '').trim());
}

function roleToPath(role) {
    if (role === 'clinic_admin' || role === 'tenant_admin' || role === 'admin') return '/admin';
    if (role === 'therapist') return '/therapist';
    if (role === 'supervisor') return '/supervisor';
    if (role === 'portal_user' || role === 'patient') return '/portal';
    if (role === 'saas_admin') return '/saas';
    return '/';
}

function persistRememberedEmail() {
    const mail = String(email.value || '').trim();
    try {
        if (checked.value && mail) localStorage.setItem('remember_login_email', mail);
        else localStorage.removeItem('remember_login_email');
    } catch {
        // ignora storage bloqueado
    }
}

async function onSubmit() {
    authError.value = '';
    loading.value = true;

    try {
        // 🔥 HARD RESET do contexto tenant ANTES de autenticar
        try {
            tenant.reset();
        } catch {}
        try {
            localStorage.removeItem('tenant_id');
            localStorage.removeItem('tenant');
            localStorage.removeItem('currentTenantId');
        } catch {}

        const mail = String(email.value || '').trim();

        const res = await supabase.auth.signInWithPassword({
            email: mail,
            password: password.value
        });

        if (res.error) throw res.error;

        // ✅ garante que sessionIsSaasAdmin esteja hidratado após login
        try {
            await initSession({ initial: false });
        } catch (e) {
            console.warn('[Login] initSession pós-login falhou:', e);
        }

        persistRememberedEmail();

        const redirect = sessionStorage.getItem('redirect_after_login');
        if (sessionIsSaasAdmin.value) {
            if (redirect) {
                sessionStorage.removeItem('redirect_after_login');
                router.push(redirect);
                return;
            }
            router.push('/saas');
            return;
        }

        // 🔥 identidade global (profiles.role) define área macro
        const { data: profile, error: pErr } = await supabase.from('profiles').select('role').eq('id', res.data.user.id).single();

        if (pErr) throw pErr;

        const globalRole = profile?.role || null;
        if (!globalRole) {
            authError.value = 'Perfil não configurado corretamente.';
            return;
        }

        const safeRedirect = (path) => {
            const p = String(path || '');
            if (!p) return null;
            if (globalRole === 'saas_admin') return p === '/saas' || p.startsWith('/saas/') ? p : '/saas';
            if (globalRole === 'portal_user') return p === '/portal' || p.startsWith('/portal/') ? p : '/portal';
            if (globalRole === 'tenant_member') {
                return p.startsWith('/admin') || p.startsWith('/therapist') || p.startsWith('/supervisor') ? p : null;
            }
            return null;
        };

        let tenantTarget = null;

        if (globalRole === 'tenant_member') {
            try {
                await supabase.rpc('ensure_personal_tenant');
            } catch (e) {
                console.warn('[Login] ensure_personal_tenant falhou:', e);
            }

            await tenant.loadSessionAndTenant();

            console.log('[LOGIN] tenant.user', tenant.user);
            console.log('[LOGIN] memberships', tenant.memberships);
            console.log('[LOGIN] activeTenantId', tenant.activeTenantId);
            console.log('[LOGIN] activeRole', tenant.activeRole);

            if (!tenant.user) {
                authError.value = 'Não foi possível obter a sessão após login.';
                return;
            }

            if (!tenant.activeRole) {
                authError.value = 'Sua conta não tem vínculo ativo com uma clínica (tenant_members).';
                await supabase.auth.signOut();
                return;
            }

            tenantTarget = roleToPath(tenant.activeRole);
        } else {
            try {
                localStorage.removeItem('tenant_id');
                localStorage.removeItem('tenant');
                localStorage.removeItem('currentTenantId');
            } catch {}
        }

        if (redirect) {
            sessionStorage.removeItem('redirect_after_login');
            const sr = safeRedirect(redirect);

            if (sr) {
                router.push(sr);
                return;
            }
            if (globalRole === 'tenant_member' && tenantTarget) {
                router.push(tenantTarget);
                return;
            }
            router.push(globalRole === 'portal_user' ? '/portal' : globalRole === 'saas_admin' ? '/saas' : '/');
            return;
        }

        const intended = sessionStorage.getItem('intended_area');
        sessionStorage.removeItem('intended_area');

        let target = '/';

        if (globalRole === 'tenant_member') target = tenantTarget || '/therapist';
        else if (globalRole === 'portal_user') target = '/portal';
        else if (globalRole === 'saas_admin') target = '/saas';

        if (intended && intended !== globalRole) {
            router.push(target);
            return;
        }

        router.push(target);
    } catch (e) {
        authError.value = e?.message || 'Não foi possível entrar.';
    } finally {
        loading.value = false;
    }
}

function openForgot() {
    recoverySent.value = false;
    recoveryEmail.value = email.value?.trim() || '';
    openRecovery.value = true;
}

async function sendRecoveryEmail() {
    const mail = String(recoveryEmail.value || '').trim();
    if (!mail || !isEmail(mail)) {
        toast.add({ severity: 'warn', summary: 'E-mail', detail: 'Digite um e-mail válido.', life: 3000 });
        return;
    }

    loadingRecovery.value = true;
    recoverySent.value = false;
    try {
        const redirectTo = `${window.location.origin}/auth/reset-password`;
        const { error } = await supabase.auth.resetPasswordForEmail(mail, { redirectTo });
        if (error) throw error;
        recoverySent.value = true;
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'Falha ao enviar e-mail.', life: 4500 });
    } finally {
        loadingRecovery.value = false;
    }
}

function openForgotEmail() {
    recoverSlug.value = '';
    recoverHint.value = '';
    recoverDone.value = false;
    openRecoverEmail.value = true;
}

async function recoverEmailBySlug() {
    const slug = String(recoverSlug.value || '').trim().toLowerCase();
    if (slug.length < 3) {
        toast.add({ severity: 'warn', summary: 'Identificador', detail: 'Informe o identificador do seu ambiente.', life: 3000 });
        return;
    }
    loadingRecoverEmail.value = true;
    recoverDone.value = false;
    try {
        const { data, error } = await supabase.functions.invoke('recover-access', { body: { slug } });
        if (error) throw error;
        if (data?.ok && data?.hint) {
            recoverHint.value = data.hint;
            recoverDone.value = true;
        } else {
            toast.add({ severity: 'warn', summary: 'Não encontrado', detail: 'Nenhum ambiente com esse identificador.', life: 4000 });
        }
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'Falha ao recuperar acesso.', life: 4500 });
    } finally {
        loadingRecoverEmail.value = false;
    }
}

onMounted(async () => {
    await loadCarouselSlides();

    const preEmail = sessionStorage.getItem('login_prefill_email');
    const prePass = sessionStorage.getItem('login_prefill_password');

    let remembered = '';
    try {
        remembered = localStorage.getItem('remember_login_email') || '';
    } catch {}

    if (preEmail) email.value = preEmail;
    else if (remembered) email.value = remembered;

    if (prePass) password.value = prePass;

    checked.value = !!remembered;

    sessionStorage.removeItem('login_prefill_email');
    sessionStorage.removeItem('login_prefill_password');

    startCarousel();
});

onBeforeUnmount(() => {
    stopCarousel();
});
</script>

<template>
    <div class="min-h-screen w-full flex">
        <!-- ===== ESQUERDA: CARROSSEL ===== -->
        <div class="hidden lg:flex lg:w-1/2 relative overflow-hidden flex-col">
            <!-- Fundo gradiente -->
            <div class="absolute inset-0 bg-gradient-to-br from-indigo-600 via-violet-600 to-purple-700" />

            <!-- Grade decorativa -->
            <div class="absolute inset-0 opacity-[0.08]" style="background-image: linear-gradient(to right, white 1px, transparent 1px), linear-gradient(to bottom, white 1px, transparent 1px); background-size: 48px 48px" />

            <!-- Orbs -->
            <div class="absolute -top-40 -left-40 h-[32rem] w-[32rem] rounded-full bg-white/10 blur-3xl pointer-events-none" />
            <div class="absolute bottom-0 right-0 h-80 w-80 rounded-full bg-violet-300/20 blur-3xl pointer-events-none" />
            <div class="absolute top-1/2 -right-20 h-64 w-64 rounded-full bg-indigo-300/10 blur-3xl pointer-events-none" />

            <!-- Conteúdo -->
            <div class="relative z-10 flex flex-col h-full p-10 xl:p-14">
                <!-- Brand -->
                <div class="flex items-center gap-3">
                    <div class="grid h-10 w-10 place-items-center rounded-xl bg-white/20 backdrop-blur-sm border border-white/20 shadow-lg">
                        <i class="pi pi-heart-fill text-white text-sm" />
                    </div>
                    <span class="text-white font-bold text-lg tracking-tight">Agência PSI</span>
                </div>

                <!-- Slides -->
                <div class="flex-1 flex flex-col justify-center">
                    <Transition name="slide-fade" mode="out-in">
                        <div :key="currentSlide" class="space-y-6">
                            <div class="grid h-16 w-16 place-items-center rounded-2xl bg-white/15 backdrop-blur-sm border border-white/20 shadow-lg">
                                <i :class="['pi', slides[currentSlide].icon, 'text-white text-2xl']" />
                            </div>

                            <div class="space-y-4">
                                <div class="text-3xl xl:text-4xl font-bold text-white leading-tight prose prose-invert prose-xl max-w-none" v-html="slides[currentSlide].title" />
                                <div class="text-base xl:text-lg text-white/70 leading-relaxed max-w-sm prose prose-invert max-w-none" v-html="slides[currentSlide].body" />
                            </div>
                        </div>
                    </Transition>
                </div>

                <!-- Dots -->
                <div class="flex items-center gap-2">
                    <button
                        v-for="(_, i) in slides"
                        :key="i"
                        class="transition-all duration-300 rounded-full focus:outline-none"
                        :class="i === currentSlide ? 'w-7 h-2 bg-white shadow' : 'w-2 h-2 bg-white/35 hover:bg-white/60'"
                        @click="goToSlide(i)"
                    />
                    <span class="ml-3 text-xs text-white/40 tabular-nums">{{ currentSlide + 1 }}/{{ slides.length }}</span>
                </div>
            </div>
        </div>

        <!-- ===== DIREITA: FORMULÁRIO ===== -->
        <div class="flex-1 lg:w-1/2 flex flex-col min-h-screen bg-[var(--surface-ground)] overflow-y-auto relative">
            <!-- Halos sutis de fundo -->
            <div class="pointer-events-none absolute inset-0">
                <div class="absolute top-10 right-10 h-64 w-64 rounded-full blur-3xl bg-indigo-400/5" />
                <div class="absolute bottom-10 left-10 h-56 w-56 rounded-full blur-3xl bg-violet-400/5" />
            </div>

            <div class="relative flex flex-col flex-1 justify-center px-6 py-10 sm:px-10 lg:px-12 xl:px-16 w-full max-w-lg mx-auto">
                <!-- Mobile: Brand -->
                <div class="flex lg:hidden items-center gap-2 mb-8">
                    <div class="grid h-8 w-8 place-items-center rounded-lg bg-indigo-500/10 border border-indigo-500/20">
                        <i class="pi pi-heart-fill text-indigo-500 text-xs" />
                    </div>
                    <span class="text-[var(--text-color)] font-bold text-base tracking-tight">Agência PSI</span>
                </div>

                <!-- Cabeçalho -->
                <div class="mb-7">
                    <h1 class="text-3xl font-bold text-[var(--text-color)] leading-tight">Bem-vindo de volta</h1>
                    <p class="mt-1.5 text-sm text-[var(--text-color-secondary)]">Entre com sua conta para continuar</p>
                </div>

                <!-- Login social (marcação — em breve) -->
                <div class="grid grid-cols-2 gap-3 mb-5">
                    <button
                        type="button"
                        disabled
                        title="Em breve"
                        class="flex items-center justify-center gap-2 rounded-xl border border-[var(--surface-border)] bg-[var(--surface-card)] px-4 py-2.5 text-sm font-medium text-[var(--text-color-secondary)] opacity-50 cursor-not-allowed"
                    >
                        <svg class="h-4 w-4 shrink-0" viewBox="0 0 24 24">
                            <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" />
                            <path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" />
                            <path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" />
                            <path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" />
                        </svg>
                        Google
                    </button>

                    <button
                        type="button"
                        disabled
                        title="Em breve"
                        class="flex items-center justify-center gap-2 rounded-xl border border-[var(--surface-border)] bg-[var(--surface-card)] px-4 py-2.5 text-sm font-medium text-[var(--text-color-secondary)] opacity-50 cursor-not-allowed"
                    >
                        <svg class="h-4 w-4 shrink-0" viewBox="0 0 24 24" fill="currentColor">
                            <path
                                d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.8-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"
                            />
                        </svg>
                        Apple
                    </button>
                </div>

                <!-- Divisor -->
                <div class="flex items-center gap-3 mb-5">
                    <div class="h-px flex-1 bg-[var(--surface-border)]" />
                    <span class="text-xs text-[var(--text-color-secondary)] font-medium whitespace-nowrap">ou continue com e-mail</span>
                    <div class="h-px flex-1 bg-[var(--surface-border)]" />
                </div>

                <!-- Formulário -->
                <form class="space-y-4" @submit.prevent="onSubmit">
                    <div>
                        <label class="block text-sm font-semibold text-[var(--text-color)] mb-1.5">E-mail</label>
                        <InputText v-model="email" class="w-full" placeholder="seuemail@dominio.com" autocomplete="email" :disabled="loading || loadingRecovery" />
                    </div>

                    <div>
                        <label class="block text-sm font-semibold text-[var(--text-color)] mb-1.5">Senha</label>
                        <Password v-model="password" placeholder="Sua senha" toggleMask :feedback="false" class="w-full" inputClass="w-full" autocomplete="current-password" :disabled="loading || loadingRecovery" />
                    </div>

                    <div class="flex items-center justify-between">
                        <div class="flex items-center gap-2">
                            <Checkbox v-model="checked" inputId="rememberme1" binary :disabled="loading || loadingRecovery" />
                            <label for="rememberme1" class="text-sm text-[var(--text-color-secondary)] cursor-pointer select-none"> Lembrar e-mail </label>
                        </div>
                        <div class="flex items-center gap-3">
                            <button type="button" class="text-sm font-medium text-[var(--text-color-secondary)] hover:text-[var(--text-color)] transition-colors" :disabled="loading || loadingRecovery" @click="openForgotEmail">Esqueci meu e-mail</button>
                            <button type="button" class="text-sm font-medium text-indigo-500 hover:text-indigo-600 transition-colors" :disabled="loading || loadingRecovery" @click="openForgot">Esqueceu a senha?</button>
                        </div>
                    </div>

                    <!-- Erro -->
                    <div v-if="authError" class="rounded-xl border border-red-200 bg-red-50 dark:border-red-900/30 dark:bg-red-950/20 px-4 py-3 text-sm text-red-600 dark:text-red-400 flex items-center gap-2">
                        <i class="pi pi-exclamation-triangle shrink-0" />
                        {{ authError }}
                    </div>

                    <Button type="submit" label="Entrar" class="w-full" icon="pi pi-sign-in" :loading="loading" :disabled="!canSubmit" />
                </form>

                <!-- Rodapé -->
                <div class="mt-8 pt-6 border-t border-[var(--surface-border)] flex flex-wrap items-center justify-between gap-3 text-xs text-[var(--text-color-secondary)]">
                    <RouterLink to="/" class="flex items-center gap-1.5 hover:text-[var(--text-color)] transition-colors">
                        <i class="pi pi-code text-[10px]" />
                        Dev logins
                    </RouterLink>

                    <RouterLink :to="{ name: 'resetPassword' }" class="flex items-center gap-1.5 hover:text-[var(--text-color)] transition-colors">
                        <span class="h-1.5 w-1.5 rounded-full bg-emerald-400 inline-block" />
                        Trocar senha
                    </RouterLink>

                    <span class="text-[var(--text-color-secondary)]/60"> Agência PSI &copy; {{ new Date().getFullYear() }} </span>
                </div>
            </div>
        </div>
    </div>

    <!-- Dialog: Recuperar acesso -->
    <Dialog v-model:visible="openRecovery" modal header="Recuperar acesso" :draggable="false" :style="{ width: '28rem', maxWidth: '92vw' }">
        <div class="space-y-3">
            <div class="text-sm text-[var(--text-color-secondary)]">Informe seu e-mail. Vamos enviar um link para redefinir sua senha.</div>

            <div class="space-y-2">
                <label class="text-sm font-semibold">E-mail</label>
                <InputText v-model="recoveryEmail" class="w-full" placeholder="seuemail@dominio.com" :disabled="loadingRecovery" />
            </div>

            <div class="flex flex-col gap-2 sm:flex-row sm:justify-end pt-2">
                <Button label="Cancelar" severity="secondary" outlined :disabled="loadingRecovery" @click="openRecovery = false" />
                <Button label="Enviar link" icon="pi pi-envelope" :loading="loadingRecovery" @click="sendRecoveryEmail" />
            </div>

            <div v-if="recoverySent" class="rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] p-3 text-xs text-[var(--text-color-secondary)]">
                <i class="pi pi-check mr-2 text-emerald-500" />
                Se o e-mail existir, você receberá o link em instantes. Verifique também spam/lixo eletrônico.
            </div>
        </div>
    </Dialog>

    <!-- Dialog: Esqueci meu e-mail (recupera por slug) -->
    <Dialog v-model:visible="openRecoverEmail" modal header="Esqueci meu e-mail" :draggable="false" :style="{ width: '28rem', maxWidth: '92vw' }">
        <div class="space-y-3">
            <div class="text-sm text-[var(--text-color-secondary)]">Informe o <b>identificador</b> do seu ambiente (aquele que você escolheu no cadastro). Enviamos um link de acesso pro e-mail do dono.</div>

            <div class="space-y-2">
                <label class="text-sm font-semibold">Identificador</label>
                <InputText v-model="recoverSlug" class="w-full" placeholder="meu_consultorio" :disabled="loadingRecoverEmail" @keydown.enter.prevent="recoverEmailBySlug" />
            </div>

            <div class="flex flex-col gap-2 sm:flex-row sm:justify-end pt-2">
                <Button label="Cancelar" severity="secondary" outlined :disabled="loadingRecoverEmail" @click="openRecoverEmail = false" />
                <Button label="Enviar link de acesso" icon="pi pi-envelope" :loading="loadingRecoverEmail" @click="recoverEmailBySlug" />
            </div>

            <div v-if="recoverDone" class="rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] p-3 text-xs text-[var(--text-color-secondary)]">
                <i class="pi pi-check mr-2 text-emerald-500" />
                Enviamos um link de acesso para <b>{{ recoverHint }}</b>. Abra o e-mail e clique no link pra entrar.
            </div>
        </div>
    </Dialog>
</template>

<style scoped>
.slide-fade-enter-active,
.slide-fade-leave-active {
    transition:
        opacity 0.4s ease,
        transform 0.4s ease;
}

.slide-fade-enter-from {
    opacity: 0;
    transform: translateY(18px);
}

.slide-fade-leave-to {
    opacity: 0;
    transform: translateY(-12px);
}
</style>
