/**
 * src/billing/invoicing.ts
 * إدارة الفواتير الشهرية — Monthly invoice management
 *
 * كل شهر نولد فاتورة لكل مستأجر:
 * - سعر الخطة + أي رسوم إضافية (إذا مسموح بالتجاوز)
 * - تكلفة API الفعلية (داخلية — ما يشوفها العميل)
 * - الربح = السعر - التكلفة
 */
import { createChildLogger } from '../utils/logger.js';
import { supabase } from '../utils/supabase.js';
import { getPlan } from './plans.js';
import { walletManager } from './wallet.js';
const log = createChildLogger('billing:invoicing');
// ─── Invoice Operations ──────────────────────────────────────────────
/**
 * توليد فاتورة شهرية لمستأجر
 * تجمع: سعر الخطة + أي رسوم تجاوز + تكلفة API الداخلية + الربح
 */
export async function generateMonthlyInvoice(tenantId, month) {
    log.info({ tenantId, month }, 'Generating monthly invoice');
    // 1. جلب بيانات المستأجر والخطة
    const { data: tenant, error: tenantErr } = await supabase
        .from('tenants')
        .select('plan, business_name')
        .eq('id', tenantId)
        .single();
    if (tenantErr || !tenant) {
        throw new Error(`Tenant not found: ${tenantId}`);
    }
    const plan = getPlan(tenant.plan);
    if (!plan) {
        throw new Error(`Unknown plan: ${tenant.plan}`);
    }
    // 2. حساب تكلفة API الفعلية (بالريال)
    const apiCostSar = await walletManager.getCurrentSpend(tenantId, month);
    // 3. حساب التجاوز (إذا كان مسموح)
    const budgetConfig = await walletManager.getBudgetConfig(tenantId);
    let overageSar = 0;
    if (budgetConfig.overageAllowed && apiCostSar > budgetConfig.monthlyBudgetSar) {
        // رسوم التجاوز = (التكلفة الزائدة × معامل التجاوز)
        const excess = apiCostSar - budgetConfig.monthlyBudgetSar;
        overageSar = Math.round(excess * budgetConfig.overageRateMultiplier * 100) / 100;
    }
    // 4. حساب الإجمالي والربح
    const planPriceSar = plan.price_sar;
    const totalSar = planPriceSar + overageSar;
    const profitSar = Math.round((totalSar - apiCostSar) * 100) / 100;
    // 5. حفظ أو تحديث الفاتورة (upsert بناءً على tenant_id + month)
    const invoiceData = {
        tenant_id: tenantId,
        month,
        plan_name: plan.id,
        plan_price_sar: planPriceSar,
        api_cost_sar: apiCostSar,
        overage_sar: overageSar,
        total_sar: totalSar,
        profit_sar: profitSar,
        status: 'pending',
    };
    const { data: invoice, error: upsertErr } = await supabase
        .from('invoices')
        .upsert(invoiceData, { onConflict: 'tenant_id,month' })
        .select()
        .single();
    if (upsertErr) {
        log.error({ tenantId, month, error: upsertErr.message }, 'Failed to upsert invoice');
        throw new Error(`Failed to generate invoice: ${upsertErr.message}`);
    }
    log.info({ tenantId, month, total: totalSar, profit: profitSar, apiCost: apiCostSar }, 'Invoice generated ✅');
    return invoice;
}
/**
 * جلب فاتورة واحدة بالمعرف
 */
export async function getInvoice(invoiceId) {
    const { data, error } = await supabase
        .from('invoices')
        .select('*')
        .eq('id', invoiceId)
        .single();
    if (error) {
        if (error.code === 'PGRST116')
            return null;
        log.error({ invoiceId, error: error.message }, 'Failed to get invoice');
        throw new Error(`Failed to get invoice: ${error.message}`);
    }
    return data;
}
/**
 * قائمة فواتير مستأجر معين
 */
export async function getTenantInvoices(tenantId, options = {}) {
    const { limit = 12, offset = 0 } = options;
    const { data, error, count } = await supabase
        .from('invoices')
        .select('*', { count: 'exact' })
        .eq('tenant_id', tenantId)
        .order('month', { ascending: false })
        .range(offset, offset + limit - 1);
    if (error) {
        log.error({ tenantId, error: error.message }, 'Failed to list invoices');
        throw new Error(`Failed to list invoices: ${error.message}`);
    }
    return {
        invoices: (data ?? []),
        total: count ?? 0,
    };
}
/**
 * تحديث حالة الفاتورة إلى "مدفوعة"
 */
export async function markInvoicePaid(invoiceId, paymentRef) {
    const { data, error } = await supabase
        .from('invoices')
        .update({
        status: 'paid',
        payment_ref: paymentRef,
        paid_at: new Date().toISOString(),
    })
        .eq('id', invoiceId)
        .select()
        .single();
    if (error) {
        log.error({ invoiceId, error: error.message }, 'Failed to mark invoice as paid');
        throw new Error(`Failed to mark invoice as paid: ${error.message}`);
    }
    log.info({ invoiceId, paymentRef }, 'Invoice marked as paid ✅');
    return data;
}
/**
 * تحديث الفواتير المتأخرة — تُنفذ دورياً (cron)
 * أي فاتورة pending من شهر سابق تصبح overdue
 */
export async function markOverdueInvoices() {
    const now = new Date();
    const currentMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
    const { data, error } = await supabase
        .from('invoices')
        .update({ status: 'overdue' })
        .eq('status', 'pending')
        .lt('month', currentMonth)
        .select('id');
    if (error) {
        log.error({ error: error.message }, 'Failed to mark overdue invoices');
        return 0;
    }
    const count = data?.length ?? 0;
    if (count > 0) {
        log.info({ count }, `Marked ${count} invoices as overdue`);
    }
    return count;
}
//# sourceMappingURL=invoicing.js.map