/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/features/tenantship/services/tenantMembersRepository.js
|
| Repository de tenant_members. Pure functions seguindo
| blueprints/repository-blueprint.md.
|
| Tabela: tenant_members (id, tenant_id, user_id, role, status='active', created_at)
| View enriched: v_tenant_members_with_profiles (inclui full_name e email)
|--------------------------------------------------------------------------
*/
import { supabase } from '@/lib/supabase/client';
import { useTenantStore } from '@/stores/tenantStore';
import { assertTenantId, getUid } from './_tenantGuards';
import { TENANT_MEMBER_PROFILE_SELECT, TENANT_MEMBER_RAW_SELECT, flattenMemberRow } from './tenantMembersSelects';

const VALID_ROLES = ['tenant_admin', 'therapist', 'secretary'];
const VALID_STATUSES = ['active', 'inactive', 'suspended'];

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

/**
 * Lista membros de um tenant com profile (full_name, email).
 *
 * @param {Object} [opts]
 * @param {string} [opts.tenantId]
 * @param {string} [opts.status]  - filtra por status (active/inactive/suspended)
 */
export async function listForTenant({ tenantId, status } = {}) {
    const tid = resolveTenantId(tenantId);

    let q = supabase.from('v_tenant_members_with_profiles').select(TENANT_MEMBER_PROFILE_SELECT).eq('tenant_id', tid).order('created_at', { ascending: false });

    if (status) q = q.eq('status', status);

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

/**
 * Lê o tenant_member ativo do usuário LOGADO no tenant ativo (ou no tenantId passado).
 * Retorna `{ id, tenant_id, role, status }` ou null.
 *
 * Útil pra criar entidades que precisam de `responsible_member_id` (ex: patients).
 *
 * @param {Object} [opts]
 * @param {string} [opts.tenantId]
 */
export async function getMyActiveMember({ tenantId } = {}) {
    const tid = resolveTenantId(tenantId);
    const uid = await getUid();

    const { data, error } = await supabase.from('tenant_members').select(TENANT_MEMBER_RAW_SELECT).eq('user_id', uid).eq('tenant_id', tid).eq('status', 'active').order('created_at', { ascending: false }).limit(1).maybeSingle();

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

/**
 * Lê um member pela id (raw, sem profile join — útil pra verificações rápidas).
 *
 * @param {string} memberId
 * @param {Object} [opts]
 * @param {string} [opts.tenantId]
 */
export async function getById(memberId, { tenantId } = {}) {
    if (!memberId) throw new Error('ID inválido.');
    const tid = resolveTenantId(tenantId);

    const { data, error } = await supabase.from('tenant_members').select(TENANT_MEMBER_RAW_SELECT).eq('id', memberId).eq('tenant_id', tid).maybeSingle();

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

/**
 * Atualiza role de um member. Tenant_admin não pode rebaixar a si mesmo —
 * a UI deve bloquear, mas RLS no banco também deve garantir.
 *
 * @param {string} memberId
 * @param {'tenant_admin'|'therapist'|'secretary'} role
 * @param {Object} [opts]
 * @param {string} [opts.tenantId]
 */
export async function updateMemberRole(memberId, role, { tenantId } = {}) {
    if (!memberId) throw new Error('ID inválido.');
    if (!VALID_ROLES.includes(role)) {
        throw new Error(`Role inválida. Aceitos: ${VALID_ROLES.join(', ')}.`);
    }
    const tid = resolveTenantId(tenantId);

    const { data, error } = await supabase.from('tenant_members').update({ role }).eq('id', memberId).eq('tenant_id', tid).select(TENANT_MEMBER_RAW_SELECT).single();

    if (error) throw error;
    return data;
}

/**
 * Atualiza status (ativar/inativar/suspender) sem remover.
 *
 * @param {string} memberId
 * @param {'active'|'inactive'|'suspended'} status
 * @param {Object} [opts]
 * @param {string} [opts.tenantId]
 */
export async function updateMemberStatus(memberId, status, { tenantId } = {}) {
    if (!memberId) throw new Error('ID inválido.');
    if (!VALID_STATUSES.includes(status)) {
        throw new Error(`Status inválido. Aceitos: ${VALID_STATUSES.join(', ')}.`);
    }
    const tid = resolveTenantId(tenantId);

    const { data, error } = await supabase.from('tenant_members').update({ status }).eq('id', memberId).eq('tenant_id', tid).select(TENANT_MEMBER_RAW_SELECT).single();

    if (error) throw error;
    return data;
}

/**
 * Remove member (hard delete da tabela tenant_members).
 * Os dados do user em outras tabelas (pacientes, agenda, etc) PERMANECEM —
 * a remoção é apenas do vínculo membership.
 *
 * @param {string} memberId
 * @param {Object} [opts]
 * @param {string} [opts.tenantId]
 */
export async function removeMember(memberId, { tenantId } = {}) {
    if (!memberId) throw new Error('ID inválido.');
    const tid = resolveTenantId(tenantId);

    // Defesa: nunca permitir o próprio user se remover via essa função
    // (causa lockout). UI deve bloquear; aqui só sanity-check.
    const uid = await getUid();
    const target = await getById(memberId, { tenantId: tid });
    if (target && target.user_id === uid) {
        throw new Error('Não é permitido remover a si mesmo. Peça a outro admin do tenant.');
    }

    const { error } = await supabase.from('tenant_members').delete().eq('id', memberId).eq('tenant_id', tid);

    if (error) throw error;
    return true;
}
