import { FastifyInstance } from 'fastify';
import { config } from '../config';
import { getRedisSub, REDIS_KEYS } from '../redis';
import {
  appendUserMessage,
  getHistory,
  resolveSessionId,
} from './service';

export async function supportRoutes(app: FastifyInstance): Promise<void> {
  const prefix = config.intercept.supportApiPrefix;

  app.post(`${prefix}/events/user-message`, async (request, reply) => {
    if (!config.support.enabled) {
      reply.status(503).send({ ok: false });
      return;
    }

    const body = request.body as {
      sessionId?: string;
      zowieSessionKey?: string;
      pageUrl?: string;
      text?: string;
      conversationId?: string;
    };

    const visitorUuid =
      (request.cookies as Record<string, string>)[config.session.visitorCookieName] ?? undefined;

    try {
      const result = await appendUserMessage({
        sessionId: body.sessionId,
        visitorUuid,
        zowieSessionKey: body.zowieSessionKey ?? body.conversationId,
        pageUrl: body.pageUrl,
        text: body.text ?? '',
        conversationId: body.conversationId,
      });
      reply.send({ ok: true, sessionId: result.sessionId, messageId: result.messageId });
    } catch (err) {
      reply.status(400).send({ ok: false, error: (err as Error).message });
    }
  });

  app.get(`${prefix}/history`, async (request, reply) => {
    const sessionId = (request.query as { session?: string }).session;
    if (!sessionId) {
      reply.status(400).send({ ok: false, error: 'session required' });
      return;
    }
    const messages = await getHistory(sessionId);
    reply.send({ ok: true, messages });
  });

  app.get(`${prefix}/stream`, async (request, reply) => {
    const query = request.query as {
      session?: string;
      zowieSessionKey?: string;
    };

    // SSE opens only after the client has a support session id (post first message).
    // Reject anonymous stream probes early to avoid DB lookups and retry storms.
    const sessionParam = query.session?.trim();
    if (!sessionParam) {
      reply.status(400).send('session required');
      return;
    }

    const visitorUuid =
      (request.cookies as Record<string, string>)[config.session.visitorCookieName] ?? undefined;

    let sessionId: string | null = null;
    try {
      sessionId = await resolveSessionId({
        sessionId: sessionParam,
        visitorUuid,
      });
    } catch (err) {
      request.log.error({ err }, 'support stream resolveSessionId failed');
      reply.status(503).send('support unavailable');
      return;
    }

    if (!sessionId) {
      reply.status(404).send('session not found');
      return;
    }

    reply.raw.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache, no-transform',
      Connection: 'keep-alive',
      'X-Accel-Buffering': 'no',
    });

    const channel = REDIS_KEYS.supportSessionChannel(sessionId);
    const sub = getRedisSub();
    await sub.subscribe(channel);

    const onMessage = (_ch: string, message: string) => {
      reply.raw.write(`data: ${message}\n\n`);
    };
    sub.on('message', onMessage);

    const keepAlive = setInterval(() => {
      reply.raw.write(': keepalive\n\n');
    }, 25000);

    request.raw.on('close', () => {
      clearInterval(keepAlive);
      sub.off('message', onMessage);
      sub.unsubscribe(channel).catch(() => {});
    });
  });
}
