<?php
declare(strict_types=1);

namespace Infolab;

/**
 * Génère et vérifie l'unicité des slugs. Translittération ASCII via
 * l'extension intl (Transliterator), avec fallback bas niveau.
 */
final class Slugger
{
    /**
     * Slugifie un texte : minuscules, accents retirés, non-alphanum -> tirets.
     * Toujours non vide (retourne "item" en dernier recours).
     */
    public static function slugify(string $text): string
    {
        $text = trim($text);
        if ($text === '') {
            return 'item';
        }

        // Transliteration intl si dispo (cas de Marseille -> marseille, é -> e).
        if (class_exists(\Transliterator::class)) {
            $tr = \Transliterator::create('Any-Latin; Latin-ASCII; Lower()');
            if ($tr !== null) {
                $translit = $tr->transliterate($text);
                if (is_string($translit)) {
                    $text = $translit;
                }
            }
        }
        $text = mb_strtolower($text);
        // Remplace toute séquence non-[a-z0-9] par un tiret, puis trim les tirets de bord.
        $text = preg_replace('/[^a-z0-9]+/', '-', $text) ?? '';
        $text = trim($text, '-');
        return $text === '' ? 'item' : $text;
    }

    /**
     * Garantit l'unicité d'un slug dans une table : suffixe `-2`, `-3`, …
     * Si `$excludeId` est fourni, ignore cette ligne (cas PATCH d'un slug existant).
     */
    public static function unique(string $base, string $table, string $column = 'slug', ?int $excludeId = null): string
    {
        $candidate = $base;
        $n = 2;
        while (self::exists($candidate, $table, $column, $excludeId)) {
            $candidate = $base . '-' . $n;
            $n++;
        }
        return $candidate;
    }

    private static function exists(string $slug, string $table, string $column, ?int $excludeId): bool
    {
        // Noms de table/colonne câblés depuis le code, jamais depuis l'utilisateur.
        $sql = sprintf('SELECT 1 FROM `%s` WHERE `%s` = :slug', $table, $column);
        $params = [':slug' => $slug];
        if ($excludeId !== null) {
            $sql .= ' AND id <> :id';
            $params[':id'] = $excludeId;
        }
        $sql .= ' LIMIT 1';
        return Database::fetchValue($sql, $params) !== null;
    }
}
