import { NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { authMiddleware } from '@/lib/auth-middleware' import connectDB from '@/lib/mongodb' import { Transaction } from '@/models/transaction' import { Billing } from '@/models/billing' // Query parameters schema const TransactionQuerySchema = z.object({ page: z.string().optional().default('1'), limit: z.string().optional().default('10'), type: z.enum(['debit', 'credit', 'all']).optional().default('all'), service: z.string().optional(), }) export async function GET(request: NextRequest) { try { // Authenticate user const user = await authMiddleware(request) if (!user) { return NextResponse.json( { success: false, error: { message: 'Authentication required', code: 'UNAUTHORIZED' }, }, { status: 401 } ) } await connectDB() // Parse query parameters const { searchParams } = new URL(request.url) const queryParams = TransactionQuerySchema.parse({ page: searchParams.get('page') || undefined, limit: searchParams.get('limit') || undefined, type: searchParams.get('type') || undefined, service: searchParams.get('service') || undefined, }) const page = parseInt(queryParams.page) const limit = Math.min(parseInt(queryParams.limit), 100) // Max 100 per page const skip = (page - 1) * limit // Build query filter const filter: any = { email: user.email } if (queryParams.type !== 'all') { filter.type = queryParams.type } if (queryParams.service) { filter.service = { $regex: queryParams.service, $options: 'i' } } // Build billing filter const billingFilter: any = { $or: [{ user: user.email }, { siliconId: user.id }], } // console.log('billingFilter', user.email) if (queryParams.service) { billingFilter.service = { $regex: queryParams.service, $options: 'i' } } // Get both transactions and billing records const [transactions, billingRecords, transactionCount, billingCount] = await Promise.all([ Transaction.find(filter).sort({ createdAt: -1 }).lean().exec(), Billing.find(billingFilter).sort({ createdAt: -1 }).lean().exec(), Transaction.countDocuments(filter).exec(), Billing.countDocuments(billingFilter).exec(), ]) // Transform billing records to transaction format const transformedBillings = billingRecords.map((billing: any) => ({ _id: billing._id, transactionId: billing.billing_id, type: 'debit' as const, amount: billing.amount, service: billing.service, serviceId: billing.serviceId, description: billing.remarks || `${billing.service} - ${billing.cycle} billing`, status: billing.status === 'pending' ? 'pending' : 'completed', previousBalance: 0, // We don't have this data in billing newBalance: 0, // We don't have this data in billing createdAt: billing.createdAt, updatedAt: billing.updatedAt, email: billing.user, userId: billing.siliconId, })) // Combine and sort all records const allRecords = [...transactions, ...transformedBillings].sort( (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() ) // Apply type filter to combined records const filteredRecords = queryParams.type === 'all' ? allRecords : allRecords.filter((record) => record.type === queryParams.type) // Apply pagination to filtered records const totalCount = filteredRecords.length const paginatedRecords = filteredRecords.slice(skip, skip + limit) const totalPages = Math.ceil(totalCount / limit) return NextResponse.json({ success: true, data: { transactions: paginatedRecords, pagination: { page, limit, totalCount, totalPages, hasNext: page < totalPages, hasPrev: page > 1, }, }, }) } catch (error) { console.error('Get transactions error:', error) if (error instanceof z.ZodError) { return NextResponse.json( { success: false, error: { message: 'Invalid query parameters', code: 'VALIDATION_ERROR', details: error.format(), }, }, { status: 400 } ) } return NextResponse.json( { success: false, error: { message: 'Failed to fetch transactions', code: 'INTERNAL_ERROR' }, }, { status: 500 } ) } }