import { prisma } from '../config/database';
import { sendMail } from '../config/mailer';

// --------------- Types ---------------

interface TriggerConfig {
  enabled: boolean;
  templateId: string;
  name: string;
}

interface EmailTriggers {
  onRegistration?: TriggerConfig;
  onFirstScan?: TriggerConfig;
  before24h?: TriggerConfig;
}

export interface AttendeeData {
  name: string;
  email: string | null;
  mobile: string;
  shortId: string;
  companyName?: string | null;
  jobTitle?: string | null;
  numberOfGuests?: number;
  category?: { name: string } | null;
  qrCodeUrl?: string | null;
}

export interface EventData {
  id: string;
  name: string;
  startDate: Date | string;
  location?: string | null;
  fromName?: string | null;
  fromEmail?: string | null;
  emailTriggers: any;
}

// --------------- Merge tag resolution ---------------

export function resolveTags(text: string, attendee: AttendeeData, event: EventData): string {
  const eventDate = new Date(event.startDate).toLocaleDateString('en-US', {
    weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',
  });

  const rsvpLink = `${process.env.FRONTEND_URL || 'http://localhost:3000'}/e/${event.id}`;

  // Generate a simple QR code img tag if attendee has a qrCodeUrl
  const qrHtml = attendee.qrCodeUrl
    ? `<img src="${attendee.qrCodeUrl}" alt="QR Code" width="200" height="200" style="display:block;margin:0 auto;" />`
    : `<p style="text-align:center;color:#6b7280;">[QR Code]</p>`;

  return text
    .replace(/\{name\}/g, attendee.name || '')
    .replace(/\{email\}/g, attendee.email || '')
    .replace(/\{mobile\}/g, attendee.mobile || '')
    .replace(/\{shortId\}/g, attendee.shortId || '')
    .replace(/\{category\}/g, attendee.category?.name || 'General')
    .replace(/\{companyName\}/g, attendee.companyName || '')
    .replace(/\{jobTitle\}/g, attendee.jobTitle || '')
    .replace(/\{numberOfGuests\}/g, String(attendee.numberOfGuests ?? 1))
    .replace(/\{eventName\}/g, event.name || '')
    .replace(/\{eventDate\}/g, eventDate)
    .replace(/\{eventLocation\}/g, event.location || '')
    .replace(/\{QRCode\}/g, qrHtml)
    .replace(/\{qrCode\}/g, qrHtml)
    .replace(/\{rsvpLink\}/g, rsvpLink);
}

// --------------- Send triggered email ---------------

async function sendTriggeredEmail(
  triggerKey: keyof EmailTriggers,
  event: EventData,
  attendee: AttendeeData
): Promise<void> {
  try {
    const triggers = event.emailTriggers as EmailTriggers | null;
    if (!triggers) return;

    const config = triggers[triggerKey];
    if (!config || !config.enabled || !config.templateId) return;

    // Attendee must have an email
    if (!attendee.email) return;

    const template = await prisma.emailTemplate.findUnique({
      where: { id: config.templateId },
    });
    if (!template) {
      console.warn(`[Email Trigger] Template ${config.templateId} not found for trigger ${triggerKey}`);
      return;
    }

    const resolvedSubject = resolveTags(template.subject, attendee, event);
    const resolvedBody = resolveTags(template.body, attendee, event);

    await sendMail(attendee.email, resolvedSubject, resolvedBody);

    console.log(`[Email Trigger] ${triggerKey}: sent to ${attendee.email} for event ${event.name}`);
  } catch (error) {
    console.error(`[Email Trigger] ${triggerKey} failed for ${attendee.email}:`, error);
  }
}

// --------------- Public trigger functions ---------------

/** Call after a new attendee is created/registered */
export async function fireOnRegistration(eventId: string, attendeeId: string): Promise<void> {
  const event = await prisma.event.findUnique({ where: { id: eventId } });
  if (!event) return;

  const attendee = await prisma.attendee.findUnique({
    where: { id: attendeeId },
    include: { category: true },
  });
  if (!attendee) return;

  await sendTriggeredEmail('onRegistration', event as any, attendee as any);
}

/** Call after first successful scan (attendance changes to ARRIVED) */
export async function fireOnFirstScan(eventId: string, attendeeId: string): Promise<void> {
  const event = await prisma.event.findUnique({ where: { id: eventId } });
  if (!event) return;

  const attendee = await prisma.attendee.findUnique({
    where: { id: attendeeId },
    include: { category: true },
  });
  if (!attendee) return;

  await sendTriggeredEmail('onFirstScan', event as any, attendee as any);
}

/** Background job: send reminders 24h before event start */
export async function fireBefore24hReminders(): Promise<void> {
  try {
    const now = new Date();
    const in24h = new Date(now.getTime() + 24 * 60 * 60 * 1000);
    // Window: events starting between 23.5h and 24.5h from now (to handle cron drift)
    const windowStart = new Date(now.getTime() + 23.5 * 60 * 60 * 1000);
    const windowEnd = new Date(now.getTime() + 24.5 * 60 * 60 * 1000);

    const events = await prisma.event.findMany({
      where: {
        startDate: { gte: windowStart, lte: windowEnd },
        emailTriggers: { not: null },
      },
    });

    for (const event of events) {
      const triggers = event.emailTriggers as EmailTriggers | null;
      if (!triggers?.before24h?.enabled || !triggers.before24h.templateId) continue;

      // Get all attendees with email who haven't been sent this reminder
      const attendees = await prisma.attendee.findMany({
        where: {
          eventId: event.id,
          email: { not: null },
          status: 'APPROVED',
        },
        include: { category: true },
      });

      let sent = 0;
      for (const attendee of attendees) {
        await sendTriggeredEmail('before24h', event as any, attendee as any);
        sent++;
      }

      if (sent > 0) {
        console.log(`[Email Trigger] before24h: sent ${sent} reminders for event ${event.name}`);
      }
    }
  } catch (error) {
    console.error('[Email Trigger] before24h job failed:', error);
  }
}
