import { Body, Controller, ForbiddenException, Get, Headers, Param, Patch, Post } from '@nestjs/common';

import { JwtService } from '@nestjs/jwt';

import { ApiBearerAuth, ApiBody, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger';

import { CoreGrpcService } from '../core-grpc.service';

import { getAuthorizedUserId } from '../document-access';

import { SetPasswordDto, UpdateAvatarDto, UpdateContactsDto, UpdateProfileDto } from '../dto/profile.dto';



@ApiTags('Профиль и биометрия')

@ApiBearerAuth()

@Controller('profile/users/:userId')

export class ProfileController {

  constructor(

    private readonly core: CoreGrpcService,

    private readonly jwt: JwtService

  ) {}



  private async assertSelfAccess(authorization: string | undefined, userId: string) {

    const requesterId = await getAuthorizedUserId(this.jwt, this.core, authorization);

    if (requesterId !== userId) {

      throw new ForbiddenException('Можно изменять только свой профиль');

    }

    return requesterId;

  }



  @Get()

  @ApiOperation({ summary: 'Получить профиль пользователя', description: 'Возвращает публичный профиль, аватар и основные/резервные контакты пользователя.' })

  @ApiParam({ name: 'userId', description: 'ID пользователя' })

  @ApiResponse({ status: 200, description: 'Профиль пользователя успешно получен' })

  @ApiResponse({ status: 404, description: 'Пользователь не найден' })

  getProfile(@Param('userId') userId: string) {

    return this.core.profile.GetProfile({ userId });

  }



  @Patch('avatar')

  @ApiOperation({ summary: 'Обновить аватар', description: 'Сохраняет URL или ключ объекта MinIO как аватар пользователя.' })

  @ApiParam({ name: 'userId', description: 'ID пользователя' })

  @ApiBody({ type: UpdateAvatarDto })

  @ApiResponse({ status: 200, description: 'Аватар обновлен' })

  updateAvatar(@Param('userId') userId: string, @Body() dto: UpdateAvatarDto) {

    return this.core.profile.UpdateAvatar({ userId, avatarUrl: dto.avatarUrl, avatarStorageKey: dto.avatarStorageKey });

  }



  @Patch()

  @ApiOperation({ summary: 'Обновить профиль', description: 'Обновляет firstName, lastName, bio, age и gender в UserProfile, а displayName синхронизирует с именем и фамилией.' })

  @ApiParam({ name: 'userId', description: 'ID пользователя' })

  @ApiBody({ type: UpdateProfileDto })

  @ApiResponse({ status: 200, description: 'Профиль обновлен' })

  updateProfile(@Param('userId') userId: string, @Body() dto: UpdateProfileDto) {

    return this.core.profile.UpdateProfile({ userId, ...dto });

  }



  @Patch('contacts')

  @ApiOperation({ summary: 'Обновить контакты', description: 'Обновляет основную и резервную почту/телефон в модели User.' })

  @ApiParam({ name: 'userId', description: 'ID пользователя' })

  @ApiBody({ type: UpdateContactsDto })

  @ApiResponse({ status: 200, description: 'Контакты обновлены' })

  @ApiResponse({ status: 400, description: 'Переданы некорректные контактные данные' })

  updateContacts(@Param('userId') userId: string, @Body() dto: UpdateContactsDto) {

    return this.core.profile.UpdateContacts({ userId, ...dto });

  }



  @Post('password')

  @ApiOperation({ summary: 'Установить пароль', description: 'Устанавливает пароль для аккаунта. После этого пароль становится доступным как альтернативный способ входа.' })

  @ApiParam({ name: 'userId', description: 'ID пользователя' })

  @ApiBody({ type: SetPasswordDto })

  @ApiResponse({ status: 201, description: 'Пароль установлен' })

  setPassword(@Param('userId') userId: string, @Body() dto: SetPasswordDto) {

    return this.core.profile.SetPassword({ userId, password: dto.password });

  }



  @Post('self-delete')

  @ApiOperation({

    summary: 'Удалить свой профиль',

    description: 'Мягко удаляет профиль: помечает аккаунт как удалённый, освобождает логин и контакты для повторной регистрации, сбрасывает роли и завершает все сессии.'

  })

  @ApiParam({ name: 'userId', description: 'ID пользователя' })

  @ApiResponse({ status: 201, description: 'Профиль удалён' })

  async selfDelete(@Headers('authorization') authorization: string | undefined, @Param('userId') userId: string) {

    await this.assertSelfAccess(authorization, userId);

    return this.core.profile.SoftDeleteProfile({ userId });

  }

}


