<?php

namespace App\Support;

/**
 * Qué versión del Manager corre aquí y qué trajo cada una, desde el panel.
 *
 * **La pregunta que responde es «¿está ya arriba lo de X?»**, que hasta ahora se contestaba
 * preguntando a quien lo hubiera desplegado. El `CHANGELOG.md` del repositorio existe, pero
 * está en inglés, es largo y explica el porqué de cada decisión: es para quien toca el
 * código. Esto es lo contrario —una línea por cambio— y es para quien atiende a un cliente.
 *
 * **Cómo sabe una instancia qué tiene desplegado.** No lo pregunta a ningún sitio: lo sabe
 * porque *es* ese código. Lo que corre en producción es el commit de la versión publicada,
 * así que `ACTUAL` es exactamente lo que hay arriba. Por eso la cabecera enseña también el
 * entorno (`APP_ENV`): sin él, dos pestañas con la misma pantalla son indistinguibles, que
 * es justo cuando uno se equivoca de instancia.
 *
 * **No hay lista de «pendiente de subir», y es a propósito.** Sería una lista que solo está
 * bien si nadie se olvida de añadir su línea, y ya existe un sitio donde se anota lo que
 * está hecho y no ha salido: el bloque `Unreleased` del `CHANGELOG.md`. Al publicar, ese
 * bloque se resume aquí en una entrada nueva.
 */
class Historial
{
    /**
     * La versión que corre aquí.
     *
     * No se saca de `git describe` ni de un fichero que escriba el despliegue: en el
     * servidor puede no haber `.git`, `exec()` suele estar capado y un fichero generado se
     * pierde en el primer despliegue que no lo genere. Una constante viaja con el código,
     * que es justo lo que hay que identificar.
     *
     * Se sube en cada despliegue, con `MAJOR.MINOR.PATCH`. Es norma del proyecto:
     * `.tresipunt/…/manager/operations/versionado.md`.
     */
    public const ACTUAL = '2.2.0';

    /**
     * Lo publicado, de lo más nuevo a lo más viejo.
     *
     * **Sin fecha, a propósito.** La fecha que serviría es el día que salió a producción, y
     * eso pasa después del commit que la escribe: quedaría puesta a mano, a ojo, y una
     * fecha que nadie puede comprobar es peor que ninguna —se lee como un dato y es una
     * suposición—. Cuándo salió cada versión lo dicen la etiqueta de git y el registro del
     * despliegue, que sí lo saben.
     *
     * @var list<array{version: string, titular: string, cambios: list<string>}>
     */
    public const VERSIONES = [
        [
            'version' => '2.2.0',
            'titular' => 'Ninguna petición recibe contenido si su dominio no está dado de alta.',
            'cambios' => [
                'Las peticiones de funcionalidades, tutoriales y recursos ya comprueban el dominio, como el resto.',
                'Un sitio cuyo dominio no esté dado de alta en su licencia deja de recibir esos tres contenidos.',
                'Las reglas de seguridad de la API se declaran en un solo sitio en vez de repetirse en cada acción.',
            ],
        ],
        [
            'version' => '2.1.0',
            'titular' => 'Anotar lo que le pasa a un sitio, y ver el parque de un vistazo.',
            'cambios' => [
                'Los entornos admiten una observación, con nivel y autor, para anotar qué le pasa a un sitio.',
                'Cada entorno puede llevar su propio enlace de login, para los sitios que entran por SSO.',
                'Plugins pasa de una pantalla con pestañas a cinco pantallas con portada.',
                'El listado de entornos estrena KPIs: de qué está hecho el parque, y cada dato filtra.',
                'El listado enseña el logo de la plataforma y separa el estado técnico en dos columnas.',
                'El dashboard enseña los cinco sitios más grandes por usuarios, cursos y matriculaciones.',
                'Los registros y los avisos se pueden limpiar desde sus propias pantallas.',
                'Los permisos de los roles ya se editan desde el panel; los de Admin siguen bloqueados.',
                'Esta pantalla: qué versión corre en cada instancia y qué trajo cada una.',
                'Arreglado: los bloqueos de la API no había forma de borrarlos mientras los límites solo observaban.',
                'Arreglado: el KPI de desincronizados contaba unos sitios y al pulsarlo enseñaba otros.',
                'Arreglado: un rechazo 2002 decía siempre lo mismo y ahora distingue los tres casos que son.',
                'Arreglado: un sitio con la descripción larga perdía su envío diario de telemetría.',
                'Arreglado: fresk_premium ya no aparece como plugin licenciado y sin instalar.',
                'Arreglado: cuando un Moodle no tiene aceptadas las políticas, el error lo dice.',
            ],
        ],
        [
            'version' => '2.0.0',
            'titular' => 'El panel rehecho alrededor de la monitorización y el diagnóstico por entorno.',
            'cambios' => [
                'Ficha de entorno con un único veredicto por sitio, su uso y su inventario de plugins.',
                'Visor de peticiones ordenado por gravedad, con el detalle de qué pasó en cada una.',
                'Los códigos *002 dejan de ser errores: significan que no hay contenido para esa versión.',
                'Topes y bloqueos de la API, por IP y por licencia, con modo de solo observar.',
                'El Manager puede pedirle a un Moodle que sincronice o que mande sus datos ahora.',
                'Contratos de soporte por entorno, con aviso de caducidad.',
                'Los tokens de los Moodle de cliente se guardan cifrados y no se vuelven a enseñar.',
                'Los permisos de las rutas se comprueban también en las llamadas de Livewire.',
            ],
        ],
    ];

    /** @return list<array{version: string, titular: string, cambios: list<string>}> */
    public static function versiones(): array
    {
        return self::VERSIONES;
    }

    /**
     * Si la versión que corre tiene escrito qué trajo.
     *
     * Existe para que haya algo que comprobar: subir `ACTUAL` y olvidarse de la entrada
     * deja la pantalla enseñando un número pelado, que parece información y no lo es. Hay
     * un test que lo caza antes de que llegue a ninguna instancia.
     */
    public static function laActualEstaDocumentada(): bool
    {
        foreach (self::VERSIONES as $version) {
            if ($version['version'] === self::ACTUAL) {
                return true;
            }
        }

        return false;
    }

    /**
     * Dónde está corriendo esto, con el nombre que usa el equipo.
     *
     * `APP_ENV` trae `production`, `local`… y en el panel se habla de «producción» y «pre».
     */
    public static function donde(): string
    {
        return match (config('app.env')) {
            'production' => 'producción',
            'pre', 'staging' => 'pre',
            'local' => 'local',
            'testing' => 'tests',
            default => (string) config('app.env'),
        };
    }
}
