<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Límite de peticiones de la API de plugins
    |--------------------------------------------------------------------------
    |
    | El endpoint `POST /api/v1` no tenía ningún límite: el único freno era el
    | `usage_limit` del token, que se evalúa DENTRO del middleware y solo después de
    | haber consultado la base. Con un token inválido no había tope, y cada intento
    | escribía una fila en `api_request_logs`. Ver known-issues MGR-008.
    |
    | Caso real medido en producción (2026-08-26): un entorno de desarrollo interno
    | con un token inexistente hizo 437 peticiones `licence` en 17 minutos, todas
    | 401, todas registradas. Con el límite de fallos de abajo se habrían cortado a
    | las 20 primeras.
    |
    | Dos contadores, los dos por IP y los dos configurables:
    |
    | 1. FALLOS (`failures_*`) — cuenta solo las respuestas 401 y 403. Es el que
    |    importa: el tráfico legítimo lleva token válido y nunca acumula aquí, así
    |    que da igual cuántos Moodle compartan IP (los Goodle se están unificando en
    |    servidores compartidos). Puede ser estricto sin riesgo.
    |
    | 2. TECHO (`requests_*`) — cuenta todas las peticiones. Es una red por si algo
    |    se desmadra sin fallar. Deliberadamente holgado: el pico legítimo medido en
    |    producción es de 84 peticiones/minuto por IP, así que 600 deja siete veces
    |    de margen para la unificación en servidores compartidos.
    |
    */

    'throttle' => [

        'enabled' => env('API_THROTTLE_ENABLED', true),

        // Respuestas 401/403 por IP antes de cortar.
        'failures' => (int) env('API_THROTTLE_FAILURES', 20),
        'failures_decay' => (int) env('API_THROTTLE_FAILURES_DECAY', 60),

        // Techo total de peticiones por IP.
        'requests' => (int) env('API_THROTTLE_REQUESTS', 600),
        'requests_decay' => (int) env('API_THROTTLE_REQUESTS_DECAY', 60),

        // IPs que nunca se limitan (monitorización, pruebas internas).
        // Coma como separador: API_THROTTLE_ALLOWLIST=1.2.3.4,5.6.7.8
        'allowlist' => array_values(array_filter(array_map(
            'trim',
            explode(',', (string) env('API_THROTTLE_ALLOWLIST', ''))
        ))),

        // Registrar los rechazos en el canal `api`. Ver known-issues MGR-003.
        'log_rejections' => env('API_THROTTLE_LOG_REJECTIONS', true),

        /*
        |----------------------------------------------------------------------
        | Aviso anticipado
        |----------------------------------------------------------------------
        |
        | Margen a partir del cual una IP se considera "a punto de" alcanzar el
        | tope. 0.5 = al llegar a la mitad del límite. Sirve para enterarse ANTES
        | de cortar a nadie, que es cuando se puede avisar al cliente y arreglarlo
        | sin que note nada.
        */
        'warning_ratio' => (float) env('API_THROTTLE_WARNING_RATIO', 0.5),

        // Guardar las incidencias en la tabla `api_rate_events`. Una fila por IP,
        // ventana y tipo de límite: no una por petición.
        'record_events' => env('API_THROTTLE_RECORD_EVENTS', true),

        // Cada cuántos segundos, como mucho, se actualiza la fila de una misma IP.
        // Evita que una avalancha genere una escritura por petición.
        'record_throttle_seconds' => (int) env('API_THROTTLE_RECORD_EVERY', 10),

    ],

    /*
    |--------------------------------------------------------------------------
    | Avisos por correo
    |--------------------------------------------------------------------------
    |
    | Aviso a Sistemas cuando una IP cruza el margen o alcanza el tope.
    |
    | Con enfriamiento OBLIGATORIO: sin él, una avalancha de peticiones se
    | convertiría en una avalancha de correos, que es el mismo problema cambiando
    | de sitio. Un correo por IP y motivo cada `cooldown_minutes`.
    |
    | `queue` a false por defecto y a propósito: la cola usa driver `database` y si
    | no hay worker corriendo, el aviso se quedaría en la tabla `jobs` para siempre.
    | Un aviso que no sale es peor que una petición un poco más lenta, y con el
    | enfriamiento eso pasa como mucho una vez por hora y por IP. El envío va
    | envuelto en try/catch: un fallo de correo nunca rompe la respuesta de la API.
    |
    */

    /*
    |--------------------------------------------------------------------------
    | Visor de logs (/api-logs)
    |--------------------------------------------------------------------------
    |
    | Los indicadores de la cabecera (totales, % de error, percentiles, tops) se
    | calculan una vez y se reutilizan durante estos segundos.
    |
    | Livewire ejecuta `render()` en CADA interacción, así que sin caché cada tecla
    | del buscador repetía doce consultas sobre millones de filas: eso es lo que
    | hacía imposible abrir la pantalla en producción. El listado paginado NO se
    | cachea, va siempre al día. Poner 0 desactiva la caché.
    |
    | Ver known-issues MGR-027.
    */

    'logs_viewer' => [
        'stats_cache_seconds' => (int) env('API_LOGS_STATS_CACHE', 300),

        /*
         * Tope de segundos para las consultas del visor.
         *
         * `api_request_logs` es la tabla que más crece —una fila por llamada de cada
         * Moodle del parque— y los indicadores hacen doce agregados sobre un rango de
         * fechas. Con un rango amplio o un filtro sin índice, la consulta puede tardar
         * minutos y **la pantalla se queda en blanco**: sin cabecera, sin filtros y sin
         * forma de corregir el filtro que la ha colgado.
         *
         * Con el tope, la página se pinta siempre: si la consulta no llega a tiempo, sale
         * el aviso y los filtros quedan a mano para acotar la búsqueda.
         *
         * Ocho segundos porque por encima de eso ya nadie está esperando: está
         * recargando. A 0 se desactiva el tope.
         */
        'timeout_seconds' => (int) env('API_LOGS_TIMEOUT', 8),
    ],

    'alerts' => [

        'enabled' => env('API_ALERTS_ENABLED', false),

        // Coma como separador: API_ALERTS_TO=sistemas@tresipunt.com,soporte@tresipunt.com
        'to' => array_values(array_filter(array_map(
            'trim',
            explode(',', (string) env('API_ALERTS_TO', ''))
        ))),

        // `warning` (solo el aviso anticipado), `blocked` (solo cortes) o `both`.
        'notify_on' => env('API_ALERTS_NOTIFY_ON', 'both'),

        'cooldown_minutes' => (int) env('API_ALERTS_COOLDOWN_MINUTES', 60),

        'queue' => env('API_ALERTS_QUEUE', false),

    ],

];
