import { Body, Controller, Get, Param, Post, Patch, Delete, UseGuards, Request, Query } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiQuery } from '@nestjs/swagger'; import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.decorator'; import { PackagesService } from './packages.service'; import { CreatePackageDto, BookPackageDto, CreatePriceTierDto, UpdatePriceTierDto, CreateInquiryDto, UpdateInquiryStatusDto, PackageBookingContextDto } from './packages.dto'; import { IamGuard } from '../../common/iam-adapter'; import { JwtGuard } from '../../common/jwt.guard'; import { OptionalJwtGuard } from '../verifayda/optional-jwt.guard'; @ApiTags('Packages') @Controller('packages') export class PackagesController { constructor(private readonly service: PackagesService) {} @Post('inquiries') @IsPublic() @ApiOperation({ summary: 'Submit a package inquiry (public)' }) createInquiry(@Body() dto: CreateInquiryDto) { return this.service.createInquiry(dto); } @Get('inquiries') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'List all inquiries (backoffice)' }) listInquiries( @Query('packageId') packageId?: string, @Query('status') status?: string, @Query('page') page?: string, @Query('pageSize') pageSize?: string, ) { return this.service.listInquiries({ packageId, status, page: page ? +page : 1, pageSize: pageSize ? +pageSize : 20 }); } @Patch('inquiries/:id/status') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'Update inquiry status (backoffice)' }) updateInquiryStatus(@Param('id') id: string, @Body() dto: UpdateInquiryStatusDto) { return this.service.updateInquiryStatus(id, dto.status); } @Delete('inquiries/:id') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'Delete inquiry (backoffice)' }) deleteInquiry(@Param('id') id: string) { return this.service.deleteInquiry(id); } @Get() @IsPublic() @ApiOperation({ summary: 'List active packages' }) listActive() { return this.service.listActive(); } @Get('all') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'List all packages (backoffice)' }) listAll(@Query('page') page?: string, @Query('pageSize') pageSize?: string) { return this.service.listAll(page ? +page : 1, pageSize ? +pageSize : 20); } @Get('bookings') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'List all package bookings (backoffice)' }) listBookings( @Query('packageId') packageId?: string, @Query('status') status?: string, @Query('page') page?: string, @Query('pageSize') pageSize?: string, ) { return this.service.listBookings({ packageId, status, page: page ? +page : 1, pageSize: pageSize ? +pageSize : 20 }); } @Get('my-bookings') @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') @ApiOperation({ summary: 'Get my package bookings' }) myBookings(@Request() req: any) { return this.service.getMyBookings(req.user.passengerId); } @Get('booking/:ref') @IsPublic() @ApiOperation({ summary: 'Get package booking by reference' }) getBookingByRef(@Param('ref') ref: string) { return this.service.getBookingByRef(ref); } @Post('book') @IsPublic() @UseGuards(OptionalJwtGuard) @ApiBearerAuth('JWT-auth') @ApiOperation({ summary: 'Book a package (public or authenticated)' }) book(@Body() dto: BookPackageDto, @Request() req: any) { return this.service.book(dto, req.user?.passengerId); } @Get(':id/booking-context') @IsPublic() @ApiOperation({ summary: 'Get booking context for self-service package booking' }) @ApiQuery({ name: 'tierId', required: true }) @ApiQuery({ name: 'adultCount', required: true }) @ApiQuery({ name: 'childCount', required: false }) getBookingContext( @Param('id') id: string, @Query('tierId') tierId: string, @Query('adultCount') adultCount: string, @Query('childCount') childCount?: string, ) { return this.service.getBookingContext(id, tierId, parseInt(adultCount), childCount ? parseInt(childCount) : 0); } @Get(':id') @IsPublic() @ApiOperation({ summary: 'Get package details' }) getById(@Param('id') id: string) { return this.service.getById(id); } @Post() @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'Create package (admin)' }) create(@Body() dto: CreatePackageDto) { return this.service.create(dto); } @Patch(':id') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'Update package (admin)' }) update(@Param('id') id: string, @Body() dto: Partial) { return this.service.update(id, dto); } @Delete(':id') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'Delete package (admin)' }) @ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete even with active bookings' }) remove(@Param('id') id: string, @Query('cascade') cascade?: string) { return this.service.remove(id, cascade === 'true'); } @Patch(':id/activate') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'Activate package (admin)' }) activate(@Param('id') id: string) { return this.service.activate(id); } @Patch(':id/deactivate') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'Deactivate package (admin)' }) deactivate(@Param('id') id: string) { return this.service.deactivate(id); } @Post(':id/tiers') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'Add price tier to package (admin)' }) addTier(@Param('id') id: string, @Body() dto: CreatePriceTierDto) { return this.service.addTier(id, dto); } @Patch('tiers/:tierId') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'Update price tier (admin)' }) updateTier(@Param('tierId') tierId: string, @Body() dto: UpdatePriceTierDto) { return this.service.updateTier(tierId, dto); } @Delete('tiers/:tierId') @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') @ApiOperation({ summary: 'Delete price tier (admin)' }) deleteTier(@Param('tierId') tierId: string) { return this.service.deleteTier(tierId); } }