import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Post,
  Put,
  Query,
  UseGuards,
} from '@nestjs/common';
import {
  ApiBearerAuth,
  ApiBody,
  ApiParam,
  ApiQuery,
  ApiTags,
} from '@nestjs/swagger';
import { UsersService } from './services/users.service';
import { ResponseMessage } from 'src/common/decorators/response_message.decorator';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
import { Roles } from 'src/common/decorators/roles.decorator';
import { USER_ROLE } from './users.constant';
import { CurrentUser } from 'src/common/decorators/user.decorator';
import { PaginatedQueryDto } from 'src/common/builder/QueryBuilder.dto';
import { UpdateFullUserDto, UpdateUserDto } from './users.validation';
import { IFullUser } from './users.interface';
import { AdminService } from './services/admin.service';
import { SuperAdminService } from './services/super-admin.service';

@ApiTags('Users')
@Controller('users')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
export class UserController {
  constructor(
    private userService: UsersService,
    private adminService: AdminService,
    private superAdminService: SuperAdminService,
  ) {}

  // @Get('get-users')
  // @UseGuards(RolesGuard)
  // @Roles(USER_ROLE.admin, USER_ROLE.super_admin)
  // @ApiQuery({ type: PaginatedQueryDto })
  // @ResponseMessage('Fetched Users Succesfully')
  // async findAll(
  // 	@Query() query: Record<string, unknown>,
  // ) {
  // 	return await this.adminService.findAll(query);
  // }

  // TODO add pagination
  @Get('get-users')
  @ApiQuery({ name: 'page', required: false })
  @ApiQuery({ name: 'limit', required: false })
  @ApiQuery({ name: 'name', required: false })
  @ApiQuery({ name: 'email', required: false })
  @ApiQuery({ name: 'searchTerm', required: false })
  @ApiQuery({ name: 'sortBy', required: false })
  @ApiQuery({ name: 'sortOrder', required: false })
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.super_admin)
  searchOrFilterUsers(
    @Query('page') page: number,
    @Query('limit') limit: number,
    @Query('searchTerm') searchTerm: string,
    @Query('name') name: string,
    @Query('email') email: string,
    @Query('sortBy') sortBy: string,
    @Query('sortOrder') sortOrder: number,
  ) {
    let filter = {
      name,
      email,
      searchTerm,
      sortBy,
      sortOrder,
    };

    return this.adminService.getpartialUsers(page, limit, filter);
  }

  // Export the users data
  @Get('export-users')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.super_admin)
  exportAllUsers() {
    return this.adminService.getExportedUsers();
  }

  @Get('get-user/:userId')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.super_admin)
  @ResponseMessage('Fetched User Succesfully')
  @ApiParam({
    name: 'userId',
    type: String,
    required: true,
    description: 'User Id',
    example: '60f1b0b9c9b9b1b4e8f7b0a0',
  })
  async findOne(@Param('userId') userId: string) {
    return await this.userService.findUser(userId);
  }

  @Put('edit-user/:userId')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.super_admin)
  @ApiBody({ type: UpdateFullUserDto })
  @ResponseMessage('User updated Succesfully')
  @ApiParam({
    name: 'userId',
    type: String,
    required: true,
    description: 'User Id',
    example: '60f1b0b9c9b9b1b4e8f7b0a0',
  })
  async updateOne(
    @Param('userId') userId: string,
    @Body() body: UpdateFullUserDto,
  ) {
    return await this.superAdminService.updateUser(body, userId);
  }

  @Delete('delete-user/:userId')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.super_admin)
  @ResponseMessage('User deleted successfully')
  async deleteImage(
    @Param('userId') userId: string,
  ) {
    return this.superAdminService.deleteUser(userId);
  }

  @Get('me')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.user, USER_ROLE.super_admin)
  @ResponseMessage('Fetched User Succesfully')
  async findMe(@CurrentUser() user: any) {
    return await this.userService.findUser(user._id);
  }

  @Put('edit-current-user')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.user, USER_ROLE.super_admin)
  @ApiBody({ type: UpdateUserDto })
  @ResponseMessage('Updated settings Succesfully')
  async updatePartialUser(
    @Body() body: UpdateUserDto,
    @CurrentUser() user: IFullUser,
  ) {
    try {
      return await this.userService.updatePartialUser(body, user);
    } catch (err) {
      throw err;
    }
  }

  @Delete('delete-current-user')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.user, USER_ROLE.super_admin)
  @ResponseMessage('User deleted successfully')
  async deleteCurrentUser(@CurrentUser() user: IFullUser) {
    return this.superAdminService.deleteUser(user._id);
  }

  @Get('images')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.super_admin)
  @ResponseMessage('Fetched User Images Successfully')
  async findUsersImages(
    @Query('page') page: number = 1,
    @Query('limit') limit: number = 10,
  ) {
    return await this.adminService.findPaginatedImages(page, limit);
  }

  @Post('connect-google-drive')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.super_admin, USER_ROLE.user)
  @ResponseMessage('Google Drive Connected Successfully')
  async connectGoogleDrive(
    @CurrentUser() user: IFullUser,
    @Body('code') code: string,
  ) {
    return await this.userService.connectGoogleDrive(user, code);
  }

  @Get('get-google-drive')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.super_admin, USER_ROLE.user)
  @ResponseMessage('Google Drive Connected Successfully')
  async getGoogleDrive(@CurrentUser() user: IFullUser) {
    return await this.userService.getGoogleDrive(user);
  }

  @Post('disconnect-google-drive')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.super_admin, USER_ROLE.user)
  @ResponseMessage('Google Drive Disconnected Successfully')
  async disconnectGoogleDrive(@CurrentUser() user: IFullUser) {
    return await this.userService.disconnectGoogleDrive(user);
  }

  @Get('memories')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.super_admin, USER_ROLE.user)
  @ResponseMessage('Fetched memories successfully')
  async getMemories(@CurrentUser() user: IFullUser) {
    return await this.userService.getMemories(user);
  }

  @Delete('memories/:memoryIndex')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.super_admin, USER_ROLE.user)
  @ResponseMessage('Memory deleted successfully')
  @ApiParam({
    name: 'memoryIndex',
    type: Number,
    required: true,
    description: 'Memory index',
  })
  async deleteMemory(
    @CurrentUser() user: IFullUser,
    @Param('memoryIndex') memoryIndex: string,
  ) {
    return await this.userService.deleteMemory(user, parseInt(memoryIndex));
  }

  @Delete('memories')
  @UseGuards(RolesGuard)
  @Roles(USER_ROLE.admin, USER_ROLE.super_admin, USER_ROLE.user)
  @ResponseMessage('All memories deleted successfully')
  async deleteAllMemories(@CurrentUser() user: IFullUser) {
    return await this.userService.deleteAllMemories(user);
  }
}
