/**
 * src/billing/wallet.ts
 * إدارة الميزانية الداخلية والتكاليف — Internal credit/cost management
 *
 * نموذج العمل: العميل يدفع اشتراك شهري ثابت.
 * TaseesAI يتتبع التكاليف داخلياً — العميل لا يرى شيء عن التوكنات أو التكاليف.
 */
import { createChildLogger } from '../utils/logger.js';
import { supabase } from '../utils/supabase.js';
import { getPlan } from './plans.js';
const log = createChildLogger('billing:wallet');
// ─── سعر الصرف التقريبي ─────────────────────────────────────────────
const SAR_TO_USD = 0.2667; // 1 SAR ≈ $0.2667
// ─── ميزانية API الداخلية لكل خطة ─────────────────────────────────
// هذي التكلفة اللي نتحملها من الاشتراك — الباقي ربح
const PLAN_INTERNAL_BUDGETS = {
    trial: 30, // 30 ريال (~$8) — فترة تجربة محدودة
    starter: 150, // 150 ريال (~$40) من 499 ريال اشتراك
    growth: 375, // 375 ريال (~$100) من 1,499 ريال اشتراك
    enterprise: 1125, // 1,125 ريال (~$300) من 4,999 ريال اشتراك
};
// ─── WalletManager ───────────────────────────────────────────────────
export class WalletManager {
    /**
     * حساب ميزانية API الشهرية الداخلية بناءً على الخطة
     */
    async getInternalBudget(tenantId) {
        // أولاً: فحص إذا عنده إعدادات مخصصة (custom budget)
        const { data: customConfig } = await supabase
            .from('budget_config')
            .select('monthly_budget_sar')
            .eq('tenant_id', tenantId)
            .single();
        if (customConfig?.monthly_budget_sar) {
            return Number(customConfig.monthly_budget_sar);
        }
        // ثانياً: الميزانية الافتراضية حسب الخطة
        const { data: tenant } = await supabase
            .from('tenants')
            .select('plan')
            .eq('id', tenantId)
            .single();
        if (!tenant) {
            log.warn({ tenantId }, 'Tenant not found for budget calculation');
            return 0;
        }
        return PLAN_INTERNAL_BUDGETS[tenant.plan] ?? 0;
    }
    /**
     * إعدادات الميزانية الكاملة (مع نسب التقليص)
     */
    async getBudgetConfig(tenantId) {
        const { data: config } = await supabase
            .from('budget_config')
            .select('*')
            .eq('tenant_id', tenantId)
            .single();
        const budget = await this.getInternalBudget(tenantId);
        return {
            monthlyBudgetSar: budget,
            throttleAtPercent: config?.throttle_at_percent ?? 90,
            hardLimitAtPercent: config?.hard_limit_at_percent ?? 100,
            overageAllowed: config?.overage_allowed ?? false,
            overageRateMultiplier: Number(config?.overage_rate_multiplier ?? 1.5),
        };
    }
    /**
     * المصروف الحالي من API هذا الشهر (بالريال)
     * يحسب من جدول usage (الإجمالي اليومي)
     */
    async getCurrentSpend(tenantId, month) {
        const targetMonth = month ?? this.getCurrentMonth();
        const startDate = `${targetMonth}-01`;
        const endDate = this.getMonthEndDate(targetMonth);
        const { data, error } = await supabase
            .from('usage')
            .select('cost_usd')
            .eq('tenant_id', tenantId)
            .gte('date', startDate)
            .lt('date', endDate);
        if (error) {
            log.error({ tenantId, error: error.message }, 'Failed to get current spend');
            return 0;
        }
        const totalUsd = (data ?? []).reduce((sum, row) => sum + (Number(row.cost_usd) || 0), 0);
        // تحويل من دولار إلى ريال
        return Math.round((totalUsd / SAR_TO_USD) * 100) / 100;
    }
    /**
     * حالة الميزانية الكاملة
     */
    async getBudgetStatus(tenantId) {
        const [budget, spent, tenantData, budgetConfig] = await Promise.all([
            this.getInternalBudget(tenantId),
            this.getCurrentSpend(tenantId),
            supabase.from('tenants').select('plan').eq('id', tenantId).single(),
            this.getBudgetConfig(tenantId),
        ]);
        const remaining = Math.max(0, budget - spent);
        const percentUsed = budget > 0 ? Math.round((spent / budget) * 10000) / 100 : 0;
        return {
            tenantId,
            planName: tenantData.data?.plan ?? 'unknown',
            budget,
            spent,
            remaining,
            percentUsed,
            isOverBudget: spent > budget,
            throttleActive: percentUsed >= budgetConfig.throttleAtPercent,
        };
    }
    /**
     * حساب الربح: سعر الاشتراك - تكلفة API
     */
    async getProfit(tenantId, month) {
        const targetMonth = month ?? this.getCurrentMonth();
        const { data: tenant } = await supabase
            .from('tenants')
            .select('plan')
            .eq('id', tenantId)
            .single();
        if (!tenant) {
            return { contractPrice: 0, apiCost: 0, profit: 0, margin: 0 };
        }
        const plan = getPlan(tenant.plan);
        const contractPrice = plan?.price_sar ?? 0;
        const apiCost = await this.getCurrentSpend(tenantId, targetMonth);
        const profit = contractPrice - apiCost;
        const margin = contractPrice > 0 ? Math.round((profit / contractPrice) * 10000) / 100 : 0;
        return { contractPrice, apiCost, profit, margin };
    }
    /**
     * هل يجب تقليل جودة النموذج لتوفير التكاليف؟
     * true إذا المصروف تجاوز 90% من الميزانية
     */
    async shouldThrottle(tenantId) {
        const status = await this.getBudgetStatus(tenantId);
        return status.throttleActive;
    }
    /**
     * توصية النموذج المناسب بناءً على الميزانية المتبقية
     *
     * - عادي (<80%): النموذج الأمثل حسب النية (brain/reasoning)
     * - ميزانية ضيقة (80-95%): Gemini Flash أكثر
     * - ميزانية حرجة (>95%): كل شيء Gemini Flash إلا الشكاوى والتصعيد
     */
    async getRecommendedTier(tenantId, intent, originalTier = 'brain') {
        const status = await this.getBudgetStatus(tenantId);
        // الميزانية مريحة — استخدم النموذج الأصلي
        if (status.percentUsed < 80) {
            return { tier: originalTier, reason: 'budget_healthy', downgraded: false };
        }
        // النوايا اللي ما نقلل فيها أبداً (حتى لو الميزانية حرجة)
        const criticalIntents = ['escalate_to_human', 'complaint', 'urgent_complaint'];
        if (criticalIntents.includes(intent)) {
            return { tier: originalTier, reason: 'critical_intent_protected', downgraded: false };
        }
        // ميزانية ضيقة (80-95%) — نقلل على بعض الأمور
        if (status.percentUsed < 95) {
            // reasoning يتحول لـ brain، brain يتحول لـ flash على الأشياء البسيطة
            const simpleIntents = ['greeting', 'faq', 'hours', 'location', 'contact_info'];
            if (originalTier === 'reasoning') {
                return { tier: 'brain', reason: 'budget_tight_downgrade_reasoning', downgraded: true };
            }
            if (originalTier === 'brain' && simpleIntents.includes(intent)) {
                return { tier: 'flash', reason: 'budget_tight_simple_to_flash', downgraded: true };
            }
            return { tier: originalTier, reason: 'budget_tight_keeping_tier', downgraded: false };
        }
        // ميزانية حرجة (>95%) — كل شيء flash
        log.warn({ tenantId, percentUsed: status.percentUsed, intent }, 'Budget critical — forcing Gemini Flash');
        return { tier: 'flash', reason: 'budget_critical_all_flash', downgraded: true };
    }
    /**
     * نظرة شاملة على جميع المستأجرين — للوحة إدارة TaseesAI
     */
    async getAllTenantsFinancials(month) {
        const targetMonth = month ?? this.getCurrentMonth();
        const { data: tenants, error } = await supabase
            .from('tenants')
            .select('id, business_name, plan, status')
            .in('status', ['active', 'trial']);
        if (error || !tenants) {
            log.error({ error: error?.message }, 'Failed to fetch tenants for financials');
            return [];
        }
        const results = [];
        for (const tenant of tenants) {
            const plan = getPlan(tenant.plan);
            const contractPrice = plan?.price_sar ?? 0;
            const apiBudget = PLAN_INTERNAL_BUDGETS[tenant.plan] ?? 0;
            const apiSpent = await this.getCurrentSpend(tenant.id, targetMonth);
            const profit = contractPrice - apiSpent;
            const margin = contractPrice > 0 ? Math.round((profit / contractPrice) * 10000) / 100 : 0;
            // عدد الرسائل هذا الشهر
            const startDate = `${targetMonth}-01`;
            const endDate = this.getMonthEndDate(targetMonth);
            const { data: usageRows } = await supabase
                .from('usage')
                .select('messages_count')
                .eq('tenant_id', tenant.id)
                .gte('date', startDate)
                .lt('date', endDate);
            const messagesCount = (usageRows ?? []).reduce((sum, row) => sum + (row.messages_count ?? 0), 0);
            results.push({
                tenantId: tenant.id,
                businessName: tenant.business_name,
                planName: tenant.plan,
                contractPrice,
                apiBudget,
                apiSpent,
                profit,
                margin,
                messagesCount,
                budgetPercent: apiBudget > 0 ? Math.round((apiSpent / apiBudget) * 10000) / 100 : 0,
            });
        }
        // ترتيب حسب الربح (الأعلى أولاً)
        return results.sort((a, b) => b.profit - a.profit);
    }
    // ─── Helpers ─────────────────────────────────────────────────────
    getCurrentMonth() {
        const now = new Date();
        return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
    }
    getMonthEndDate(month) {
        const [year, m] = month.split('-').map(Number);
        if (m === 12)
            return `${year + 1}-01-01`;
        return `${year}-${String(m + 1).padStart(2, '0')}-01`;
    }
}
// ─── Singleton Export ────────────────────────────────────────────────
export const walletManager = new WalletManager();
//# sourceMappingURL=wallet.js.map