/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/features/financeiro/services/financialExceptionsRepository.js
|
| Regras de exceção financeira (no-show, cancelamento, etc).
| Extraído de src/composables/useAgendaFinanceiro.js.
|
| Prioridade: regra própria do owner > regra global do tenant (owner_id IS NULL).
|--------------------------------------------------------------------------
*/
import { supabase } from '@/lib/supabase/client';
import { tenantDb } from '@/lib/supabase/tenantClient';
import { useTenantStore } from '@/stores/tenantStore';
import { assertTenantId, getUid } from './_tenantGuards';
import { FINANCIAL_EXCEPTION_SELECT } from './financialSelects';

const VALID_EXCEPTION_TYPES = ['patient_no_show', 'patient_cancellation', 'professional_cancellation'];

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

/**
 * Lê a regra de exceção ativa pra um tipo + tenant.
 * Prioriza owner próprio se existir; senão regra global do tenant.
 */
export async function getRule(exceptionType, { tenantId } = {}) {
    if (!VALID_EXCEPTION_TYPES.includes(exceptionType)) {
        throw new Error(`exception_type inválido. Aceitos: ${VALID_EXCEPTION_TYPES.join(', ')}.`);
    }
    const tid = resolveTenantId(tenantId);
    const uid = await getUid();

    const { data, error } = await tenantDb().from('financial_exceptions')
        .select(FINANCIAL_EXCEPTION_SELECT)
        
        .eq('exception_type', exceptionType)
        .or(`owner_id.eq.${uid},owner_id.is.null`)
        .order('owner_id', { ascending: false, nullsLast: true })
        .limit(1)
        .maybeSingle();

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

/**
 * Lista todas as regras do tenant (config page).
 */
export async function listAll({ tenantId } = {}) {
    const tid = resolveTenantId(tenantId);
    const { data, error } = await tenantDb().from('financial_exceptions').select(FINANCIAL_EXCEPTION_SELECT).order('exception_type', { ascending: true });
    if (error) throw error;
    return data || [];
}

/**
 * Cria/atualiza regra (upsert).
 */
export async function upsertRule(payload) {
    if (!payload?.exception_type) throw new Error('exception_type obrigatório.');
    if (!VALID_EXCEPTION_TYPES.includes(payload.exception_type)) {
        throw new Error(`exception_type inválido. Aceitos: ${VALID_EXCEPTION_TYPES.join(', ')}.`);
    }

    const uid = await getUid();
    const tid = resolveTenantId(payload.tenantId);

    const row = {
        owner_id: payload.ownerScoped ? uid : null,
        exception_type: payload.exception_type,
        charge_mode: payload.charge_mode || 'none',
        charge_value: payload.charge_value != null ? Number(payload.charge_value) : null,
        charge_pct: payload.charge_pct != null ? Number(payload.charge_pct) : null,
        min_hours_notice: payload.min_hours_notice != null ? Number(payload.min_hours_notice) : null,
        default_consume_on_miss: !!payload.default_consume_on_miss,
        updated_at: new Date().toISOString()
    };

    // TODO(schema-per-tenant): conferir unique (PK é só id; antes era tenant_id,owner_id,exception_type)
    const { data, error } = await tenantDb().from('financial_exceptions').upsert(row, { onConflict: 'owner_id,exception_type' }).select(FINANCIAL_EXCEPTION_SELECT).single();

    if (error) throw error;
    return data;
}

/**
 * Calcula valor a cobrar conforme charge_mode.
 *   - none: 0 (não cobra)
 *   - full: amount original
 *   - fixed_fee: charge_value fixo
 *   - percentage: amount * (charge_pct / 100)
 */
export function calcChargeAmount(originalAmount, rule) {
    if (!rule || rule.charge_mode === 'none') return 0;
    if (rule.charge_mode === 'full') return Number(originalAmount) || 0;
    if (rule.charge_mode === 'fixed_fee') return Number(rule.charge_value ?? 0);
    if (rule.charge_mode === 'percentage') {
        const pct = Number(rule.charge_pct ?? 0);
        return parseFloat(((Number(originalAmount) * pct) / 100).toFixed(2));
    }
    return Number(originalAmount) || 0;
}
