import { Body, Controller, Delete, Get, Param, Patch, Post, Query, UseGuards } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiQuery, ApiBody, ApiResponse } from '@nestjs/swagger'; import { FleetService } from './fleet.service'; import { CreateTrainDto, CreateCoachDto, UpdateCoachDto, AssignCoachDto, CreateSeatBatchDto, ListCoachesDto } from './fleet.dto'; import { JwtGuard } from '../../common/jwt.guard'; @ApiTags('Fleet') @Controller('fleet') @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') export class FleetController { constructor(private service: FleetService) {} @Get('trains') @ApiOperation({ summary: 'List all trains with their recent schedules' }) @ApiResponse({ status: 200, description: 'Array of trains each with up to 5 most recent schedules' }) getTrains() { return this.service.getTrains(); } @Post('trains') @ApiOperation({ summary: 'Create a train service' }) @ApiBody({ type: CreateTrainDto }) @ApiResponse({ status: 201, description: 'Train created' }) createTrain(@Body() dto: CreateTrainDto) { return this.service.createTrain(dto); } @Get('coaches') @ApiOperation({ summary: 'List coaches filtered by status, mode, seat class, or schedule assignment' }) @ApiQuery({ name: 'isActive', required: false, type: Boolean, description: 'true = active only, false = inactive only, omit = all' }) @ApiQuery({ name: 'mode', required: false, description: 'Filter by mode: seat | bed | convertible' }) @ApiQuery({ name: 'seatClassId', required: false, description: 'Filter by SeatClass UUID' }) @ApiQuery({ name: 'scheduleId', required: false, description: 'Filter to coaches assigned to this TrainSchedule UUID' }) @ApiResponse({ status: 200, description: 'Coaches with seat class info, assignment count, and seat status summary (total/available/held/booked/blocked)' }) listCoaches( @Query('isActive') isActive?: string, @Query('mode') mode?: string, @Query('seatClassId') seatClassId?: string, @Query('scheduleId') scheduleId?: string, ) { const dto: ListCoachesDto = { isActive: isActive === 'true' ? true : isActive === 'false' ? false : undefined, mode, seatClassId, scheduleId, }; return this.service.listCoaches(dto); } @Get('coaches/:id') @ApiOperation({ summary: 'Get a single coach with full seat layout and arrangement' }) @ApiParam({ name: 'id', description: 'Coach UUID' }) @ApiResponse({ status: 200, description: `Coach detail including: - seatClass: seat class info - seatsByRow: seats grouped by row number, each seat includes label, seatNumber, col, kind (STANDARD/PREMIUM/ACCESSIBLE), status (AVAILABLE/HELD/BOOKED/BLOCKED), isWindow, isAisle, bedPosition (bed mode only), premiumFeeMinor - seatStatusSummary: total/available/held/booked/blocked counts - assignments: up to 5 most recent schedule assignments with origin/destination`, }) @ApiResponse({ status: 404, description: 'Coach not found' }) getCoach(@Param('id') id: string) { return this.service.getCoach(id); } @Post('coaches') @ApiOperation({ summary: 'Register a new physical coach and auto-generate its seats from arrangement config' }) @ApiBody({ type: CreateCoachDto }) @ApiResponse({ status: 201, description: 'Coach created with seats auto-generated from mode + arrangement + totalUnits' }) @ApiResponse({ status: 400, description: 'Invalid arrangement format' }) createCoach(@Body() dto: CreateCoachDto) { return this.service.createCoach(dto); } @Patch('coaches/:id') @ApiOperation({ summary: 'Update coach properties (label, mode, arrangement, etc.)' }) @ApiParam({ name: 'id', description: 'Coach UUID' }) @ApiBody({ type: UpdateCoachDto }) @ApiResponse({ status: 200, description: 'Coach updated' }) @ApiResponse({ status: 404, description: 'Coach not found' }) updateCoach(@Param('id') id: string, @Body() dto: UpdateCoachDto) { return this.service.updateCoach(id, dto); } @Post('assignments') @ApiOperation({ summary: 'Assign a physical coach to a train schedule at a given position' }) @ApiBody({ type: AssignCoachDto }) @ApiResponse({ status: 201, description: 'CoachAssignment created' }) @ApiResponse({ status: 404, description: 'Schedule or coach not found' }) assignCoach(@Body() dto: AssignCoachDto) { return this.service.assignCoach(dto); } @Delete('assignments/:id') @ApiOperation({ summary: 'Remove a coach assignment from a schedule' }) @ApiParam({ name: 'id', description: 'CoachAssignment UUID' }) @ApiResponse({ status: 200, description: 'Assignment removed' }) @ApiResponse({ status: 404, description: 'Assignment not found' }) removeAssignment(@Param('id') id: string) { return this.service.removeAssignment(id); } @Post('seats/batch') @ApiOperation({ summary: 'Batch-generate seats for a coach (rows × cols)' }) @ApiBody({ type: CreateSeatBatchDto }) @ApiResponse({ status: 201, description: 'Returns count of seats created' }) @ApiResponse({ status: 404, description: 'Coach not found' }) createSeatBatch(@Body() dto: CreateSeatBatchDto) { return this.service.createSeatBatch(dto); } @Get('analytics') @ApiOperation({ summary: 'Fleet analytics: train count, schedule count, seat occupancy rate' }) @ApiResponse({ status: 200, description: 'Returns totalTrains, totalSchedules, totalSeats, bookedSeats, occupancyRate' }) getAnalytics() { return this.service.getAnalytics(); } }