import { Controller, Get, Param, Query } from '@nestjs/common'; import { ApiOperation, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger'; import { VideoService } from './video.service'; import { VideoPageDto, VideoDetailDto, VideoCategoryDto, VideoTagDto, } from './dto'; @ApiTags('Videos') @Controller('api/v1/video') export class VideoController { constructor(private readonly videoService: VideoService) {} /** * Get categories for a channel from Redis cache. */ @Get('categories/:channelId') @ApiOperation({ summary: 'Get video categories for channel', description: 'Returns list of video categories from prebuilt Redis cache.', }) @ApiResponse({ status: 200, description: 'List of categories', type: VideoCategoryDto, isArray: true, }) async getCategories( @Param('channelId') channelId: string, ): Promise { return this.videoService.getCategoryListForChannel(channelId); } /** * Get tags for a category within a channel. */ @Get('tags/:channelId/:categoryId') @ApiOperation({ summary: 'Get video tags for category', description: 'Returns list of tags in a specific category from Redis cache.', }) @ApiResponse({ status: 200, description: 'List of tags', type: VideoTagDto, isArray: true, }) async getTags( @Param('channelId') channelId: string, @Param('categoryId') categoryId: string, ): Promise { return this.videoService.getTagListForCategory(channelId, categoryId); } /** * Get videos in a category with pagination. */ @Get('category/:channelId/:categoryId') @ApiOperation({ summary: 'Get videos by category', description: 'Returns paginated videos for a specific category from Redis cache.', }) @ApiQuery({ name: 'page', required: false, description: 'Page number (default: 1)', example: 1, }) @ApiQuery({ name: 'pageSize', required: false, description: 'Items per page (default: 20)', example: 20, }) @ApiResponse({ status: 200, description: 'Paginated video list', type: VideoPageDto, }) async getVideosByCategory( @Param('channelId') channelId: string, @Param('categoryId') categoryId: string, @Query('page') page?: string, @Query('pageSize') pageSize?: string, ): Promise> { const parsedPage = page ? Math.max(1, Number.parseInt(page, 10)) : 1; const parsedPageSize = pageSize ? Math.min(100, Number.parseInt(pageSize, 10)) : 20; return this.videoService.getVideosByCategoryWithPaging({ channelId, categoryId, page: parsedPage, pageSize: parsedPageSize, }); } /** * Get videos for a tag with pagination. */ @Get('tag/:channelId/:tagId') @ApiOperation({ summary: 'Get videos by tag', description: 'Returns paginated videos for a specific tag from Redis cache.', }) @ApiQuery({ name: 'page', required: false, description: 'Page number (default: 1)', example: 1, }) @ApiQuery({ name: 'pageSize', required: false, description: 'Items per page (default: 20)', example: 20, }) @ApiResponse({ status: 200, description: 'Paginated video list', type: VideoPageDto, }) async getVideosByTag( @Param('channelId') channelId: string, @Param('tagId') tagId: string, @Query('page') page?: string, @Query('pageSize') pageSize?: string, ): Promise> { const parsedPage = page ? Math.max(1, Number.parseInt(page, 10)) : 1; const parsedPageSize = pageSize ? Math.min(100, Number.parseInt(pageSize, 10)) : 20; return this.videoService.getVideosByTagWithPaging({ channelId, tagId, page: parsedPage, pageSize: parsedPageSize, }); } /** * Get home section videos (e.g., featured, latest, editorPick). */ @Get('home/:channelId/:section') @ApiOperation({ summary: 'Get home section videos', description: 'Returns videos for home page sections (featured, latest, editorPick) from Redis cache.', }) @ApiResponse({ status: 200, description: 'List of videos in section', type: VideoDetailDto, isArray: true, }) async getHomeSectionVideos( @Param('channelId') channelId: string, @Param('section') section: string, ): Promise { // Validate section is a known type const validSections = ['featured', 'latest', 'editorPick']; if (!validSections.includes(section)) { return []; } return this.videoService.getHomeSectionVideos(channelId, section as any); } }