/**
 * src/billing/routes.ts
 * مسارات الفوترة والاشتراكات — Billing & subscription routes
 */
import { z } from 'zod';
import { createChildLogger } from '../utils/logger.js';
import { supabase } from '../utils/supabase.js';
import { listPlans, getPlan, getUsageVsPlan, checkLimit } from './plans.js';
import { walletManager } from './wallet.js';
import { generateMonthlyInvoice, getTenantInvoices, markInvoicePaid } from './invoicing.js';
import { getDailyCostReport, getModelCostComparison } from './cost-optimizer.js';
import { authMiddleware, tenantMiddleware } from '../auth/middleware.js';
const log = createChildLogger('billing:routes');
// ─── Route Registration ──────────────────────────────────────────────
export async function registerBillingRoutes(app) {
    // ─── GET /api/billing/plans — قائمة الخطط المتاحة (عام) ───
    app.get('/api/billing/plans', async (_request, reply) => {
        const plans = listPlans();
        return reply.send({
            success: true,
            data: plans,
        });
    });
    // ─── GET /api/billing/:tenantId/usage — الاستخدام مقابل الخطة ───
    app.get('/api/billing/:tenantId/usage', { preHandler: [authMiddleware, tenantMiddleware] }, async (request, reply) => {
        try {
            const { tenantId } = request.params;
            const usage = await getUsageVsPlan(tenantId);
            if (!usage) {
                return reply.status(404).send({
                    success: false,
                    error: 'Tenant not found or invalid plan',
                });
            }
            return reply.send({ success: true, data: usage });
        }
        catch (err) {
            log.error({ error: err instanceof Error ? err.message : String(err) }, 'Failed to get usage');
            return reply.status(500).send({ success: false, error: 'Internal server error' });
        }
    });
    // ─── POST /api/billing/:tenantId/upgrade — ترقية الخطة ───
    app.post('/api/billing/:tenantId/upgrade', { preHandler: [authMiddleware, tenantMiddleware] }, async (request, reply) => {
        try {
            const { tenantId } = request.params;
            const upgradeSchema = z.object({
                plan_id: z.enum(['starter', 'growth', 'enterprise']),
            });
            const { plan_id } = upgradeSchema.parse(request.body);
            const plan = getPlan(plan_id);
            if (!plan) {
                return reply.status(400).send({
                    success: false,
                    error: 'خطة غير صالحة — Invalid plan',
                });
            }
            // TODO: تكامل مع بوابة دفع (مثل Moyasar / Tap / HyperPay)
            // حالياً: ترقية مباشرة بدون دفع (placeholder)
            const { error } = await supabase
                .from('tenants')
                .update({
                plan: plan_id,
                status: 'active',
                updated_at: new Date().toISOString(),
            })
                .eq('id', tenantId);
            if (error) {
                log.error({ tenantId, planId: plan_id, error: error.message }, 'Failed to upgrade plan');
                return reply.status(500).send({
                    success: false,
                    error: 'فشل ترقية الخطة — Failed to upgrade',
                });
            }
            log.info({ tenantId, newPlan: plan_id }, 'Plan upgraded successfully');
            return reply.send({
                success: true,
                message: `تم الترقية إلى خطة ${plan.name_ar} — Upgraded to ${plan.name}`,
                data: {
                    plan_id,
                    plan_name: plan.name,
                    plan_name_ar: plan.name_ar,
                    price_sar: plan.price_sar,
                    // TODO: إضافة رابط الدفع هنا
                    payment_url: null,
                },
            });
        }
        catch (err) {
            if (err instanceof z.ZodError) {
                return reply.status(400).send({
                    success: false,
                    error: 'Validation error',
                    details: err.issues.map(i => ({ field: i.path.join('.'), message: i.message })),
                });
            }
            log.error({ error: err instanceof Error ? err.message : String(err) }, 'Upgrade error');
            return reply.status(500).send({ success: false, error: 'Internal server error' });
        }
    });
    // ─── GET /api/billing/:tenantId/check/:resource — فحص سريع لحد معين ───
    app.get('/api/billing/:tenantId/check/:resource', { preHandler: [authMiddleware, tenantMiddleware] }, async (request, reply) => {
        try {
            const { tenantId, resource } = request.params;
            if (!['messages', 'agents', 'documents'].includes(resource)) {
                return reply.status(400).send({
                    success: false,
                    error: 'Invalid resource — allowed: messages, agents, documents',
                });
            }
            const result = await checkLimit(tenantId, resource);
            return reply.send({ success: true, data: result });
        }
        catch (err) {
            log.error({ error: err instanceof Error ? err.message : String(err) }, 'Limit check error');
            return reply.status(500).send({ success: false, error: 'Internal server error' });
        }
    });
    // ─── GET /api/billing/:tenantId/wallet — حالة الميزانية الداخلية (إدارة فقط) ───
    app.get('/api/billing/:tenantId/wallet', { preHandler: [authMiddleware, tenantMiddleware] }, async (request, reply) => {
        try {
            const { tenantId } = request.params;
            const [budgetStatus, profit] = await Promise.all([
                walletManager.getBudgetStatus(tenantId),
                walletManager.getProfit(tenantId),
            ]);
            return reply.send({
                success: true,
                data: {
                    budget: budgetStatus,
                    profit,
                },
            });
        }
        catch (err) {
            log.error({ error: err instanceof Error ? err.message : String(err) }, 'Failed to get wallet status');
            return reply.status(500).send({ success: false, error: 'Internal server error' });
        }
    });
    // ─── GET /api/billing/:tenantId/invoices — قائمة فواتير المستأجر ───
    app.get('/api/billing/:tenantId/invoices', { preHandler: [authMiddleware, tenantMiddleware] }, async (request, reply) => {
        try {
            const { tenantId } = request.params;
            const query = request.query;
            const result = await getTenantInvoices(tenantId, {
                limit: query.limit ? parseInt(query.limit, 10) : undefined,
                offset: query.offset ? parseInt(query.offset, 10) : undefined,
            });
            return reply.send({ success: true, data: result });
        }
        catch (err) {
            log.error({ error: err instanceof Error ? err.message : String(err) }, 'Failed to list invoices');
            return reply.status(500).send({ success: false, error: 'Internal server error' });
        }
    });
    // ─── POST /api/billing/:tenantId/invoices/generate — توليد فاتورة شهرية ───
    app.post('/api/billing/:tenantId/invoices/generate', { preHandler: [authMiddleware, tenantMiddleware] }, async (request, reply) => {
        try {
            const { tenantId } = request.params;
            const generateSchema = z.object({
                month: z.string().regex(/^\d{4}-\d{2}$/, 'Format: YYYY-MM'),
            });
            const { month } = generateSchema.parse(request.body);
            const invoice = await generateMonthlyInvoice(tenantId, month);
            return reply.send({ success: true, data: invoice });
        }
        catch (err) {
            if (err instanceof z.ZodError) {
                return reply.status(400).send({
                    success: false,
                    error: 'Validation error',
                    details: err.issues.map(i => ({ field: i.path.join('.'), message: i.message })),
                });
            }
            log.error({ error: err instanceof Error ? err.message : String(err) }, 'Failed to generate invoice');
            return reply.status(500).send({ success: false, error: 'Internal server error' });
        }
    });
    // ─── POST /api/billing/invoices/:invoiceId/pay — تسجيل دفع فاتورة ───
    app.post('/api/billing/invoices/:invoiceId/pay', { preHandler: [authMiddleware] }, async (request, reply) => {
        try {
            const { invoiceId } = request.params;
            const paySchema = z.object({
                payment_ref: z.string().min(1, 'Payment reference is required'),
            });
            const { payment_ref } = paySchema.parse(request.body);
            const invoice = await markInvoicePaid(invoiceId, payment_ref);
            return reply.send({ success: true, data: invoice });
        }
        catch (err) {
            if (err instanceof z.ZodError) {
                return reply.status(400).send({
                    success: false,
                    error: 'Validation error',
                    details: err.issues.map(i => ({ field: i.path.join('.'), message: i.message })),
                });
            }
            log.error({ error: err instanceof Error ? err.message : String(err) }, 'Failed to mark invoice paid');
            return reply.status(500).send({ success: false, error: 'Internal server error' });
        }
    });
    // ─── GET /api/billing/overview — نظرة شاملة على كل المستأجرين (إدارة) ───
    app.get('/api/billing/overview', { preHandler: [authMiddleware] }, async (request, reply) => {
        try {
            const query = request.query;
            const financials = await walletManager.getAllTenantsFinancials(query.month);
            // حساب الإجماليات
            const totals = financials.reduce((acc, t) => ({
                revenue: acc.revenue + t.contractPrice,
                apiCost: acc.apiCost + t.apiSpent,
                profit: acc.profit + t.profit,
                messages: acc.messages + t.messagesCount,
            }), { revenue: 0, apiCost: 0, profit: 0, messages: 0 });
            return reply.send({
                success: true,
                data: {
                    tenants: financials,
                    totals: {
                        ...totals,
                        margin: totals.revenue > 0
                            ? Math.round((totals.profit / totals.revenue) * 10000) / 100
                            : 0,
                        tenantCount: financials.length,
                    },
                },
            });
        }
        catch (err) {
            log.error({ error: err instanceof Error ? err.message : String(err) }, 'Failed to get billing overview');
            return reply.status(500).send({ success: false, error: 'Internal server error' });
        }
    });
    // ─── GET /api/billing/cost-report — تقرير التكاليف العام ───
    app.get('/api/billing/cost-report', { preHandler: [authMiddleware] }, async (request, reply) => {
        try {
            const query = request.query;
            const modelComparison = getModelCostComparison();
            // إذا حُدد مستأجر، نجيب تقرير يومي مفصل
            let dailyReport = null;
            if (query.tenant_id) {
                dailyReport = await getDailyCostReport(query.tenant_id, query.date);
            }
            return reply.send({
                success: true,
                data: {
                    models: modelComparison,
                    dailyReport,
                },
            });
        }
        catch (err) {
            log.error({ error: err instanceof Error ? err.message : String(err) }, 'Failed to get cost report');
            return reply.status(500).send({ success: false, error: 'Internal server error' });
        }
    });
    log.info('Billing routes registered ✅');
}
//# sourceMappingURL=routes.js.map