/**
 * src/gateway/routes.ts
 * مسارات إدارة البوابة — Gateway admin routes
 */
import { z } from 'zod';
import { supabase } from '../utils/supabase.js';
import { createChildLogger } from '../utils/logger.js';
import { MODELS } from '../config.js';
import { authMiddleware } from '../auth/middleware.js';
const log = createChildLogger('gateway:routes');
const startTime = Date.now();
// (v2.5.10) Cached package version. The CLI binary doesn't have
// `npm_package_version` set so we walk up the dist tree to find
// package.json. Cached after first read.
let _cachedVersion = null;
async function readPackageVersion() {
    if (_cachedVersion)
        return _cachedVersion;
    try {
        const { readFile } = await import('node:fs/promises');
        const { fileURLToPath } = await import('node:url');
        const { dirname, resolve } = await import('node:path');
        const here = dirname(fileURLToPath(import.meta.url));
        // Walk up from dist/gateway/ → dist → package root
        const candidates = [
            resolve(here, '..', '..', 'package.json'),
            resolve(here, '..', '..', '..', 'package.json'),
            resolve(here, '..', 'package.json'),
        ];
        for (const p of candidates) {
            try {
                const raw = await readFile(p, 'utf-8');
                const json = JSON.parse(raw);
                if (json.version && (json.name === '@almoasisai/muassis' || !_cachedVersion)) {
                    _cachedVersion = json.version;
                    return _cachedVersion;
                }
            }
            catch { /* try next */ }
        }
    }
    catch { /* fall through */ }
    _cachedVersion = process.env['npm_package_version'] ?? '0.0.0-dev';
    return _cachedVersion;
}
// ─── Schemas ─────────────────────────────────────────────────────────
const testMessageSchema = z.object({
    tenantId: z.string().uuid(),
    message: z.string().min(1).max(4096),
    from: z.string().default('test-user'),
});
// ─── Route Registration ─────────────────────────────────────────────
export function registerGatewayRoutes(app) {
    // (v2.5.10) GET /api/version — Public, no auth. Used by the dashboard
    // footer + sidebar so the user sees the actually-running version.
    // package.json is the source of truth; we read it at request time
    // (cached after first read) because `npm_package_version` env var
    // isn't set when the CLI binary is invoked directly outside `npm run`.
    app.get('/api/version', async (_req, reply) => {
        return reply.send({ version: await readPackageVersion() });
    });
    // GET /api/status — System status (auth-required: leaks tenant count + version)
    app.get('/api/status', { preHandler: [authMiddleware] }, async (_req, reply) => {
        try {
            const uptimeMs = Date.now() - startTime;
            const uptimeHours = Math.round(uptimeMs / 3600000 * 10) / 10;
            // Tenant count
            const { count: tenantCount, error: tenantErr } = await supabase
                .from('tenants')
                .select('*', { count: 'exact', head: true });
            // Messages today
            const todayStart = new Date();
            todayStart.setHours(0, 0, 0, 0);
            const { count: messageCount, error: msgErr } = await supabase
                .from('messages')
                .select('*', { count: 'exact', head: true })
                .gte('created_at', todayStart.toISOString());
            if (tenantErr)
                log.warn({ error: tenantErr.message }, 'Failed to count tenants');
            if (msgErr)
                log.warn({ error: msgErr.message }, 'Failed to count messages');
            return reply.send({
                status: 'operational',
                uptime: {
                    ms: uptimeMs,
                    hours: uptimeHours,
                    since: new Date(startTime).toISOString(),
                },
                tenants: tenantCount ?? 0,
                messagesToday: messageCount ?? 0,
                version: process.env['npm_package_version'] ?? '0.1.0',
                environment: process.env['NODE_ENV'] ?? 'development',
            });
        }
        catch (err) {
            log.error({ err }, 'Status endpoint error');
            return reply.code(500).send({ error: 'Internal server error' });
        }
    });
    // GET /api/models — Available models (auth-required: leaks provider/cost config)
    app.get('/api/models', { preHandler: [authMiddleware] }, async (_req, reply) => {
        const models = Object.entries(MODELS).map(([tier, cfg]) => ({
            tier,
            provider: cfg.provider,
            model: cfg.model,
            costPer1MInput: cfg.costPer1MInput,
            costPer1MOutput: cfg.costPer1MOutput,
            status: 'available', // TODO: health check each provider
        }));
        return reply.send({ models });
    });
    // POST /api/test-message — Send test message to agent
    // Public + writes to messages table — anyone with a tenant UUID can poison
    // conversation history. Tight rate limit until this gets proper auth.
    app.post('/api/test-message', {
        config: { rateLimit: { max: 10, timeWindow: '1 minute' } },
    }, async (req, reply) => {
        try {
            const parsed = testMessageSchema.safeParse(req.body);
            if (!parsed.success) {
                return reply.code(400).send({
                    error: 'Invalid request',
                    details: parsed.error.issues,
                });
            }
            const { tenantId, message, from } = parsed.data;
            // Verify tenant exists
            const { data: tenant, error: tenantErr } = await supabase
                .from('tenants')
                .select('id, name, status')
                .eq('id', tenantId)
                .single();
            if (tenantErr || !tenant) {
                return reply.code(404).send({ error: 'Tenant not found' });
            }
            if (tenant.status !== 'active') {
                return reply.code(403).send({ error: 'Tenant is not active' });
            }
            // Log the test message
            const { data: msgRecord, error: msgErr } = await supabase
                .from('messages')
                .insert({
                tenant_id: tenantId,
                direction: 'inbound',
                type: 'text',
                content: message,
                from_number: from,
                channel: 'test',
                metadata: { test: true },
            })
                .select('id')
                .single();
            if (msgErr) {
                log.error({ error: msgErr.message }, 'Failed to log test message');
                return reply.code(500).send({ error: 'Failed to process test message' });
            }
            log.info({ tenantId, messageId: msgRecord?.id }, 'Test message sent');
            return reply.send({
                success: true,
                messageId: msgRecord?.id,
                note: 'Message logged. Agent processing is async — check messages table for response.',
            });
        }
        catch (err) {
            log.error({ err }, 'Test message endpoint error');
            return reply.code(500).send({ error: 'Internal server error' });
        }
    });
    log.info('Gateway admin routes registered');
}
//# sourceMappingURL=routes.js.map