<?php
/**
 * Themes — catalogue de fontes curated pour le thème custom.
 *
 * Chaque entrée :
 *   id    : identifiant stable (utilisé dans settings : 'curated:<id>')
 *   label : libellé d'affichage
 *   stack : valeur CSS pour font-family (premier choix + fallback)
 *   url   : URL Google Fonts CSS2 (vide pour 'system' — pas de chargement)
 *
 * En mode portable, l'URL CSS est téléchargée par packaging.php et son
 * `url(...)` (woff2) est extrait par le parseur générique des CSS.
 */

class Themes
{
    public const FONT_SANS = [
        'system' => [
            'label' => 'System (default)',
            'stack' => 'system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif',
            'url'   => '',
        ],
        'inter' => [
            'label' => 'Inter',
            'stack' => '"Inter", system-ui, sans-serif',
            'url'   => 'https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap',
        ],
        'roboto' => [
            'label' => 'Roboto',
            'stack' => '"Roboto", system-ui, sans-serif',
            'url'   => 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap',
        ],
        'open-sans' => [
            'label' => 'Open Sans',
            'stack' => '"Open Sans", system-ui, sans-serif',
            'url'   => 'https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap',
        ],
        'source-sans-3' => [
            'label' => 'Source Sans 3',
            'stack' => '"Source Sans 3", system-ui, sans-serif',
            'url'   => 'https://fonts.googleapis.com/css2?family=Source+Sans+3:wght@400;600;700&display=swap',
        ],
    ];

    public const FONT_MONO = [
        'system' => [
            'label' => 'System (default)',
            'stack' => '"Fira Code", "Cascadia Code", Consolas, monospace',
            'url'   => '',
        ],
        'jetbrains-mono' => [
            'label' => 'JetBrains Mono',
            'stack' => '"JetBrains Mono", Consolas, monospace',
            'url'   => 'https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600&display=swap',
        ],
        'fira-code' => [
            'label' => 'Fira Code',
            'stack' => '"Fira Code", Consolas, monospace',
            'url'   => 'https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;600&display=swap',
        ],
        'source-code-pro' => [
            'label' => 'Source Code Pro',
            'stack' => '"Source Code Pro", Consolas, monospace',
            'url'   => 'https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;600&display=swap',
        ],
        'ibm-plex-mono' => [
            'label' => 'IBM Plex Mono',
            'stack' => '"IBM Plex Mono", Consolas, monospace',
            'url'   => 'https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap',
        ],
    ];

    /** Liste des 14 clés settings pour les couleurs du thème custom. */
    public const COLOR_KEYS = [
        'bg', 'surface', 'border', 'text', 'text_muted',
        'primary', 'primary_h', 'secondary',
        'danger', 'success', 'warning',
        'nav_bg', 'nav_text', 'nav_hover',
    ];

    /** Valeurs par défaut du thème custom (= light theme). */
    public const COLOR_DEFAULTS = [
        'bg'         => '#f1f5f9',
        'surface'    => '#ffffff',
        'border'     => '#cbd5e1',
        'text'       => '#1e293b',
        'text_muted' => '#64748b',
        'primary'    => '#2563eb',
        'primary_h'  => '#1d4ed8',
        'secondary'  => '#64748b',
        'danger'     => '#dc2626',
        'success'    => '#16a34a',
        'warning'    => '#d97706',
        'nav_bg'     => '#1e293b',
        'nav_text'   => '#e2e8f0',
        'nav_hover'  => '#3b82f6',
    ];

    /**
     * Résout une valeur 'system' / 'curated:<id>' / 'uploaded:<file>' en
     * tuple [stack, css_url, font_face_src]. Retourne null si la valeur
     * est invalide ou si la cible n'existe pas.
     *
     * @return array{stack:string, css_url:string, font_face_src:string}|null
     */
    public static function resolveFont(string $value, string $kind): ?array
    {
        $catalog = $kind === 'sans' ? self::FONT_SANS : self::FONT_MONO;

        if ($value === '' || $value === 'system') {
            $sys = $catalog['system'];
            return ['stack' => $sys['stack'], 'css_url' => '', 'font_face_src' => ''];
        }

        if (str_starts_with($value, 'curated:')) {
            $id = substr($value, 8);
            if (!isset($catalog[$id])) return null;
            // Override éventuel (positionné par les paquets portables :
            // pointe sur le CSS local /vendor/js/fonts/<id>/font.css).
            $url = $catalog[$id]['url'];
            $overrides = json_decode(
                (string)Settings::getInstance()->get('theme_font_url_overrides', ''), true
            );
            if (is_array($overrides) && isset($overrides[$id])) {
                $url = (string)$overrides[$id];
            }
            return [
                'stack'         => $catalog[$id]['stack'],
                'css_url'       => $url,
                'font_face_src' => '',
            ];
        }

        if (str_starts_with($value, 'uploaded:')) {
            $file = substr($value, 9);
            // Sanitize : autoriser que [A-Za-z0-9._-]
            if (!preg_match('/^[A-Za-z0-9._-]+$/', $file)) return null;
            $abs = WEBROOT_PATH . '/assets/fonts/uploads/' . $file;
            if (!is_file($abs)) return null;
            $fmt = strtolower(pathinfo($file, PATHINFO_EXTENSION)) === 'woff2'
                ? 'woff2' : 'truetype';
            $logical = $kind === 'sans' ? 'sw-custom-sans' : 'sw-custom-mono';
            $url = '/assets/fonts/uploads/' . $file;
            return [
                'stack'         => '"' . $logical . '", ' . ($kind === 'sans' ? 'system-ui, sans-serif' : 'Consolas, monospace'),
                'css_url'       => '',
                'font_face_src' => "@font-face { font-family: '$logical'; src: url('$url') format('$fmt'); font-display: swap; }",
            ];
        }

        return null;
    }
}
