/**
 * src/routes/admin.js — маршруты администратора.
 *
 * Маршруты:
 *   GET  /audit                    — журнал аудита всех изменений
 *   GET  /admin                    — страница управления лимитами компаний
 *   POST /admin/limit/:companyId   — изменить или сбросить лимит компании
 *
 * Все маршруты защищены requireAdmin — возвращают 403 для не-admin.
 * Дополнительно POST /admin/limit:
 *   - mutationLimiter: не более 30 запросов/мин с одного IP
 *   - doubleCsrfProtection: проверка CSRF-токена
 *
 * Зависимости (через deps):
 *   q                    — объект из src/queries.js (все DB-операции)
 *   requireAdmin         — middleware из src/auth.js
 *   doubleCsrfProtection — middleware проверки CSRF
 *   mutationLimiter      — middleware ограничения частоты POST
 *   generateCsrfToken    — функция генерации CSRF-токена для шаблонов
 *
 * @param {{ q, requireAdmin, doubleCsrfProtection, mutationLimiter, generateCsrfToken }} deps
 * @returns {import('express').Router}
 */

'use strict';

const { Router } = require('express');

function createRouter({ q, requireAdmin, doubleCsrfProtection, mutationLimiter, generateCsrfToken }) {
  const router = Router();

  // ── GET /audit ────────────────────────────────────────────────────────────────
  // Журнал всех изменений белого списка (CREATE / UPDATE / DELETE).
  // ТЗ 4.6: «журнал доступен для просмотра только администратору».
  //
  // ?company=<id> — фильтр по конкретной компании (необязательно).
  // Максимум 500 строк (ограничение в queries.js).
  router.get('/audit', requireAdmin, async (req, res) => {
    try {
      // Парсим фильтр: если ?company не задан — показываем все компании
      const companyId = req.query.company ? parseInt(req.query.company, 10) : null;

      // Грузим список компаний для dropdown-фильтра в шаблоне
      const companies = await q.getAllCompanies();

      // Строки аудита (JOIN с companies → company_name, client_id)
      const rows = await q.getAudit(companyId || null);

      res.render('audit', {
        user:              req.user,
        rows,
        companies,
        selectedCompanyId: companyId,
        error:             req.query.error || null,
      });
    } catch (e) {
      console.error('GET /audit error:', e);
      // При ошибке рендерим страницу с пустым списком, не падаем с 500
      res.render('audit', {
        user:              req.user,
        rows:              [],
        companies:         [],
        selectedCompanyId: null,
        error:             'Ошибка загрузки: ' + e.message,
      });
    }
  });

  // ── GET /admin ────────────────────────────────────────────────────────────────
  // Страница управления лимитами: таблица компаний с их active_count и лимитом.
  // Для каждой компании — форма изменения лимита (POST /admin/limit/:id).
  //
  // DEFAULT_LIMIT из env — используется как дефолт при отображении и при сбросе.
  router.get('/admin', requireAdmin, async (req, res) => {
    try {
      const companies    = await q.getAllCompanies();
      // Если DEFAULT_LIMIT не задан в env — используем 15 (как в queries.js)
      const defaultLimit = parseInt(process.env.DEFAULT_LIMIT, 10) || 15;

      res.render('admin', {
        user:         req.user,
        companies,
        defaultLimit,
        message:      req.query.message || null,
        error:        req.query.error   || null,
        // CSRF-токен для форм /admin/limit/:id (по одной на каждую строку таблицы)
        csrfToken:    generateCsrfToken(req, res),
      });
    } catch (e) {
      console.error('GET /admin error:', e);
      res.status(500).send('Ошибка: ' + e.message);
    }
  });

  // ── POST /admin/limit/:companyId ──────────────────────────────────────────────
  // Изменить или сбросить индивидуальный лимит компании.
  // ТЗ 4.5: «администратор может задать индивидуальный лимит».
  //
  // Логика:
  //   - Пустое поле limit → null → сброс на DEFAULT_LIMIT (глобальный дефолт)
  //   - Число ≥ 0 → custom_limit = это число
  //   - Отрицательное или нечисловое → ошибка
  router.post('/admin/limit/:companyId', requireAdmin, mutationLimiter, doubleCsrfProtection,
    async (req, res) => {
      // Валидация числового PK компании из URL-параметра
      const companyId = parseInt(req.params.companyId, 10);
      if (!Number.isFinite(companyId) || companyId <= 0) {
        return res.redirect('/admin?error=' + encodeURIComponent('Некорректный ID компании'));
      }

      try {
        const raw = req.body.limit;
        let newLimit;

        if (raw === '' || raw === null || raw === undefined) {
          // Пустое поле — сброс: setLimit(id, null) → queries.js удаляет custom_limit
          newLimit = null;
        } else {
          newLimit = parseInt(raw, 10);
          if (!Number.isFinite(newLimit) || newLimit < 0) {
            throw new Error('Лимит должен быть целым числом ≥ 0, или пустым для сброса');
          }
        }

        await q.setLimit(companyId, newLimit);

        // Формируем человекочитаемое сообщение для flash-уведомления
        const label = newLimit === null ? 'сброшен на дефолт' : `установлен: ${newLimit}`;
        res.redirect('/admin?message=' + encodeURIComponent(`Лимит ${label}`));
      } catch (e) {
        res.redirect('/admin?error=' + encodeURIComponent(e.message));
      }
    }
  );

  return router;
}

module.exports = { createRouter };
