import {
  BadRequestException,
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Query,
  UploadedFiles,
  UseGuards,
  UseInterceptors,
} from '@nestjs/common';
import { FileFieldsInterceptor } from '@nestjs/platform-express';
import { MEDIA_MAX_SIZE_BYTES } from '../../common/media/allowed-media';
import { ApiBearerAuth, ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { Throttle } from '../../common/decorators/throttle.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { JwtPayload } from '../../common/interfaces/jwt-payload.interface';
import { ChatService } from './chat.service';
import { CreateConversationDto } from './dto/create-conversation.dto';
import { MessageReactionDto } from './dto/message-reaction.dto';
import { MessageQueryDto } from './dto/message-query.dto';
import { SendMessageDto } from './dto/send-message.dto';

@ApiTags('Chat')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('chat')
export class ChatController {
  constructor(private readonly chatService: ChatService) {}

  @Post('conversations')
  @Throttle(40, 60_000)
  async createConversation(@CurrentUser() user: JwtPayload, @Body() dto: CreateConversationDto) {
    return this.chatService.createConversation(user.sub, dto);
  }

  @Get('conversations')
  async myConversations(@CurrentUser() user: JwtPayload, @Query() query: MessageQueryDto) {
    return this.chatService.getMyConversations(user.sub, query);
  }

  @Get('conversations/messages')
  async messagesMissingConversationId() {
    throw new BadRequestException('conversationId is required. Use /chat/conversations/:conversationId/messages');
  }

  @Get('conversations/:conversationId/messages')
  async messages(
    @CurrentUser() user: JwtPayload,
    @Param('conversationId') conversationId: string,
    @Query() query: MessageQueryDto,
  ) {
    return this.chatService.getMessages(user.sub, conversationId, query);
  }

  @Delete('conversations/:conversationId')
  @Throttle(80, 60_000)
  async hideConversationForMe(
    @CurrentUser() user: JwtPayload,
    @Param('conversationId') conversationId: string,
  ) {
    return this.chatService.hideConversationForMe(user.sub, conversationId);
  }

  @Post('messages')
  @Throttle(120, 60_000)
  async sendMessage(@CurrentUser() user: JwtPayload, @Body() dto: SendMessageDto) {
    return this.chatService.sendMessage(user.sub, dto);
  }

  @Post('messages/upload')
  @Throttle(60, 60_000)
  @UseInterceptors(
    FileFieldsInterceptor([{ name: 'mediaFile', maxCount: 1 }], {
      limits: { fileSize: MEDIA_MAX_SIZE_BYTES.postsVideo, files: 1 },
    }),
  )
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        conversationId: { type: 'string' },
        content: { type: 'string' },
        replyToMessageId: { type: 'string' },
        mediaFile: { type: 'string', format: 'binary' },
      },
    },
  })
  async sendMessageUpload(
    @CurrentUser() user: JwtPayload,
    @Body() dto: SendMessageDto,
    @UploadedFiles()
    files?: {
      mediaFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
    },
  ) {
    return this.chatService.sendMessageWithUpload(user.sub, dto, files?.mediaFile?.[0]);
  }

  @Patch('messages/:messageId/seen')
  @Throttle(200, 60_000)
  async markSeen(@CurrentUser() user: JwtPayload, @Param('messageId') messageId: string) {
    return this.chatService.markMessageSeen(user.sub, messageId);
  }

  @Patch('messages/:messageId/unsend')
  @Throttle(80, 60_000)
  async unsend(@CurrentUser() user: JwtPayload, @Param('messageId') messageId: string) {
    return this.chatService.unsendMessage(user.sub, messageId);
  }

  @Patch('messages/:messageId/reaction')
  @Throttle(120, 60_000)
  async react(
    @CurrentUser() user: JwtPayload,
    @Param('messageId') messageId: string,
    @Body() dto: MessageReactionDto,
  ) {
    return this.chatService.reactToMessage(user.sub, messageId, dto.reactionType);
  }

  @Patch('messages/:messageId/delete-for-me')
  @Throttle(120, 60_000)
  async deleteForMe(@CurrentUser() user: JwtPayload, @Param('messageId') messageId: string) {
    return this.chatService.deleteMessageForMe(user.sub, messageId);
  }

  @Post('blocks/:targetUserId')
  @Throttle(20, 60_000)
  async blockUser(@CurrentUser() user: JwtPayload, @Param('targetUserId') targetUserId: string) {
    return this.chatService.blockUser(user.sub, targetUserId);
  }

  @Patch('blocks/:targetUserId/unblock')
  @Throttle(20, 60_000)
  async unblockUser(@CurrentUser() user: JwtPayload, @Param('targetUserId') targetUserId: string) {
    return this.chatService.unblockUser(user.sub, targetUserId);
  }

  @Get('blocks/status/:targetUserId')
  async blockStatus(@CurrentUser() user: JwtPayload, @Param('targetUserId') targetUserId: string) {
    return this.chatService.getBlockStatus(user.sub, targetUserId);
  }

  @Get('blocks')
  async myBlocks(@CurrentUser() user: JwtPayload) {
    return this.chatService.getMyBlockedUsers(user.sub);
  }
}
