<?php

namespace App\Helpers;

use App\Models\SystemSetting;

/**
 * FontHelper — emits the Google Fonts <link> tag + a tiny inline
 * @font-face fallback so layouts don't each hardcode "Outfit".
 *
 * Why this is its own helper instead of a Blade partial:
 * - Tight control over which family names + weight ranges are allowed
 *   (the admin picks from a whitelist on the settings page, but we
 *   still sanitize here as a defense-in-depth measure — a hostile
 *   value would just inject raw URL into the layout's <head>).
 * - Easy to swap the resolver later (e.g. switch from Google Fonts to
 *   Bunny Fonts / self-hosted woff2 — single function to change).
 *
 * Output strategy:
 *   <link rel="preconnect" href="https://fonts.googleapis.com">
 *   <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 *   <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;...&display=swap" rel="stylesheet">
 *   <style>:root { --app-font: 'Inter', system-ui, sans-serif; } body { font-family: var(--app-font); }</style>
 *
 * The --app-font variable lets components keep using `font-sans` from
 * Tailwind while the actual face changes at runtime.
 */
class FontHelper
{
    /**
     * Resolve + sanitize the configured font family. Returns the default
     * (Outfit) if the saved value isn't on the allow-list.
     */
    public static function getFamily(): string
    {
        $allow = [
            'Outfit', 'Inter', 'Roboto', 'Open Sans', 'Poppins', 'Nunito',
            'Lato', 'Montserrat', 'Raleway', 'Source Sans 3', 'DM Sans',
            'IBM Plex Sans', 'Manrope', 'Plus Jakarta Sans', 'Work Sans',
            'Rubik', 'Space Grotesk', 'Public Sans', 'Figtree', 'Quicksand',
        ];

        try {
            $saved = trim((string) SystemSetting::get('font_family', 'Outfit'));
        } catch (\Throwable $e) {
            return 'Outfit';
        }

        return in_array($saved, $allow, true) ? $saved : 'Outfit';
    }

    /**
     * Sanitize the weights string. Allows digits, semicolons, commas.
     * Falls back to a sane default if empty or malformed.
     */
    public static function getWeights(): string
    {
        try {
            $raw = trim((string) SystemSetting::get('font_weights', '300;400;500;600;700;800'));
        } catch (\Throwable $e) {
            return '300;400;500;600;700;800';
        }

        // Strip anything that isn't digits, semicolon, or comma
        $clean = preg_replace('/[^0-9;,]/', '', $raw);
        return $clean !== '' ? $clean : '300;400;500;600;700;800';
    }

    /**
     * Render the complete <link>+<style> block for injection into <head>.
     */
    public static function renderHead(): string
    {
        $family  = self::getFamily();
        $weights = self::getWeights();

        // family names with spaces need + in the URL
        $urlFamily = str_replace(' ', '+', $family);

        $href = sprintf(
            'https://fonts.googleapis.com/css2?family=%s:wght@%s&display=swap',
            $urlFamily,
            $weights,
        );

        return implode('', [
            '<link rel="preconnect" href="https://fonts.googleapis.com">',
            '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>',
            '<link href="' . htmlspecialchars($href, ENT_QUOTES) . '" rel="stylesheet">',
            '<style id="app-font-vars">',
            ':root{--app-font:\'' . $family . '\',system-ui,-apple-system,sans-serif;}',
            'body,.font-sans{font-family:var(--app-font)!important;}',
            '</style>',
        ]);
    }
}
