import Event from "../../../models/event";
import Member from "../../../models/member";
import {
  sendEventCancellationEmail,
  sendWaitlistNotificationEmail,
} from "../../../utils/resend.js";
import { connectDB } from "../../../utils/mongoose.js";

export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, "id");
  const body = await validateBody(event, cancelRegistrationSchema);
  const { email } = body;

  await connectDB();

  try {
    // Check if id is a valid ObjectId or treat as slug
    const isObjectId = /^[0-9a-fA-F]{24}$/.test(id);
    const query = isObjectId
      ? { $or: [{ _id: id }, { slug: id }] }
      : { slug: id };

    const eventDoc = await Event.findOne(query);

    if (!eventDoc) {
      throw createError({
        statusCode: 404,
        statusMessage: "Event not found",
      });
    }

    // Find the registration index
    const registrationIndex = eventDoc.registrations.findIndex(
      (registration) =>
        registration.email.toLowerCase() === email.toLowerCase(),
    );

    if (registrationIndex === -1) {
      throw createError({
        statusCode: 404,
        statusMessage: "Registration not found",
      });
    }

    const existingRegistration = eventDoc.registrations[registrationIndex];
    const ticketType = existingRegistration.ticketType;
    const amountPaid = existingRegistration.amountPaid || 0;
    // member tickets can be free (default) or paid via circle overrides — gate on amountPaid
    const isPaidRegistration =
      ticketType === "public" ||
      ticketType === "series_pass" ||
      (ticketType === "member" && amountPaid > 0);

    if (isPaidRegistration) {
      throw createError({
        statusCode: 403,
        statusMessage:
          "Paid registrations can't be self-cancelled. Email us for a refund — see /policies/refunds.",
      });
    }

    // Store registration data before removing (convert to plain object)
    const registration = {
      name: eventDoc.registrations[registrationIndex].name,
      email: eventDoc.registrations[registrationIndex].email,
      membershipLevel:
        eventDoc.registrations[registrationIndex].membershipLevel,
    };

    // Use $pull to avoid re-validating the whole document (e.g. legacy location formats)
    await Event.findByIdAndUpdate(
      eventDoc._id,
      {
        $pull: { registrations: { email: registration.email } },
        $inc: { registeredCount: -1 },
      },
      { runValidators: false },
    );

    // Log activity + send cancellation confirmation email
    const cancellingMember = await Member.findOne({
      email: registration.email,
    }).lean();

    if (cancellingMember) {
      logActivity(cancellingMember._id, 'event_cancelled', {
        eventId: eventDoc._id,
        eventTitle: eventDoc.title,
        eventSlug: eventDoc.slug
      })
    }

    try {
      const shouldSendCancellation =
        !cancellingMember || cancellingMember.notifications?.events !== false;
      if (shouldSendCancellation) {
        const eventData = {
          title: eventDoc.title,
          slug: eventDoc.slug,
          _id: eventDoc._id,
        };
        await sendEventCancellationEmail(registration, eventData);
        if (cancellingMember) {
          logActivity(cancellingMember._id, 'email_sent', {
            emailType: 'event_cancellation',
            subject: `Registration cancelled for ${eventDoc.title}`
          })
        }
      }
    } catch (emailError) {
      console.error("Failed to send cancellation email:", emailError);
    }

    // Notify waitlisted users if waitlist is enabled and there are entries
    if (
      eventDoc.tickets?.waitlist?.enabled &&
      eventDoc.tickets.waitlist.entries?.length > 0
    ) {
      try {
        const eventData = {
          title: eventDoc.title,
          slug: eventDoc.slug,
          _id: eventDoc._id,
          startDate: eventDoc.startDate,
          endDate: eventDoc.endDate,
          location: eventDoc.location,
        };

        // Notify the first person on the waitlist who hasn't been notified yet
        const waitlistEntry = eventDoc.tickets.waitlist.entries.find(
          (entry) => !entry.notified,
        );

        if (waitlistEntry) {
          const waitlistedMember = await Member.findOne({
            email: waitlistEntry.email,
          }).lean();
          const shouldNotifyWaitlist =
            !waitlistedMember ||
            waitlistedMember.notifications?.events !== false;
          if (shouldNotifyWaitlist) {
            await sendWaitlistNotificationEmail(waitlistEntry, eventData);
          }
          // Always mark as notified so we move on regardless
          const entryIndex =
            eventDoc.tickets.waitlist.entries.indexOf(waitlistEntry);
          await Event.findByIdAndUpdate(
            eventDoc._id,
            {
              $set: {
                [`tickets.waitlist.entries.${entryIndex}.notified`]: true,
              },
            },
            { runValidators: false },
          );
        }
      } catch (waitlistError) {
        // Log error but don't fail the cancellation
        console.error("Failed to notify waitlist:", waitlistError);
      }
    }

    return {
      success: true,
      message: "Registration cancelled successfully",
      registeredCount: eventDoc.registeredCount,
    };
  } catch (error) {
    console.error("Error cancelling registration:", error);

    // Re-throw known errors
    if (error.statusCode) {
      throw error;
    }

    throw createError({
      statusCode: 500,
      statusMessage: "Failed to cancel registration",
    });
  }
});
