<?php

namespace App\Services;

use Illuminate\Support\Facades\Cache;

class CssGeneratorService
{
    private const CSS_VAR_MAP = [
        'colors.primary'          => '--color-primary',
        'colors.primary_dark'     => '--color-primary-dark',
        'colors.accent'           => '--color-accent',
        'colors.background_light' => '--color-background-light',
        'colors.background_dark'  => '--color-background-dark',
        'colors.surface_light'    => '--color-surface-light',
        'colors.surface_dark'     => '--color-surface-dark',
        'colors.border_light'     => '--color-border-light',
        'colors.border_dark'      => '--color-border-dark',
        'colors.text_main'        => '--color-text-main',
        'colors.text_muted'       => '--color-text-muted',
    ];

    public function __construct(private AppearanceService $appearance) {}

    private const GOOGLE_FONTS = ['Roboto', 'Poppins', 'Lato', 'Open Sans'];

    public function generate(): string
    {
        $cacheKey = config('appearance.css_cache_key', 'appearance_css')
            . '_' . setting('site_theme', 'tailwind');

        return Cache::remember($cacheKey, config('appearance.cache_ttl', 86400), function () {
            $parts = [];

            $font = $this->appearance->get('typography.font_family');
            if ($font !== null && in_array($font, self::GOOGLE_FONTS, true)) {
                $encoded = str_replace(' ', '+', $font);
                $parts[] = "@import url('https://fonts.googleapis.com/css2?family={$encoded}:wght@400;600;700;800&display=swap');";
            }

            $lines = [':root {'];

            foreach (self::CSS_VAR_MAP as $settingKey => $cssVar) {
                $value = $this->appearance->get($settingKey);
                if ($value !== null) {
                    $lines[] = '  ' . $cssVar . ': ' . $this->sanitizeValue($value) . ';';
                }
            }

            if ($font !== null) {
                $safe = $this->sanitizeValue($font);
                $lines[] = '  --font-display: ' . $safe . ', sans-serif;';
                $lines[] = '  --font-sans: ' . $safe . ', sans-serif;';
            }

            $size = $this->appearance->get('typography.base_font_size');
            if ($size !== null) {
                $lines[] = '  font-size: ' . ((int) $size) . 'px;';
            }

            $headingWeight = $this->appearance->get('typography.heading_weight');
            if ($headingWeight !== null) {
                $lines[] = '  --heading-weight: ' . ((int) $headingWeight) . ';';
            }

            $lines[] = '}';
            $parts[] = implode("\n", $lines);

            $customCss = $this->appearance->get('advanced.custom_css', '');
            if ($customCss) {
                $parts[] = $this->sanitizeCustomCss($customCss);
            }

            return implode("\n\n", $parts);
        });
    }

    private function sanitizeValue(string $value): string
    {
        return preg_replace('/[^a-zA-Z0-9\s\-_#,.%()]/', '', $value);
    }

    private function sanitizeCustomCss(string $css): string
    {
        // Prevent breaking out of the <style> block
        $css = preg_replace('/<\/\s*style/i', '<\\/style', $css);
        // Strip IE CSS expression() to prevent JS injection
        $css = preg_replace('/\bexpression\s*\(/i', 'expression_(', $css);
        return $css;
    }
}
