<?php

use App\Http\Controllers\Api\Admin\V1\CatalogosController;
use App\Http\Controllers\Api\Admin\V1\ClientesController;
use App\Http\Controllers\Api\Admin\V1\EntornosController;
use App\Http\Controllers\Api\Admin\V1\LicenciasController;
use App\Http\Controllers\Api\V1\MoodleApiController;
use Illuminate\Routing\Middleware\SubstituteBindings;
use App\Http\Controllers\ScssCdn\CdnFileController;
use Illuminate\Support\Facades\Route;

// API v1 - Endpoint principal para plugins de Moodle
//
// `api_throttle` va PRIMERO a propósito: si fuera detrás del logger, cada petición
// rechazada seguiría escribiendo una fila en `api_request_logs`, que es la
// amplificación que el límite existe para cortar. Ver known-issues MGR-008.
//
// **Con un matiz desde el 2026-09-10**: el limitador escribe **una fila por episodio**
// de corte —la primera vez que se aplica, no las 720 siguientes—, porque si no, un corte
// no dejaba ningún rastro en el visor de peticiones y ahí es donde se investiga qué le
// pasó a un sitio. El coste queda acotado por el número de episodios y no por el volumen
// del ataque. Ver `ThrottleApiRequests::registrarCorte()`.
//
// Los rechazos siguen contándose además en `api_blocks`, en `api_rate_events` y en el
// canal de log `api`.
Route::prefix('v1')->middleware(['api_throttle', 'api_request_logger', 'product_token'])->group(function () {
    Route::post('/', [MoodleApiController::class, 'handle']);
});

// API de administración (PRODSECU-215): Sistemas da de alta clientes, licencias y
// entornos con un token de servicio de Sanctum. Contrato: resources/openapi/admin-v1.yaml.
//
// **El orden de la cadena es a propósito, y por eso no está `auth:sanctum`:**
//
// 1. `throttle:api-admin` — primero, por lo mismo que en la v1: un ataque no llena el log.
// 2. `api_request_logger` — antes de autenticar, para que los 401 queden registrados.
// 3. `admin_api:<permiso>` — token válido, del usuario de servicio y con ese permiso.
// 4. `admin_api_bindings` — y solo entonces se buscan los modelos de la ruta: sin token,
//    `/clients/999` es un 401 y no un 404 que diga qué ids existen.
//
// `auth:sanctum` y `SubstituteBindings` están en la lista de prioridad del kernel, y
// Laravel los adelantaría por delante del throttle y del logger. Ver `AdminApiAbility` y
// `AdminApiBindings`.
Route::prefix('admin/v1')
    ->name('api.admin.v1.')
    ->withoutMiddleware([SubstituteBindings::class])
    ->middleware(['throttle:api-admin', 'api_request_logger'])
    ->group(function () {
        $con = fn (string $permiso) => ['admin_api:' . $permiso, 'admin_api_bindings'];

        Route::middleware($con('admin.catalogs.read'))->group(function () {
            Route::get('types', [CatalogosController::class, 'types'])->name('types.index');
            Route::get('envs', [CatalogosController::class, 'envs'])->name('envs.index');
            Route::get('products', [CatalogosController::class, 'products'])->name('products.index');
        });

        Route::middleware($con('admin.clients.read'))->group(function () {
            Route::get('clients', [ClientesController::class, 'index'])->name('clients.index');
            Route::get('clients/{client}', [ClientesController::class, 'show'])->name('clients.show');
        });

        Route::middleware($con('admin.clients.read,admin.clients.write'))->group(function () {
            Route::post('clients', [ClientesController::class, 'store'])->name('clients.store');
            Route::patch('clients/{client}', [ClientesController::class, 'update'])->name('clients.update');
        });

        Route::middleware($con('admin.license-tokens.read'))->group(function () {
            Route::get('license-tokens', [LicenciasController::class, 'index'])->name('license-tokens.index');
            // **La única ruta que devuelve el token `3IP-…`.** Las demás sirven para encontrar
            // el id de la licencia (`GET /environments?domain=…` trae `license_token_id`).
            Route::get('license-tokens/{licenseToken}', [LicenciasController::class, 'show'])->whereNumber('licenseToken')->name('license-tokens.show');
        });

        Route::middleware($con('admin.license-tokens.read,admin.license-tokens.write'))->group(function () {
            Route::post('clients/{client}/license-tokens', [LicenciasController::class, 'store'])->name('license-tokens.store');
            Route::patch('license-tokens/{licenseToken}', [LicenciasController::class, 'update'])->whereNumber('licenseToken')->name('license-tokens.update');
            Route::put('license-tokens/{licenseToken}/products', [LicenciasController::class, 'products'])->whereNumber('licenseToken')->name('license-tokens.products');
        });

        Route::middleware($con('admin.environments.read'))->group(function () {
            Route::get('environments', [EntornosController::class, 'index'])->name('environments.index');
            Route::get('environments/{environment}', [EntornosController::class, 'show'])->name('environments.show');
        });

        Route::middleware($con('admin.environments.read,admin.environments.write'))->group(function () {
            Route::post('clients/{client}/environments', [EntornosController::class, 'store'])->name('environments.store');
            Route::patch('environments/{environment}', [EntornosController::class, 'update'])->name('environments.update');
        });
    });

// Preparado para futuras versiones
// Route::prefix('v2')->middleware('product_token')->group(function () {
//     Route::post('/', [MoodleApiV2Controller::class, 'handle']);
// });

// CDN para archivos SCSS - URLs firmadas
Route::get('/cdn/scss/{token}/{filename}', [CdnFileController::class, 'serve'])
    ->name('cdn.scss.serve')
    ->middleware('signed');

