import { Controller, Get, Post, Put, Delete, Body, Param, Query, UseGuards, ParseUUIDPipe, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, } from '@nestjs/swagger'; import { AgentsService } from './agents.service'; import { CreateAgentProfileDto, UpdateAgentProfileDto, SearchAgentsDto, SaveFieldValuesDto, } from './dto'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { RolesGuard } from '../auth/guards/roles.guard'; import { Roles } from '../auth/decorators/roles.decorator'; import { Public } from '../auth/decorators/public.decorator'; import { CurrentUser } from '../auth/decorators/current-user.decorator'; import { UserRole, VerificationStatus } from '@prisma/client'; @ApiTags('agents') @Controller('agents') export class AgentsController { constructor(private readonly agentsService: AgentsService) {} // Public endpoints - accessible by anyone @Get() @Public() @ApiOperation({ summary: 'Search and list agents' }) @ApiResponse({ status: 200, description: 'Agents retrieved successfully' }) async searchAgents(@Query() dto: SearchAgentsDto) { return this.agentsService.searchAgents(dto); } @Get('featured') @Public() @ApiOperation({ summary: 'Get featured agents' }) @ApiResponse({ status: 200, description: 'Featured agents retrieved successfully', }) async getFeaturedAgents(@Query('limit') limit?: number) { return this.agentsService.getFeaturedAgents(limit || 10); } @Get('top-rated') @Public() @ApiOperation({ summary: 'Get top rated agents' }) @ApiResponse({ status: 200, description: 'Top rated agents retrieved successfully', }) async getTopRatedAgents(@Query('limit') limit?: number) { return this.agentsService.getTopRatedAgents(limit || 10); } // Agent-only endpoints - requires AGENT role @Get('profile/me') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.AGENT) @ApiBearerAuth() @ApiOperation({ summary: 'Get current user agent profile' }) @ApiResponse({ status: 200, description: 'Profile retrieved successfully' }) @ApiResponse({ status: 404, description: 'Profile not found' }) async getMyProfile(@CurrentUser('id') userId: string) { return this.agentsService.getProfile(userId); } @Get('profile/field-values') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.AGENT) @ApiBearerAuth() @ApiOperation({ summary: 'Get dynamic field values for agent profile' }) @ApiResponse({ status: 200, description: 'Field values retrieved successfully' }) @ApiResponse({ status: 404, description: 'Profile not found' }) async getFieldValues(@CurrentUser('id') userId: string) { return this.agentsService.getFieldValues(userId); } @Post('profile') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.AGENT) @ApiBearerAuth() @ApiOperation({ summary: 'Create agent profile' }) @ApiResponse({ status: 201, description: 'Profile created successfully' }) @ApiResponse({ status: 409, description: 'Profile already exists' }) async createProfile( @CurrentUser('id') userId: string, @Body() dto: CreateAgentProfileDto, ) { return this.agentsService.createProfile(userId, dto); } @Put('profile') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.AGENT) @ApiBearerAuth() @ApiOperation({ summary: 'Update current user agent profile' }) @ApiResponse({ status: 200, description: 'Profile updated successfully' }) @ApiResponse({ status: 404, description: 'Profile not found' }) async updateProfile( @CurrentUser('id') userId: string, @Body() dto: UpdateAgentProfileDto, ) { return this.agentsService.updateProfile(userId, dto); } @Put('profile/field-values') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.AGENT) @ApiBearerAuth() @ApiOperation({ summary: 'Save dynamic field values for agent profile' }) @ApiResponse({ status: 200, description: 'Field values saved successfully' }) @ApiResponse({ status: 404, description: 'Profile not found' }) async saveFieldValues( @CurrentUser('id') userId: string, @Body() dto: SaveFieldValuesDto, ) { return this.agentsService.saveFieldValues(userId, dto); } // Notification preferences endpoints @Get('preferences/notifications') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.AGENT) @ApiBearerAuth() @ApiOperation({ summary: 'Get notification preferences (Agents only)' }) @ApiResponse({ status: 200, description: 'Notification preferences retrieved', schema: { example: { email: { new_leads: true, messages: true, connection_requests: true, property_updates: false, marketing: false, }, push: { push_messages: true, push_leads: true, push_reminders: false, }, }, }, }) async getNotificationPreferences(@CurrentUser('id') userId: string) { return this.agentsService.getNotificationPreferences(userId); } @Put('preferences/notifications') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.AGENT) @ApiBearerAuth() @ApiOperation({ summary: 'Update notification preferences (Agents only)' }) @ApiResponse({ status: 200, description: 'Notification preferences updated' }) async updateNotificationPreferences( @CurrentUser('id') userId: string, @Body() data: { email?: Record; push?: Record; }, ) { return this.agentsService.updateNotificationPreferences(userId, data); } // Privacy preferences endpoints @Get('preferences/privacy') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.AGENT) @ApiBearerAuth() @ApiOperation({ summary: 'Get privacy preferences (Agents only)' }) @ApiResponse({ status: 200, description: 'Privacy preferences retrieved', schema: { example: { privacySettings: { profile_visibility: 'public', contact_info: 'connections', activity_status: 'public', }, dataSettings: { shareAnalytics: false, personalizedAds: false, thirdPartySharing: false, }, }, }, }) async getPrivacyPreferences(@CurrentUser('id') userId: string) { return this.agentsService.getPrivacyPreferences(userId); } @Put('preferences/privacy') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.AGENT) @ApiBearerAuth() @ApiOperation({ summary: 'Update privacy preferences (Agents only)' }) @ApiResponse({ status: 200, description: 'Privacy preferences updated' }) async updatePrivacyPreferences( @CurrentUser('id') userId: string, @Body() data: { privacySettings?: Record; dataSettings?: Record; }, ) { return this.agentsService.updatePrivacyPreferences(userId, data); } // Delete account endpoint @Delete('account') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.AGENT) @ApiBearerAuth() @ApiOperation({ summary: 'Delete agent account permanently (Agents only)' }) @ApiResponse({ status: 200, description: 'Account deleted successfully' }) @ApiResponse({ status: 404, description: 'User not found' }) async deleteAccount(@CurrentUser('id') userId: string) { return this.agentsService.deleteAccount(userId); } // Public parameterized routes - MUST come after specific routes like profile/* @Get(':id') @Public() @ApiOperation({ summary: 'Get agent profile by ID' }) @ApiResponse({ status: 200, description: 'Agent profile retrieved successfully' }) @ApiResponse({ status: 404, description: 'Agent profile not found' }) async getAgentById(@Param('id', ParseUUIDPipe) id: string) { return this.agentsService.getProfileById(id); } @Get(':id/field-values') @Public() @ApiOperation({ summary: 'Get field values for an agent profile by ID (public)' }) @ApiResponse({ status: 200, description: 'Field values retrieved successfully' }) @ApiResponse({ status: 404, description: 'Agent profile not found' }) async getFieldValuesByAgentId(@Param('id', ParseUUIDPipe) id: string) { return this.agentsService.getFieldValuesByAgentId(id); } // Admin endpoints @Get('admin/list') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.ADMIN) @ApiBearerAuth() @ApiOperation({ summary: 'Admin: List all agents' }) @ApiResponse({ status: 200, description: 'Agents retrieved successfully' }) async adminListAgents(@Query() dto: SearchAgentsDto) { return this.agentsService.getAllAgentsAdmin(dto); } @Put('admin/:id') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.ADMIN) @ApiBearerAuth() @ApiOperation({ summary: 'Admin: Update agent profile' }) @ApiResponse({ status: 200, description: 'Profile updated successfully' }) @ApiResponse({ status: 404, description: 'Profile not found' }) async adminUpdateProfile( @Param('id', ParseUUIDPipe) id: string, @Body() dto: UpdateAgentProfileDto, ) { return this.agentsService.adminUpdateProfile(id, dto); } @Delete('admin/:id') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.ADMIN) @ApiBearerAuth() @ApiOperation({ summary: 'Admin: Delete agent profile' }) @ApiResponse({ status: 200, description: 'Profile deleted successfully' }) @ApiResponse({ status: 404, description: 'Profile not found' }) async adminDeleteProfile(@Param('id', ParseUUIDPipe) id: string) { return this.agentsService.adminDeleteProfile(id); } @Put('admin/:id/verify') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.ADMIN) @ApiBearerAuth() @ApiOperation({ summary: 'Admin: Update agent verification status' }) @ApiResponse({ status: 200, description: 'Verification status updated' }) @ApiResponse({ status: 404, description: 'Profile not found' }) async adminVerifyAgent( @Param('id', ParseUUIDPipe) id: string, @Body() data: { status: VerificationStatus; note?: string }, @CurrentUser() admin: { id: string }, ) { return this.agentsService.adminVerifyAgent(id, { status: data.status, note: data.note, adminId: admin.id, }); } @Put('admin/:id/featured') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(UserRole.ADMIN) @ApiBearerAuth() @ApiOperation({ summary: 'Admin: Set agent as featured' }) @ApiResponse({ status: 200, description: 'Featured status updated' }) @ApiResponse({ status: 404, description: 'Profile not found' }) async adminSetFeatured( @Param('id', ParseUUIDPipe) id: string, @Body('isFeatured') isFeatured: boolean, ) { return this.agentsService.adminSetFeatured(id, isFeatured); } }