<?php

declare(strict_types=1);

namespace App\Domain\Blog;

use Mews\Purifier\Facades\Purifier;

class HtmlTeaser
{
    /**
     * Build a teaser from already-rendered HTML.
     *
     * The result is always a plain-text excerpt and always withholds part of the
     * body: when the configured limit covers the whole article we still cut it
     * in half, so a gated article can never be served in full through a teaser.
     */
    public function truncate(string $html, int $maxChars): string
    {
        if ($maxChars <= 0 || trim($html) === '') {
            return '';
        }

        $text = html_entity_decode(strip_tags($html), ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $text = trim(preg_replace('/\s+/u', ' ', $text) ?? '');

        if ($text === '') {
            return '';
        }

        $length = mb_strlen($text);
        $limit = min($maxChars, max(1, (int) floor($length / 2)));

        $snippet = mb_substr($text, 0, $limit);
        if ($limit < $length) {
            $snippet .= '…';
        }

        return Purifier::clean('<p>'.e($snippet).'</p>', 'article');
    }
}
