import { Request, Response } from 'express';
import { nanoid } from 'nanoid';
import { prisma } from '../config/database';
import { generateQRCodeBuffer } from '../utils/qrcode';
import { uploadToS3 } from '../config/s3';
import { RsvpFormConfig, validateRsvpSubmission, splitSubmission } from '../utils/rsvp-form';
import { fireOnRegistration } from '../utils/email-triggers';
import { io } from '../server';

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

    const event = await prisma.event.findUnique({
      where: { id: eventId },
      select: {
        id: true,
        name: true,
        description: true,
        startDate: true,
        endDate: true,
        location: true,
        bannerUrl: true,
        isPaid: true,
        rsvpFormConfig: true,
        categories: {
          select: {
            id: true,
            name: true,
            price: true,
          },
          orderBy: { order: 'asc' },
        },
      },
    });

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

    res.json(event);
  } catch (error) {
    console.error('getEventForRsvp error:', error);
    res.status(500).json({ error: 'Failed to fetch event details' });
  }
}

export async function submitRsvp(req: Request, res: Response): Promise<void> {
  try {
    const { eventId } = req.params;
    const body = (req.body || {}) as Record<string, unknown>;

    // Core fields (always required regardless of form mode)
    const name = typeof body.name === 'string' ? body.name.trim() : '';
    const mobile = typeof body.mobile === 'string' ? body.mobile.trim() : '';
    if (!name || !mobile) {
      res.status(400).json({ error: 'Name and mobile are required' });
      return;
    }

    const event = await prisma.event.findUnique({
      where: { id: eventId },
      include: { organizer: { include: { plan: true } } },
    });

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

    // Plan-credit gate
    const plan = event.organizer.plan;
    if (plan && plan.usedCredits >= plan.totalCredits) {
      res.status(403).json({ error: 'Organizer has reached their RSVP credit limit' });
      return;
    }

    // Determine form config and validate custom fields if applicable
    const config = (event.rsvpFormConfig as unknown as RsvpFormConfig | null) || null;
    const isCustom = !!config && config.mode === 'custom' && Array.isArray(config.fields);

    let coreEmail: string | null = null;
    let coreCompanyName: string | null = null;
    let coreJobTitle: string | null = null;
    let coreNumberOfGuests = 1;
    let extraInfo: Record<string, unknown> = {};

    if (isCustom) {
      const result = validateRsvpSubmission(config!, body);
      if (!result.ok) {
        res.status(400).json({ error: 'Form validation failed', fieldErrors: result.errors });
        return;
      }
      const split = splitSubmission(config!, body);
      coreEmail = split.core.email ?? null;
      coreCompanyName = split.core.companyName ?? null;
      coreJobTitle = split.core.jobTitle ?? null;
      coreNumberOfGuests = split.core.numberOfGuests ?? 1;
      extraInfo = split.additionalInfo;
    } else {
      // Default form: pick known core columns out of body
      if (typeof body.email === 'string') coreEmail = body.email.trim() || null;
      if (typeof body.companyName === 'string') coreCompanyName = body.companyName.trim() || null;
      if (typeof body.jobTitle === 'string') coreJobTitle = body.jobTitle.trim() || null;
      const ng = Number(body.numberOfGuests);
      if (Number.isFinite(ng) && ng > 0) coreNumberOfGuests = ng;
      // Allow caller to pass additionalInfo blob explicitly (legacy)
      if (body.additionalInfo && typeof body.additionalInfo === 'object') {
        extraInfo = body.additionalInfo as Record<string, unknown>;
      }
    }

    const countryCode = typeof body.countryCode === 'string' && body.countryCode ? body.countryCode : '+91';
    const categoryId = typeof body.categoryId === 'string' && body.categoryId ? body.categoryId : null;

    const shortId = nanoid(10).toUpperCase();

    const qrBuffer = await generateQRCodeBuffer(shortId);
    const qrKey = `qrcodes/${eventId}/${shortId}.png`;
    const qrCodeUrl = await uploadToS3(qrBuffer, qrKey, 'image/png');

    const attendee = await prisma.attendee.create({
      data: {
        shortId,
        eventId,
        name,
        email: coreEmail,
        mobile,
        countryCode,
        companyName: coreCompanyName,
        jobTitle: coreJobTitle,
        numberOfGuests: coreNumberOfGuests,
        categoryId: categoryId || undefined,
        additionalInfo: Object.keys(extraInfo).length ? (extraInfo as any) : undefined,
        qrCodeUrl,
        status: event.requireApproval ? 'PENDING' : 'APPROVED',
        source: 'rsvp',
      },
      include: { category: true },
    });

    if (plan) {
      await prisma.plan.update({
        where: { id: plan.id },
        data: { usedCredits: { increment: 1 } },
      });
    }

    // Fire onRegistration email trigger (non-blocking)
    fireOnRegistration(eventId, attendee.id).catch(() => {});

    // Create organizer-facing notification
    try {
      const notification = await prisma.notification.create({
        data: {
          organizerId: event.organizerId,
          eventId,
          attendeeId: attendee.id,
          type: 'RSVP_RECEIVED',
          title: 'New RSVP',
          message: `${attendee.name} RSVP'd to ${event.name}`,
          link: `/events/${eventId}/attendees`,
        },
        include: {
          attendee: { select: { id: true, name: true, shortId: true } },
          event: { select: { id: true, name: true } },
        },
      });
      io.to(`org:${event.organizerId}`).emit('notification:new', notification);
    } catch (err) {
      console.warn('Failed to create RSVP notification:', err);
    }

    res.status(201).json(attendee);
  } catch (error) {
    console.error('submitRsvp error:', error);
    res.status(500).json({ error: 'Failed to submit RSVP' });
  }
}
