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); } // 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); } }