/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/features/insurance/services/insurancePlansRepository.js
|
| Repository da tabela public.insurance_plans.
| Pure functions seguindo blueprints/repository-blueprint.md.
|
| Schema (servicos_prontuarios.sql):
|   id, owner_id,
|   name text, notes text, default_value numeric(10,2),
|   active boolean DEFAULT 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 { INSURANCE_PLAN_SELECT } from './insurancePlansSelects';

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

/**
 * Lista convênios ativos do owner. Ordenados por name ascending.
 *
 * @param {Object} [opts]
 * @param {string} [opts.ownerId]
 * @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('insurance_plans').select(INSURANCE_PLAN_SELECT).eq('owner_id', uid).order('name', { ascending: true });

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

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

/**
 * Lê convênio por id. Filtra owner_id por segurança.
 */
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('insurance_plans').select(INSURANCE_PLAN_SELECT).eq('id', id).eq('owner_id', uid).maybeSingle();

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

/**
 * Procura convênio ativo por nome (case-insensitive). Usado pra duplicate check
 * antes de criar (uniqueness check do quick-create blueprint).
 *
 * @param {Object} opts
 * @param {string} opts.name
 * @param {string} [opts.ownerId]
 * @param {string} [opts.tenantId]
 */
export async function findByName({ name, ownerId, tenantId } = {}) {
    if (!name) return null;
    const tid = resolveTenantId(tenantId);
    const uid = ownerId || (await getUid());
    const safeName = String(name).trim();
    if (!safeName) return null;

    const { data, error } = await tenantDb().from('insurance_plans').select(INSURANCE_PLAN_SELECT).eq('owner_id', uid).eq('active', true).ilike('name', safeName).limit(1).maybeSingle();

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

/**
 * Cria convênio. Pré-checa duplicidade por nome (case-insensitive) — se já
 * existe ativo, lança erro PT-BR. Repository injeta owner_id.
 */
export async function create(payload) {
    if (!payload) throw new Error('Payload vazio.');
    const name = String(payload.name || '').trim();
    if (!name) throw new Error('Nome do convênio é obrigatório.');
    if (name.length > 120) throw new Error('Nome do convênio muito longo (máx 120).');

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

    // Uniqueness check (quick-create blueprint)
    const dup = await findByName({ name, ownerId: uid, tenantId: tid });
    if (dup) {
        throw new Error('Já existe um convênio com esse nome.');
    }

    const insertPayload = {
        owner_id: uid,
        name: name.slice(0, 120),
        notes: payload.notes ? String(payload.notes).trim().slice(0, 500) || null : null,
        default_value: payload.default_value != null && payload.default_value !== '' ? Number(payload.default_value) : null,
        active: payload.active !== false
    };

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

    if (error) throw error;
    return data;
}

/**
 * Atualiza convênio. Filtra por id.
 */
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);
    safePatch.updated_at = new Date().toISOString();

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

    if (error) throw error;
    return data;
}

/**
 * Soft delete: marca active=false. Preserva histórico.
 */
export async function softDelete(id, { tenantId } = {}) {
    if (!id) throw new Error('ID inválido.');
    const tid = resolveTenantId(tenantId);

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

    if (error) throw error;
    return true;
}

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

function sanitize(payload) {
    // Dropa tenant_id defensivamente (schema-per-tenant: coluna não existe mais)
    const { tenant_id: _drop, ...rest } = payload;
    const out = { ...rest };
    if ('name' in out && typeof out.name === 'string') {
        const t = out.name.trim();
        out.name = t === '' ? null : t.slice(0, 120);
    }
    if ('notes' in out && typeof out.notes === 'string') {
        const t = out.notes.trim();
        out.notes = t === '' ? null : t.slice(0, 500);
    }
    if ('default_value' in out) {
        const v = out.default_value;
        out.default_value = v == null || v === '' ? null : Number(v);
    }
    return out;
}
