import Member from "../../../../models/member.js";
import { loadPublicEvent } from "../../../../utils/loadEvent.js";
import { validateBody } from "../../../../utils/validateBody.js";
import { ticketPurchaseSchema } from "../../../../utils/schemas.js";
import {
  validateTicketPurchase,
  completeTicketPurchase,
  hasMemberAccess,
} from "../../../../utils/tickets.js";
import { sendEventRegistrationEmail } from "../../../../utils/resend.js";

/**
 * POST /api/events/[id]/tickets/purchase
 * Purchase a ticket for an event
 * Body: { name, email, paymentToken? }
 */
export default defineEventHandler(async (event) => {
  try {
    const identifier = getRouterParam(event, "id");
    const body = await validateBody(event, ticketPurchaseSchema);

    const eventData = await loadPublicEvent(event, identifier);

    // Check if user is a member. Only members with access (active or
    // pending_payment) count for pricing/validation; guest, suspended,
    // and cancelled members are treated as non-members.
    let member = await Member.findOne({ email: body.email.toLowerCase() });
    let accountCreated = false;

    // Validate ticket purchase
    const validation = validateTicketPurchase(eventData, {
      email: body.email,
      name: body.name,
      member: hasMemberAccess(member) ? member : null,
    });

    if (!validation.valid) {
      throw createError({
        statusCode: 400,
        statusMessage: validation.reason,
        data: {
          waitlistAvailable: validation.waitlistAvailable,
        },
      });
    }

    const { ticketInfo } = validation;
    const requiresPayment = ticketInfo.price > 0;

    // Handle payment if required
    let transactionId = null;
    if (requiresPayment) {
      // For HelcimPay.js with purchase type, the transaction is already completed
      // We just need to verify we received the transaction ID
      if (!body.transactionId) {
        throw createError({
          statusCode: 400,
          statusMessage:
            "Transaction ID is required. Payment must be completed first.",
        });
      }

      transactionId = body.transactionId;

      // Optional: Verify the transaction with Helcim API
      // This adds extra security to ensure the transaction is legitimate
      // For now, we trust the transaction ID from HelcimPay.js
    }

    // If no Member yet and the user consented, atomically create a guest Member.
    // findOneAndUpdate with $setOnInsert handles concurrent registrations on the
    // same email (email has a unique index).
    if (!member && body.createAccount) {
      member = await Member.findOneAndUpdate(
        { email: body.email.toLowerCase() },
        {
          $setOnInsert: {
            email: body.email.toLowerCase(),
            name: body.name,
            circle: "community",
            contributionAmount: 0,
            status: "guest",
          },
        },
        { upsert: true, new: true, setDefaultsOnInsert: true }
      );
      accountCreated = true;
    }

    // Create registration
    const memberHasAccess = hasMemberAccess(member);
    const registration = {
      memberId: member ? member._id : null,
      name: body.name,
      email: body.email.toLowerCase(),
      membershipLevel: memberHasAccess
        ? `${member.circle}-${member.contributionAmount}`
        : "non-member",
      isMember: memberHasAccess,
      ticketType: ticketInfo.ticketType,
      ticketPrice: ticketInfo.price,
      paymentStatus: requiresPayment ? "completed" : "not_required",
      paymentId: transactionId,
      amountPaid: ticketInfo.price,
      registeredAt: new Date(),
    };

    // Add registration to event
    eventData.registrations.push(registration);

    // Complete ticket purchase (updates sold/reserved counts)
    await completeTicketPurchase(eventData, ticketInfo.ticketType);

    // Save event with registration; skip validators to avoid tripping on
    // legacy location data unrelated to this write.
    await eventData.save({ validateBeforeSave: false });

    // Decide on auto-login: safe for new accounts and existing guests, not for
    // real members (stranger could hijack by typing email into a public form).
    let signedIn = false;
    let requiresSignIn = false;
    if (member && (accountCreated || member.status === "guest")) {
      setAuthCookie(event, member);
      signedIn = true;
    } else if (member) {
      requiresSignIn = true;
    }

    // Send confirmation email
    try {
      await sendEventRegistrationEmail(registration, eventData, { requiresSignIn });
    } catch (emailError) {
      console.error("Failed to send confirmation email:", emailError);
      // Don't fail the registration if email fails
    }

    return {
      success: true,
      message: "Ticket purchased successfully!",
      registration: {
        id: eventData.registrations[eventData.registrations.length - 1]._id,
        name: registration.name,
        email: registration.email,
        ticketType: registration.ticketType,
        amountPaid: registration.amountPaid,
      },
      accountCreated,
      signedIn,
      payment: transactionId
        ? {
            transactionId: transactionId,
            amount: ticketInfo.price,
            currency: ticketInfo.currency,
          }
        : null,
    };
  } catch (error) {
    console.error("Error purchasing ticket:", error);

    if (error.statusCode) {
      throw error;
    }

    throw createError({
      statusCode: 500,
      statusMessage: "Failed to purchase ticket. Please try again.",
    });
  }
});
