/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/features/medicos/services/medicosRepository.js
|
| Repository da tabela public.medicos. Pure functions seguindo
| blueprints/repository-blueprint.md.
|
| Schema (servicos_prontuarios.sql):
|   id, owner_id, nome, crm, especialidade,
|   telefone_profissional, telefone_pessoal, email, clinica,
|   cidade, estado='SP', observacoes, ativo=true, created_at, updated_at
|--------------------------------------------------------------------------
*/
import { supabase } from '@/lib/supabase/client';
import { tenantDb } from '@/lib/supabase/tenantClient';
import { useTenantStore } from '@/stores/tenantStore';
import { assertTenantId, getUid } from './_tenantGuards';
import { MEDICO_LIST_SELECT, MEDICO_FULL_SELECT } from './medicosSelects';

function resolveTenantId(tenantIdArg) {
    const tenantStore = useTenantStore();
    const tenantId = tenantIdArg || tenantStore.activeTenantId || tenantStore.tenantId;
    assertTenantId(tenantId);
    return tenantId;
}

/**
 * Lista médicos ativos do owner (escopo terapeuta solo).
 * Ordenados por nome ascending.
 *
 * @param {Object} [opts]
 * @param {string} [opts.ownerId]   - default: uid logado
 * @param {string} [opts.tenantId]
 * @param {boolean} [opts.includeInactive=false]
 */
export async function listForOwner({ ownerId, tenantId, includeInactive = false } = {}) {
    const tid = resolveTenantId(tenantId);
    const uid = ownerId || (await getUid());

    let q = tenantDb().from('medicos').select(MEDICO_LIST_SELECT).eq('owner_id', uid).order('nome', { ascending: true });

    if (!includeInactive) q = q.eq('ativo', true);

    const { data, error } = await q;
    if (error) throw error;
    return data || [];
}

/**
 * Lê um médico completo (pra edit). Filtra owner_id por segurança.
 *
 * @param {string} id
 * @param {Object} [opts]
 * @param {string} [opts.tenantId]
 */
export async function getById(id, { tenantId } = {}) {
    if (!id) throw new Error('ID inválido.');
    const tid = resolveTenantId(tenantId);
    const uid = await getUid();

    const { data, error } = await tenantDb().from('medicos').select(MEDICO_FULL_SELECT).eq('id', id).eq('owner_id', uid).maybeSingle();

    if (error) throw error;
    return data || null;
}

/**
 * Cria médico. Injeta owner_id (uid logado).
 * Payload aceita os campos canônicos da tabela; o repository sanitiza
 * trims e nullif vazio.
 *
 * @param {Object} payload
 */
export async function create(payload) {
    if (!payload) throw new Error('Payload vazio.');
    if (!payload.nome || !String(payload.nome).trim()) {
        throw new Error('Nome do médico é obrigatório.');
    }
    const uid = await getUid();
    const tid = resolveTenantId();

    const insertPayload = {
        ...sanitize(payload),
        owner_id: uid,
        ativo: payload.ativo !== false
    };

    const { data, error } = await tenantDb().from('medicos').insert([insertPayload]).select(MEDICO_FULL_SELECT).single();

    if (error) throw error;
    return data;
}

/**
 * Atualiza médico. Filtra por id (defesa em profundidade — RLS reforça).
 * updated_at é atualizado server-side ou aqui se não houver trigger.
 *
 * @param {string} id
 * @param {Object} patch
 * @param {Object} [opts]
 * @param {string} [opts.tenantId]
 */
export async function update(id, patch, { tenantId } = {}) {
    if (!id) throw new Error('ID inválido.');
    if (!patch) throw new Error('Patch vazio.');
    const tid = resolveTenantId(tenantId);

    const safePatch = {
        ...sanitize(patch),
        updated_at: new Date().toISOString()
    };

    const { data, error } = await tenantDb().from('medicos').update(safePatch).eq('id', id).select(MEDICO_FULL_SELECT).single();

    if (error) throw error;
    return data;
}

/**
 * Soft delete: marca ativo=false em vez de DELETE. Preserva histórico
 * de encaminhamentos antigos referentes a este médico.
 *
 * @param {string} id
 * @param {Object} [opts]
 * @param {string} [opts.tenantId]
 */
export async function softDelete(id, { tenantId } = {}) {
    if (!id) throw new Error('ID inválido.');
    const tid = resolveTenantId(tenantId);

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

    if (error) throw error;
    return true;
}

// ─── helpers internos ────────────────────────────────────────────────────────

/**
 * Sanitiza payload: trim em strings, nullif vazio.
 * Não sanitiza telefones (já chegam digits-only do componente)
 * nem owner_id/ativo (controlados pelo repository).
 * Dropa tenant_id defensivamente (schema-per-tenant: coluna não existe mais).
 */
function sanitize(payload) {
    const stringFields = ['nome', 'crm', 'especialidade', 'telefone_profissional', 'telefone_pessoal', 'email', 'clinica', 'cidade', 'estado', 'observacoes'];

    const { tenant_id: _drop, ...rest } = payload;
    const out = { ...rest };
    for (const f of stringFields) {
        if (f in out) {
            const v = out[f];
            if (typeof v === 'string') {
                const trimmed = v.trim();
                out[f] = trimmed === '' ? null : trimmed;
            }
        }
    }
    return out;
}
