import { Response } from 'express';
import { prisma } from '../config/database';
import { AuthRequest } from '../middleware/auth';
import { sendMail } from '../config/mailer';
import { resolveTags } from '../utils/email-triggers';

export async function listTemplates(req: AuthRequest, res: Response): Promise<void> {
  try {
    const { eventId } = req.params;

    const event = await prisma.event.findFirst({
      where: { id: eventId, organizerId: req.organizerId },
    });

    if (!event) {
      res.status(404).json({ error: 'Event not found' });
      return;
    }

    const templates = await prisma.emailTemplate.findMany({
      where: { eventId },
      orderBy: { createdAt: 'desc' },
    });

    res.json(templates);
  } catch (error) {
    console.error('listTemplates error:', error);
    res.status(500).json({ error: 'Failed to fetch templates' });
  }
}

export async function createTemplate(req: AuthRequest, res: Response): Promise<void> {
  try {
    const { eventId } = req.params;

    const event = await prisma.event.findFirst({
      where: { id: eventId, organizerId: req.organizerId },
    });

    if (!event) {
      res.status(404).json({ error: 'Event not found' });
      return;
    }

    const { name, subject, body } = req.body;

    if (!name || !subject || !body) {
      res.status(400).json({ error: 'Name, subject, and body are required' });
      return;
    }

    const template = await prisma.emailTemplate.create({
      data: { eventId, name, subject, body },
    });

    res.status(201).json(template);
  } catch (error) {
    console.error('createTemplate error:', error);
    res.status(500).json({ error: 'Failed to create template' });
  }
}

export async function updateTemplate(req: AuthRequest, res: Response): Promise<void> {
  try {
    const { eventId, id } = req.params;

    const event = await prisma.event.findFirst({
      where: { id: eventId, organizerId: req.organizerId },
    });

    if (!event) {
      res.status(404).json({ error: 'Event not found' });
      return;
    }

    const existing = await prisma.emailTemplate.findFirst({
      where: { id, eventId },
    });

    if (!existing) {
      res.status(404).json({ error: 'Template not found' });
      return;
    }

    const { name, subject, body } = req.body;

    const template = await prisma.emailTemplate.update({
      where: { id },
      data: {
        ...(name !== undefined && { name }),
        ...(subject !== undefined && { subject }),
        ...(body !== undefined && { body }),
      },
    });

    res.json(template);
  } catch (error) {
    console.error('updateTemplate error:', error);
    res.status(500).json({ error: 'Failed to update template' });
  }
}

export async function deleteTemplate(req: AuthRequest, res: Response): Promise<void> {
  try {
    const { eventId, id } = req.params;

    const event = await prisma.event.findFirst({
      where: { id: eventId, organizerId: req.organizerId },
    });

    if (!event) {
      res.status(404).json({ error: 'Event not found' });
      return;
    }

    const existing = await prisma.emailTemplate.findFirst({
      where: { id, eventId },
    });

    if (!existing) {
      res.status(404).json({ error: 'Template not found' });
      return;
    }

    await prisma.emailTemplate.delete({ where: { id } });

    res.json({ message: 'Template deleted' });
  } catch (error) {
    console.error('deleteTemplate error:', error);
    res.status(500).json({ error: 'Failed to delete template' });
  }
}

export async function createBroadcast(req: AuthRequest, res: Response): Promise<void> {
  try {
    const { eventId } = req.params;

    const event = await prisma.event.findFirst({
      where: { id: eventId, organizerId: req.organizerId },
    });

    if (!event) {
      res.status(404).json({ error: 'Event not found' });
      return;
    }

    const { templateId, fromName, fromEmail, subject, body, recipientIds } = req.body;

    if (!subject || !body) {
      res.status(400).json({ error: 'Subject and body are required' });
      return;
    }

    if (!Array.isArray(recipientIds) || recipientIds.length === 0) {
      res.status(400).json({ error: 'At least one recipient is required' });
      return;
    }

    const attendees = await prisma.attendee.findMany({
      where: { id: { in: recipientIds }, eventId },
      include: { category: { select: { name: true } } },
    });

    const senderName = fromName || event.fromName || 'Visity';
    const senderEmail = fromEmail || event.fromEmail || 'noreply@visity.io';

    let delivered = 0;
    let failed = 0;

    for (const a of attendees) {
      if (!a.email) {
        failed++;
        continue;
      }
      try {
        const resolvedSubject = resolveTags(subject, a as any, event as any);
        const resolvedBody = resolveTags(body, a as any, event as any);
        await sendMail(a.email, resolvedSubject, resolvedBody);
        delivered++;
      } catch (err) {
        console.error(`Broadcast: failed to send to ${a.email}:`, err);
        failed++;
      }
    }

    const broadcast = await prisma.emailBroadcast.create({
      data: {
        eventId,
        templateId,
        fromName: senderName,
        fromEmail: senderEmail,
        subject,
        body,
        totalSent: attendees.length,
        delivered,
        failed,
        sentAt: new Date(),
      },
    });

    res.status(201).json({
      ...broadcast,
      message: `Sent to ${delivered} of ${attendees.length} recipient${attendees.length === 1 ? '' : 's'}`,
    });
  } catch (error) {
    console.error('createBroadcast error:', error);
    res.status(500).json({ error: 'Failed to create broadcast' });
  }
}

export async function getDeliveryReport(req: AuthRequest, res: Response): Promise<void> {
  try {
    const { eventId } = req.params;

    const event = await prisma.event.findFirst({
      where: { id: eventId, organizerId: req.organizerId },
    });

    if (!event) {
      res.status(404).json({ error: 'Event not found' });
      return;
    }

    const broadcasts = await prisma.emailBroadcast.findMany({
      where: { eventId },
      include: { template: true },
      orderBy: { createdAt: 'desc' },
    });

    res.json(broadcasts);
  } catch (error) {
    console.error('getDeliveryReport error:', error);
    res.status(500).json({ error: 'Failed to fetch delivery report' });
  }
}
