import { Router, Response } from 'express'; import { prisma } from '../index'; import { authenticate, AuthRequest } from '../middleware/auth'; const router = Router(); router.get('/me', authenticate, async (req: AuthRequest, res: Response) => { try { const user = await prisma.user.findUnique({ where: { id: req.user!.id }, select: { id: true, email: true, name: true, screenName: true, avatarUrl: true, unitPreference: true, createdAt: true } }); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json(user); } catch (error) { console.error('Get user error:', error); res.status(500).json({ error: 'Failed to get user' }); } }); router.put('/me', authenticate, async (req: AuthRequest, res: Response) => { try { const { name, screenName, avatarUrl, unitPreference } = req.body; const updated = await prisma.user.update({ where: { id: req.user!.id }, data: { name: name || undefined, screenName: screenName !== undefined ? screenName || null : undefined, avatarUrl: avatarUrl !== undefined ? avatarUrl || null : undefined, unitPreference: unitPreference || undefined }, select: { id: true, email: true, name: true, screenName: true, avatarUrl: true, unitPreference: true, createdAt: true } }); res.json(updated); } catch (error) { console.error('Update user error:', error); res.status(500).json({ error: 'Failed to update user' }); } }); router.get('/me/location-history', authenticate, async (req: AuthRequest, res: Response) => { try { const locations = await prisma.locationHistory.findMany({ where: { userId: req.user!.id }, include: { game: { select: { id: true, name: true } } }, orderBy: { recordedAt: 'desc' } }); const games = await prisma.game.findMany({ where: { teams: { some: { members: { some: { userId: req.user!.id } } } } }, select: { id: true, name: true } }); const locationByGame = games.map(game => { const gameLocations = locations.filter(l => l.gameId === game.id); return { game: game, locations: gameLocations, locationCount: gameLocations.length }; }).filter(g => g.locationCount > 0); res.json({ totalLocations: locations.length, byGame: locationByGame }); } catch (error) { console.error('Get location history error:', error); res.status(500).json({ error: 'Failed to get location history' }); } }); router.get('/me/games', authenticate, async (req: AuthRequest, res: Response) => { try { const memberships = await prisma.teamMember.findMany({ where: { userId: req.user!.id }, include: { team: { include: { game: { select: { id: true, name: true, status: true, startDate: true, locationLat: true, locationLng: true, gameMasterId: true, gameMaster: { select: { name: true } } } }, teamRoutes: { include: { route: { include: { routeLegs: { orderBy: { sequenceNumber: 'asc' } } } } } }, photoSubmissions: true } } } }); const gamesWithDetails = memberships.map(m => { const team = m.team; const game = team.game; const teamRoute = team.teamRoutes[0]; const route = teamRoute?.route; const photoSubmissions = team.photoSubmissions; const routeLegs = route?.routeLegs || []; const proofLocations = routeLegs.filter(leg => photoSubmissions.some(p => p.routeLegId === leg.id) ); let totalDistance = 0; if (game.locationLat && game.locationLng) { let prevLat = game.locationLat; let prevLng = game.locationLng; for (const leg of routeLegs) { if (leg.locationLat && leg.locationLng) { const R = 6371; const dLat = (leg.locationLat - prevLat) * Math.PI / 180; const dLng = (leg.locationLng - prevLng) * Math.PI / 180; const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(prevLat * Math.PI / 180) * Math.cos(leg.locationLat * Math.PI / 180) * Math.sin(dLng/2) * Math.sin(dLng/2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); totalDistance += R * c; prevLat = leg.locationLat; prevLng = leg.locationLng; } } } return { gameId: game.id, gameName: game.name, gameStatus: game.status, gameMaster: game.gameMaster.name, startDate: game.startDate, teamId: team.id, teamName: team.name, teamStatus: team.status, routeId: route?.id || null, routeName: route?.name || null, routeColor: route?.color || null, totalLegs: routeLegs.length, totalDistance: Math.round(totalDistance * 100) / 100, proofLocations: proofLocations.map(leg => ({ legNumber: leg.sequenceNumber, description: leg.description, locationLat: leg.locationLat, locationLng: leg.locationLng, hasPhotoProof: photoSubmissions.some(p => p.routeLegId === leg.id) })) }; }); res.json(gamesWithDetails); } catch (error) { console.error('Get user games error:', error); res.status(500).json({ error: 'Failed to get user games' }); } }); router.delete('/me/location-data', authenticate, async (req: AuthRequest, res: Response) => { try { await prisma.locationHistory.deleteMany({ where: { userId: req.user!.id } }); res.json({ message: 'Location data deleted' }); } catch (error) { console.error('Delete location data error:', error); res.status(500).json({ error: 'Failed to delete location data' }); } }); router.delete('/me/account', authenticate, async (req: AuthRequest, res: Response) => { try { await prisma.user.delete({ where: { id: req.user!.id } }); res.json({ message: 'Account deleted' }); } catch (error) { console.error('Delete account error:', error); res.status(500).json({ error: 'Failed to delete account' }); } }); export default router;