import { Body, Controller, ForbiddenException, Get, Param, Patch, Post, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiBody, ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger';
import { firstValueFrom } from 'rxjs';
import { map } from 'rxjs';
import { CoreGrpcService } from '../core-grpc.service';
import { CurrentAdmin } from '../decorators/current-admin.decorator';
import { ListUsersQueryDto, ResetPasswordDto, SetSuperAdminDto, SetUserVerificationDto, UpdateUserDto } from '../dto/admin.dto';
import { AdminGuard, AdminRequestUser, assertAdminPermission, SuperAdminGuard } from '../guards/admin.guard';

@ApiTags('Администрирование')
@ApiBearerAuth()
@UseGuards(AdminGuard)
@Controller('admin/users')
export class AdminController {
  constructor(private readonly core: CoreGrpcService) {}

  @Get()
  @ApiOperation({ summary: 'Список пользователей', description: 'Возвращает пользователей для административной таблицы.' })
  listUsers(@Query() query: ListUsersQueryDto, @CurrentAdmin() admin: AdminRequestUser) {
    if (!admin.canViewUsers && !admin.canManageUsers) {
      throw new ForbiddenException('Недостаточно прав для просмотра пользователей');
    }
    return this.core.admin.ListUsers(query).pipe(
      map((response) => {
        const payload = response as { users?: Array<{ roles?: string[] }> };
        return {
          users: (payload.users ?? []).map((user) => ({
            ...user,
            roles: user.roles ?? []
          }))
        };
      })
    );
  }

  @Get('verification-icons')
  @ApiOperation({ summary: 'Список значков верификации', description: 'Доступные значки для выбора при верификации пользователя.' })
  listVerificationIcons(@CurrentAdmin() admin: AdminRequestUser) {
    if (!admin.canVerifyUsers) {
      throw new ForbiddenException('Недостаточно прав для верификации пользователей');
    }
    return this.core.admin.ListVerificationIcons({});
  }

  @Patch(':userId')
  @ApiOperation({ summary: 'Обновить профиль пользователя', description: 'Обновляет основные и резервные контакты пользователя.' })
  @ApiParam({ name: 'userId', description: 'ID пользователя' })
  @ApiBody({ type: UpdateUserDto })
  updateUser(@Param('userId') userId: string, @Body() dto: UpdateUserDto, @CurrentAdmin() admin: AdminRequestUser) {
    assertAdminPermission(admin, 'canManageUsers');
    return this.core.admin.UpdateUserProfile({ userId, ...dto });
  }

  @Post(':userId/reset-password')
  @ApiOperation({ summary: 'Сбросить пароль', description: 'Назначает пользователю новый пароль.' })
  @ApiParam({ name: 'userId', description: 'ID пользователя' })
  @ApiBody({ type: ResetPasswordDto })
  resetPassword(@Param('userId') userId: string, @Body() dto: ResetPasswordDto, @CurrentAdmin() admin: AdminRequestUser) {
    assertAdminPermission(admin, 'canManageUsers');
    return this.core.admin.ResetPassword({ userId, newPassword: dto.newPassword });
  }

  @Post(':userId/suspend')
  @ApiOperation({ summary: 'Заблокировать пользователя', description: 'Переводит пользователя в статус SUSPENDED и отзывает активные сессии.' })
  @ApiParam({ name: 'userId', description: 'ID пользователя' })
  suspend(@Param('userId') userId: string, @CurrentAdmin() admin: AdminRequestUser) {
    assertAdminPermission(admin, 'canManageUsers');
    return this.core.admin.SuspendUser({ userId });
  }

  @Patch(':userId/super-admin')
  @UseGuards(SuperAdminGuard)
  @ApiOperation({ summary: 'Выдать или снять права супер-администратора', description: 'Доступно только супер-администратору.' })
  @ApiParam({ name: 'userId', description: 'ID пользователя' })
  @ApiBody({ type: SetSuperAdminDto })
  setSuperAdmin(@Param('userId') userId: string, @Body() dto: SetSuperAdminDto, @CurrentAdmin() admin: AdminRequestUser) {
    return this.core.admin.SetSuperAdmin({ actorUserId: admin.id, userId, isSuperAdmin: dto.isSuperAdmin });
  }

  @Get('bot-accounts')
  @ApiOperation({ summary: 'Системные учётные записи ботов', description: 'Возвращает пользователей, связанных с Telegram-ботами (BotFather и боты пользователей).' })
  listBotAccounts(@Query() query: ListUsersQueryDto, @CurrentAdmin() admin: AdminRequestUser) {
    if (!admin.canViewUsers && !admin.canManageUsers && !admin.isSuperAdmin && !admin.permissions.includes('bots.manage.all')) {
      throw new ForbiddenException('Недостаточно прав для просмотра ботов');
    }
    return this.core.admin.ListBotAccounts(query).pipe(
      map((response) => {
        const payload = response as { users?: Array<{ roles?: string[] }> };
        return {
          users: (payload.users ?? []).map((user) => ({
            ...user,
            roles: user.roles ?? []
          }))
        };
      })
    );
  }

  @Post(':userId/totp/admin-disable')
  @UseGuards(SuperAdminGuard)
  @ApiOperation({ summary: 'Отключить 2FA пользователя', description: 'Супер-администратор может принудительно отключить TOTP без кода пользователя.' })
  @ApiParam({ name: 'userId', description: 'ID пользователя' })
  adminDisableTotp(@Param('userId') userId: string, @CurrentAdmin() admin: AdminRequestUser) {
    return firstValueFrom(
      this.core.security.AdminDisableTotp({
        actorUserId: admin.id,
        userId
      })
    );
  }

  @Patch(':userId/verification')
  @ApiOperation({ summary: 'Верифицировать или снять верификацию', description: 'Требуется право users.verify.' })
  @ApiParam({ name: 'userId', description: 'ID пользователя' })
  @ApiBody({ type: SetUserVerificationDto })
  setUserVerification(@Param('userId') userId: string, @Body() dto: SetUserVerificationDto, @CurrentAdmin() admin: AdminRequestUser) {
    if (!admin.canVerifyUsers) {
      throw new ForbiddenException('Недостаточно прав для верификации пользователей');
    }
    return this.core.admin.SetUserVerification({
      actorUserId: admin.id,
      userId,
      isVerified: dto.isVerified,
      verificationIcon: dto.verificationIcon
    });
  }
}
