/**
 * src/middleware/csrf.js — инициализация CSRF-защиты.
 *
 * Используется паттерн «double-submit cookie»:
 *   1. Сервер генерирует подписанный CSRF-токен и кладёт его в cookie.
 *   2. Шаблон (EJS) вставляет токен в скрытое поле формы (<input name="_csrf">).
 *   3. При POST-запросе doubleCsrfProtection сравнивает cookie и поле формы.
 *   4. Если они не совпадают или токен протух — 403 Forbidden.
 *
 * Почему не стандартный csurf:
 *   csurf устарел (deprecated), csrf-csrf — его современная замена для Express 5+.
 *
 * Функция initCsrf() возвращает два объекта:
 *   - doubleCsrfProtection — middleware, вешается на POST-роуты
 *   - generateCsrfToken(req, res) — вызывается в GET-роутах для получения токена
 *     и передачи его в шаблон через csrfToken.
 */

'use strict';

const { doubleCsrf } = require('csrf-csrf');

/**
 * Создаёт и возвращает CSRF middleware и генератор токенов.
 *
 * Вызывается один раз при старте приложения (в server.js → start()).
 * Параметры берутся из process.env:
 *   - CSRF_SECRET: секрет для HMAC подписи. В dev используется дефолтное
 *     значение — в продакшене ОБЯЗАТЕЛЬНО задать через env!
 *   - NODE_ENV: если 'production' — cookie выставляется с флагом secure (HTTPS only).
 *
 * @returns {{ doubleCsrfProtection: Function, generateCsrfToken: Function }}
 */
function initCsrf() {
  const { doubleCsrfProtection, generateCsrfToken } = doubleCsrf({
    // Секрет для HMAC-подписи токена.
    // ⚠️  В продакшене задать CSRF_SECRET в .env или через k8s Secret.
    getSecret: () => process.env.CSRF_SECRET || 'dev-csrf-secret-change-in-prod',

    // Идентификатор сессии — привязывает CSRF-токен к конкретной сессии пользователя.
    // Используем req.sessionID (выставляется express-session до вызова CSRF middleware).
    // Если сессии нет — пустая строка (допустимо для /login до установки сессии).
    getSessionIdentifier: (req) => req.sessionID || '',

    // ⚠️ csrf-csrf v4 по умолчанию читает токен из заголовка x-csrf-token.
    // Наши формы (EJS) отправляют его в теле POST как поле _csrf.
    // Без этой строки токен не находится → 403 на каждый POST.
    getCsrfTokenFromRequest: (req) => req.body && req.body._csrf,

    // Имя cookie без префикса __Host- (дефолт __Host-psifi.x-csrf-token
    // требует Secure-флаг; при NODE_ENV≠production secure:false → cookie
    // отклоняется браузером по HTTPS и валидация падает).
    cookieName: 'csrf-token',

    cookieOptions: {
      // secure: true → cookie передаётся только по HTTPS. Важно в продакшене.
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',   // lax: cookie отправляется при навигации, но не из iframe
      httpOnly: true,    // cookie недоступна из JS (защита от XSS-кражи CSRF-токена)
    },

    size: 64, // длина случайной части токена в байтах (достаточно для безопасности)
  });

  return { doubleCsrfProtection, generateCsrfToken };
}

module.exports = { initCsrf };
