/**
 * Internal routes — called by the Baileys WhatsApp worker.
 * These are NOT exposed via Kong / public gateway.
 * Restrict access by ensuring this route is only bound on a private interface
 * or protected by an internal secret.
 */
import type { FastifyInstance } from 'fastify';
import { channelService } from '../services/channelService.js';
import { auditService } from '../services/auditService.js';
import {
  processWhatsAppInbound,
  InboundChannelNotFoundError,
  type NormalizedWhatsAppInbound,
} from '../services/whatsappInboundService.js';

export async function internalRoutes(fastify: FastifyInstance) {
  // Large JSON bodies: inbound media as base64 (max aligned with storage FILE_SIZE_LIMIT)
  fastify.post('/messages', { bodyLimit: 58 * 1024 * 1024 }, async (req, reply) => {
    const body = req.body as NormalizedWhatsAppInbound;
    const { channelId, phone, text, messageType, mediaBase64, mediaMime } = body;

    if (!channelId || !phone) {
      return reply.status(400).send({ error: 'channelId and phone are required' });
    }

    const isMedia = messageType === 'image' || messageType === 'voice_note' || messageType === 'document';

    if (!isMedia && !(text?.trim())) {
      return reply.status(400).send({ error: 'text is required for text messages' });
    }

    if (isMedia && (!mediaBase64?.trim() || !mediaMime?.trim())) {
      return reply.status(400).send({ error: 'mediaBase64 and mediaMime are required for media messages' });
    }

    try {
      const result = await processWhatsAppInbound(body, { io: fastify.io, log: fastify.log });
      return reply.status(200).send(result);
    } catch (err) {
      if (err instanceof InboundChannelNotFoundError) {
        return reply.status(404).send({ error: 'Channel not found' });
      }
      throw err;
    }
  });

  fastify.post('/ws-event', async (req, reply) => {
    const { event, payload } = req.body as { event: string; payload: unknown };
    fastify.io.emit(event, payload);
    return reply.send({ ok: true });
  });

  fastify.post('/channel-status', async (req, reply) => {
    const { channelId, status, sessionData, reason } = req.body as {
      channelId: string;
      status: 'connected' | 'disconnected' | null;
      sessionData?: unknown;
      reason?: string;
    };

    if (status) {
      await channelService.setStatus(channelId, status);
      if (status === 'connected') {
        fastify.io.emit('channel:connected', { channelId });
        await auditService.log(null, 'system', 'channel.connected', 'channel', channelId, {});
      } else {
        fastify.io.emit('channel:disconnected', { channelId, reason: reason ?? 'Unknown' });
        await auditService.log(null, 'system', 'channel.disconnected', 'channel', channelId, { reason });
      }
    }

    if (sessionData !== undefined) {
      await channelService.saveSession(channelId, sessionData);
    }

    return reply.send({ ok: true });
  });

  fastify.post('/worker-ready', async (_req, reply) => {
    fastify.log.info('[Internal] Worker signalled ready — restoring sessions');
    channelService.restoreAllSessions(fastify.io).catch(err => {
      fastify.log.warn({ err }, 'Session restore after worker-ready failed');
    });
    return reply.send({ ok: true });
  });
}
