/**
 * worker.ts — WhatsApp worker entrypoint
 *
 * Exposes a small HTTP API on port 3002 for the main API to:
 *   POST   /sessions         — start/restore a Baileys session
 *   DELETE /sessions/:id     — terminate a session
 *   GET    /health           — health check
 *
 * Inbound messages are forwarded to the main API via /internal/messages.
 */
import 'dotenv/config';
import http from 'http';
import { createBaileysSession } from './session.js';
import type { ActiveSession } from './session.js';

const PORT       = Number(process.env.PORT ?? 3002);
const API_URL    = process.env.API_INTERNAL_URL ?? 'http://api:3001';

const sessions = new Map<string, ActiveSession>();

async function waitForApi(retries = 20): Promise<void> {
  for (let i = 0; i < retries; i++) {
    try {
      const res = await fetch(`${API_URL}/health`);
      if (res.ok) { console.log('[Worker] API is ready'); return; }
    } catch { /* not ready yet */ }
    console.log(`[Worker] Waiting for API… (${i + 1}/${retries})`);
    await new Promise(r => setTimeout(r, 3000));
  }
  throw new Error('[Worker] API did not become ready in time');
}

function json(res: http.ServerResponse, status: number, body: unknown) {
  const payload = JSON.stringify(body);
  res.writeHead(status, { 'Content-Type': 'application/json' });
  res.end(payload);
}

async function readBody(req: http.IncomingMessage): Promise<string> {
  return new Promise(resolve => {
    let data = '';
    req.on('data', c => { data += c; });
    req.on('end', () => resolve(data));
  });
}

const server = http.createServer(async (req, res) => {
  const url    = req.url ?? '/';
  const method = req.method ?? 'GET';

  // GET /health
  if (method === 'GET' && url === '/health') {
    return json(res, 200, { status: 'ok', sessions: sessions.size });
  }

  // POST /sessions  — start a session
  if (method === 'POST' && url === '/sessions') {
    try {
      const body   = await readBody(req);
      const { channelId } = JSON.parse(body) as { channelId: string };
      if (!channelId) return json(res, 400, { error: 'channelId required' });

      if (sessions.has(channelId)) {
        console.log(`[Worker] Session already active for ${channelId}`);
        return json(res, 200, { ok: true, existing: true });
      }

      const session = await createBaileysSession({
        channelId,
        apiUrl: API_URL,
        onReconnect: (newSession) => {
          sessions.set(channelId, newSession);
          console.log(`[Worker] Session reconnected and updated for ${channelId}`);
        },
      });
      sessions.set(channelId, session);
      console.log(`[Worker] Started session for ${channelId}`);
      return json(res, 201, { ok: true });
    } catch (err) {
      console.error('[Worker] Failed to start session:', err);
      return json(res, 500, { error: String(err) });
    }
  }

  // POST /send  — send a WhatsApp message
  if (method === 'POST' && url === '/send') {
    try {
      const body = await readBody(req);
      const { channelId, phone, text } = JSON.parse(body) as { channelId: string; phone: string; text: string };
      if (!channelId || !phone || !text) return json(res, 400, { error: 'channelId, phone, and text are required' });

      const session = sessions.get(channelId);
      if (!session) return json(res, 404, { error: 'No active session for this channel' });

      // Normalise to WhatsApp JID (strip + prefix)
      const jid = phone.replace(/^\+/, '') + '@s.whatsapp.net';
      const sent = await session.socket.sendMessage(jid, { text });
      console.log(`[Worker] Sent message to ${jid} via channel ${channelId}: ${sent?.key?.id}`);
      return json(res, 200, { ok: true, waMessageId: sent?.key?.id ?? null });
    } catch (err) {
      console.error('[Worker] Failed to send message:', err);
      return json(res, 500, { error: String(err) });
    }
  }

  // DELETE /sessions/:id  — terminate a session
  const deleteMatch = url.match(/^\/sessions\/(.+)$/);
  if (method === 'DELETE' && deleteMatch) {
    const channelId = deleteMatch[1];
    const session   = sessions.get(channelId);
    if (session) {
      try { await session.socket.logout(); } catch { /* ignore */ }
      sessions.delete(channelId);
    }
    return json(res, 204, null);
  }

  json(res, 404, { error: 'Not found' });
});

async function notifyApiReady(): Promise<void> {
  // Tell the API the worker is up so it can restore sessions
  try {
    await fetch(`${API_URL}/internal/worker-ready`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ready: true }),
    });
    console.log('[Worker] Notified API of readiness');
  } catch (err) {
    console.warn('[Worker] Could not notify API of readiness:', err);
  }
}

async function main() {
  console.log('[Worker] WhatsApp worker starting…');
  await waitForApi();

  server.listen(PORT, '0.0.0.0', async () => {
    console.log(`[Worker] HTTP API listening on port ${PORT}`);
    // Small delay to ensure the HTTP server is fully accepting connections
    setTimeout(notifyApiReady, 1000);
  });
}

main().catch(err => {
  console.error('[Worker] Fatal error:', err);
  process.exit(1);
});
