import { Body, Controller, Post, Req, UsePipes, ValidationPipe } from '@nestjs/common';
import { ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import type { Request } from 'express';
import { AuthService } from './auth.service';
import { SendCodeDto } from './dto/send-code.dto';
import { VerifyCodeDto } from './dto/verify-code.dto';
import { RefreshTokenDto } from './dto/refresh.dto';

function getClientIp(req: Request): string {
  const xff = req.headers['x-forwarded-for'];
  if (typeof xff === 'string') return xff.split(',')[0].trim();
  if (Array.isArray(xff) && xff[0]) return xff[0].trim();
  return req.socket?.remoteAddress ?? req.ip ?? '127.0.0.1';
}

@ApiTags('auth')
@Controller('auth')
@UsePipes(new ValidationPipe({ whitelist: true }))
export class AuthController {
  constructor(private readonly authService: AuthService) {}

  @Post('send-code')
  @ApiOperation({ summary: 'Создать код верификации и отправить по SMS' })
  @ApiBody({ type: SendCodeDto })
  @ApiResponse({ status: 201, description: 'Код отправлен' })
  @ApiResponse({ status: 429, description: 'Превышены лимиты отправки' })
  async sendCode(@Body() dto: SendCodeDto, @Req() req: Request) {
    const ip = getClientIp(req);
    return this.authService.sendVerificationCode(dto.phone, ip);
  }

  @Post('verify-code')
  @ApiOperation({ summary: 'Проверить код и получить access/refresh токены' })
  @ApiBody({ type: VerifyCodeDto })
  @ApiResponse({ status: 201, description: 'Токены выданы', schema: { properties: { access_token: { type: 'string' }, refresh_token: { type: 'string' } } } })
  @ApiResponse({ status: 400, description: 'Неверный или просроченный код' })
  @ApiResponse({ status: 429, description: 'Блокировка после 5 неверных попыток' })
  async verifyCode(@Body() dto: VerifyCodeDto, @Req() req: Request) {
    const ip = getClientIp(req);
    return this.authService.verifyCode(dto.phone, dto.code, ip);
  }

  @Post('refresh')
  @ApiOperation({ summary: 'Обновить access токен по refresh токену' })
  @ApiBody({ type: RefreshTokenDto })
  @ApiResponse({ status: 201, description: 'Новые токены выданы' })
  @ApiResponse({ status: 400, description: 'Недействительный refresh token' })
  async refresh(@Body() dto: RefreshTokenDto) {
    return this.authService.refresh(dto.refresh_token);
  }
}
