<!--
|--------------------------------------------------------------------------
| Agência PSI — Drawer global de conversa
|--------------------------------------------------------------------------
| Uso: <ConversationDrawer /> no AppLayout. Controlado via store:
|   const store = useConversationDrawerStore();
|   store.openForPatient(patientId);
|   store.openForThread(thread);
|--------------------------------------------------------------------------
-->
<script setup>
import { ref, computed, nextTick, watch, onMounted, onBeforeUnmount } from 'vue';
import { useToast } from 'primevue/usetoast';
import { useConfirm } from 'primevue/useconfirm';
import { useConversationDrawerStore } from '@/stores/conversationDrawerStore';
import { useConversationNotes } from '@/composables/useConversationNotes';
import { useConversationTags } from '@/composables/useConversationTags';
import { useConversationAssignment } from '@/composables/useConversationAssignment';
import { supabase } from '@/lib/supabase/client';
import ComponentCadastroRapido from '@/components/ComponentCadastroRapido.vue';

const toast = useToast();
const confirm = useConfirm();
const store = useConversationDrawerStore();
const notesApi = useConversationNotes();
const tagsApi = useConversationTags();
const assignApi = useConversationAssignment();
const tagsPopover = ref(null);

// ── Current user (pra saber se pode editar/deletar notas próprias) ────
const currentUserId = ref(null);
supabase.auth.getUser().then(({ data }) => { currentUserId.value = data?.user?.id ?? null; });

// ── Notas internas ────────────────────────────────────────────
const notesOpen = ref(false);
const newNoteText = ref('');
const editingNoteId = ref(null);
const editingText = ref('');

// ── Converter número desconhecido em paciente (CRM 3.5) ────
const quickPatientDialog = ref(false);
const linkPatientDialog = ref(false);
const linkPatientOptions = ref([]);
const linkPatientLoading = ref(false);
const linkPatientSelected = ref(null);
const linkingPatient = ref(false);

// Strip "55" DDI prefix se tiver (InputMask espera 10-11 dígitos BR)
function phoneForForm(raw) {
    const d = String(raw || '').replace(/\D/g, '');
    if (d.length === 13 && d.startsWith('55')) return d.slice(2);
    if (d.length === 12 && d.startsWith('55')) return d.slice(2);
    return d;
}

function openConvertToPatient() {
    quickPatientDialog.value = true;
}

function openLinkPatient() {
    linkPatientSelected.value = null;
    linkPatientDialog.value = true;
    loadPatients();
}

async function loadPatients() {
    const tenantId = store.thread?.tenant_id;
    if (!tenantId) return;
    linkPatientLoading.value = true;
    try {
        // Carrega todos os pacientes do tenant (até 500) — filter é client-side
        const { data, error } = await supabase
            .from('patients')
            .select('id, nome_completo, telefone, email_principal, status')
            .eq('tenant_id', tenantId)
            .order('nome_completo', { ascending: true })
            .limit(500);
        if (error) throw error;
        // Formata label combinado pra filter achar
        linkPatientOptions.value = (data || []).map((p) => ({
            ...p,
            _label: `${p.nome_completo}${p.telefone ? ' · ' + formatPhoneShort(p.telefone) : ''}${p.email_principal ? ' · ' + p.email_principal : ''}`
        }));
    } catch (e) {
        console.error('[ConversationDrawer] load patients:', e?.message);
        linkPatientOptions.value = [];
        toast.add({ severity: 'error', summary: 'Erro', detail: 'Falha ao carregar pacientes: ' + e?.message, life: 4000 });
    } finally {
        linkPatientLoading.value = false;
    }
}

async function confirmLinkPatient() {
    const patient = linkPatientSelected.value;
    if (!patient?.id || !store.thread?.contact_number) return;
    linkingPatient.value = true;
    try {
        const phone = store.thread.contact_number;
        const tenantId = store.thread.tenant_id;

        // 1) Vincula conversation_messages
        const { error } = await supabase
            .from('conversation_messages')
            .update({ patient_id: patient.id })
            .or(`from_number.eq.${phone},to_number.eq.${phone}`)
            .is('patient_id', null);
        if (error) throw error;

        // 2) Adiciona telefone WhatsApp no contact_phones (se não existir ainda)
        await upsertWhatsappForExisting(tenantId, patient.id, phone);

        store.thread.patient_id = patient.id;
        store.thread.patient_name = patient.nome_completo;
        store.thread.thread_key = patient.id;
        for (const m of store.messages) {
            if (!m.patient_id) m.patient_id = patient.id;
        }
        linkPatientDialog.value = false;
        toast.add({
            severity: 'success',
            summary: 'Conversa vinculada',
            detail: `${patient.nome_completo} agora está ligado a essa conversa. Número salvo como WhatsApp (vinculado).`,
            life: 3500
        });
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro ao vincular', detail: e?.message, life: 4000 });
    } finally {
        linkingPatient.value = false;
    }
}

// Helper: adiciona telefone WhatsApp (vinculado) ao paciente existente.
// Se já tem um telefone com o mesmo número, só marca como vinculado em vez de duplicar.
async function upsertWhatsappForExisting(tenantId, patientId, threadPhone) {
    if (!tenantId || !patientId || !threadPhone) return;
    try {
        const phoneDigits = String(threadPhone).replace(/\D/g, '');

        // Busca se já tem esse número cadastrado
        const { data: existing } = await supabase
            .from('contact_phones')
            .select('id, contact_type_id, whatsapp_linked_at')
            .eq('entity_type', 'patient')
            .eq('entity_id', patientId)
            .eq('number', phoneDigits)
            .limit(1)
            .maybeSingle();

        if (existing) {
            // Atualiza vinculado_at se ainda não tinha
            if (!existing.whatsapp_linked_at) {
                await supabase
                    .from('contact_phones')
                    .update({ whatsapp_linked_at: new Date().toISOString() })
                    .eq('id', existing.id);
            }
            return;
        }

        // Não tem — cria novo com type='whatsapp'
        const { data: types } = await supabase
            .from('contact_types')
            .select('id, slug')
            .is('tenant_id', null)
            .eq('slug', 'whatsapp')
            .maybeSingle();
        const whatsappTypeId = types?.id;
        if (!whatsappTypeId) return;

        await supabase.from('contact_phones').insert({
            tenant_id: tenantId,
            entity_type: 'patient',
            entity_id: patientId,
            contact_type_id: whatsappTypeId,
            number: phoneDigits,
            is_primary: false,
            whatsapp_linked_at: new Date().toISOString(),
            position: 100
        });
    } catch (e) {
        console.warn('[ConversationDrawer] upsert whatsapp contact_phones:', e?.message);
    }
}

function formatPhoneShort(p) {
    const s = String(p || '').replace(/\D/g, '');
    if (s.length === 11) return `(${s.slice(0, 2)}) ${s.slice(2, 7)}-${s.slice(7)}`;
    if (s.length === 10) return `(${s.slice(0, 2)}) ${s.slice(2, 6)}-${s.slice(6)}`;
    if (s.length === 13 && s.startsWith('55')) return `(${s.slice(2, 4)}) ${s.slice(4, 9)}-${s.slice(9)}`;
    return p;
}

// Após criar paciente: vincula conversation_messages + registra telefone WhatsApp em contact_phones
async function onPatientCreated(row) {
    const newPatientId = row?.id;
    const phone = store.thread?.contact_number;
    const tenantId = store.thread?.tenant_id;
    if (!newPatientId || !phone) {
        toast.add({ severity: 'warn', summary: 'Paciente criado', detail: 'Mas não foi possível vincular a conversa. Recarregue.', life: 4000 });
        return;
    }
    try {
        // 1) Vincula TODAS as mensagens do thread (anon) a esse patient_id
        const { error: msgErr } = await supabase
            .from('conversation_messages')
            .update({ patient_id: newPatientId })
            .or(`from_number.eq.${phone},to_number.eq.${phone}`)
            .is('patient_id', null);
        if (msgErr) throw msgErr;

        // 2) Insere telefone WhatsApp em contact_phones (se ainda não tem)
        //    O Celular primary já foi criado pelo trigger quando cadastrou via ComponentCadastroRapido? NÃO.
        //    ComponentCadastroRapido insere em patients.telefone direto. Vou adicionar contact_phones AGORA.
        await insertWhatsappContactPhone(tenantId, newPatientId, phone, row.telefone);

        // 3) Atualiza o store localmente (thread_key vai mudar pra UUID)
        store.thread.patient_id = newPatientId;
        store.thread.patient_name = row.nome_completo || row.nome || null;
        store.thread.thread_key = newPatientId;
        for (const m of store.messages) {
            if (!m.patient_id) m.patient_id = newPatientId;
        }
        toast.add({
            severity: 'success',
            summary: 'Paciente criado e vinculado',
            detail: `${store.thread.patient_name} agora está ligado a essa conversa.`,
            life: 3500
        });
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro ao vincular', detail: e?.message || 'Falha ao atualizar mensagens', life: 4000 });
    }
}

// Helper: insere entries em contact_phones pra novo paciente criado via ComponentCadastroRapido.
// 1) Celular (primary) = telefone do form (se tiver, já diferente do whatsapp)
// 2) WhatsApp com whatsapp_linked_at = phone da thread (se não for igual ao celular)
async function insertWhatsappContactPhone(tenantId, patientId, threadPhone, formPhone) {
    if (!tenantId || !patientId || !threadPhone) return;
    try {
        // Busca tipos system
        const { data: types } = await supabase
            .from('contact_types')
            .select('id, slug')
            .is('tenant_id', null);
        const celularType = types?.find((t) => t.slug === 'celular');
        const whatsappType = types?.find((t) => t.slug === 'whatsapp');

        const phoneDigits = String(threadPhone).replace(/\D/g, '');
        const formDigits = String(formPhone || '').replace(/\D/g, '');
        // formPhone vem do quick create sem DDI (10-11 dig); threadPhone com DDI (13 dig).
        // Normaliza: remove DDI 55 pra comparar
        const formNoDdi = formDigits.length >= 12 && formDigits.startsWith('55') ? formDigits.slice(2) : formDigits;
        const threadNoDdi = phoneDigits.length >= 12 && phoneDigits.startsWith('55') ? phoneDigits.slice(2) : phoneDigits;

        const rows = [];

        // Celular primary (from form — o que o user digitou no cadastro rápido)
        if (celularType && formDigits && formDigits.length >= 8) {
            rows.push({
                tenant_id: tenantId,
                entity_type: 'patient',
                entity_id: patientId,
                contact_type_id: celularType.id,
                number: formDigits.length < 12 ? '55' + formDigits : formDigits, // garante DDI
                is_primary: true,
                position: 10
            });
        }

        // WhatsApp linked (from thread) — só se diferente do celular
        if (whatsappType && phoneDigits && formNoDdi !== threadNoDdi) {
            rows.push({
                tenant_id: tenantId,
                entity_type: 'patient',
                entity_id: patientId,
                contact_type_id: whatsappType.id,
                number: phoneDigits,
                is_primary: false,
                whatsapp_linked_at: new Date().toISOString(),
                position: 20
            });
        } else if (whatsappType && phoneDigits && formNoDdi === threadNoDdi && rows.length > 0) {
            // Mesmo número → marca o celular como também vinculado WhatsApp
            rows[0].whatsapp_linked_at = new Date().toISOString();
        }

        if (rows.length > 0) {
            await supabase.from('contact_phones').insert(rows);
        }
    } catch (e) {
        console.warn('[ConversationDrawer] insert whatsapp contact_phones:', e?.message);
        // Não bloqueia o fluxo — paciente já foi criado
    }
}

// ── Resolução de URLs de mídia ─────────────────────────────
// Mensagens de WhatsApp vêm com media_url em dois formatos:
//  1) URL externa (http/https) — Twilio e outras; usa direto
//  2) Path interno do bucket privado whatsapp-media — precisa signed URL
const mediaUrls = ref({}); // { [msgId]: resolvedUrl }

async function ensureMediaUrl(m) {
    if (!m?.id || !m.media_url) return;
    if (mediaUrls.value[m.id]) return;
    const raw = m.media_url;
    if (/^https?:\/\//i.test(raw)) {
        mediaUrls.value[m.id] = raw;
        return;
    }
    // Path interno — gera signed URL (expira em 1h, re-resolvido ao reabrir drawer)
    const { data, error } = await supabase.storage.from('whatsapp-media').createSignedUrl(raw, 3600);
    if (error) {
        console.error('[ConversationDrawer] signed URL error:', error.message);
        mediaUrls.value[m.id] = null;
        return;
    }
    mediaUrls.value[m.id] = data?.signedUrl || null;
}

const composeText = ref('');
const composeTextareaRef = ref(null);
const messagesContainerRef = ref(null);
const templatesPopover = ref(null);
const emojiPopover = ref(null);

const isOpen = computed({
    get: () => store.isOpen,
    set: (v) => { if (!v) store.close(); }
});

const KANBAN_COLUMNS = [
    { key: 'urgent', label: 'Urgente', icon: 'pi pi-exclamation-triangle' },
    { key: 'awaiting_us', label: 'Aguardando resposta', icon: 'pi pi-inbox' },
    { key: 'awaiting_patient', label: 'Aguardando paciente', icon: 'pi pi-hourglass' },
    { key: 'resolved', label: 'Resolvido', icon: 'pi pi-check' }
];

// ── Formatters ─────────────────────────────────────────────
function fmtDateTime(iso) {
    if (!iso) return '';
    return new Date(iso).toLocaleString('pt-BR', {
        day: '2-digit', month: '2-digit', year: 'numeric',
        hour: '2-digit', minute: '2-digit'
    });
}

function channelIcon(ch) {
    const map = { whatsapp: 'pi-whatsapp', sms: 'pi-comment', email: 'pi-envelope' };
    return map[ch] || 'pi-comment';
}

function isImage(mime) { return !!mime && mime.startsWith('image/'); }
function isAudio(mime) { return !!mime && mime.startsWith('audio/'); }
function isVideo(mime) { return !!mime && mime.startsWith('video/'); }

function contactLabel() {
    return store.thread?.patient_name || store.thread?.contact_number || 'Desconhecido';
}

function whatsappLink() {
    const num = (store.thread?.contact_number || '').replace(/\D/g, '');
    if (!num) return '';
    return `https://wa.me/${num}`;
}

// ── Auto-scroll ────────────────────────────────────────────
function scrollToBottom() {
    nextTick(() => {
        const el = messagesContainerRef.value;
        if (el) el.scrollTop = el.scrollHeight;
    });
}

watch(() => store.messages.length, () => {
    if (store.isOpen) scrollToBottom();
    // Resolve URLs de novas mensagens com mídia
    for (const m of store.messages) {
        if (m.media_url && !mediaUrls.value[m.id]) ensureMediaUrl(m);
    }
});
watch(() => store.isOpen, (open) => {
    if (open) {
        composeText.value = '';
        scrollToBottom();
        // Re-resolve URLs ao abrir (signed URLs podem ter expirado)
        mediaUrls.value = {};
        for (const m of store.messages) {
            if (m.media_url) ensureMediaUrl(m);
        }
        // Carrega notas, tags e atribuição da thread
        if (store.thread?.thread_key) {
            notesApi.load(store.thread.thread_key);
            tagsApi.loadAllTags();
            tagsApi.loadForThread(store.thread.thread_key);
            assignApi.loadMembers().then(() => assignApi.load(store.thread.thread_key));
        }
    } else {
        notesApi.clear();
        tagsApi.clear();
        assignApi.clear();
        notesOpen.value = false;
        editingNoteId.value = null;
    }
});

// Recarrega notas + tags + atribuição ao trocar de thread sem fechar drawer
watch(() => store.thread?.thread_key, (key) => {
    if (key && store.isOpen) {
        notesApi.load(key);
        tagsApi.loadForThread(key);
        assignApi.load(key);
    }
});

// ── Handlers de atribuição ──────────────────────────────────
async function onAssignChange(newUserId) {
    if (!store.thread?.thread_key) return;
    const res = await assignApi.assign({
        threadKey: store.thread.thread_key,
        patientId: store.thread.patient_id || null,
        contactNumber: store.thread.contact_number || null,
        assignedTo: newUserId || null
    });
    if (res.ok) {
        toast.add({
            severity: 'success',
            summary: newUserId ? 'Conversa atribuída' : 'Atribuição removida',
            life: 2000
        });
    } else {
        toast.add({ severity: 'error', summary: 'Erro', detail: res.error || 'Falha ao atribuir', life: 3500 });
    }
}

async function assignToMe() {
    const uid = currentUserId.value;
    if (!uid) return;
    await onAssignChange(uid);
}

// ── Handlers de tags ────────────────────────────────────────
function openTagsPopover(ev) {
    tagsPopover.value?.toggle(ev);
}

async function onToggleTag(tagId) {
    if (!store.thread?.thread_key) return;
    const res = await tagsApi.toggleOnThread(store.thread.thread_key, tagId);
    if (!res.ok) {
        toast.add({ severity: 'error', summary: 'Erro', detail: res.error || 'Falha ao atualizar tag', life: 3500 });
    }
}

// ── Handlers de notas ─────────────────────────────────────────
async function addNote() {
    const text = newNoteText.value.trim();
    if (!text || !store.thread) return;
    const res = await notesApi.create({
        threadKey: store.thread.thread_key,
        patientId: store.thread.patient_id || null,
        contactNumber: store.thread.contact_number || null,
        body: text
    });
    if (res.ok) {
        newNoteText.value = '';
        toast.add({ severity: 'success', summary: 'Nota adicionada', life: 1800 });
    } else {
        toast.add({ severity: 'error', summary: 'Erro', detail: res.error || 'Falha ao salvar nota', life: 3500 });
    }
}

function startEditNote(note) {
    editingNoteId.value = note.id;
    editingText.value = note.body;
}

function cancelEditNote() {
    editingNoteId.value = null;
    editingText.value = '';
}

async function saveEditNote(id) {
    const res = await notesApi.update(id, editingText.value);
    if (res.ok) {
        editingNoteId.value = null;
        editingText.value = '';
        toast.add({ severity: 'success', summary: 'Nota atualizada', life: 1800 });
    } else {
        toast.add({ severity: 'error', summary: 'Erro', detail: res.error || 'Falha ao atualizar', life: 3500 });
    }
}

function confirmDeleteNote(id) {
    confirm.require({
        group: 'conversation-drawer',
        message: 'Remover esta nota? Essa ação não pode ser desfeita.',
        header: 'Remover nota',
        icon: 'pi pi-exclamation-triangle',
        acceptLabel: 'Remover',
        rejectLabel: 'Cancelar',
        acceptClass: 'p-button-danger',
        accept: async () => {
            const res = await notesApi.remove(id);
            if (res.ok) {
                toast.add({ severity: 'success', summary: 'Nota removida', life: 1800 });
            } else {
                toast.add({ severity: 'error', summary: 'Erro', detail: res.error, life: 3500 });
            }
        }
    });
}

function fmtNoteDate(iso) {
    if (!iso) return '';
    const d = new Date(iso);
    const today = new Date();
    const isToday = d.toDateString() === today.toDateString();
    if (isToday) {
        return 'Hoje, ' + d.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' });
    }
    return d.toLocaleString('pt-BR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });
}

// ── Injeta botão de download no toolbar do <Image preview> ────
// PrimeVue Image não expõe slot pra adicionar buttons no preview,
// então observamos o DOM: quando o toolbar aparece, inserimos o botão.
let _toolbarObserver = null;

function triggerImageDownload(src) {
    if (!src) return;
    // Fetch + blob pra forçar download (atributo 'download' não funciona cross-origin)
    fetch(src)
        .then((r) => r.blob())
        .then((blob) => {
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            // Extrai nome do arquivo da URL (último segmento antes de ?)
            const filename = (src.split('?')[0].split('/').pop() || 'imagem').slice(0, 120);
            a.download = filename;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        })
        .catch((err) => {
            console.error('[ConversationDrawer] download error:', err);
            toast.add({ severity: 'error', summary: 'Erro', detail: 'Falha ao baixar imagem.', life: 3500 });
        });
}

function injectDownloadButton(toolbar) {
    if (!toolbar || toolbar.querySelector('[data-download-btn]')) return;
    const btn = document.createElement('button');
    btn.type = 'button';
    btn.setAttribute('aria-label', 'Baixar imagem');
    btn.setAttribute('data-download-btn', '1');
    btn.setAttribute('data-pc-group-section', 'action');
    // Herda a classe p-image-closeButton pra pegar o mesmo styling do toolbar
    btn.className = 'p-image-close-button';
    btn.innerHTML = '<span class="pi pi-download" style="font-size: 1rem;"></span>';
    btn.addEventListener('click', (e) => {
        e.stopPropagation();
        // Escopa o lookup ao mask específico deste botão (seguro se houver múltiplos previews)
        const mask = btn.closest('.p-image-mask');
        const img = mask?.querySelector('img.p-image-original, img')
            ?? document.querySelector('.p-image-original');
        triggerImageDownload(img?.src);
    });
    // Insere antes do close (último)
    const closeBtn = toolbar.querySelector('[aria-label*="lose" i]') || toolbar.lastElementChild;
    toolbar.insertBefore(btn, closeBtn);
}

onMounted(() => {
    _toolbarObserver = new MutationObserver((mutations) => {
        for (const m of mutations) {
            for (const node of m.addedNodes) {
                if (!(node instanceof HTMLElement)) continue;
                const toolbar = node.matches?.('.p-image-toolbar') ? node : node.querySelector?.('.p-image-toolbar');
                if (toolbar) injectDownloadButton(toolbar);
            }
        }
    });
    _toolbarObserver.observe(document.body, { childList: true, subtree: true });
});

onBeforeUnmount(() => {
    _toolbarObserver?.disconnect();
    _toolbarObserver = null;
});

// ── Compose ────────────────────────────────────────────────
async function sendMessage() {
    const text = composeText.value.trim();
    if (!text) return;
    const result = await store.sendMessage(text);
    if (result.ok) {
        composeText.value = '';
        toast.add({ severity: 'success', summary: 'Mensagem enviada', life: 2000 });
    } else {
        toast.add({ severity: 'error', summary: 'Falha ao enviar', detail: result.error, life: 5000 });
    }
}

function onComposeKeydown(e) {
    if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();
        sendMessage();
    }
}

async function onMoveTo(newStatus) {
    try {
        await store.setKanbanStatus(newStatus);
        const label = KANBAN_COLUMNS.find(c => c.key === newStatus)?.label;
        toast.add({ severity: 'success', summary: 'Movido', detail: `Conversa movida para ${label}.`, life: 2000 });
    } catch (err) {
        toast.add({ severity: 'error', summary: 'Erro', detail: err?.message || 'Falha ao mover.', life: 4000 });
    }
}

// ── Templates ──────────────────────────────────────────────
function templateFriendlyLabel(key) {
    const map = {
        'session.lembrete': 'Lembrete de sessão (24h antes)',
        'session.lembrete_2h': 'Lembrete de sessão (2h antes)',
        'session.confirmacao': 'Confirmação de agendamento',
        'session.cancelamento': 'Sessão cancelada',
        'session.reagendamento': 'Sessão reagendada',
        'cobranca.pendente': 'Cobrança pendente',
        'sistema.boas_vindas': 'Boas-vindas ao paciente'
    };
    const stripped = key.replace('.whatsapp', '');
    const prefix = stripped.split('.').slice(0, 2).join('.');
    return map[prefix] || stripped;
}

async function applyTemplate(tpl) {
    const { text, missing } = await store.resolveTemplate(tpl);
    composeText.value = composeText.value ? composeText.value + '\n' + text : text;
    templatesPopover.value?.hide();
    nextTick(() => {
        const el = composeTextareaRef.value?.$el?.querySelector('textarea') ?? null;
        if (el?.focus) el.focus();
    });
    if (missing.length) {
        toast.add({
            severity: 'warn',
            summary: 'Variáveis sem valor',
            detail: `Não consegui preencher: ${missing.join(', ')}. Edita a mensagem antes de enviar.`,
            life: 5000
        });
    }
}

function openTemplatesPopover(ev) {
    if (!store.templatesLoaded) store.loadTemplates();
    templatesPopover.value?.toggle(ev);
}

// ── Emoji ──────────────────────────────────────────────────
const emojiList = [
    '😀','😃','😄','😁','😆','😅','🤣','😂','🙂','🙃','😉','😊',
    '😍','🥰','😘','😗','😙','😚','😋','😛','😜','🤪','😝','🤗',
    '🤔','🤨','😐','😑','😶','🙄','😏','😒','😔','😪','🤤','😴',
    '😎','🤓','🧐','🤯','😳','🥵','🥶','😱','😨','😰','😥','😓',
    '👍','👎','👌','✌️','🤞','🤟','🤘','👈','👉','👆','🖕','👇',
    '👋','🙌','👏','🤝','🙏','💪','🫶','❤️','🧡','💛','💚','💙',
    '💜','🖤','🤍','🤎','💔','❣️','💕','💞','💓','💗','💖','💘',
    '✨','⭐','🌟','💫','⚡','🔥','💯','✅','❌','⚠️','💬','💭'
];

function toggleEmojiPopover(ev) {
    emojiPopover.value?.toggle(ev);
}

function insertEmoji(emoji) {
    const el = composeTextareaRef.value?.$el?.querySelector('textarea') ?? null;
    if (el && typeof el.selectionStart === 'number') {
        const start = el.selectionStart;
        const end = el.selectionEnd;
        const before = composeText.value.slice(0, start);
        const after = composeText.value.slice(end);
        composeText.value = before + emoji + after;
        nextTick(() => {
            el.focus();
            const pos = start + emoji.length;
            el.setSelectionRange(pos, pos);
        });
    } else {
        composeText.value += emoji;
    }
}
</script>

<template>
    <!-- group="conversation-drawer" isola esse confirm das páginas (evita 2x modal). -->
    <ConfirmDialog group="conversation-drawer" />
    <Drawer v-model:visible="isOpen" position="right" class="!w-full md:!w-[520px]">
        <template #header>
            <div v-if="store.thread" class="flex items-center gap-2">
                <i :class="['pi', channelIcon(store.thread.channel)]" />
                <div class="flex flex-col">
                    <span class="font-semibold">{{ contactLabel() }}</span>
                    <span v-if="store.thread.contact_number" class="text-xs text-[var(--text-color-secondary)]">{{ store.thread.contact_number }}</span>
                </div>
            </div>
        </template>

        <div v-if="store.thread" class="flex flex-col gap-3 h-full">
            <!-- Ações: responder no WhatsApp Web + converter em paciente -->
            <div class="flex items-center gap-1.5 flex-wrap border-b border-[var(--surface-border)] pb-3">
                <a v-if="whatsappLink()" :href="whatsappLink()" target="_blank" rel="noopener">
                    <Button label="Abrir no WhatsApp Web" icon="pi pi-external-link" severity="secondary" outlined size="small" />
                </a>
                <template v-if="!store.thread.patient_id && store.thread.contact_number">
                    <Button
                        label="Novo paciente"
                        icon="pi pi-user-plus"
                        severity="primary"
                        size="small"
                        class="rounded-full"
                        v-tooltip.top="'Cadastra este número como novo paciente e vincula a conversa'"
                        @click="openConvertToPatient"
                    />
                    <Button
                        label="Vincular existente"
                        icon="pi pi-link"
                        severity="secondary"
                        outlined
                        size="small"
                        class="rounded-full"
                        v-tooltip.top="'Liga essa conversa a um paciente já cadastrado'"
                        @click="openLinkPatient"
                    />
                </template>
            </div>

            <!-- Cadastro rápido pré-preenchido com telefone da thread -->
            <ComponentCadastroRapido
                v-model="quickPatientDialog"
                title="Cadastrar novo paciente"
                :initial-data="{
                    nome_completo: store.thread.patient_name || '',
                    telefone: phoneForForm(store.thread.contact_number)
                }"
                @created="onPatientCreated"
            />

            <!-- Dialog: vincular a paciente existente -->
            <Dialog
                v-model:visible="linkPatientDialog"
                header="Vincular a paciente existente"
                modal
                :style="{ width: 'min(480px, 95vw)' }"
            >
                <div class="flex flex-col gap-3">
                    <div class="text-xs text-[var(--text-color-secondary)]">
                        Escolha ou busque um paciente pra vincular ao número
                        <strong class="font-mono">{{ formatPhoneShort(store.thread?.contact_number) }}</strong>.
                    </div>

                    <Select
                        v-model="linkPatientSelected"
                        :options="linkPatientOptions"
                        optionLabel="_label"
                        :filter="true"
                        filterPlaceholder="Buscar por nome, telefone ou email…"
                        :filterFields="['nome_completo', 'telefone', 'email_principal', '_label']"
                        placeholder="Selecione um paciente"
                        :loading="linkPatientLoading"
                        class="w-full"
                        :emptyFilterMessage="'Nenhum paciente encontrado'"
                        :emptyMessage="'Nenhum paciente cadastrado ainda'"
                        appendTo="body"
                    >
                        <template #value="slotProps">
                            <div v-if="slotProps.value" class="flex items-center gap-2">
                                <div class="w-7 h-7 rounded-full grid place-items-center bg-indigo-500/10 text-indigo-500 font-bold text-[0.65rem] shrink-0">
                                    {{ (slotProps.value.nome_completo || '?').slice(0, 2).toUpperCase() }}
                                </div>
                                <div class="flex-1 min-w-0 text-sm">
                                    <div class="font-semibold truncate">{{ slotProps.value.nome_completo }}</div>
                                    <div v-if="slotProps.value.telefone" class="text-[0.68rem] text-[var(--text-color-secondary)] font-mono">{{ formatPhoneShort(slotProps.value.telefone) }}</div>
                                </div>
                            </div>
                            <span v-else class="text-[var(--text-color-secondary)]">{{ slotProps.placeholder }}</span>
                        </template>

                        <template #option="slotProps">
                            <div class="flex items-center gap-2 w-full">
                                <div class="w-8 h-8 rounded-full grid place-items-center bg-indigo-500/10 text-indigo-500 font-bold text-xs shrink-0">
                                    {{ (slotProps.option.nome_completo || '?').slice(0, 2).toUpperCase() }}
                                </div>
                                <div class="flex-1 min-w-0">
                                    <div class="text-sm font-semibold truncate">{{ slotProps.option.nome_completo }}</div>
                                    <div class="text-[0.68rem] text-[var(--text-color-secondary)] flex items-center gap-1.5">
                                        <span v-if="slotProps.option.telefone" class="font-mono">{{ formatPhoneShort(slotProps.option.telefone) }}</span>
                                        <span v-if="slotProps.option.email_principal" class="truncate">· {{ slotProps.option.email_principal }}</span>
                                    </div>
                                </div>
                            </div>
                        </template>
                    </Select>
                </div>

                <template #footer>
                    <Button label="Cancelar" severity="secondary" text :disabled="linkingPatient" @click="linkPatientDialog = false" />
                    <Button
                        label="Vincular"
                        icon="pi pi-link"
                        :loading="linkingPatient"
                        :disabled="!linkPatientSelected"
                        @click="confirmLinkPatient"
                    />
                </template>
            </Dialog>

            <!-- Mover entre colunas Kanban -->
            <div class="flex items-center gap-1.5 flex-wrap">
                <span class="text-xs text-[var(--text-color-secondary)]">Mover pra:</span>
                <Button
                    v-for="col in KANBAN_COLUMNS"
                    :key="col.key"
                    :label="col.label"
                    :icon="col.icon"
                    size="small"
                    :severity="store.thread.kanban_status === col.key ? 'primary' : 'secondary'"
                    :outlined="store.thread.kanban_status !== col.key"
                    :disabled="store.thread.kanban_status === col.key"
                    @click="onMoveTo(col.key)"
                />
            </div>

            <!-- Tags da thread -->
            <div class="flex items-center gap-1.5 flex-wrap">
                <span class="text-xs text-[var(--text-color-secondary)] shrink-0">Tags:</span>
                <span
                    v-for="t in tagsApi.threadTags.value"
                    :key="t.id"
                    class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[0.7rem] font-semibold cursor-pointer hover:opacity-80 transition-opacity"
                    :style="{
                        background: t.color + '20',
                        color: t.color,
                        border: `1px solid ${t.color}40`
                    }"
                    @click="onToggleTag(t.id)"
                    v-tooltip.top="'Clique para remover'"
                >
                    <i v-if="t.icon" :class="t.icon" class="text-[0.65rem]" />
                    {{ t.name }}
                    <i class="pi pi-times text-[0.6rem] opacity-60" />
                </span>
                <Button
                    icon="pi pi-plus"
                    severity="secondary"
                    outlined
                    size="small"
                    class="h-6 w-6 rounded-full"
                    v-tooltip.top="'Adicionar tag'"
                    :loading="tagsApi.saving.value"
                    @click="openTagsPopover"
                />
            </div>

            <!-- Popover de seleção de tags -->
            <Popover ref="tagsPopover" class="!w-[260px]">
                <div class="flex flex-col gap-0.5">
                    <div class="px-2 pb-1 text-[0.65rem] font-bold uppercase text-[var(--text-color-secondary)] opacity-65">
                        Selecione tags
                    </div>
                    <div v-if="tagsApi.loading.value" class="text-xs text-center py-3 text-[var(--text-color-secondary)]">
                        <i class="pi pi-spin pi-spinner mr-1" /> Carregando…
                    </div>
                    <div v-else-if="!tagsApi.allTags.value.length" class="text-xs text-center py-3 italic text-[var(--text-color-secondary)]">
                        Nenhuma tag disponível.
                    </div>
                    <button
                        v-else
                        v-for="t in tagsApi.allTags.value"
                        :key="t.id"
                        class="flex items-center gap-2 px-2 py-1.5 rounded-md text-sm text-left bg-transparent border-0 cursor-pointer hover:bg-[var(--surface-hover)] transition-colors"
                        @click="onToggleTag(t.id)"
                    >
                        <span
                            class="inline-block w-3 h-3 rounded-full shrink-0"
                            :style="{ background: t.color }"
                        />
                        <i v-if="t.icon" :class="t.icon" class="text-xs opacity-70 shrink-0" />
                        <span class="flex-1 truncate">{{ t.name }}</span>
                        <i v-if="tagsApi.threadTagIds.value.has(t.id)" class="pi pi-check text-xs text-[var(--primary-color)] shrink-0" />
                    </button>
                </div>
            </Popover>

            <!-- Atribuição da conversa -->
            <div class="flex items-center gap-1.5 flex-wrap">
                <span class="text-xs text-[var(--text-color-secondary)] shrink-0">Atribuída a:</span>
                <Select
                    :modelValue="assignApi.assignment.value?.assigned_to || null"
                    :options="assignApi.members.value"
                    optionLabel="label"
                    optionValue="user_id"
                    placeholder="Ninguém"
                    filter
                    showClear
                    size="small"
                    class="!min-w-[220px]"
                    :loading="assignApi.loading.value || assignApi.saving.value"
                    @update:modelValue="onAssignChange"
                />
                <Button
                    v-if="currentUserId && assignApi.assignment.value?.assigned_to !== currentUserId"
                    label="Assumir"
                    icon="pi pi-user-plus"
                    size="small"
                    severity="secondary"
                    outlined
                    class="rounded-full"
                    :loading="assignApi.saving.value"
                    v-tooltip.top="'Atribuir essa conversa a mim'"
                    @click="assignToMe"
                />
                <span
                    v-if="assignApi.assignment.value?.assigned_to"
                    class="text-[0.68rem] text-[var(--text-color-secondary)] italic"
                >
                    desde {{ fmtNoteDate(assignApi.assignment.value.assigned_at) }}
                </span>
            </div>

            <!-- Notas internas -->
            <div class="border border-[var(--surface-border)] rounded-md bg-[var(--surface-ground)]">
                <button
                    class="w-full flex items-center gap-2 px-3 py-2 text-left bg-transparent border-0 cursor-pointer hover:bg-[var(--surface-hover)] rounded-md transition-colors"
                    @click="notesOpen = !notesOpen"
                >
                    <i class="pi pi-file-edit text-[var(--primary-color)]" />
                    <span class="text-sm font-semibold">Notas internas</span>
                    <Badge v-if="notesApi.count.value" :value="notesApi.count.value" severity="secondary" />
                    <span v-else class="text-xs text-[var(--text-color-secondary)] italic">(nenhuma)</span>
                    <i class="pi ml-auto text-xs" :class="notesOpen ? 'pi-chevron-up' : 'pi-chevron-down'" />
                </button>

                <div v-if="notesOpen" class="px-3 pb-3 flex flex-col gap-2">
                    <!-- Adicionar nota -->
                    <div class="flex gap-2 items-start">
                        <Textarea
                            v-model="newNoteText"
                            rows="2"
                            autoResize
                            placeholder="Escreva uma nota interna (só a equipe vê)…"
                            class="flex-1 text-sm"
                            :maxlength="4000"
                            :disabled="notesApi.saving.value"
                            @keydown.ctrl.enter="addNote"
                            @keydown.meta.enter="addNote"
                        />
                        <Button
                            icon="pi pi-plus"
                            severity="primary"
                            v-tooltip.left="'Adicionar (Ctrl+Enter)'"
                            :loading="notesApi.saving.value"
                            :disabled="!newNoteText.trim()"
                            @click="addNote"
                        />
                    </div>

                    <!-- Lista -->
                    <div v-if="notesApi.loading.value" class="text-xs text-[var(--text-color-secondary)] text-center py-2">
                        <i class="pi pi-spin pi-spinner mr-1" /> Carregando notas…
                    </div>
                    <div v-else-if="!notesApi.notes.value.length" class="text-xs text-[var(--text-color-secondary)] text-center py-2 italic">
                        Nenhuma nota ainda. Use o campo acima pra registrar observações da equipe.
                    </div>
                    <div v-else class="flex flex-col gap-1.5 max-h-[40vh] overflow-y-auto pr-1">
                        <div
                            v-for="n in notesApi.notes.value"
                            :key="n.id"
                            class="rounded-md border border-[var(--surface-border)] p-2 bg-[var(--surface-card)]"
                        >
                            <!-- Modo edição -->
                            <template v-if="editingNoteId === n.id">
                                <Textarea
                                    v-model="editingText"
                                    rows="3"
                                    autoResize
                                    class="w-full text-sm mb-1.5"
                                    :maxlength="4000"
                                    :disabled="notesApi.saving.value"
                                />
                                <div class="flex gap-1 justify-end">
                                    <Button label="Cancelar" size="small" severity="secondary" text @click="cancelEditNote" />
                                    <Button label="Salvar" size="small" :loading="notesApi.saving.value" :disabled="!editingText.trim()" @click="saveEditNote(n.id)" />
                                </div>
                            </template>

                            <!-- Modo leitura -->
                            <template v-else>
                                <div class="text-sm whitespace-pre-wrap break-words text-[var(--text-color)]">{{ n.body }}</div>
                                <div class="flex items-center justify-between mt-1.5 text-[0.7rem] text-[var(--text-color-secondary)]">
                                    <span class="truncate">
                                        <i class="pi pi-user text-[0.6rem] mr-0.5 opacity-60" />
                                        {{ n._author_name || 'Usuário' }}
                                        <span class="mx-1 opacity-50">·</span>
                                        {{ fmtNoteDate(n.created_at) }}
                                        <span v-if="n.updated_at && n.updated_at !== n.created_at" class="ml-1 italic opacity-70">(editada)</span>
                                    </span>
                                    <div v-if="n.created_by === currentUserId" class="flex gap-0.5 shrink-0">
                                        <button
                                            class="w-6 h-6 rounded-full border-none bg-transparent text-[var(--text-color-secondary)] grid place-items-center cursor-pointer hover:bg-[var(--surface-hover)]"
                                            v-tooltip.top="'Editar'"
                                            @click="startEditNote(n)"
                                        >
                                            <i class="pi pi-pencil text-[0.7rem]" />
                                        </button>
                                        <button
                                            class="w-6 h-6 rounded-full border-none bg-transparent text-[var(--text-color-secondary)] grid place-items-center cursor-pointer hover:bg-red-500/10 hover:text-red-500"
                                            v-tooltip.top="'Remover'"
                                            @click="confirmDeleteNote(n.id)"
                                        >
                                            <i class="pi pi-trash text-[0.7rem]" />
                                        </button>
                                    </div>
                                </div>
                            </template>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Mensagens -->
            <div ref="messagesContainerRef" class="flex-1 overflow-y-auto flex flex-col gap-2 p-1">
                <div v-if="store.loading" class="text-xs text-[var(--text-color-secondary)] text-center py-6">
                    <i class="pi pi-spin pi-spinner mr-2" />Carregando mensagens...
                </div>
                <div v-else-if="!store.messages.length" class="text-xs text-[var(--text-color-secondary)] text-center py-6 italic">
                    Nenhuma mensagem ainda. Envie a primeira abaixo.
                </div>

                <div
                    v-for="m in store.messages"
                    :key="m.id"
                    class="flex flex-col gap-0.5"
                    :class="m.direction === 'inbound' ? 'items-start' : 'items-end'"
                >
                    <div
                        class="max-w-[85%] px-3 py-2 rounded-lg text-sm whitespace-pre-wrap break-words"
                        :class="m.direction === 'inbound' ? 'bg-[var(--surface-ground)] rounded-tl-none' : 'bg-emerald-500/10 text-emerald-900 dark:text-emerald-100 rounded-tr-none'"
                    >
                        <template v-if="m.media_url">
                            <!-- Loading enquanto resolve signed URL -->
                            <div v-if="!mediaUrls[m.id]" class="flex items-center gap-2 text-xs text-[var(--text-color-secondary)] py-2">
                                <i class="pi pi-spin pi-spinner" /> carregando mídia…
                            </div>
                            <template v-else>
                                <Image
                                    v-if="isImage(m.media_mime)"
                                    :src="mediaUrls[m.id]"
                                    :preview="true"
                                    alt="imagem"
                                    imageClass="max-w-full rounded-md cursor-zoom-in"
                                    class="mb-1 block"
                                />
                                <audio
                                    v-else-if="isAudio(m.media_mime)"
                                    :src="mediaUrls[m.id]"
                                    controls
                                    preload="metadata"
                                    class="block w-full min-w-[260px] max-w-full mb-1"
                                />
                                <video
                                    v-else-if="isVideo(m.media_mime)"
                                    :src="mediaUrls[m.id]"
                                    controls
                                    class="max-w-full rounded-md mb-1"
                                />
                                <a
                                    v-else
                                    :href="mediaUrls[m.id]"
                                    target="_blank"
                                    rel="noopener"
                                    class="inline-flex items-center gap-2 text-xs underline text-[var(--primary-color)] mb-1"
                                >
                                    <i class="pi pi-paperclip" />
                                    Baixar anexo ({{ m.media_mime || 'arquivo' }})
                                </a>
                            </template>
                        </template>
                        <div v-if="m.body">{{ m.body }}</div>
                    </div>
                    <div class="text-[0.65rem] text-[var(--text-color-secondary)] opacity-75 px-1 flex items-center gap-1">
                        <span>{{ fmtDateTime(m.created_at) }}</span>
                        <span v-if="m.direction === 'outbound'" class="flex items-center">
                            <i v-if="m.delivery_status === 'read'" class="pi pi-check-double text-sky-500" v-tooltip.top="'Lida'" />
                            <i v-else-if="m.delivery_status === 'delivered'" class="pi pi-check-double" v-tooltip.top="'Entregue'" />
                            <i v-else-if="m.delivery_status === 'sent'" class="pi pi-check" v-tooltip.top="'Enviada'" />
                            <i v-else-if="m.delivery_status === 'failed'" class="pi pi-exclamation-circle text-red-500" v-tooltip.top="'Falhou'" />
                        </span>
                        <span v-if="m.direction === 'inbound' && !m.patient_id" class="italic">· número não vinculado</span>
                    </div>
                </div>
            </div>

            <!-- Compose -->
            <div v-if="store.thread.channel === 'whatsapp' && store.thread.contact_number" class="border-t border-[var(--surface-border)] pt-2 flex flex-col gap-2">
                <div class="flex items-end gap-2">
                    <Textarea
                        ref="composeTextareaRef"
                        v-model="composeText"
                        autoResize
                        rows="1"
                        placeholder="Digite sua mensagem... (Enter envia, Shift+Enter quebra linha)"
                        class="flex-1 !text-sm !resize-none"
                        :disabled="store.sending"
                        :maxlength="4000"
                        @keydown="onComposeKeydown"
                    />
                    <Button
                        icon="pi pi-send"
                        severity="success"
                        class="!w-10 !h-10 shrink-0"
                        :loading="store.sending"
                        :disabled="!composeText.trim() || store.sending"
                        v-tooltip.top="'Enviar (Enter)'"
                        @click="sendMessage"
                    />
                </div>
                <div class="flex items-center gap-1 text-[var(--text-color-secondary)]">
                    <Button icon="pi pi-bookmark" text rounded size="small" class="!w-8 !h-8" v-tooltip.top="'Templates'" @click="openTemplatesPopover" />
                    <Button icon="pi pi-face-smile" text rounded size="small" class="!w-8 !h-8" v-tooltip.top="'Emoji'" @click="toggleEmojiPopover" />
                    <span class="ml-auto text-[0.65rem] opacity-60">{{ composeText.length }}/4000</span>
                </div>
            </div>
            <div v-else class="text-[0.7rem] text-[var(--text-color-secondary)] italic text-center py-2 border-t border-[var(--surface-border)]">
                Envio direto indisponível (canal: {{ store.thread.channel }}).
            </div>
        </div>

        <!-- Popover: Templates -->
        <Popover ref="templatesPopover" :pt="{ content: { class: '!p-0' } }">
            <div class="w-[320px] max-h-[400px] overflow-y-auto">
                <div class="px-3 py-2 border-b border-[var(--surface-border)] text-xs font-semibold text-[var(--text-color-secondary)] uppercase tracking-wide">
                    Templates WhatsApp
                </div>
                <div v-if="store.templatesLoading" class="p-4 text-xs text-center text-[var(--text-color-secondary)]">
                    <i class="pi pi-spin pi-spinner mr-1" /> Carregando...
                </div>
                <div v-else-if="!store.templates.length" class="p-4 text-xs text-center text-[var(--text-color-secondary)] italic">
                    Nenhum template disponível.
                </div>
                <button
                    v-for="tpl in store.templates"
                    :key="tpl.id"
                    class="w-full text-left px-3 py-2 border-none bg-transparent cursor-pointer hover:bg-[var(--surface-hover)] border-b border-[var(--surface-border)] last:border-b-0"
                    @click="applyTemplate(tpl)"
                >
                    <div class="text-xs font-semibold text-[var(--text-color)] truncate">{{ templateFriendlyLabel(tpl.key) }}</div>
                    <div class="text-[0.7rem] text-[var(--text-color-secondary)] line-clamp-2 mt-0.5">{{ tpl.body_text }}</div>
                </button>
            </div>
        </Popover>

        <!-- Popover: Emoji picker -->
        <Popover ref="emojiPopover" :pt="{ content: { class: '!p-2' } }">
            <div class="w-[280px] max-h-[280px] overflow-y-auto grid grid-cols-8 gap-1">
                <button
                    v-for="e in emojiList"
                    :key="e"
                    class="w-8 h-8 rounded hover:bg-[var(--surface-hover)] border-none bg-transparent cursor-pointer text-lg"
                    @click="insertEmoji(e)"
                >{{ e }}</button>
            </div>
        </Popover>
    </Drawer>
</template>
