← back to Handbag Auth Nextjs

src/app/api/stats/route.ts

67 lines

import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
import { rateLimit, getClientIp } from '@/lib/rateLimit'
import { addSecurityHeaders } from '@/lib/securityHeaders'

export async function GET(request: NextRequest) {
  try {
    // Rate limiting
    const clientIp = getClientIp(request)
    const rateLimitResult = rateLimit(clientIp, {
      windowMs: 60 * 1000,
      maxRequests: 60, // 60 requests per minute for stats
    })

    if (!rateLimitResult.allowed) {
      const response = NextResponse.json(
        { success: false, error: 'Rate limit exceeded' },
        { status: 429 }
      )
      response.headers.set('Retry-After', String(Math.ceil((rateLimitResult.resetTime - Date.now()) / 1000)))
      addSecurityHeaders(response)
      return response
    }
    const [
      totalListings,
      totalDeals,
      avgDealResult,
      maxDealResult,
      brandsResult
    ] = await Promise.all([
      prisma.listing.count({ where: { isActive: 1 } }),
      prisma.dealAnalysis.count({ where: { isDeal: 1 } }),
      prisma.dealAnalysis.aggregate({
        where: { isDeal: 1 },
        _avg: { dealPercentage: true }
      }),
      prisma.dealAnalysis.aggregate({
        _max: { dealPercentage: true }
      }),
      prisma.listing.findMany({
        where: { isActive: 1 },
        select: { brand: true },
        distinct: ['brand']
      })
    ])

    const response = NextResponse.json({
      success: true,
      total_listings: totalListings,
      total_deals: totalDeals,
      avg_deal_percentage: Math.round((avgDealResult._avg.dealPercentage || 0) * 10) / 10,
      best_deal_percentage: Math.round((maxDealResult._max.dealPercentage || 0) * 10) / 10,
      brands: brandsResult.filter(b => b.brand).length,
    })
    addSecurityHeaders(response)
    return response
  } catch (error) {
    console.error('Stats API error:', error)
    const response = NextResponse.json(
      { success: false, error: 'Failed to fetch statistics' },
      { status: 500 }
    )
    addSecurityHeaders(response)
    return response
  }
}