import Event from "../../../models/event.js";
import Member from "../../../models/member.js";
import { connectDB } from "../../../utils/mongoose.js";
import { sendEventRegistrationEmail } from "../../../utils/resend.js";
import { validateBody } from "../../../utils/validateBody.js";
import { eventRegistrationSchema } from "../../../utils/schemas.js";
import mongoose from "mongoose";

export default defineEventHandler(async (event) => {
  try {
    // Ensure database connection
    await connectDB();
    const identifier = getRouterParam(event, "id");
    const body = await validateBody(event, eventRegistrationSchema);

    if (!identifier) {
      throw createError({
        statusCode: 400,
        statusMessage: "Event identifier is required",
      });
    }

    // Fetch the event - try by slug first, then by ID
    let eventData;

    // Check if identifier is a valid MongoDB ObjectId
    if (mongoose.Types.ObjectId.isValid(identifier)) {
      eventData = await Event.findById(identifier);
    }

    // If not found by ID or not a valid ObjectId, try by slug
    if (!eventData) {
      eventData = await Event.findOne({ slug: identifier });
    }

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

    // Check if event is full
    if (
      eventData.maxAttendees &&
      eventData.registrations.length >= eventData.maxAttendees
    ) {
      throw createError({
        statusCode: 400,
        statusMessage: "Event is full",
      });
    }

    // Check if already registered
    const alreadyRegistered = eventData.registrations.some(
      (reg) => reg.email.toLowerCase() === body.email.toLowerCase(),
    );

    if (alreadyRegistered) {
      throw createError({
        statusCode: 400,
        statusMessage: "You are already registered for this event",
      });
    }

    // Check member status and handle different registration scenarios
    const member = await Member.findOne({ email: body.email.toLowerCase() });

    if (eventData.membersOnly && !member) {
      throw createError({
        statusCode: 403,
        statusMessage:
          "This event is for members only. Please become a member to register.",
      });
    }

    // If event requires payment and user is not a member, redirect to payment flow
    if (
      eventData.pricing?.paymentRequired &&
      !eventData.pricing?.isFree &&
      !member
    ) {
      throw createError({
        statusCode: 402, // Payment Required
        statusMessage:
          "This event requires payment. Please use the payment registration endpoint.",
      });
    }

    // Set member status and membership level
    let isMember = false;
    let membershipLevel = "non-member";

    if (member) {
      isMember = true;
      membershipLevel = `${member.circle}-${member.contributionTier}`;
    }

    // Add registration
    const registration = {
      memberId: member ? member._id : null,
      name: body.name,
      email: body.email.toLowerCase(),
      membershipLevel,
      isMember,
      paymentStatus: "not_required", // Free events or member registrations
      amountPaid: 0,
      dietary: body.dietary || false,
      registeredAt: new Date(),
    };

    // Use $push to avoid re-validating the whole document (e.g. legacy location formats)
    const result = await Event.findByIdAndUpdate(
      eventData._id,
      { $push: { registrations: registration } },
      { new: true, runValidators: false }
    );
    const newRegistration = result.registrations[result.registrations.length - 1];

    // Send confirmation email using Resend
    try {
      await sendEventRegistrationEmail(registration, eventData);
    } catch (emailError) {
      // Log error but don't fail the registration
      console.error("Failed to send confirmation email:", emailError);
    }

    return {
      success: true,
      message: "Successfully registered for the event",
      registrationId: newRegistration._id,
    };
  } catch (error) {
    console.error("Error registering for event:", error);

    if (error.statusCode) {
      throw error;
    }

    throw createError({
      statusCode: 500,
      statusMessage: "Failed to register for event",
    });
  }
});
