import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete,
  Query,
  UseGuards,
  Logger,
  HttpStatus,
  HttpCode,
  UseInterceptors,
  UploadedFile,
  Req,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiConsumes, ApiBody, ApiQuery } from '@nestjs/swagger';
import { LibraryService } from './library.service';
import { CreateLibraryDto } from './dto/create-library.dto';
import { UpdateLibraryDto } from './dto/update-library.dto';
import { QueryLibraryDto } from './dto/query-library.dto';
import { JwtAuthGuard } from 'common/guards/jwt-auth.guard';
import { RolesGuard } from 'common/guards/roles.guard';
import { Roles } from 'common/decorators/role.decorator';
import { UserRole } from 'common/enum/UserRole.enum';

@ApiTags('library')
@Controller({ path: 'library', version: '1' })
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(UserRole.ADMIN, UserRole.SUPER_ADMIN)
export class LibraryController {
  private readonly logger = new Logger(LibraryController.name);

  constructor(private readonly libraryService: LibraryService) {
    this.logger.log('LibraryController initialized');
  }

  @Post()
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN)
  @UseInterceptors(FileInterceptor('file'))
  @ApiOperation({ summary: 'Create new library item' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({ description: 'Create library item', type: CreateLibraryDto })
  @ApiResponse({ status: HttpStatus.CREATED, description: 'The library item has been successfully created.' })
  @ApiBearerAuth()
  async create(@Req() req: any, @Body() createLibraryDto: CreateLibraryDto, @UploadedFile() file: Express.Multer.File) {
    this.logger.log(`Creating library item: ${JSON.stringify(createLibraryDto)}`);

    const { user } = req;
    if (!user) {
      this.logger.error('User not found in request');
      throw new Error('User not found in request');
    }

    this.logger.log(`User ID: ${user}`);
    createLibraryDto.attachmentPostedBy = req.user;

    return this.libraryService.create(createLibraryDto, file);
  }

  @Get()
  @ApiOperation({ summary: 'Get all library items with filtering' })
  @ApiResponse({ status: HttpStatus.OK, description: 'Return all library items.' })
  async findAll(@Query() queryParams: QueryLibraryDto) {
    this.logger.log(`Getting all library items with filters: ${JSON.stringify(queryParams)}`);
    const [items, count] = await this.libraryService.findAll(queryParams);
    return {
      items,
      meta: {
        total: count,
        page: queryParams.page || 1,
        limit: queryParams.limit || 10,
        pages: Math.ceil(count / (queryParams.limit || 10)),
      },
    };
  }

  @Get('all-attachments-url')
  @ApiOperation({ summary: 'Get paginated library attachment URLs' })
  @ApiResponse({ status: HttpStatus.OK, description: 'Return paginated library items with attachment URLs.' })
  @ApiQuery({ name: 'page', required: false, type: Number, example: 1 })
  @ApiQuery({ name: 'limit', required: false, type: Number, example: 10 })
  async findAllAttachmentsUrl(@Query('page') page = 1, @Query('limit') limit = 10) {
    this.logger.log(`Getting attachment URLs for page ${page}, limit ${limit}`);
    return this.libraryService.getAllAttachmentUrls(Number(page), Number(limit));
  }

  @Get('public')
  @ApiOperation({ summary: 'Get all public library items' })
  @ApiResponse({ status: HttpStatus.OK, description: 'Return all public library items.' })
  async findPublic() {
    this.logger.log('Getting all public library items');
    return this.libraryService.findPublic();
  }

  @Get('user/:userId')
  @UseGuards(JwtAuthGuard)
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Get all library items by user ID' })
  @ApiResponse({ status: HttpStatus.OK, description: 'Return all library items for a specific user.' })
  async findByUserId(@Param('userId') userId: string) {
    this.logger.log(`Getting library items for user ID ${userId}`);
    return this.libraryService.findByUserId(+userId);
  }

  @Get('category/:category')
  @ApiOperation({ summary: 'Get library items by category' })
  @ApiResponse({ status: HttpStatus.OK, description: 'Return library items by category.' })
  async findByCategory(@Param('category') category: string) {
    this.logger.log(`Getting library items for category ${category}`);
    return this.libraryService.findByCategory(category);
  }

  @Get('tags')
  @ApiOperation({ summary: 'Get library items by tags' })
  @ApiResponse({ status: HttpStatus.OK, description: 'Return library items by tags.' })
  async findByTags(@Query('tags') tags: string) {
    const tagArray = tags.split(',');
    this.logger.log(`Getting library items for tags: ${tags}`);
    return this.libraryService.findByTags(tagArray);
  }

  @Get(':id')
  @ApiOperation({ summary: 'Get library item by ID' })
  @ApiResponse({ status: HttpStatus.OK, description: 'Return the library item.' })
  @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Library item not found.' })
  async findOne(@Param('id') id: string) {
    this.logger.log(`Getting library item with ID ${id}`);
    return this.libraryService.findOne(+id);
  }

  @Patch(':id')
  @UseGuards(JwtAuthGuard)
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Update library item' })
  @ApiResponse({ status: HttpStatus.OK, description: 'The library item has been successfully updated.' })
  async update(@Param('id') id: string, @Body() updateLibraryDto: UpdateLibraryDto) {
    this.logger.log(`Updating library item with ID ${id}`);
    return this.libraryService.update(+id, updateLibraryDto);
  }

  @Patch(':id/toggle-public')
  @UseGuards(JwtAuthGuard)
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Toggle public status of library item' })
  @ApiResponse({ status: HttpStatus.OK, description: 'The public status has been toggled.' })
  async togglePublicStatus(@Param('id') id: string) {
    this.logger.log(`Toggling public status for library item with ID ${id}`);
    return this.libraryService.togglePublicStatus(+id);
  }

  @Delete(':id')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Delete library item' })
  @ApiResponse({ status: HttpStatus.NO_CONTENT, description: 'The library item has been successfully deleted.' })
  async remove(@Param('id') id: string) {
    this.logger.log(`Deleting library item with ID ${id}`);
    await this.libraryService.remove(+id);
  }

  @Patch(':id/soft-delete')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Soft delete library item' })
  @ApiResponse({ status: HttpStatus.OK, description: 'The library item has been soft deleted.' })
  async softDelete(@Param('id') id: string) {
    this.logger.log(`Soft deleting library item with ID ${id}`);
    return this.libraryService.softDelete(+id);
  }
}
