/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Criado e desenvolvido por Leonardo Nohama
|
| Tecnologia aplicada à escuta.
| Estrutura para o cuidado.
|
| Arquivo: src/services/Medicos.service.js
| Data: 2026
| Local: São Carlos/SP — Brasil
|--------------------------------------------------------------------------
| © 2026 — Todos os direitos reservados
|--------------------------------------------------------------------------
*/
import { supabase } from '@/lib/supabase/client';

import { tenantDb } from '@/lib/supabase/tenantClient';
// ── Helpers ──────────────────────────────────────────────────

async function getOwnerId() {
    const { data, error } = await supabase.auth.getUser();
    if (error) throw error;
    const uid = data?.user?.id;
    if (!uid) throw new Error('Sessão inválida.');
    return uid;
}

async function getActiveTenantId(uid) {
    const { data, error } = await supabase
        .from('tenant_members')
        .select('tenant_id')
        .eq('user_id', uid)
        .eq('status', 'active')
        .order('created_at', { ascending: false })
        .limit(1)
        .single();
    if (error) throw error;
    if (!data?.tenant_id) throw new Error('Tenant não encontrado.');
    return data.tenant_id;
}

function normalizeNome(s) {
    return String(s || '').trim().toLowerCase().replace(/\s+/g, ' ');
}

function isUniqueViolation(err) {
    if (!err) return false;
    if (err.code === '23505') return true;
    return /duplicate key value violates unique constraint/i.test(String(err.message || ''));
}

// ── List ─────────────────────────────────────────────────────

/**
 * Lista médicos ativos do owner com contagem de pacientes encaminhados.
 * A contagem é feita buscando quantos patients possuem o nome do médico
 * no campo `encaminhado_por` (text).
 */
export async function listMedicosWithPatientCounts() {
    const ownerId = await getOwnerId();

    const { data: medicos, error } = await tenantDb().from('medicos')
        .select('id, nome, crm, especialidade, telefone_profissional, telefone_pessoal, email, clinica, cidade, estado, observacoes, ativo, owner_id, created_at, updated_at')
        .eq('owner_id', ownerId)
        .eq('ativo', true)
        .order('nome', { ascending: true });

    if (error) throw error;

    // Busca pacientes do owner para contar encaminhamentos por médico
    const { data: patients, error: pErr } = await tenantDb().from('patients')
        .select('id, encaminhado_por')
        .eq('owner_id', ownerId);

    if (pErr) throw pErr;

    const countMap = new Map();
    for (const med of medicos || []) {
        countMap.set(med.id, 0);
    }

    for (const p of patients || []) {
        const enc = String(p.encaminhado_por || '').toLowerCase();
        if (!enc) continue;
        for (const med of medicos || []) {
            const nomeLower = med.nome.toLowerCase();
            if (enc.includes(nomeLower)) {
                countMap.set(med.id, (countMap.get(med.id) || 0) + 1);
            }
        }
    }

    return (medicos || []).map((m) => ({
        ...m,
        patients_count: countMap.get(m.id) || 0
    }));
}

// ── Create ───────────────────────────────────────────────────

export async function createMedico(payload) {
    const ownerId = await getOwnerId();
    const tenantId = await getActiveTenantId(ownerId);

    const nome = String(payload.nome || '').trim();
    if (!nome) throw new Error('Nome do médico é obrigatório.');

    const row = {
        owner_id: ownerId,
        nome,
        crm: String(payload.crm || '').trim() || null,
        especialidade: payload.especialidade || null,
        telefone_profissional: payload.telefone_profissional || null,
        telefone_pessoal: payload.telefone_pessoal || null,
        email: String(payload.email || '').trim() || null,
        clinica: String(payload.clinica || '').trim() || null,
        cidade: String(payload.cidade || '').trim() || null,
        estado: String(payload.estado || '').trim() || null,
        observacoes: String(payload.observacoes || '').trim() || null,
        ativo: true
    };

    const { data, error } = await tenantDb().from('medicos')
        .insert(row)
        .select('*')
        .single();

    if (error) {
        if (isUniqueViolation(error)) throw new Error('Já existe um médico com este CRM.');
        throw error;
    }

    return data;
}

// ── Update ───────────────────────────────────────────────────

export async function updateMedico(id, payload) {
    const ownerId = await getOwnerId();

    if (!id) throw new Error('ID inválido.');
    const nome = String(payload.nome || '').trim();
    if (!nome) throw new Error('Nome do médico é obrigatório.');

    const row = {
        nome,
        crm: String(payload.crm || '').trim() || null,
        especialidade: payload.especialidade || null,
        telefone_profissional: payload.telefone_profissional || null,
        telefone_pessoal: payload.telefone_pessoal || null,
        email: String(payload.email || '').trim() || null,
        clinica: String(payload.clinica || '').trim() || null,
        cidade: String(payload.cidade || '').trim() || null,
        estado: String(payload.estado || '').trim() || null,
        observacoes: String(payload.observacoes || '').trim() || null,
        updated_at: new Date().toISOString()
    };

    const { data, error } = await tenantDb().from('medicos')
        .update(row)
        .eq('id', id)
        .eq('owner_id', ownerId)
        .select('*')
        .single();

    if (error) {
        if (isUniqueViolation(error)) throw new Error('Já existe um médico com este CRM.');
        throw error;
    }

    return data;
}

// ── Delete (soft) ────────────────────────────────────────────

export async function deleteMedico(id) {
    const ownerId = await getOwnerId();
    if (!id) throw new Error('ID inválido.');

    const { error } = await tenantDb().from('medicos')
        .update({ ativo: false, updated_at: new Date().toISOString() })
        .eq('id', id)
        .eq('owner_id', ownerId);

    if (error) throw error;
    return true;
}

// ── Pacientes de um médico ───────────────────────────────────

/**
 * Busca pacientes do owner cujo campo `encaminhado_por` contém o nome do médico.
 */
export async function fetchPatientsByMedicoNome(medicoNome) {
    const ownerId = await getOwnerId();
    const nomeLower = String(medicoNome || '').trim().toLowerCase();
    if (!nomeLower) return [];

    const { data, error } = await tenantDb().from('patients')
        .select('id, nome_completo, email_principal, telefone, avatar_url, encaminhado_por')
        .eq('owner_id', ownerId)
        .ilike('encaminhado_por', `%${nomeLower}%`);

    if (error) throw error;

    return (data || [])
        .map((p) => ({
            id: p.id,
            full_name: p.nome_completo || '—',
            email: p.email_principal || '—',
            phone: p.telefone || '—',
            avatar_url: p.avatar_url || null,
            encaminhado_por: p.encaminhado_por || ''
        }))
        .sort((a, b) => String(a.full_name).localeCompare(String(b.full_name), 'pt-BR'));
}
