import {
  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 { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { SuperAdminPermissions } from '../../common/decorators/superadmin-permissions.decorator';
import { SuperAdminPermissionsGuard } from '../../common/guards/superadmin-permissions.guard';
import { SuperAdminJwtAuthGuard } from '../../common/guards/super-admin-jwt-auth.guard';
import { JwtPayload } from '../../common/interfaces/jwt-payload.interface';
import { AdminDisableUserDto } from './dto/admin-disable-user.dto';
import { CreateAdminDto } from './dto/create-admin.dto';
import { MusicSetupDto } from './dto/music-setup.dto';
import { ProfileSetupDto } from './dto/profile-setup.dto';
import { ShareFriendsQueryDto } from './dto/share-friends-query.dto';
import { TalentDiscoverQueryDto } from './dto/talent-discover-query.dto';
import { UpdateUserRoleDto } from './dto/update-user-role.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { UserQueryDto } from './dto/user-query.dto';
import { UsersService } from './users.service';
import { SUPERADMIN_PERMISSIONS } from '../superadmin/superadmin-permissions';

@ApiTags('Users')
@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Patch('me/profile-setup')
  @UseInterceptors(
    FileFieldsInterceptor([
      { name: 'avatarFile', maxCount: 1 },
      { name: 'coverImageFile', maxCount: 1 },
    ], { limits: { fileSize: MEDIA_MAX_SIZE_BYTES.userImage, files: 2 } }),
  )
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        stageName: { type: 'string', example: 'Artist One' },
        bio: { type: 'string', example: 'Short bio' },
        location: { type: 'string', example: 'Riyadh, Saudi Arabia' },
        latitude: { type: 'number', example: 24.7136 },
        longitude: { type: 'number', example: 46.6753 },
        avatar: { type: 'string', example: 'https://cdn.example.com/avatar.jpg' },
        coverImage: { type: 'string', example: 'https://cdn.example.com/profile-cover.jpg' },
        avatarFile: { type: 'string', format: 'binary' },
        coverImageFile: { type: 'string', format: 'binary' },
      },
      required: ['latitude', 'longitude'],
    },
  })
  async updateProfileSetup(
    @CurrentUser() user: JwtPayload,
    @Body() dto: ProfileSetupDto,
    @UploadedFiles()
    files?: {
      avatarFile?: Array<{
        mimetype?: string;
        size: number;
        buffer: Buffer;
        originalname?: string;
      }>;
      coverImageFile?: Array<{
        mimetype?: string;
        size: number;
        buffer: Buffer;
        originalname?: string;
      }>;
    },
  ) {
    return this.usersService.updateProfileSetup(
      user.sub,
      dto,
      files?.avatarFile?.[0],
      files?.coverImageFile?.[0],
    );
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Patch('me/music-setup')
  async updateMusicSetup(@CurrentUser() user: JwtPayload, @Body() dto: MusicSetupDto) {
    return this.usersService.updateMusicSetup(user.sub, dto);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Patch('me')
  @UseInterceptors(
    FileFieldsInterceptor([
      { name: 'avatarFile', maxCount: 1 },
      { name: 'coverImageFile', maxCount: 1 },
    ], { limits: { fileSize: MEDIA_MAX_SIZE_BYTES.userImage, files: 2 } }),
  )
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        name: { type: 'string', example: 'Raffi Wadeea' },
        stageName: { type: 'string', example: 'Artist One' },
        bio: { type: 'string', example: 'Short bio' },
        avatar: { type: 'string', example: 'https://cdn.example.com/avatar.jpg' },
        coverImage: { type: 'string', example: 'https://cdn.example.com/profile-cover.jpg' },
        location: { type: 'string', example: 'Riyadh, Saudi Arabia' },
        isPrivate: { type: 'boolean', example: false },
        avatarFile: { type: 'string', format: 'binary' },
        coverImageFile: { type: 'string', format: 'binary' },
      },
    },
  })
  async updateMe(
    @CurrentUser() user: JwtPayload,
    @Body() dto: UpdateUserDto,
    @UploadedFiles()
    files?: {
      avatarFile?: Array<{
        mimetype?: string;
        size: number;
        buffer: Buffer;
        originalname?: string;
      }>;
      coverImageFile?: Array<{
        mimetype?: string;
        size: number;
        buffer: Buffer;
        originalname?: string;
      }>;
    },
  ) {
    return this.usersService.updateProfile(
      user.sub,
      dto,
      files?.avatarFile?.[0],
      files?.coverImageFile?.[0],
    );
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_MANAGE)
  @Post('admin/create-admin')
  async createAdmin(
    @CurrentUser() user: JwtPayload,
    @Body() dto: CreateAdminDto,
  ) {
    return this.usersService.createAdminBySuperAdmin(user.email ?? user.sub, dto);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_READ)
  @Get('admin')
  async adminFindMany(@Query() query: UserQueryDto) {
    return this.usersService.searchUsersForSuperAdmin(query);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_READ)
  @Get('admin/admins')
  async adminListAdmins(@Query() query: UserQueryDto) {
    return this.usersService.listAdminsBySuperAdmin(query);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_READ)
  @Get('admin/:id')
  async adminFindOne(@Param('id') targetUserId: string) {
    return this.usersService.findUserByIdForSuperAdmin(targetUserId);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_MANAGE)
  @Patch('admin/:id')
  async adminUpdateUser(
    @CurrentUser() user: JwtPayload,
    @Param('id') targetUserId: string,
    @Body() dto: UpdateUserDto,
  ) {
    return this.usersService.updateUserBySuperAdmin(user.email ?? user.sub, targetUserId, dto);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_MANAGE)
  @Patch('admin/:id/role')
  async adminUpdateUserRole(
    @CurrentUser() user: JwtPayload,
    @Param('id') targetUserId: string,
    @Body() dto: UpdateUserRoleDto,
  ) {
    return this.usersService.updateUserRoleBySuperAdmin(user.email ?? user.sub, targetUserId, dto);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_MANAGE)
  @Patch('admin/:id/disable')
  async disableUser(
    @CurrentUser() user: JwtPayload,
    @Param('id') targetUserId: string,
    @Body() dto: AdminDisableUserDto,
  ) {
    return this.usersService.disableUserBySuperAdmin(user.email ?? user.sub, targetUserId, dto);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_MANAGE)
  @Patch('admin/:id/enable')
  async enableUser(@CurrentUser() user: JwtPayload, @Param('id') targetUserId: string) {
    return this.usersService.enableUserBySuperAdmin(user.email ?? user.sub, targetUserId);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_MANAGE)
  @Delete('admin/:id')
  async deleteUser(@CurrentUser() user: JwtPayload, @Param('id') targetUserId: string) {
    await this.usersService.deleteUserBySuperAdmin(user.email ?? user.sub, targetUserId);
    return { message: 'User deleted successfully' };
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_MANAGE)
  @Patch('admin/admins/:id')
  async adminUpdateAdmin(
    @CurrentUser() user: JwtPayload,
    @Param('id') targetUserId: string,
    @Body() dto: UpdateUserDto,
  ) {
    return this.usersService.updateAdminBySuperAdmin(user.email ?? user.sub, targetUserId, dto);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_MANAGE)
  @Delete('admin/admins/:id')
  async adminDeleteAdmin(@CurrentUser() user: JwtPayload, @Param('id') targetUserId: string) {
    await this.usersService.deleteAdminBySuperAdmin(user.email ?? user.sub, targetUserId);
    return { message: 'Admin deleted successfully' };
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_READ)
  @Get('admin/discover')
  async adminDiscoverTalents(@Query() query: TalentDiscoverQueryDto) {
    return this.usersService.discoverTalentsForSuperAdmin(query);
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.USERS_READ)
  @Get('admin/:id/profile-overview')
  async adminGetProfileOverview(@Param('id') id: string) {
    return this.usersService.getProfileOverviewForSuperAdmin(id);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get('discover')
  async discoverTalents(@Query() query: TalentDiscoverQueryDto) {
    return this.usersService.discoverTalents(query);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get('me/dashboard')
  async getMyDashboard(@CurrentUser() user: JwtPayload) {
    return this.usersService.getMyDashboard(user.sub);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get('me/share-friends')
  async getShareFriends(@CurrentUser() user: JwtPayload, @Query() query: ShareFriendsQueryDto) {
    return this.usersService.getShareFriends(user.sub, query);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get('by-username/:username')
  async getProfileOverviewByUsername(
    @CurrentUser() user: JwtPayload,
    @Param('username') username: string,
  ) {
    return this.usersService.getProfileOverviewByUsername(username, user.sub);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get(':id/follow-counts')
  async getFollowCounts(@CurrentUser() user: JwtPayload, @Param('id') id: string) {
    return this.usersService.getFollowCounts(id, user.sub);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get(':id/profile-overview')
  async getProfileOverview(@CurrentUser() user: JwtPayload, @Param('id') id: string) {
    return this.usersService.getProfileOverview(id, user.sub);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get(':id/presence')
  async getPresence(@Param('id') id: string) {
    return this.usersService.getPresence(id);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get(':id')
  async findOne(@CurrentUser() user: JwtPayload, @Param('id') id: string) {
    return this.usersService.findPublicByIdForViewer(id, user.sub);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get()
  async findMany(@Query() query: UserQueryDto) {
    return this.usersService.searchUsers(query);
  }
}
