import { Controller, Get, Post, Patch, Delete, Body, Param, Query, UseGuards, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiQuery } from '@nestjs/swagger'; import { ConnectionRequestsService } from './connection-requests.service'; import { CreateConnectionRequestDto, RespondConnectionRequestDto } 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 { CurrentUser } from '../auth/decorators/current-user.decorator'; import { UserRole, ConnectionStatus } from '@prisma/client'; import { PrismaService } from '../prisma/prisma.service'; @ApiTags('Connection Requests') @Controller('connection-requests') @UseGuards(JwtAuthGuard, RolesGuard) @ApiBearerAuth() export class ConnectionRequestsController { constructor( private readonly connectionRequestsService: ConnectionRequestsService, private readonly prisma: PrismaService, ) {} @Post() @Roles(UserRole.USER) @ApiOperation({ summary: 'Create a connection request to an agent' }) @ApiResponse({ status: 201, description: 'Connection request created successfully' }) @ApiResponse({ status: 400, description: 'Agent is not available or invalid request' }) @ApiResponse({ status: 409, description: 'Connection request already exists' }) async createRequest( @CurrentUser() user: { id: string }, @Body() dto: CreateConnectionRequestDto, ) { // Return raw data - TransformInterceptor will wrap it return this.connectionRequestsService.createRequest(user.id, dto); } @Get('my-requests') @Roles(UserRole.USER) @ApiOperation({ summary: 'Get all connection requests sent by the current user' }) @ApiQuery({ name: 'status', enum: ConnectionStatus, required: false }) @ApiResponse({ status: 200, description: 'Connection requests retrieved successfully' }) async getMyRequests( @CurrentUser() user: { id: string }, @Query('status') status?: ConnectionStatus, ) { // Return raw data - TransformInterceptor will wrap it return this.connectionRequestsService.getMyRequests(user.id, status); } @Get('received') @Roles(UserRole.AGENT) @ApiOperation({ summary: 'Get all connection requests received by the current agent' }) @ApiQuery({ name: 'status', enum: ConnectionStatus, required: false }) @ApiResponse({ status: 200, description: 'Connection requests retrieved successfully' }) async getReceivedRequests( @CurrentUser() user: { id: string }, @Query('status') status?: ConnectionStatus, ) { // Get agent profile for the current user const agentProfile = await this.prisma.agentProfile.findUnique({ where: { userId: user.id }, select: { id: true }, }); if (!agentProfile) { // Return empty array - TransformInterceptor will wrap it return []; } // Return raw data - TransformInterceptor will wrap it return this.connectionRequestsService.getReceivedRequests( agentProfile.id, status, ); } @Get('received/counts') @Roles(UserRole.AGENT) @ApiOperation({ summary: 'Get connection request counts for the current agent' }) @ApiResponse({ status: 200, description: 'Request counts retrieved successfully' }) async getRequestCounts(@CurrentUser() user: { id: string }) { const agentProfile = await this.prisma.agentProfile.findUnique({ where: { userId: user.id }, select: { id: true }, }); if (!agentProfile) { // Return default counts - TransformInterceptor will wrap it return { pending: 0, accepted: 0, rejected: 0, total: 0 }; } // Return raw data - TransformInterceptor will wrap it return this.connectionRequestsService.getRequestCounts(agentProfile.id); } @Get('status/:agentProfileId') @Roles(UserRole.USER, UserRole.AGENT) @ApiOperation({ summary: 'Get connection status between current user and an agent' }) @ApiResponse({ status: 200, description: 'Connection status retrieved successfully' }) async getConnectionStatus( @CurrentUser() user: { id: string }, @Param('agentProfileId') agentProfileId: string, ) { // Return raw data - TransformInterceptor will wrap it return this.connectionRequestsService.getConnectionStatus( user.id, agentProfileId, ); } @Get(':id') @ApiOperation({ summary: 'Get a specific connection request by ID' }) @ApiResponse({ status: 200, description: 'Connection request retrieved successfully' }) @ApiResponse({ status: 404, description: 'Connection request not found' }) async getRequestById( @CurrentUser() user: { id: string; role: UserRole }, @Param('id') id: string, ) { let agentProfileId: string | undefined; if (user.role === UserRole.AGENT) { const agentProfile = await this.prisma.agentProfile.findUnique({ where: { userId: user.id }, select: { id: true }, }); agentProfileId = agentProfile?.id; } // Return raw data - TransformInterceptor will wrap it return this.connectionRequestsService.getRequestById( id, user.id, agentProfileId, ); } @Patch(':id/respond') @Roles(UserRole.AGENT) @ApiOperation({ summary: 'Respond to a connection request (accept/reject)' }) @ApiResponse({ status: 200, description: 'Response recorded successfully' }) @ApiResponse({ status: 400, description: 'Request already responded to' }) @ApiResponse({ status: 403, description: 'Not authorized to respond to this request' }) @ApiResponse({ status: 404, description: 'Connection request not found' }) async respondToRequest( @CurrentUser() user: { id: string }, @Param('id') id: string, @Body() dto: RespondConnectionRequestDto, ) { const agentProfile = await this.prisma.agentProfile.findUnique({ where: { userId: user.id }, select: { id: true }, }); if (!agentProfile) { // Throw an error instead of returning non-standard response throw new Error('Agent profile not found'); } // Return raw data - TransformInterceptor will wrap it return this.connectionRequestsService.respondToRequest( id, agentProfile.id, dto, ); } @Delete(':id') @Roles(UserRole.USER) @ApiOperation({ summary: 'Cancel a pending connection request' }) @ApiResponse({ status: 200, description: 'Connection request cancelled successfully' }) @ApiResponse({ status: 400, description: 'Only pending requests can be cancelled' }) @ApiResponse({ status: 403, description: 'Not authorized to cancel this request' }) @ApiResponse({ status: 404, description: 'Connection request not found' }) async cancelRequest( @CurrentUser() user: { id: string }, @Param('id') id: string, ) { await this.connectionRequestsService.cancelRequest(id, user.id); // Return null/undefined - TransformInterceptor will wrap it as { success: true, data: null } return null; } }