/* |-------------------------------------------------------------------------- | AgĂȘncia PSI |-------------------------------------------------------------------------- | Arquivo: src/composables/useConversationAssignment.js | Data: 2026-04-21 | | Atribuicao de thread de conversa a um terapeuta/membro do tenant. | Uma linha por (tenant_id, thread_key). Reatribuir = UPSERT. |-------------------------------------------------------------------------- */ import { ref } from 'vue'; import { supabase } from '@/lib/supabase/client'; import { useTenantStore } from '@/stores/tenantStore'; export function useConversationAssignment() { const tenantStore = useTenantStore(); const assignment = ref(null); // { assigned_to, assigned_by, assigned_at, _assignee_name } const members = ref([]); // lista de membros do tenant (pra Select) const loading = ref(false); const saving = ref(false); const error = ref(null); async function loadMembers() { const tenantId = tenantStore.activeTenantId; if (!tenantId) { members.value = []; return; } try { const { data, error: err } = await supabase .from('v_tenant_members_with_profiles') .select('user_id, full_name, email, role') .eq('tenant_id', tenantId) .in('role', ['tenant_admin', 'therapist', 'secretary']) .eq('status', 'active') .order('full_name', { ascending: true }); if (err) throw err; members.value = (data || []).map((m) => ({ user_id: m.user_id, label: m.full_name || m.email || m.user_id, email: m.email, role: m.role })); } catch (e) { error.value = e?.message || 'Falha ao carregar membros'; members.value = []; } } async function load(threadKey) { if (!threadKey) { assignment.value = null; return; } const tenantId = tenantStore.activeTenantId; if (!tenantId) { assignment.value = null; return; } loading.value = true; error.value = null; try { const { data, error: err } = await supabase .from('conversation_assignments') .select('tenant_id, thread_key, patient_id, contact_number, assigned_to, assigned_by, assigned_at') .eq('tenant_id', tenantId) .eq('thread_key', threadKey) .maybeSingle(); if (err) throw err; if (!data || !data.assigned_to) { assignment.value = data || null; return; } // Resolve nome do assignee via membros (se carregado) ou profiles let assigneeName = null; const hit = members.value.find((m) => m.user_id === data.assigned_to); if (hit) assigneeName = hit.label; if (!assigneeName) { const { data: u } = await supabase.from('profiles').select('full_name').eq('id', data.assigned_to).maybeSingle(); assigneeName = u?.full_name || null; } assignment.value = { ...data, _assignee_name: assigneeName }; } catch (e) { error.value = e?.message || 'Falha ao carregar atribuicao'; assignment.value = null; } finally { loading.value = false; } } async function assign({ threadKey, patientId = null, contactNumber = null, assignedTo }) { const tenantId = tenantStore.activeTenantId; if (!tenantId || !threadKey) return { ok: false, error: 'invalid_params' }; saving.value = true; try { const { data: authData } = await supabase.auth.getUser(); const userId = authData?.user?.id; if (!userId) return { ok: false, error: 'not_authenticated' }; const payload = { tenant_id: tenantId, thread_key: threadKey, patient_id: patientId || null, contact_number: contactNumber || null, assigned_to: assignedTo || null, assigned_by: userId, assigned_at: new Date().toISOString() }; const { data, error: err } = await supabase .from('conversation_assignments') .upsert(payload, { onConflict: 'tenant_id,thread_key' }) .select('tenant_id, thread_key, patient_id, contact_number, assigned_to, assigned_by, assigned_at') .single(); if (err) throw err; let assigneeName = null; if (data.assigned_to) { const hit = members.value.find((m) => m.user_id === data.assigned_to); assigneeName = hit?.label || null; if (!assigneeName) { const { data: u } = await supabase.from('profiles').select('full_name').eq('id', data.assigned_to).maybeSingle(); assigneeName = u?.full_name || null; } } assignment.value = { ...data, _assignee_name: assigneeName }; return { ok: true, assignment: assignment.value }; } catch (e) { return { ok: false, error: e?.message || 'assign_failed' }; } finally { saving.value = false; } } async function unassign({ threadKey, patientId = null, contactNumber = null }) { return assign({ threadKey, patientId, contactNumber, assignedTo: null }); } function clear() { assignment.value = null; error.value = null; } return { assignment, members, loading, saving, error, loadMembers, load, assign, unassign, clear }; }