const couchdbService = require("../services/couchdbService"); class Event { static async create(eventData) { const event = { _id: `event_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, type: "event", title: eventData.title, description: eventData.description, date: eventData.date, location: eventData.location, participants: [], participantsCount: 0, status: eventData.status || "upcoming", createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; return await couchdbService.create(event); } static async findById(eventId) { return await couchdbService.getById(eventId); } static async find(query = {}, options = {}) { const defaultQuery = { type: "event", ...query }; return await couchdbService.find({ selector: defaultQuery, ...options }); } static async findOne(query) { const events = await this.find(query, { limit: 1 }); return events[0] || null; } static async update(eventId, updateData) { const event = await this.findById(eventId); if (!event) { throw new Error("Event not found"); } const updatedEvent = { ...event, ...updateData, updatedAt: new Date().toISOString() }; return await couchdbService.update(eventId, updatedEvent); } static async delete(eventId) { return await couchdbService.delete(eventId); } static async addParticipant(eventId, userId, userName, userProfilePicture) { const event = await this.findById(eventId); if (!event) { throw new Error("Event not found"); } // Check if user is already a participant const existingParticipant = event.participants.find(p => p.userId === userId); if (existingParticipant) { throw new Error("User already participating in this event"); } // Add participant with embedded user data const newParticipant = { userId: userId, name: userName, profilePicture: userProfilePicture || "", joinedAt: new Date().toISOString() }; event.participants.push(newParticipant); event.participantsCount = event.participants.length; event.updatedAt = new Date().toISOString(); return await couchdbService.update(eventId, event); } static async removeParticipant(eventId, userId) { const event = await this.findById(eventId); if (!event) { throw new Error("Event not found"); } // Remove participant event.participants = event.participants.filter(p => p.userId !== userId); event.participantsCount = event.participants.length; event.updatedAt = new Date().toISOString(); return await couchdbService.update(eventId, event); } static async updateStatus(eventId, newStatus) { const validStatuses = ["upcoming", "ongoing", "completed", "cancelled"]; if (!validStatuses.includes(newStatus)) { throw new Error("Invalid status"); } return await this.update(eventId, { status: newStatus }); } static async findByStatus(status) { return await this.find({ status }); } static async findByDateRange(startDate, endDate) { return await couchdbService.find({ selector: { type: "event", date: { $gte: startDate.toISOString(), $lte: endDate.toISOString() } }, sort: [{ date: "asc" }] }); } static async findByParticipant(userId) { return await couchdbService.view("events", "by-participant", { key: userId, include_docs: true }); } static async getUpcomingEvents(limit = 10) { const now = new Date().toISOString(); return await couchdbService.find({ selector: { type: "event", status: "upcoming", date: { $gte: now } }, sort: [{ date: "asc" }], limit }); } static async getAllPaginated(page = 1, limit = 10) { const skip = (page - 1) * limit; const events = await couchdbService.find({ selector: { type: "event" }, sort: [{ date: "desc" }], skip, limit }); // Get total count const totalCount = await couchdbService.find({ selector: { type: "event" }, fields: ["_id"] }); return { events, pagination: { page, limit, totalCount: totalCount.length, totalPages: Math.ceil(totalCount.length / limit) } }; } static async getEventsByUser(userId) { return await this.find({ "participants": { $elemMatch: { userId: userId } } }); } // Migration helper static async migrateFromMongo(mongoEvent) { const eventData = { title: mongoEvent.title, description: mongoEvent.description, date: mongoEvent.date, location: mongoEvent.location, status: mongoEvent.status || "upcoming" }; // Create event without participants first const event = await this.create(eventData); // If there are participants, add them with embedded user data if (mongoEvent.participants && mongoEvent.participants.length > 0) { for (const participantId of mongoEvent.participants) { try { // Get user data to embed const user = await couchdbService.findUserById(participantId.toString()); if (user) { await this.addParticipant(event._id, participantId.toString(), user.name, user.profilePicture); } } catch (error) { console.error(`Error migrating participant ${participantId}:`, error.message); } } } return event; } } module.exports = Event;