/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/features/patients/prontuario/services/clinicalNoteTemplatesRepository.js
|
| Repository de clinical_note_templates. Escopo escalonado:
|   - Sistema (is_system=true) — todos authenticated leem
|   - Tenant-wide (owner_id NULL) — membros do tenant (schema do tenant)
|   - Owner (owner_id) — só o owner
|
| RLS bloqueia INSERT/UPDATE/DELETE de templates is_system — só via seed.
| Templates do tenant podem ser criados/editados pelo tenant_admin.
|
| Schema: ver migrations/20260520000001_clinical_notes_tables.sql
|--------------------------------------------------------------------------
*/
import { supabase } from '@/lib/supabase/client';
import { tenantDb } from '@/lib/supabase/tenantClient';
import { useTenantStore } from '@/stores/tenantStore';
import { assertTenantId, getUid } from './_tenantGuards';
import { CLINICAL_NOTE_TEMPLATE_SELECT } from './clinicalNotesSelects';

const VALID_NOTE_TYPES = ['anamnese', 'evolucao_sessao', 'plano_terapeutico', 'observacao_livre', 'resumo_caso'];

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

/**
 * Lista templates visíveis pelo usuário ativo (sistema + tenant + owner).
 * RLS no banco filtra automaticamente; aqui só ordenamos.
 *
 * @param {Object} [opts]
 * @param {string} [opts.noteType]      - filtra por tipo de nota
 * @param {string} [opts.tenantId]
 * @param {boolean} [opts.includeInactive=false]
 */
export async function listAvailable({ noteType, tenantId, includeInactive = false } = {}) {
    resolveTenantId(tenantId); // garante tenant ativo (RLS depende)

    let q = tenantDb().from('clinical_note_templates').select(CLINICAL_NOTE_TEMPLATE_SELECT).order('is_system', { ascending: false }).order('name', { ascending: true });

    if (!includeInactive) q = q.eq('active', true);
    if (noteType) q = q.eq('note_type', noteType);

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

/**
 * Lê template por id.
 */
export async function getById(templateId) {
    if (!templateId) throw new Error('ID inválido.');

    const { data, error } = await tenantDb().from('clinical_note_templates').select(CLINICAL_NOTE_TEMPLATE_SELECT).eq('id', templateId).maybeSingle();

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

/**
 * Lê template por key (útil pra defaults — 'soap', 'dap', 'birp', 'anamnese_padrao').
 * Prioriza is_system se houver conflito de key (cobre seed primeiro).
 */
export async function getByKey(key, { noteType } = {}) {
    if (!key) throw new Error('Key inválida.');

    let q = tenantDb().from('clinical_note_templates').select(CLINICAL_NOTE_TEMPLATE_SELECT).eq('key', key).eq('active', true);
    if (noteType) q = q.eq('note_type', noteType);

    const { data, error } = await q.order('is_system', { ascending: false }).limit(1).maybeSingle();
    if (error) throw error;
    return data || null;
}

/**
 * Cria template tenant-wide ou owner-scoped. is_system bloqueado em RLS.
 */
export async function create(payload) {
    if (!payload?.key) throw new Error('key obrigatória.');
    if (!payload?.name) throw new Error('name obrigatório.');
    if (!payload?.note_type) throw new Error('note_type obrigatório.');
    if (!VALID_NOTE_TYPES.includes(payload.note_type)) {
        throw new Error(`note_type inválido. Aceitos: ${VALID_NOTE_TYPES.join(', ')}.`);
    }
    if (!payload?.structure) throw new Error('structure (jsonb) obrigatória.');

    const uid = await getUid();
    const tid = resolveTenantId();

    const row = {
        owner_id: payload.ownerScoped ? uid : null,
        key: String(payload.key).trim(),
        name: String(payload.name).trim(),
        note_type: payload.note_type,
        description: payload.description ? String(payload.description).trim() || null : null,
        structure: payload.structure,
        is_system: false,
        is_global: false,
        active: payload.active !== false
    };

    const { data, error } = await tenantDb().from('clinical_note_templates').insert([row]).select(CLINICAL_NOTE_TEMPLATE_SELECT).single();

    if (error) throw error;
    return data;
}

/**
 * Atualiza template. is_system bloqueado em RLS.
 */
export async function update(templateId, patch) {
    if (!templateId) throw new Error('ID inválido.');

    const safePatch = { ...patch, updated_at: new Date().toISOString() };
    if ('is_system' in safePatch) delete safePatch.is_system; // RLS bloqueia mas defesa em profundidade
    if ('tenant_id' in safePatch) delete safePatch.tenant_id; // schema-per-tenant: coluna não existe mais

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

    if (error) throw error;
    return data;
}

/**
 * Soft delete via active=false.
 */
export async function softDelete(templateId) {
    if (!templateId) throw new Error('ID inválido.');

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

    if (error) throw error;
    return true;
}
