/** * @description API route for encrypted member lookup * This endpoint receives an encrypted member ID and returns member information * for the Expo Android app */ import dbConnect from "@/database/dbConnect"; import { NextResponse } from "next/server"; import memberModel from "@/database/models/memberModel"; import { decryptMemberId } from "@/utils/encryption"; // GET METHOD - Lookup member by encrypted ID export async function GET(req: Request) { try { // Connect to the database await dbConnect(); // Get the encrypted member ID from query parameters const { searchParams } = new URL(req.url); const encryptedId = searchParams.get('encryptedId'); // Validate the encrypted ID parameter if (!encryptedId) { return NextResponse.json({ success: false, message: "Missing encrypted member ID", }, { status: 400, headers: { "content-type": "application/json" } }); } // Decrypt the member ID let memberId: string; try { memberId = decryptMemberId(encryptedId); } catch (error) { return NextResponse.json({ success: false, message: "Invalid encrypted member ID", }, { status: 400, headers: { "content-type": "application/json" } }); } // Find the member by ID const member = await memberModel.findById(memberId); if (!member) { return NextResponse.json({ success: false, message: "Member not found", }, { status: 404, headers: { "content-type": "application/json" } }); } // Calculate plan status based on individual services (active/expired) const currentTime = Math.floor(Date.now() / 1000); const activeServices = member.services?.filter(service => service.active && service.planExpAt_unix > currentTime ) || []; const expiredServices = member.services?.filter(service => !service.active || service.planExpAt_unix <= currentTime ) || []; const planStatus = activeServices.length > 0 ? 'active' : 'expired'; // Get the latest expiration date from active services const latestExpiration = activeServices.length > 0 ? Math.max(...activeServices.map(s => s.planExpAt_unix)) : member.planExpAt_unix; // Prepare detailed services information const servicesInfo = member.services?.map(service => ({ serviceID: service.serviceID, serviceName: service.serviceName, registeredAt: service.registeredAt, registeredAt_unix: service.registeredAt_unix, planDelay: service.planDelay, planDelay_unix: service.planDelay_unix, planExpAt: service.planExpAt, planExpAt_unix: service.planExpAt_unix, planUpdatedAt: service.planUpdatedAt, planUpdatedAt_unix: service.planUpdatedAt_unix, active: service.active, status: (service.active && service.planExpAt_unix > currentTime) ? 'active' : 'expired', daysRemaining: service.planExpAt_unix > currentTime ? Math.ceil((service.planExpAt_unix - currentTime) / (24 * 60 * 60)) : 0 })) || []; // Prepare the response data with detailed services information const memberInfo = { name: `${member.firstName} ${member.lastName}`, gender: member.gendre, planDelay: member.planDelay, planStart: member.planUpdatedAt, planStatus: planStatus, planExpAt: new Date(latestExpiration * 1000).toUTCString(), activeServicesCount: activeServices.length, expiredServicesCount: expiredServices.length, totalServicesCount: member.services?.length || 0, services: servicesInfo }; // Return the member information return NextResponse.json({ success: true, message: "Member information retrieved successfully", data: memberInfo, }, { status: 200, headers: { "content-type": "application/json" } }); } catch (error) { console.error('Error in member lookup API:', error); // Return server error response return NextResponse.json({ success: false, message: "Server error", }, { status: 500, headers: { "content-type": "application/json" } }); } } // Set revalidation time export const revalidate = 5;