/**
 * ╔═══════════════════════════════════════════════════════════════╗
 * ║  AuthController — Контроллер аутентификации                   ║
 * ╚═══════════════════════════════════════════════════════════════╝
 *
 * Эндпоинты (все 1:1 с Express-бэкендом):
 *   POST /api/auth/login   — вход, возвращает { token, user }
 *   POST /api/auth/logout  — выход, инвалидирует сессию
 *   GET  /api/auth/me      — текущий пользователь
 *   POST /api/auth/forgot  — запрос ссылки сброса пароля
 *   POST /api/auth/reset   — применить новый пароль по токену
 *   GET  /api/auth/online  — активные сессии (level ≥ 4)
 *
 * Архитектурные решения:
 *  1. IP-защита: пробрасываем IP в сервис для scoring'а
 *  2. User-agent: передаём в сессию для аудита
 *  3. RateLimit на /login — защита от brute-force
 *  4. @CurrentUser() вместо req.user — типобезопасность
 */

import {
  Controller, Post, Get, Body, Req, HttpCode, UseGuards, Logger,
} from '@nestjs/common';
import { Request }         from 'express';
import { Throttle }        from '@nestjs/throttler';

import { AuthService }     from './auth.service';
import { JwtAuthGuard }    from '../../common/guards/jwt-auth.guard';
import { RoleGuard, MinLevel } from '../../common/guards/role.guard';
import { CurrentUser, JwtPayload } from '../../common/decorators/current-user.decorator';

import { LoginDto }          from '../../dto/auth/login.dto';
import { ForgotPasswordDto } from '../../dto/auth/forgot-password.dto';
import { ResetPasswordDto }  from '../../dto/auth/reset-password.dto';

@Controller('api/auth')
export class AuthController {
  private readonly logger = new Logger(AuthController.name);

  constructor(private readonly authSvc: AuthService) {}

  // ─────────────────────────────────────────────────────────────
  // POST /api/auth/login
  // ─────────────────────────────────────────────────────────────
  /**
   * Вход в систему.
   * Throttle: 10 запросов в минуту с одного IP (brute-force защита).
   *
   * Ответ (1:1 с Express):
   *   {
   *     "token": "eyJ...",
   *     "user": { "id", "login", "name", "role", "dept", "ext", "sipExt" }
   *   }
   *
   * Ошибки:
   *   401 — неверный логин/пароль
   *   403 — аккаунт заблокирован / IP заблокирован
   *   429 — превышен lockout
   */
  @Post('login')
  @HttpCode(200)
  @Throttle({ default: { limit: 10, ttl: 60_000 } })
  async login(
    @Body() dto: LoginDto,
    @Req()  req: Request,
  ) {
    const ip = this.extractIp(req);
    const ua = String(req.headers['user-agent'] ?? '');
    this.logger.log(`Попытка входа: ${dto.login} (IP: ${ip})`);
    return this.authSvc.login(dto.login, dto.password, ip, ua);
  }

  // ─────────────────────────────────────────────────────────────
  // POST /api/auth/logout
  // ─────────────────────────────────────────────────────────────
  /**
   * Выход: инвалидирует JWT-сессию (удаляет из activeSessions).
   * Ответ: { "ok": true }
   */
  @Post('logout')
  @HttpCode(200)
  @UseGuards(JwtAuthGuard)
  async logout(
    @CurrentUser() user: JwtPayload,
    @Req()         req:  Request,
  ) {
    const ip = this.extractIp(req);
    await this.authSvc.logout(user.jti, user.id, user.login, ip);
    return { ok: true };
  }

  // ─────────────────────────────────────────────────────────────
  // GET /api/auth/me
  // ─────────────────────────────────────────────────────────────
  /**
   * Текущий пользователь.
   * Ответ: { id, login, name, role, dept, ext, email, sipExt, lastLogin, lastIp }
   */
  @Get('me')
  @UseGuards(JwtAuthGuard)
  me(@CurrentUser() user: JwtPayload) {
    return this.authSvc.getMe(user.id);
  }

  // ─────────────────────────────────────────────────────────────
  // POST /api/auth/forgot
  // ─────────────────────────────────────────────────────────────
  /**
   * Запрос ссылки сброса пароля.
   * Throttle: 5 запросов в минуту (предотвращает email-flooding).
   *
   * Ответ: { "ok": true, "emailSent": true/false }
   * В dev-режиме добавляет "devToken" для тестирования без SMTP.
   */
  @Post('forgot')
  @HttpCode(200)
  @Throttle({ default: { limit: 5, ttl: 60_000 } })
  async forgot(
    @Body() dto: ForgotPasswordDto,
    @Req()  req: Request,
  ) {
    const ip      = this.extractIp(req);
    const baseUrl = `${req.protocol}://${req.get('host')}`;
    return this.authSvc.forgotPassword(dto.email, baseUrl, ip);
  }

  // ─────────────────────────────────────────────────────────────
  // POST /api/auth/reset
  // ─────────────────────────────────────────────────────────────
  /**
   * Применить новый пароль по одноразовому токену (15 мин).
   * Ответ: { "ok": true }
   * Ошибки: 400 — токен недействителен / истёк
   */
  @Post('reset')
  @HttpCode(200)
  async reset(
    @Body() dto: ResetPasswordDto,
    @Req()  req: Request,
  ) {
    const ip = this.extractIp(req);
    await this.authSvc.resetPassword(dto.token, dto.password, ip);
    return { ok: true };
  }

  // ─────────────────────────────────────────────────────────────
  // GET /api/auth/online (= /api/online — для совместимости)
  // ─────────────────────────────────────────────────────────────
  /**
   * Список активных сессий — только для level ≥ 4 (engineer/admin).
   * Ответ: [{ userId, login, name, role, ip, loginAt, lastSeen, ua }]
   */
  @Get('online')
  @UseGuards(JwtAuthGuard, RoleGuard)
  @MinLevel(4)
  getOnline() {
    return this.authSvc.getOnline();
  }

  // ─────────────────────────────────────────────────────────────
  // Утилиты
  // ─────────────────────────────────────────────────────────────

  /**
   * Извлечь реальный IP клиента.
   * Учитывает X-Forwarded-For (за Nginx/балансировщиком).
   */
  private extractIp(req: Request): string {
    const forwarded = req.headers['x-forwarded-for'];
    if (forwarded) return String(forwarded).split(',')[0].trim();
    return req.socket?.remoteAddress ?? req.ip ?? '?';
  }
}
