<?php

namespace App\Http\Controllers\Configurations;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Symfony\Component\HttpFoundation\Response;

/**
 * La especificación OpenAPI de la API de administración (PRODSECU-215), para el Swagger UI
 * del panel.
 *
 * **Se sirve detrás del login y del permiso**, no como un fichero de `public/`: describe
 * cómo dar de alta clientes y licencias, y eso no tiene por qué estar a la vista de
 * cualquiera que adivine la URL.
 */
class ApiDocsController
{
    use AuthorizesRequests;

    private const ESPECIFICACION = 'openapi/admin-v1.yaml';

    public function openapi(): Response
    {
        // El `permission:` de la ruta ya lo cubre; se repite por si alguien saca la ruta
        // del grupo al reorganizar (MGR-012).
        $this->authorize('admin.api-tokens.index');

        $ruta = resource_path(self::ESPECIFICACION);

        abort_unless(is_file($ruta), 404);

        return response(self::conLosServidores(file_get_contents($ruta)), 200, [
            'Content-Type' => 'application/yaml; charset=UTF-8',
            // Que el navegador no se quede con una versión vieja tras un despliegue.
            'Cache-Control' => 'no-cache, private',
        ]);
    }

    /** Los servidores fijos del contrato, por si no es el Manager desde el que se mira. */
    private const SERVIDORES = [
        'https://pre-licenses.host3ip.eu' => 'Preproducción',
        'https://managerv2.3ip.eu' => 'Producción',
    ];

    private const PREFIJO = '/api/admin/v1';

    /**
     * Cambia el bloque `servers` del fichero por los del Manager que lo sirve.
     *
     * **El primero es este mismo Manager**, que es el que Swagger selecciona de entrada:
     * desde local se prueba contra local y desde pre contra pre, sin tener que acordarse de
     * cambiarlo. Detrás van pre y pro, salvo el que ya sea este. **Nada más**: ningún host
     * que se pueda escribir, para que el token no salga hacia un servidor ajeno.
     *
     * Se hace al servir y no en el fichero porque **el fichero es también el que va a
     * Confluence**, y ahí tiene que decir solo pre y pro.
     *
     * Por texto y no parseando el YAML: el proyecto no tiene `symfony/yaml`, y volcarlo
     * otra vez cambiaría el formato de todo el documento por tocar cinco líneas.
     */
    private static function conLosServidores(string $yaml): string
    {
        $actual = rtrim(url('/'), '/');

        $servidores = ['  - url: ' . $actual . self::PREFIJO, '    description: Este Manager (' . app()->environment() . ')'];

        foreach (self::SERVIDORES as $base => $nombre) {
            if ($base === $actual) {
                continue;
            }

            $servidores[] = '  - url: ' . $base . self::PREFIJO;
            $servidores[] = '    description: ' . $nombre;
        }

        // **Sin «Otro host».** Lo hubo, con la base como variable que se podía escribir, y se
        // quitó el 2026-10-30: con «Authorize» y «Try it out», Swagger manda el token de
        // servicio a lo que se haya tecleado, y un dedazo lo enviaba a un servidor ajeno.
        // Para local ya está «Este Manager».

        $bloque = "servers:\n" . implode("\n", $servidores) . "\n";

        // El bloque son la línea `servers:` y las indentadas que la siguen.
        return preg_replace('/^servers:\r?\n(?:[ \t]+.*\r?\n)+/m', $bloque, $yaml, 1) ?? $yaml;
    }
}
