import { Body, Controller, Get, Post, Res, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import {
    ApiBearerAuth,
    ApiBody,
    ApiOkResponse,
    ApiSecurity,
    ApiTags,
} from '@nestjs/swagger';
import type { Response } from 'express';
import { Throttle, ThrottlerGuard } from '@nestjs/throttler';
import { AppTokenGuard } from 'src/app-token.guard';
import { AuthService } from './auth.service';
import {
    response_auth_login,
    response_auth_logout,
    response_auth_register,
} from './dto/doc-swagger';
import { LoginDto, LoginLogoutDto, LoginRefreshDto } from './dto/login.dto';
import { RegistroDto } from './dto/registro.dto';
import { SwitchEmpresaDto } from './dto/switch-empresa.dto';
import { GetUser } from './get-user.decorator';

@ApiTags('Auth')
@Controller({ path: 'auth', version: '1' })
export class AuthController {
  constructor(private readonly authService: AuthService) {}

  @ApiSecurity('AppKey')
  @UseGuards(AppTokenGuard)
  @ApiOkResponse(response_auth_register)
  @Post('register')
  async register(@Body() dto: RegistroDto, @Res() response: Response) {
    const responseRegister = await this.authService.register(dto);
    return response.status(201).json(responseRegister);
  }

  @ApiBody({ type: LoginDto })
  @ApiOkResponse(response_auth_login)
  @ApiSecurity('AppKey')
  // Anti fuerza-bruta: 5 intentos de login por minuto por IP.
  @Throttle({ default: { limit: 5, ttl: 60_000 } })
  @UseGuards(AppTokenGuard, ThrottlerGuard)
  @Post('login')
  async login(@Body() dto: LoginDto, @Res() response: Response) {
    const responseLogin = await this.authService.login(dto);
    return response.status(200).json(responseLogin);
  }

  @ApiSecurity('AppKey')
  @ApiBody({ type: LoginRefreshDto })
  @ApiOkResponse(response_auth_login)
  @UseGuards(AppTokenGuard)
  @Post('refresh')
  async refresh(@Body() body: LoginRefreshDto, @Res() response: Response) {
    const responseRefresh = await this.authService.refresh(body?.refresh_token);
    return response.status(200).json(responseRefresh);
  }

  @ApiSecurity('AppKey')
  @ApiBody({ type: LoginLogoutDto })
  @ApiOkResponse(response_auth_logout)
  @UseGuards(AppTokenGuard)
  @Post('logout')
  async logout(@Body() body: LoginLogoutDto, @Res() response: Response) {
    const responseLogout = await this.authService.logout(body?.refresh_token);
    return response.status(200).json(responseLogout);
  }

  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @Get('me')
  async getMe(
    @GetUser() user: { id: string; empresa_id: string },
    @Res() response: Response,
  ) {
    const result = await this.authService.getMe(user.id, user.empresa_id);
    return response.status(200).json(result);
  }

  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @ApiBody({ type: SwitchEmpresaDto })
  @Post('switch-empresa')
  async switchEmpresa(
    @Body() dto: SwitchEmpresaDto,
    @GetUser() user: { id: string; empresa_id: string },
    @Res() response: Response,
  ) {
    const result = await this.authService.switchEmpresa(
      user.id,
      dto.empresa_id,
      user.empresa_id,
    );
    return response.status(200).json(result);
  }

  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @Get('empresas-accesibles')
  async getEmpresasAccesibles(
    @GetUser() user: { id: string; empresa_id: string },
    @Res() response: Response,
  ) {
    const result = await this.authService.getEmpresasAccesibles(
      user.id,
      user.empresa_id,
    );
    return response.status(200).json(result);
  }
}
