const {addBaseUrlToImages} = require("../utils/imageHelper");
const Activity = require("../models/activity");
const mongoose = require('mongoose');

// -------------------- Public (API) exports --------------------

// API endpoint: return all active activities as JSON
exports.api = async (req, res) => {
  try {
    // Return structured response with filters and camps
    const baseUrl =
      process.env.BACKEND_URL || `${req.protocol}://${req.get("host")}`;

    // Get filters document (single doc with isFiltersDoc:true)
    const filtersDoc = await Activity.findOne({ isFiltersDoc: true }).lean();
    const filters = (filtersDoc && Array.isArray(filtersDoc.filters)) ? filtersDoc.filters : [];

    // Fetch camps (activities) excluding the filters doc
    const activities = await Activity.find({ isFiltersDoc: { $ne: true }, isActive: true })
      .sort({ order: 1, createdAt: -1 })
      .lean();

    const camps = (activities || []).map((activity) => addBaseUrlToImages(activity, baseUrl));

    // Get hero data from the first activity (assuming all activities share the same hero)
    const heroRaw = activities.length > 0 && activities[0].hero ? activities[0].hero : {};
    const hero = addBaseUrlToImages(heroRaw, baseUrl);

    return res.json({ hero, filter: filters, camps });
  } catch (err) {
    console.error("activity.api error:", err);
    return res.status(500).json({error: "Error loading activities data"});
  }
};

// API endpoint: return a single activity by ID or link
exports.apiDetail = async (req, res) => {
  try {
    const {id} = req.params;

    // Try to find by ID first, then by link
    let activity;
    if (id.match(/^[0-9a-fA-F]{24}$/)) {
      activity = await Activity.findById(id).lean();
    }

    if (!activity) {
      activity = await Activity.findOne({link: `/${id}`}).lean();
    }

    if (!activity) {
      return res.status(404).json({error: "Activity not found"});
    }

    const baseUrl =
      process.env.BACKEND_URL || `${req.protocol}://${req.get("host")}`;
    const processed = addBaseUrlToImages(activity, baseUrl);

    return res.json(processed);
  } catch (err) {
    console.error("activity.apiDetail error:", err);
    return res.status(500).json({error: "Error loading activity data"});
  }
};

// -------------------- Admin exports --------------------

// Get default activity data for creating new activity
const getDefaultActivityData = () => ({
  hero: {
    title: "",
    bannerImage: "",
  },
  name: "",
  price: 0,
  priceText: "",
  season: [],
  age: [12, 18],
  locations: [],
  image: "",
  link: "",
  program: "",
  rating: 4,
  isActive: true,
  order: 0,
});

// Display activities management page (list)
exports.index = async (req, res) => {
  try {
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 20;
    const skip = (page - 1) * limit;

    const activitiesPromise = Activity.find({ isFiltersDoc: { $ne: true } })
      .sort({order: 1, createdAt: -1})
      .skip(skip)
      .limit(limit)
      .lean();

    const totalPromise = Activity.countDocuments({ isFiltersDoc: { $ne: true } });
    const activePromise = Activity.countDocuments({ isFiltersDoc: { $ne: true }, isActive: true });

    // Fetch filters from the consolidated Activity document (isFiltersDoc:true)
    const filtersPromise = Activity.findOne({isFiltersDoc: true}).lean();

    // Get all activities with booking sessions for extracting all bookings
    const allActivitiesForBookingsPromise = Activity.find({ 
      isFiltersDoc: { $ne: true },
      'bookingSessions.bookingList': { $exists: true, $ne: [] }
    }).lean();

    const [activities, total, filtersDoc, activeCount, allActivitiesForBookings] = await Promise.all([
      activitiesPromise,
      totalPromise,
      filtersPromise,
      activePromise,
      allActivitiesForBookingsPromise,
    ]);

    // Extract all bookings from bookingSessions.bookingList
    const allBookings = [];
    const bookingCountMap = {};
    const sessionBookingCountMap = {};

    allActivitiesForBookings.forEach(activity => {
      const actId = activity._id.toString();
      let activityBookingCount = 0;
      sessionBookingCountMap[actId] = {};

      if (activity.bookingSessions && Array.isArray(activity.bookingSessions)) {
        activity.bookingSessions.forEach(session => {
          if (session.bookingList && Array.isArray(session.bookingList)) {
            const sessionBookingCount = session.bookingList.length;
            activityBookingCount += sessionBookingCount;
            sessionBookingCountMap[actId][session.sessionId] = sessionBookingCount;

            // Add each booking to allBookings array with activity info
            session.bookingList.forEach(booking => {
              const bookingWithActivityInfo = {
                ...booking,
                activityId: {
                  _id: activity._id,
                  name: activity.name,
                  link: activity.link
                },
                sessionId: session.sessionId,
                createdAt: booking.createdAt || booking.bookingDate || new Date(),
                status: booking.status || booking.bookingStatus || 'pending',
                paymentStatus: booking.paymentStatus || 'pending',
                totalAmount: booking.totalAmount || 0,
                paidAmount: booking.paidAmount || 0
              };
              allBookings.push(bookingWithActivityInfo);
            });
          }
        });
      }

      bookingCountMap[actId] = activityBookingCount;
    });

    // Sort all bookings by creation date (newest first)
    allBookings.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));

    // Add booking counts to activities
    const activitiesWithBookings = activities.map(activity => {
      const actId = activity._id.toString();
      return {
        ...activity,
        bookingCount: bookingCountMap[actId] || 0,
        sessionBookingCounts: sessionBookingCountMap[actId] || {}
      };
    });

    const filters = (filtersDoc && Array.isArray(filtersDoc.filters)) ? filtersDoc.filters : [];

    const totalPages = Math.ceil(total / limit);

    // Calculate all bookings stats
    const allBookingsStats = {
      total: allBookings.length,
      confirmed: allBookings.filter(b => b.status === 'confirmed').length,
      pending: allBookings.filter(b => b.status === 'pending').length,
      cancelled: allBookings.filter(b => b.status === 'cancelled').length,
      completed: allBookings.filter(b => b.status === 'completed').length,
      totalRevenue: allBookings.filter(b => b.status !== 'cancelled').reduce((sum, b) => sum + (b.totalAmount || 0), 0)
    };

    res.render("admin/activity/index", {
      layout: "layouts/main",
      title: "Activities Management",
      items: activitiesWithBookings,
      filters: filters, // Pass filters to view
      activeCount,
      allBookings: allBookings, // All bookings for the All Bookings tab
      allBookingsStats: allBookingsStats, // Stats for bookings
      pagination: {
        page,
        limit,
        total,
        totalPages,
        hasNext: page < totalPages,
        hasPrev: page > 1,
      },
      frontendUrl:
        process.env.FRONTEND_URL || req.protocol + "://" + req.get("host"),
      currentPath: req.path,
      user: req.session.user,
    });
  } catch (err) {
    console.error(err);
    req.flash("error_msg", "Error loading activities data");
    res.redirect("/admin/dashboard");
  }
};

// Update activity filters
exports.updateFilters = async (req, res) => {
  try {
    // Accept filters submitted as an array or as an object with numeric keys
    let filters = req.body.filters;

    // If form submission uses `filters[0]`, `filters[1]` style names, Express/body-parser
    // may produce an object with numeric keys rather than a true Array. Normalize it.
    if (!filters) {
      filters = [];
    } else if (!Array.isArray(filters) && typeof filters === 'object') {
      try {
        filters = Object.keys(filters)
          .sort((a, b) => (parseInt(a, 10) || 0) - (parseInt(b, 10) || 0))
          .map((k) => filters[k]);
      } catch (e) {
        filters = [];
      }
    }

    // Sanitize and normalize incoming filters robustly
    const sanitizedFilters = [];
    try {
      const iterable = Array.isArray(filters) ? filters : Object.keys(filters || {}).map((k) => filters[k]);
      for (let idx = 0; idx < iterable.length; idx++) {
        const filterData = iterable[idx] || {};

        // Items can be JSON string, array, or an object with numeric keys
        let items = filterData.items;
        if (typeof items === 'string') {
          try {
            items = JSON.parse(items);
          } catch (e) {
            items = [];
          }
        }

        if (!Array.isArray(items) && typeof items === 'object' && items !== null) {
          // convert object with numeric keys to array
          try {
            items = Object.keys(items)
              .sort((a, b) => (parseInt(a, 10) || 0) - (parseInt(b, 10) || 0))
              .map((k) => items[k]);
          } catch (e) {
            items = [];
          }
        }

        if (!Array.isArray(items)) items = [];

        const cleanedItems = items
          .map((it) => ({ value: (it && it.value) ? it.value.toString().trim() : "", label: (it && it.label) ? it.label.toString().trim() : "" }))
          .filter((it) => it.value && it.label);

        // normalize id to ObjectId when possible
        let subId = filterData._id || filterData.id || undefined;
        if (subId && typeof subId === 'string' && /^[0-9a-fA-F]{24}$/.test(subId)) {
          try {
            subId = mongoose.Types.ObjectId(subId);
          } catch (e) {
            subId = undefined;
          }
        } else {
          subId = undefined; // don't set invalid ids
        }

        const label = (filterData.label || '').toString().trim();
        const value = (filterData.value || '').toString().trim();
        const order = parseInt(filterData.order, 10) || idx + 1;

        if (!label || !value) continue; // skip invalid

        sanitizedFilters.push({ _id: subId, label, value, items: cleanedItems, order });
      }
    } catch (e) {
      console.error('Error normalizing filters payload:', e);
    }

    if (!Array.isArray(sanitizedFilters)) {
      req.flash('error_msg', 'Invalid filters payload');
      return res.redirect('/admin/activity');
    }

    // Upsert the single filters document in Activities collection
    try {
      // Provide minimal valid fields when inserting a new filters document so
      // schema validators (e.g., age validator) do not fail on upsert.
      const setOnInsert = {
        name: "_filters_doc",
        price: 0,
        priceText: "",
        season: [],
        age: [12, 18],
        locations: [],
        image: "",
        link: "",
        program: "",
        rating: 4,
        isActive: false,
        order: 0,
        isFiltersDoc: true,
      };

      const upsertResult = await Activity.findOneAndUpdate(
        { isFiltersDoc: true },
        { $set: { filters: sanitizedFilters }, $setOnInsert: setOnInsert },
        { upsert: true, new: true, setDefaultsOnInsert: true }
      );

      req.flash('success_msg', 'Filters updated successfully');
      return res.redirect('/admin/activity');
    } catch (e) {
      console.error('Activity upsert filters error:', e);
      req.flash('error_msg', `Error saving filters: ${e.message || 'Unknown'}`);
      return res.redirect('/admin/activity');
    }
  } catch (err) {
    console.error("Update filters error:", err);
    req.flash("error_msg", `Error updating filters: ${err.message || "Unknown error"}`);
    res.redirect("/admin/activity");
  }
};

// Update global hero section (admin) - updates filters doc and all activities
exports.updateHero = async (req, res) => {
  try {
    const titleActivities = (req.body.titleActivities || '').toString().trim();
    const titleBooking = (req.body.titleBooking || '').toString().trim();
    const bannerImageActivities = (req.body.bannerImageActivities || '').toString().trim();
    const bannerImageBooking = (req.body.bannerImageBooking || '').toString().trim();

    const hero = {
      titleActivities: titleActivities || 'Activities',
      titleBooking: titleBooking || 'Activities',
      bannerImageActivities: bannerImageActivities || '/uploads/banner/b9.jpg',
      bannerImageBooking: bannerImageBooking || '/uploads/banner/b9.jpg',
    };

    // Update all activity docs to keep hero consistent
    await Activity.updateMany({ isFiltersDoc: { $ne: true } }, { $set: { hero } });

    // Upsert hero into the filters document as well
    const setOnInsert = {
      name: "_filters_doc",
      price: 0,
      priceText: "",
      season: [],
      age: [12, 18],
      locations: [],
      image: "",
      link: "",
      program: "",
      rating: 4,
      isActive: false,
      order: 0,
      isFiltersDoc: true,
    };

    await Activity.findOneAndUpdate(
      { isFiltersDoc: true },
      { $set: { hero }, $setOnInsert: setOnInsert },
      { upsert: true, new: true, setDefaultsOnInsert: true }
    );

    req.flash('success_msg', 'Hero updated successfully');
    return res.redirect('/admin/activity');
  } catch (e) {
    console.error('Update hero error:', e);
    req.flash('error_msg', `Error updating hero: ${e.message || 'Unknown'}`);
    return res.redirect('/admin/activity');
  }
};

// Display create form
exports.createForm = async (req, res) => {
  try {
    const data = getDefaultActivityData();

    res.render("admin/activity/form", {
      layout: "layouts/main",
      title: "Create Activity",
      data,
      isEdit: false,
      currentPath: req.path,
      user: req.session.user,
    });
  } catch (err) {
    console.error(err);
    req.flash("error_msg", "Error loading create form");
    res.redirect("/admin/activity");
  }
};

// Create new activity
exports.create = async (req, res) => {
  try {
    const activityData = parseActivityFormData(req.body);

    const newActivity = new Activity(activityData);
    await newActivity.save();

    req.flash("success_msg", "Activity created successfully");
    res.redirect("/admin/activity");
  } catch (err) {
    console.error("Create error:", err);
    req.flash("error_msg", `Create error: ${err.message || "Unknown"}`);
    res.redirect("/admin/activity/create");
  }
};

// Display edit form
exports.editForm = async (req, res) => {
  try {
    const activity = await Activity.findById(req.params.id).lean();

    if (!activity) {
      req.flash("error_msg", "Activity not found");
      return res.redirect("/admin/activity");
    }

    res.render("admin/activity/form", {
      layout: "layouts/main",
      title: "Edit Activity",
      data: activity,
      isEdit: true,
      currentPath: req.path,
      user: req.session.user,
    });
  } catch (err) {
    console.error(err);
    req.flash("error_msg", "Error loading edit form");
    res.redirect("/admin/activity");
  }
};

// Update activity
exports.update = async (req, res) => {
  try {
    const activity = await Activity.findById(req.params.id);

    if (!activity) {
      req.flash("error_msg", "Activity not found");
      return res.redirect("/admin/activity");
    }

    const activityData = parseActivityFormData(req.body, activity);

    // Force status to active on update (always set isActive true when editing)
    activityData.isActive = true;

    await Activity.findByIdAndUpdate(req.params.id, activityData, {new: true});

    req.flash("success_msg", "Activity updated successfully");
    return req.session.save(() => res.redirect("/admin/activity"));
  } catch (err) {
    console.error("Update error:", err);
    req.flash("error_msg", `Update error: ${err.message || "Unknown"}`);
    return req.session.save(() =>
      res.redirect(`/admin/activity/${req.params.id}/edit`)
    );
  }
};

// Delete activity
exports.delete = async (req, res) => {
  try {
    const activity = await Activity.findById(req.params.id);

    if (!activity) {
      req.flash("error_msg", "Activity not found");
      return res.redirect("/admin/activity");
    }

    await Activity.findByIdAndDelete(req.params.id);

    req.flash("success_msg", "Activity deleted successfully");
    res.redirect("/admin/activity");
  } catch (err) {
    console.error("Delete error:", err);
    req.flash("error_msg", `Delete error: ${err.message || "Unknown"}`);
    res.redirect("/admin/activity");
  }
};

// Toggle activity status (active/inactive)
exports.toggleStatus = async (req, res) => {
  try {
    const activity = await Activity.findById(req.params.id);

    if (!activity) {
      return res.status(404).json({error: "Activity not found"});
    }

    activity.isActive = !activity.isActive;
    await activity.save();

    // Return updated global counts so front-end widgets can reflect totals
    const total = await Activity.countDocuments({ isFiltersDoc: { $ne: true } });
    const activeCount = await Activity.countDocuments({ isFiltersDoc: { $ne: true }, isActive: true });

    return res.json({
      success: true,
      isActive: activity.isActive,
      message: `Activity ${
        activity.isActive ? "activated" : "deactivated"
      } successfully`,
      total,
      activeCount,
    });
  } catch (err) {
    console.error("Toggle status error:", err);
    return res.status(500).json({error: "Error toggling activity status"});
  }
};

// Update activity order (for drag & drop reordering)
exports.updateOrder = async (req, res) => {
  try {
    const {items} = req.body; // Array of { id, order }

    if (!Array.isArray(items)) {
      return res.status(400).json({error: "Invalid data format"});
    }

    const bulkOps = items.map((item) => ({
      updateOne: {
        filter: {_id: item.id},
        update: {$set: {order: item.order}},
      },
    }));

    await Activity.bulkWrite(bulkOps);

    return res.json({success: true, message: "Order updated successfully"});
  } catch (err) {
    console.error("Update order error:", err);
    return res.status(500).json({error: "Error updating order"});
  }
};

// Preview activity
exports.preview = async (req, res) => {
  try {
    const activity = await Activity.findById(req.params.id).lean();

    if (!activity) {
      return res.status(404).json({error: "Activity not found"});
    }

    const baseUrl =
      process.env.BACKEND_URL || `${req.protocol}://${req.get("host")}`;
    const processed = addBaseUrlToImages(activity, baseUrl);

    res.json(processed);
  } catch (err) {
    console.error("Preview error:", err);
    res.status(500).json({error: "Error loading preview data"});
  }
};

// -------------------- Helper functions --------------------

function parseActivityFormData(body, existingActivity = null) {
  // Parse season (can be string or array)
  let season = body.season || [];
  if (typeof season === "string") {
    season = season
      .split(",")
      .map((s) => s.trim())
      .filter(Boolean);
  }

  // Parse age range
  let age = [12, 18];
  if (body.ageMin && body.ageMax) {
    age = [parseInt(body.ageMin) || 12, parseInt(body.ageMax) || 18];
  } else if (body.age) {
    try {
      age = JSON.parse(body.age);
    } catch (e) {
      // Keep default
    }
  }

  // Parse locations (can be string or array)
  let locations = body.locations || [];
  if (typeof locations === "string") {
    locations = locations
      .split(",")
      .map((s) => s.trim())
      .filter(Boolean);
  }

  // Parse campDetail from form data
  let campDetail = {};
  try {
    if (body.campDetail) {
      if (typeof body.campDetail === "string") {
        campDetail = JSON.parse(body.campDetail);
      } else {
        campDetail = body.campDetail;
      }
    }
    
    // Handle individual campDetail fields if sent separately
    // Hero section
    if (body.campDetailHeroTitle || body.campDetailHeroBgImage) {
      campDetail.hero = campDetail.hero || {};
      if (body.campDetailHeroTitle) campDetail.hero.title = body.campDetailHeroTitle.trim();
      if (body.campDetailHeroBgImage) campDetail.hero.bgImage = body.campDetailHeroBgImage.trim();
    }
    
    // Basic Info section
    if (body.campDetailBasicInfoLocation || body.campDetailBasicInfoAgeRange || 
        body.campDetailBasicInfoAccommodationType || body.campDetailBasicInfoCareLevel ||
        body.campDetailBasicInfoLanguages) {
      campDetail.basicInfo = campDetail.basicInfo || {};
      if (body.campDetailBasicInfoLocation) campDetail.basicInfo.location = body.campDetailBasicInfoLocation.trim();
      if (body.campDetailBasicInfoAgeRange) campDetail.basicInfo.ageRange = body.campDetailBasicInfoAgeRange.trim();
      if (body.campDetailBasicInfoAccommodationType) campDetail.basicInfo.accommodationType = body.campDetailBasicInfoAccommodationType.trim();
      if (body.campDetailBasicInfoCareLevel) campDetail.basicInfo.careLevel = body.campDetailBasicInfoCareLevel.trim();
      if (body.campDetailBasicInfoLanguages) campDetail.basicInfo.languages = body.campDetailBasicInfoLanguages.trim();
    }
    
    // Sidebar section
    if (body.campDetailSidebarContactPhone || body.campDetailSidebarContactEmail ||
        body.campDetailSidebarMenuItems || body.campDetailSidebarUpcomingTours) {
      campDetail.sidebar = campDetail.sidebar || {};
      
      // Contact info
      if (body.campDetailSidebarContactPhone || body.campDetailSidebarContactEmail) {
        campDetail.sidebar.contact = campDetail.sidebar.contact || {};
        if (body.campDetailSidebarContactPhone) campDetail.sidebar.contact.phone = body.campDetailSidebarContactPhone.trim();
        if (body.campDetailSidebarContactEmail) campDetail.sidebar.contact.email = body.campDetailSidebarContactEmail.trim();
      }
      
      // Menu items (JSON array)
      if (body.campDetailSidebarMenuItems) {
        try {
          campDetail.sidebar.menuItems = JSON.parse(body.campDetailSidebarMenuItems);
        } catch (e) {
          console.warn("Error parsing sidebar menuItems:", e);
        }
      }
      
      // Upcoming tours (JSON array)
      if (body.campDetailSidebarUpcomingTours) {
        try {
          campDetail.sidebar.upcomingTours = JSON.parse(body.campDetailSidebarUpcomingTours);
        } catch (e) {
          console.warn("Error parsing sidebar upcomingTours:", e);
        }
      }
    }
    
    // Main Gallery section
    if (body.campDetailMainGallerySlides || body.campDetailMainGalleryOverlayLocation ||
        body.campDetailMainGalleryOverlaySeason || body.campDetailMainGalleryOverlayLanguages) {
      campDetail.mainGallery = campDetail.mainGallery || {};
      
      // Gallery slides (JSON array)
      if (body.campDetailMainGallerySlides) {
        try {
          campDetail.mainGallery.slides = JSON.parse(body.campDetailMainGallerySlides);
        } catch (e) {
          console.warn("Error parsing mainGallery slides:", e);
        }
      }
      
      // Overlay info
      if (body.campDetailMainGalleryOverlayLocation || body.campDetailMainGalleryOverlaySeason || 
          body.campDetailMainGalleryOverlayLanguages) {
        campDetail.mainGallery.overlayInfo = campDetail.mainGallery.overlayInfo || {};
        if (body.campDetailMainGalleryOverlayLocation) campDetail.mainGallery.overlayInfo.location = body.campDetailMainGalleryOverlayLocation.trim();
        if (body.campDetailMainGalleryOverlaySeason) campDetail.mainGallery.overlayInfo.season = body.campDetailMainGalleryOverlaySeason.trim();
        if (body.campDetailMainGalleryOverlayLanguages) campDetail.mainGallery.overlayInfo.languages = body.campDetailMainGalleryOverlayLanguages.trim();
      }
    }
    
    // Event Schedule section
    if (body.campDetailEventScheduleStartDate || body.campDetailEventScheduleDuration || 
        body.campDetailEventScheduleTickets) {
      campDetail.eventSchedule = campDetail.eventSchedule || {};
      if (body.campDetailEventScheduleStartDate) campDetail.eventSchedule.startDate = body.campDetailEventScheduleStartDate.trim();
      if (body.campDetailEventScheduleDuration) campDetail.eventSchedule.duration = body.campDetailEventScheduleDuration.trim();
      if (body.campDetailEventScheduleTickets) campDetail.eventSchedule.tickets = body.campDetailEventScheduleTickets.trim();
    }
    
    // Sections - handle both overview individual fields and complete sections JSON
    if (body.campDetailSectionsOverviewIntro || body.campDetailSectionsOverviewMainText ||
        body.campDetailSectionsOverviewFeatures || body.campDetailSectionsOverviewFeatureImage ||
        body.campDetailSections) {
      
      // If complete sections JSON is provided, use it
      if (body.campDetailSections) {
        try {
          campDetail.sections = JSON.parse(body.campDetailSections);
        } catch (e) {
          console.warn("Error parsing complete sections JSON:", e);
        }
      }
      
      // Handle individual overview fields (will override sections JSON if both provided)
      if (body.campDetailSectionsOverviewIntro || body.campDetailSectionsOverviewMainText ||
          body.campDetailSectionsOverviewFeatures || body.campDetailSectionsOverviewFeatureImage) {
        campDetail.sections = campDetail.sections || {};
        campDetail.sections.overview = campDetail.sections.overview || {};
        
        if (body.campDetailSectionsOverviewIntro) campDetail.sections.overview.intro = body.campDetailSectionsOverviewIntro.trim();
        if (body.campDetailSectionsOverviewMainText) campDetail.sections.overview.mainText = body.campDetailSectionsOverviewMainText.trim();
        if (body.campDetailSectionsOverviewFeatureImage) campDetail.sections.overview.featureImage = body.campDetailSectionsOverviewFeatureImage.trim();
        
        // Features array
        if (body.campDetailSectionsOverviewFeatures) {
          try {
            campDetail.sections.overview.features = JSON.parse(body.campDetailSectionsOverviewFeatures);
          } catch (e) {
            console.warn("Error parsing overview features:", e);
          }
        }
      }
    }
    
    // Map tipsImage (sidebar) into campDetail.hero.bgImage when provided
    if (body.tipsImage && typeof body.tipsImage === 'string' && body.tipsImage.trim()) {
      campDetail.hero = campDetail.hero || {};
      campDetail.hero.bgImage = body.tipsImage.trim();
    }
  } catch (e) {
    console.warn("Error parsing campDetail:", e);
    campDetail = {};
  }

  // Parse hero section (activities + booking variants)
  const existingHero = existingActivity?.hero || {};
  const hero = {
    titleActivities: body.titleActivities?.trim() || existingHero.titleActivities || "",
    titleBooking: body.titleBooking?.trim() || existingHero.titleBooking || "",
    bannerImageActivities: body.bannerImageActivities?.trim() || existingHero.bannerImageActivities || "",
    bannerImageBooking: body.bannerImageBooking?.trim() || existingHero.bannerImageBooking || "",
  };

  // Parse bookingSessions
  let bookingSessions = [];
  try {
    if (body.bookingSessions) {
      if (typeof body.bookingSessions === "string") {
        bookingSessions = JSON.parse(body.bookingSessions);
      } else if (Array.isArray(body.bookingSessions)) {
        bookingSessions = body.bookingSessions;
      } else if (typeof body.bookingSessions === "object") {
        bookingSessions = Object.keys(body.bookingSessions)
          .sort((a, b) => parseInt(a) - parseInt(b))
          .map(k => body.bookingSessions[k]);
      }
    }
    
    // Validate và clean sessions
    bookingSessions = bookingSessions
      .filter(s => s && s.startDate && s.endDate)
      .map((s, index) => ({
        // Auto generate sessionId if not provided
        sessionId: s.sessionId?.trim() || `session-${Date.now()}-${index}`,
        startDate: new Date(s.startDate),
        endDate: new Date(s.endDate),
        overnightStays: parseInt(s.overnightStays) || 14,
        // Spots theo giới tính
        totalMaleSpots: parseInt(s.totalMaleSpots) || 25,
        totalFemaleSpots: parseInt(s.totalFemaleSpots) || 25,
        bookedMaleSpots: parseInt(s.bookedMaleSpots) || 0,
        bookedFemaleSpots: parseInt(s.bookedFemaleSpots) || 0,
        price: s.price ? parseFloat(s.price) : null,
        isActive: s.isActive === true || s.isActive === "true" || s.isActive === "on"
      }));
  } catch (e) {
    console.warn("Error parsing bookingSessions:", e);
    bookingSessions = existingActivity?.bookingSessions || [];
  }

  // Determine final image value from various input sources
  const finalImageValue = (function(){
    const img = body.image?.trim() || (body.sidebarImage?.trim() || '') || (body.tipsImage?.trim() || '');
    return img || "";
  })();

  // Đồng bộ campDetail.hero.bgImage với main image - 2 trường này luôn giống nhau
  if (finalImageValue && campDetail && campDetail.hero) {
    campDetail.hero.bgImage = finalImageValue;
  } else if (finalImageValue) {
    // Tạo campDetail.hero nếu chưa có và gán bgImage
    campDetail = campDetail || {};
    campDetail.hero = campDetail.hero || {};
    campDetail.hero.bgImage = finalImageValue;
  }

  return {
    hero,
    name: body.name?.trim() || "",
    price: Math.max(0, parseFloat(body.price) || 0),
    priceText: body.priceText?.trim() || `from ${body.price || 0} USD`,
    season,
    age,
    locations,
    image: finalImageValue,
    link: body.link?.trim() ? (body.link.trim().startsWith('/') ? body.link.trim() : '/' + body.link.trim()) : "",
    program: body.program?.trim() || "",
    rating: Math.max(1, Math.min(5, parseInt(body.rating) || 4)),
    isActive:
      body.isActive === "true" ||
      body.isActive === true ||
      body.isActive === "on" ||
      body.isActive === 1,
    order: Math.max(0, parseInt(body.order) || 0),
    campDetail: campDetail,
    bookingSessions: bookingSessions,
  };
}

// -------------------- Booking Submissions Management --------------------

// Get booking count for an activity
exports.getBookingCount = async (req, res) => {
  try {
    const { id } = req.params;
    const BookingSubmission = require('../models/bookingSubmission');
    
    let count = await BookingSubmission.countDocuments({ activityId: id });

    // Fallback to embedded bookingList in Activity if no separate BookingSubmission docs
    if (!count) {
      const activity = await Activity.findById(id).lean();
      if (activity && Array.isArray(activity.bookingSessions)) {
        count = activity.bookingSessions.reduce((sum, s) => {
          return sum + (Array.isArray(s.bookingList) ? s.bookingList.length : 0);
        }, 0);
      }
    }

    return res.json({ count });
  } catch (err) {
    console.error("getBookingCount error:", err);
    return res.status(500).json({ error: "Error loading booking count" });
  }
};

// Get booking submissions for an activity with stats
exports.getBookingSubmissions = async (req, res) => {
  try {
    const { id } = req.params;
    const BookingSubmission = require('../models/bookingSubmission');
    
    // Get activity with sessions
    const activity = await Activity.findById(id).lean();
    if (!activity) {
      return res.status(404).json({ error: "Activity not found" });
    }
    
    // Get all booking submissions for this activity (separate collection)
    let bookings = await BookingSubmission.find({ activityId: id })
      .sort({ createdAt: -1 })
      .lean();

    // Fallback: if there are no BookingSubmission documents, attempt to read embedded bookingList from Activity.bookingSessions
    if ((!bookings || bookings.length === 0) && Array.isArray(activity.bookingSessions)) {
      bookings = [];
      activity.bookingSessions.forEach((session) => {
        if (Array.isArray(session.bookingList)) {
          session.bookingList.forEach((b) => {
            // normalize embedded booking fields to match BookingSubmission shape
            const item = Object.assign({}, b);
            item.sessionId = session.sessionId || item.sessionDate || item.sessionId;
            item.createdAt = item.bookingDate || item.createdAt || new Date();
            // normalize status/payment field names
            item.status = item.status || item.bookingStatus || 'pending';
            item.paymentStatus = item.paymentStatus || item.paymentStatus || 'pending';
            // ensure participantBirthDate is Date
            if (item.participantBirthDate && typeof item.participantBirthDate === 'string') {
              item.participantBirthDate = new Date(item.participantBirthDate);
            }
            bookings.push(item);
          });
        }
      });
      // sort by createdAt desc
      bookings.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
    }
    
    // Calculate statistics
    const stats = {
      total: bookings.length,
      confirmed: bookings.filter(b => b.status === 'confirmed').length,
      pending: bookings.filter(b => b.status === 'pending').length,
      cancelled: bookings.filter(b => b.status === 'cancelled').length,
      completed: bookings.filter(b => b.status === 'completed').length,
      totalRevenue: bookings.filter(b => b.status !== 'cancelled').reduce((sum, b) => sum + (b.totalAmount || 0), 0)
    };
    
    // Create session breakdown
    const sessionBreakdown = {};
    const sessions = activity.bookingSessions || [];
    
    sessions.forEach(session => {
      const sessionBookings = bookings.filter(b => b.sessionId === session.sessionId);
      const totalCapacity = session.totalMaleSpots + session.totalFemaleSpots;
      const bookedCount = sessionBookings.length;
      
      sessionBreakdown[session.sessionId] = {
        sessionName: `${new Date(session.startDate).toLocaleDateString()} - ${new Date(session.endDate).toLocaleDateString()}`,
        dateRange: `${new Date(session.startDate).toLocaleDateString()} - ${new Date(session.endDate).toLocaleDateString()}`,
        totalCapacity,
        bookedCount,
        bookings: sessionBookings.length
      };
    });
    
    // Format sessions for filter dropdown
    const sessionsForFilter = sessions.map(s => ({
      sessionId: s.sessionId,
      sessionName: `${new Date(s.startDate).toLocaleDateString()} - ${new Date(s.endDate).toLocaleDateString()}`
    }));
    
    return res.json({
      bookings,
      stats,
      sessionBreakdown,
      sessions: sessionsForFilter
    });
    
  } catch (err) {
    console.error("getBookingSubmissions error:", err);
    return res.status(500).json({ error: "Error loading booking submissions" });
  }
};

// Export booking data as CSV
exports.exportBookingData = async (req, res) => {
  try {
    const { id } = req.params;
    const BookingSubmission = require('../models/bookingSubmission');
    
    const bookings = await BookingSubmission.find({ activityId: id })
      .populate('activityId', 'name')
      .sort({ createdAt: -1 })
      .lean();
    
    if (bookings.length === 0) {
      return res.status(404).json({ error: "No bookings found" });
    }
    
    // CSV headers
    const headers = [
      'Date Submitted',
      'Activity',
      'Session ID',
      'Participant Name',
      'Participant Gender',
      'Participant Birth Date',
      'Parent Name',
      'Email',
      'Phone',
      'Address',
      'City',
      'Country',
      'Postal Code',
      'Number of Participants',
      'Medical Conditions',
      'Dietary Restrictions',
      'Special Requests',
      'Emergency Contact',
      'Emergency Phone',
      'Status',
      'Payment Status',
      'Total Amount',
      'Paid Amount'
    ];
    
    // Convert bookings to CSV rows
    const rows = bookings.map(booking => [
      new Date(booking.createdAt).toISOString().split('T')[0],
      booking.activityId?.name || 'Unknown Activity',
      booking.sessionId,
      `${booking.participantFirstName} ${booking.participantLastName}`,
      booking.participantGender,
      new Date(booking.participantBirthDate).toISOString().split('T')[0],
      `${booking.parentFirstName} ${booking.parentLastName}`,
      booking.email,
      booking.phone,
      booking.address,
      booking.city,
      booking.country,
      booking.postalCode,
      booking.numberOfParticipants,
      booking.medicalConditions || '',
      booking.dietaryRestrictions || 'none',
      booking.specialRequests || '',
      booking.emergencyContact,
      booking.emergencyPhone,
      booking.status,
      booking.paymentStatus,
      booking.totalAmount || 0,
      booking.paidAmount || 0
    ]);
    
    // Generate CSV content
    const csvContent = [headers, ...rows]
      .map(row => row.map(field => `"${(field || '').toString().replace(/"/g, '""')}"`).join(','))
      .join('\n');
    
    // Set response headers for CSV download
    res.setHeader('Content-Type', 'text/csv');
    res.setHeader('Content-Disposition', `attachment; filename="bookings_${id}_${new Date().toISOString().split('T')[0]}.csv"`);
    
    return res.send(csvContent);
    
  } catch (err) {
    console.error("exportBookingData error:", err);
    return res.status(500).json({ error: "Error exporting booking data" });
  }
};

// Export ALL booking data as CSV (across all activities)
exports.exportAllBookingsData = async (req, res) => {
  try {
    // Get all activities with booking sessions
    const allActivities = await Activity.find({ 
      isFiltersDoc: { $ne: true },
      'bookingSessions.bookingList': { $exists: true, $ne: [] }
    }).lean();

    // Extract all bookings from bookingSessions.bookingList
    const allBookings = [];

    allActivities.forEach(activity => {
      if (activity.bookingSessions && Array.isArray(activity.bookingSessions)) {
        activity.bookingSessions.forEach(session => {
          if (session.bookingList && Array.isArray(session.bookingList)) {
            session.bookingList.forEach(booking => {
              const bookingWithActivityInfo = {
                ...booking,
                activityName: activity.name,
                sessionId: session.sessionId,
                createdAt: booking.createdAt || booking.bookingDate || new Date(),
                status: booking.status || booking.bookingStatus || 'pending',
                paymentStatus: booking.paymentStatus || 'pending',
                totalAmount: booking.totalAmount || 0,
                paidAmount: booking.paidAmount || 0
              };
              allBookings.push(bookingWithActivityInfo);
            });
          }
        });
      }
    });
    
    if (allBookings.length === 0) {
      return res.status(404).json({ error: "No bookings found" });
    }
    
    // Sort by creation date (newest first)
    allBookings.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
    
    // CSV headers
    const headers = [
      'Date Submitted',
      'Activity',
      'Session ID',
      'Participant Name',
      'Participant Gender',
      'Participant Birth Date',
      'Parent Name',
      'Email',
      'Phone',
      'Address',
      'City',
      'Country',
      'Postal Code',
      'Number of Participants',
      'Medical Conditions',
      'Dietary Restrictions',
      'Special Requests',
      'Emergency Contact',
      'Emergency Phone',
      'Status',
      'Payment Status',
      'Total Amount',
      'Paid Amount'
    ];
    
    // Convert bookings to CSV rows
    const rows = allBookings.map(booking => [
      new Date(booking.createdAt).toISOString().split('T')[0],
      booking.activityName || 'Unknown Activity',
      booking.sessionId,
      `${booking.participantFirstName} ${booking.participantLastName}`,
      booking.participantGender,
      booking.participantBirthDate ? new Date(booking.participantBirthDate).toISOString().split('T')[0] : '',
      `${booking.parentFirstName} ${booking.parentLastName}`,
      booking.email,
      booking.phone,
      booking.address,
      booking.city,
      booking.country,
      booking.postalCode,
      booking.numberOfParticipants,
      booking.medicalConditions || '',
      booking.dietaryRestrictions || 'none',
      booking.specialRequests || '',
      booking.emergencyContact,
      booking.emergencyPhone,
      booking.status,
      booking.paymentStatus,
      booking.totalAmount || 0,
      booking.paidAmount || 0
    ]);
    
    // Generate CSV content
    const csvContent = [headers, ...rows]
      .map(row => row.map(field => `"${(field || '').toString().replace(/"/g, '""')}"`).join(','))
      .join('\n');
    
    // Set response headers for CSV download
    res.setHeader('Content-Type', 'text/csv');
    res.setHeader('Content-Disposition', `attachment; filename="all_bookings_${new Date().toISOString().split('T')[0]}.csv"`);
    
    return res.send(csvContent);
    
  } catch (err) {
    console.error("exportAllBookingsData error:", err);
    return res.status(500).json({ error: "Error exporting all booking data" });
  }
};

// Delete a booking submission
exports.deleteBookingSubmission = async (req, res) => {
  try {
    const { bookingId } = req.params;
    const BookingSubmission = require('../models/bookingSubmission');
    
    const booking = await BookingSubmission.findById(bookingId);
    if (!booking) {
      return res.status(404).json({ error: "Booking not found" });
    }
    
    await BookingSubmission.findByIdAndDelete(bookingId);
    
    return res.json({ message: "Booking deleted successfully" });
    
  } catch (err) {
    console.error("deleteBookingSubmission error:", err);
    return res.status(500).json({ error: "Error deleting booking" });
  }
};

// -------------------- Camp Session Booking Management --------------------

// Create a new booking directly into camp session
exports.createSessionBooking = async (req, res) => {
  try {
    const { activityId, sessionId } = req.params;
    const bookingData = req.body;
    
    // Validate required fields
    const requiredFields = [
      'address', 'agreeTerms', 'city', 'country', 'email', 'emergencyContact', 
      'emergencyPhone', 'numberOfParticipants', 'parentFirstName', 'parentLastName',
      'participantBirthDate', 'participantFirstName', 'participantGender', 
      'participantLastName', 'phone', 'postalCode'
    ];
    
    for (let field of requiredFields) {
      if (!bookingData[field]) {
        return res.status(400).json({ 
          error: `Missing required field: ${field}` 
        });
      }
    }
    
    // Validate email format
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(bookingData.email)) {
      return res.status(400).json({ error: "Invalid email format" });
    }
    
    // Find the activity
    const activity = await Activity.findById(activityId);
    if (!activity) {
      return res.status(404).json({ error: "Activity not found" });
    }
    
    // Find the specific session
    const sessionIndex = activity.bookingSessions.findIndex(s => s.sessionId === sessionId);
    if (sessionIndex === -1) {
      return res.status(404).json({ error: "Session not found" });
    }
    
    const session = activity.bookingSessions[sessionIndex];
    
    // Check if session is active
    if (!session.isActive) {
      return res.status(400).json({ error: "Session is not active for booking" });
    }
    
    // Check availability based on participant gender
    const participantGender = bookingData.participantGender;
    const numberOfParticipants = parseInt(bookingData.numberOfParticipants) || 1;
    
    let availableSpots = 0;
    if (participantGender === 'male') {
      availableSpots = session.totalMaleSpots - session.bookedMaleSpots;
    } else if (participantGender === 'female') {
      availableSpots = session.totalFemaleSpots - session.bookedFemaleSpots;
    } else {
      // For 'other' gender, check both male and female availability
      const maleAvailable = session.totalMaleSpots - session.bookedMaleSpots;
      const femaleAvailable = session.totalFemaleSpots - session.bookedFemaleSpots;
      availableSpots = Math.max(maleAvailable, femaleAvailable);
    }
    
    if (availableSpots < numberOfParticipants) {
      return res.status(400).json({ 
        error: `Not enough spots available. Only ${availableSpots} spots left for ${participantGender} participants.`,
        availableSpots
      });
    }
    
    // Generate unique confirmation code
    const confirmationCode = `GG${Date.now()}${Math.random().toString(36).substr(2, 5).toUpperCase()}`;
    
    // Calculate total amount
    const pricePerParticipant = session.price || activity.price || 0;
    const totalAmount = pricePerParticipant * numberOfParticipants;
    
    // Create booking object
    const newBooking = {
      address: bookingData.address.trim(),
      agreeNewsletter: bookingData.agreeNewsletter === true || bookingData.agreeNewsletter === 'true',
      agreeTerms: bookingData.agreeTerms === true || bookingData.agreeTerms === 'true',
      city: bookingData.city.trim(),
      country: bookingData.country.trim(),
      dietaryRestrictions: bookingData.dietaryRestrictions || 'none',
      email: bookingData.email.toLowerCase().trim(),
      emergencyContact: bookingData.emergencyContact.trim(),
      emergencyPhone: bookingData.emergencyPhone.trim(),
      medicalConditions: bookingData.medicalConditions || '',
      numberOfParticipants: numberOfParticipants,
      parentFirstName: bookingData.parentFirstName.trim(),
      parentLastName: bookingData.parentLastName.trim(),
      participantBirthDate: new Date(bookingData.participantBirthDate),
      participantFirstName: bookingData.participantFirstName.trim(),
      participantGender: participantGender,
      participantLastName: bookingData.participantLastName.trim(),
      phone: bookingData.phone.trim(),
      postalCode: bookingData.postalCode.trim(),
      sessionDate: sessionId,
      specialRequests: bookingData.specialRequests || '',
      bookingStatus: 'pending',
      paymentStatus: 'pending',
      totalAmount: totalAmount,
      paidAmount: 0,
      bookingDate: new Date(),
      confirmationCode: confirmationCode,
      adminNotes: ''
    };
    
    // Add booking to session
    if (!activity.bookingSessions[sessionIndex].bookingList) {
      activity.bookingSessions[sessionIndex].bookingList = [];
    }
    activity.bookingSessions[sessionIndex].bookingList.push(newBooking);
    
    // Update booked spots count
    if (participantGender === 'male') {
      activity.bookingSessions[sessionIndex].bookedMaleSpots += numberOfParticipants;
    } else if (participantGender === 'female') {
      activity.bookingSessions[sessionIndex].bookedFemaleSpots += numberOfParticipants;
    } else {
      // For 'other' gender, distribute to the gender with more availability
      const maleAvailable = session.totalMaleSpots - session.bookedMaleSpots;
      const femaleAvailable = session.totalFemaleSpots - session.bookedFemaleSpots;
      if (maleAvailable >= femaleAvailable) {
        activity.bookingSessions[sessionIndex].bookedMaleSpots += numberOfParticipants;
      } else {
        activity.bookingSessions[sessionIndex].bookedFemaleSpots += numberOfParticipants;
      }
    }
    
    // Save the updated activity
    await activity.save();
    
    // Return success response with booking details
    return res.status(201).json({
      message: "Booking created successfully",
      booking: {
        id: activity.bookingSessions[sessionIndex].bookingList[activity.bookingSessions[sessionIndex].bookingList.length - 1]._id,
        confirmationCode: confirmationCode,
        activityName: activity.name,
        sessionId: sessionId,
        participantName: `${bookingData.participantFirstName} ${bookingData.participantLastName}`,
        parentName: `${bookingData.parentFirstName} ${bookingData.parentLastName}`,
        email: bookingData.email,
        totalAmount: totalAmount,
        numberOfParticipants: numberOfParticipants,
        status: 'pending',
        sessionDetails: {
          startDate: session.startDate,
          endDate: session.endDate,
          overnightStays: session.overnightStays
        }
      }
    });
    
  } catch (err) {
    console.error("createSessionBooking error:", err);
    return res.status(500).json({ error: "Error creating booking" });
  }
};

// Create booking by program (wrapper) - find activity by `program` then delegate
exports.createSessionBookingByProgram = async (req, res) => {
  try {
    const { program, sessionId } = req.params;
    // Find activity by program field
    const activity = await Activity.findOne({ program: program });
    if (!activity) return res.status(404).json({ error: 'Activity not found for program: ' + program });

    // Inject activityId into params and call existing handler
    req.params.activityId = activity._id.toString();
    req.params.sessionId = sessionId;
    return await exports.createSessionBooking(req, res);
  } catch (err) {
    console.error('createSessionBookingByProgram error:', err);
    return res.status(500).json({ error: 'Error creating booking by program' });
  }
};

// Get all bookings for a specific session
exports.getSessionBookings = async (req, res) => {
  try {
    const { activityId, sessionId } = req.params;
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 20;
    const status = req.query.status;
    const search = req.query.search;
    
    // Find the activity
    const activity = await Activity.findById(activityId);
    if (!activity) {
      return res.status(404).json({ error: "Activity not found" });
    }
    
    // Find the specific session
    const session = activity.bookingSessions.find(s => s.sessionId === sessionId);
    if (!session) {
      return res.status(404).json({ error: "Session not found" });
    }
    
    let bookings = session.bookingList || [];
    
    // Apply filters
    if (status) {
      bookings = bookings.filter(b => b.bookingStatus === status);
    }
    
    if (search) {
      const searchLower = search.toLowerCase();
      bookings = bookings.filter(b => 
        b.participantFirstName.toLowerCase().includes(searchLower) ||
        b.participantLastName.toLowerCase().includes(searchLower) ||
        b.parentFirstName.toLowerCase().includes(searchLower) ||
        b.parentLastName.toLowerCase().includes(searchLower) ||
        b.email.toLowerCase().includes(searchLower) ||
        b.confirmationCode.toLowerCase().includes(searchLower)
      );
    }
    
    // Calculate pagination
    const totalBookings = bookings.length;
    const totalPages = Math.ceil(totalBookings / limit);
    const startIndex = (page - 1) * limit;
    const endIndex = startIndex + limit;
    const paginatedBookings = bookings.slice(startIndex, endIndex);
    
    // Calculate statistics
    const stats = {
      total: session.bookingList?.length || 0,
      pending: bookings.filter(b => b.bookingStatus === 'pending').length,
      confirmed: bookings.filter(b => b.bookingStatus === 'confirmed').length,
      cancelled: bookings.filter(b => b.bookingStatus === 'cancelled').length,
      completed: bookings.filter(b => b.bookingStatus === 'completed').length,
      totalRevenue: bookings.filter(b => b.bookingStatus !== 'cancelled').reduce((sum, b) => sum + b.totalAmount, 0),
      paidAmount: bookings.reduce((sum, b) => sum + b.paidAmount, 0)
    };
    
    return res.json({
      bookings: paginatedBookings,
      pagination: {
        currentPage: page,
        totalPages: totalPages,
        totalBookings: totalBookings,
        limit: limit
      },
      session: {
        sessionId: session.sessionId,
        startDate: session.startDate,
        endDate: session.endDate,
        totalMaleSpots: session.totalMaleSpots,
        totalFemaleSpots: session.totalFemaleSpots,
        bookedMaleSpots: session.bookedMaleSpots,
        bookedFemaleSpots: session.bookedFemaleSpots,
        isActive: session.isActive
      },
      stats: stats,
      activity: {
        id: activity._id,
        name: activity.name,
        price: activity.price
      }
    });
    
  } catch (err) {
    console.error("getSessionBookings error:", err);
    return res.status(500).json({ error: "Error retrieving session bookings" });
  }
};

// Get session bookings by program (wrapper)
exports.getSessionBookingsByProgram = async (req, res) => {
  try {
    const { program, sessionId } = req.params;
    const activity = await Activity.findOne({ program: program });
    if (!activity) return res.status(404).json({ error: 'Activity not found for program: ' + program });

    req.params.activityId = activity._id.toString();
    req.params.sessionId = sessionId;
    return await exports.getSessionBookings(req, res);
  } catch (err) {
    console.error('getSessionBookingsByProgram error:', err);
    return res.status(500).json({ error: 'Error retrieving session bookings by program' });
  }
};

// Update a specific booking in a session
exports.updateSessionBooking = async (req, res) => {
  try {
    const { activityId, sessionId, bookingId } = req.params;
    const updateData = req.body;
    
    // Find the activity
    const activity = await Activity.findById(activityId);
    if (!activity) {
      return res.status(404).json({ error: "Activity not found" });
    }
    
    // Find the specific session
    const sessionIndex = activity.bookingSessions.findIndex(s => s.sessionId === sessionId);
    if (sessionIndex === -1) {
      return res.status(404).json({ error: "Session not found" });
    }
    
    // Find the specific booking
    const bookingIndex = activity.bookingSessions[sessionIndex].bookingList.findIndex(
      b => b._id.toString() === bookingId
    );
    if (bookingIndex === -1) {
      return res.status(404).json({ error: "Booking not found" });
    }
    
    const currentBooking = activity.bookingSessions[sessionIndex].bookingList[bookingIndex];
    
    // Update allowed fields
    const allowedUpdates = [
      'bookingStatus', 'paymentStatus', 'paidAmount', 'adminNotes',
      'emergencyContact', 'emergencyPhone', 'medicalConditions', 
      'specialRequests', 'dietaryRestrictions'
    ];
    
    for (let field of allowedUpdates) {
      if (updateData[field] !== undefined) {
        activity.bookingSessions[sessionIndex].bookingList[bookingIndex][field] = updateData[field];
      }
    }
    
    // Handle status changes that might affect spot counts
    if (updateData.bookingStatus && updateData.bookingStatus !== currentBooking.bookingStatus) {
      const numberOfParticipants = currentBooking.numberOfParticipants;
      const participantGender = currentBooking.participantGender;
      
      // If booking is being cancelled, free up spots
      if (updateData.bookingStatus === 'cancelled' && currentBooking.bookingStatus !== 'cancelled') {
        if (participantGender === 'male') {
          activity.bookingSessions[sessionIndex].bookedMaleSpots = Math.max(0, 
            activity.bookingSessions[sessionIndex].bookedMaleSpots - numberOfParticipants);
        } else if (participantGender === 'female') {
          activity.bookingSessions[sessionIndex].bookedFemaleSpots = Math.max(0, 
            activity.bookingSessions[sessionIndex].bookedFemaleSpots - numberOfParticipants);
        }
      }
      
      // If booking is being restored from cancelled, book spots again
      if (currentBooking.bookingStatus === 'cancelled' && updateData.bookingStatus !== 'cancelled') {
        if (participantGender === 'male') {
          const totalMale = activity.bookingSessions[sessionIndex].totalMaleSpots;
          const currentMale = activity.bookingSessions[sessionIndex].bookedMaleSpots;
          if (currentMale + numberOfParticipants > totalMale) {
            return res.status(400).json({ 
              error: "Not enough male spots available to restore this booking",
              availableSpots: totalMale - currentMale
            });
          }
          activity.bookingSessions[sessionIndex].bookedMaleSpots += numberOfParticipants;
        } else if (participantGender === 'female') {
          const totalFemale = activity.bookingSessions[sessionIndex].totalFemaleSpots;
          const currentFemale = activity.bookingSessions[sessionIndex].bookedFemaleSpots;
          if (currentFemale + numberOfParticipants > totalFemale) {
            return res.status(400).json({ 
              error: "Not enough female spots available to restore this booking",
              availableSpots: totalFemale - currentFemale
            });
          }
          activity.bookingSessions[sessionIndex].bookedFemaleSpots += numberOfParticipants;
        }
      }
    }
    
    // Save the updated activity
    await activity.save();
    
    return res.json({
      message: "Booking updated successfully",
      booking: activity.bookingSessions[sessionIndex].bookingList[bookingIndex]
    });
    
  } catch (err) {
    console.error("updateSessionBooking error:", err);
    return res.status(500).json({ error: "Error updating booking" });
  }
};

// Delete a specific booking from a session
exports.deleteSessionBooking = async (req, res) => {
  try {
    const { activityId, sessionId, bookingId } = req.params;
    
    // Find the activity
    const activity = await Activity.findById(activityId);
    if (!activity) {
      return res.status(404).json({ error: "Activity not found" });
    }
    
    // Find the specific session
    const sessionIndex = activity.bookingSessions.findIndex(s => s.sessionId === sessionId);
    if (sessionIndex === -1) {
      return res.status(404).json({ error: "Session not found" });
    }
    
    // Find the specific booking
    const bookingIndex = activity.bookingSessions[sessionIndex].bookingList.findIndex(
      b => b._id.toString() === bookingId
    );
    if (bookingIndex === -1) {
      return res.status(404).json({ error: "Booking not found" });
    }
    
    const bookingToDelete = activity.bookingSessions[sessionIndex].bookingList[bookingIndex];
    
    // Free up spots if booking is not cancelled
    if (bookingToDelete.bookingStatus !== 'cancelled') {
      const numberOfParticipants = bookingToDelete.numberOfParticipants;
      const participantGender = bookingToDelete.participantGender;
      
      if (participantGender === 'male') {
        activity.bookingSessions[sessionIndex].bookedMaleSpots = Math.max(0, 
          activity.bookingSessions[sessionIndex].bookedMaleSpots - numberOfParticipants);
      } else if (participantGender === 'female') {
        activity.bookingSessions[sessionIndex].bookedFemaleSpots = Math.max(0, 
          activity.bookingSessions[sessionIndex].bookedFemaleSpots - numberOfParticipants);
      }
    }
    
    // Remove the booking from the array
    activity.bookingSessions[sessionIndex].bookingList.splice(bookingIndex, 1);
    
    // Save the updated activity
    await activity.save();
    
    return res.json({
      message: "Booking deleted successfully",
      deletedBooking: {
        id: bookingId,
        confirmationCode: bookingToDelete.confirmationCode,
        participantName: `${bookingToDelete.participantFirstName} ${bookingToDelete.participantLastName}`
      }
    });
    
  } catch (err) {
    console.error("deleteSessionBooking error:", err);
    return res.status(500).json({ error: "Error deleting booking" });
  }
};
