<?php

namespace App\Support;

use Illuminate\Support\HtmlString;

/**
 * Negritas y párrafos en los textos que escribe el propio panel.
 *
 * **Por qué existe.** Los mensajes de las modales de confirmación se venían escribiendo con
 * `**negrita**` y párrafos separados por dos saltos de línea —es lo natural, y es como está
 * escrito el resto del proyecto—, pero la vista los pintaba con `{{ $message }}`: los
 * asteriscos salían literales y los saltos se comían, así que un aviso de cuatro ideas se
 * leía como un párrafo de cinco líneas seguidas. En una modal de borrado, eso es un texto que
 * nadie lee.
 *
 * Nueve mensajes del panel ya lo usaban esperando que funcionara.
 *
 * **Qué NO es.** No es un intérprete de Markdown ni quiere serlo: solo negritas y párrafos,
 * que es lo único que hace falta para un aviso. Cuanto menos admita, menos hay que pensar
 * sobre lo que puede entrar por aquí.
 *
 * **Y es seguro por el orden.** Se escapa **primero** todo el texto y se añade el marcado
 * **después**, así que nada de lo que venga en el mensaje puede convertirse en HTML: un
 * `<script>` escrito en un aviso sale como texto. El orden inverso —marcar y luego escapar—
 * sería una inyección, y es el error fácil de cometer aquí.
 */
final class TextoSencillo
{
    /**
     * Convierte el texto en HTML: `**negrita**`, párrafos y saltos.
     *
     * Devuelve un `HtmlString` para que la vista pueda imprimirlo con `{{ }}` sin volver a
     * escaparlo, en vez de con un `{!! !!}` que hay que mirar dos veces cada vez que se lee.
     */
    public static function aHtml(?string $texto): HtmlString
    {
        $texto = trim((string) $texto);

        if ($texto === '') {
            return new HtmlString('');
        }

        // Primero escapar. Todo lo que venga después es marcado que ponemos nosotros.
        $escapado = e($texto);

        // `**negrita**`, sin cruzar saltos de línea: un asterisco suelto en mitad de un aviso
        // no debe convertir media pantalla en negrita.
        $conNegritas = preg_replace(
            '/\*\*([^*\n]+)\*\*/u',
            '<strong class="font-semibold">$1</strong>',
            $escapado
        ) ?? $escapado;

        // Dos saltos separan párrafos; uno solo es un salto dentro del mismo.
        $parrafos = preg_split("/\n\s*\n/u", $conNegritas) ?: [$conNegritas];

        $html = '';

        foreach ($parrafos as $parrafo) {
            $parrafo = trim($parrafo);

            if ($parrafo === '') {
                continue;
            }

            $html .= '<p class="mb-2 last:mb-0">' . nl2br($parrafo, false) . '</p>';
        }

        return new HtmlString($html);
    }
}
