import type { FastifyInstance } from 'fastify';
import { emailContactKey } from '@wa-ticketing/shared';
import { channelService } from '../services/channelService.js';
import { contactService } from '../services/contactService.js';
import { ticketService } from '../services/ticketService.js';
import { messagingService } from '../services/messagingService.js';
import { talkbackService } from '../services/talkbackService.js';
import { notifyInboundAlerts } from '../services/channelAlertService.js';

/**
 * Public webhook (auth = secret token in URL). POST JSON from your mail parser or automation.
 * Body: { from, text, subject?, from_name?, message_id? }
 */
export async function inboundEmailRoutes(fastify: FastifyInstance) {
  fastify.post('/inbound/email/:token', async (req, reply) => {
    const { token } = req.params as { token: string };
    const body = req.body as {
      from?: string;
      text?: string;
      subject?: string;
      from_name?: string;
      message_id?: string;
    };

    const fromRaw = body.from?.trim();
    const text = body.text?.trim() ?? '';
    if (!fromRaw || !text) {
      return reply.status(400).send({ error: 'from and text are required' });
    }
    const fullText = body.subject?.trim() ? `Subject: ${body.subject.trim()}\n\n${text}` : text;

    const channel = await channelService.getByInboundToken(token);
    if (!channel) return reply.status(404).send({ error: 'Unknown token' });

    const extId = body.message_id?.trim() || null;
    if (extId && (await messagingService.isDuplicate(extId))) {
      return reply.send({ ok: true, duplicate: true });
    }

    const contactKey = emailContactKey(fromRaw);
    const contact = await contactService.findOrCreate(contactKey, body.from_name?.trim() || fromRaw);

    const priorCount = await ticketService.countForContactChannel(contact.id, channel.id);
    let ticket = await ticketService.findOpenTicket(contact.id, channel.id);
    let isNew = false;

    if (!ticket) {
      const intake = ticketService.buildInitialIntake(channel.settings!, priorCount === 0);
      ticket = await ticketService.createTicket(contact.id, channel.id, intake);
      isNew = true;
    }

    const message = await messagingService.appendMessage(ticket.id, 'inbound', fullText, extId, undefined, 'email');

    if (isNew) {
      fastify.io.emit('ticket:created', { ticket });
    } else {
      fastify.io.to(`ticket:${ticket.id}`).emit('message:new', { ticketId: ticket.id, message });
    }

    const line = fullText;
    const { flaggedEscalation } = await notifyInboundAlerts({
      ticketId: ticket.id,
      channelId: channel.id,
      channelName: channel.name,
      fromLabel: `${fromRaw}${body.from_name ? ` (${body.from_name})` : ''}`,
      preview: line,
      settings: channel.settings!,
    });
    if (flaggedEscalation) {
      const t2 = await ticketService.getById(ticket.id);
      if (t2) fastify.io.to(`ticket:${ticket.id}`).emit('ticket:updated', { ticket: t2 });
    }

    const chFull = await channelService.getById(channel.id);
    if (chFull) {
      talkbackService
        .handleInbound({
          io: fastify.io,
          log: fastify.log,
          ticket,
          channel: chFull,
          contactPhone: contact.phone_number,
          inboundText: fullText,
        })
        .catch(err => fastify.log.error({ err, ticketId: ticket.id }, '[inboundEmail] talkback failed'));
    }

    return reply.send({ ok: true, ticketId: ticket.id, messageId: message.id });
  });
}
