<?php

namespace App\Support;

class FormStyleManager
{
    /**
     * @return array<string, mixed>
     */
    public static function defaults(): array
    {
        return [
            'palette' => [
                'page_bg' => '#F1F5F9',
                'card_bg' => '#FFFFFF',
                'text' => '#0F172A',
                'muted' => '#64748B',
                'border' => '#E2E8F0',
                'input_bg' => '#FFFFFF',
                'input_text' => '#0F172A',
                'input_border' => '#CBD5E1',
                'primary' => '#4F46E5',
                'primary_hover' => '#6366F1',
                'button_text' => '#FFFFFF',
                'reset_bg' => '#FFFFFF',
                'reset_text' => '#0F172A',
            ],
            'layout' => [
                'max_width' => 768,
                'card_radius' => 16,
                'input_radius' => 8,
                'button_radius' => 10,
            ],
            'typography' => [
                'font_family' => 'Figtree, ui-sans-serif, system-ui',
                'font_url' => '',
            ],
            'custom_css' => '',
        ];
    }

    /**
     * @return list<int>
     */
    public static function widthOptions(): array
    {
        return [560, 640, 768, 896, 1024, 1200];
    }

    /**
     * @return array<string, mixed>
     */
    public static function normalize(mixed $input): array
    {
        $defaults = self::defaults();
        if (! is_array($input)) {
            return $defaults;
        }

        $paletteInput = is_array($input['palette'] ?? null) ? $input['palette'] : [];
        $layoutInput = is_array($input['layout'] ?? null) ? $input['layout'] : [];
        $typographyInput = is_array($input['typography'] ?? null) ? $input['typography'] : [];

        $palette = [];
        foreach ($defaults['palette'] as $key => $defaultValue) {
            $palette[$key] = self::normalizeColor($paletteInput[$key] ?? null, $defaultValue);
        }

        $widthOptions = self::widthOptions();
        $maxWidth = self::normalizeInt($layoutInput['max_width'] ?? null, (int) $defaults['layout']['max_width'], 480, 1600);
        if (! in_array($maxWidth, $widthOptions, true)) {
            $maxWidth = (int) $defaults['layout']['max_width'];
        }

        $layout = [
            'max_width' => $maxWidth,
            'card_radius' => self::normalizeInt($layoutInput['card_radius'] ?? null, (int) $defaults['layout']['card_radius'], 0, 32),
            'input_radius' => self::normalizeInt($layoutInput['input_radius'] ?? null, (int) $defaults['layout']['input_radius'], 0, 24),
            'button_radius' => self::normalizeInt($layoutInput['button_radius'] ?? null, (int) $defaults['layout']['button_radius'], 0, 32),
        ];

        $fontFamily = trim((string) ($typographyInput['font_family'] ?? $defaults['typography']['font_family']));
        if ($fontFamily === '') {
            $fontFamily = (string) $defaults['typography']['font_family'];
        }

        $fontUrl = trim((string) ($typographyInput['font_url'] ?? ''));
        if ($fontUrl !== '' && ! self::isAllowedUrl($fontUrl)) {
            $fontUrl = '';
        }

        $customCss = trim((string) ($input['custom_css'] ?? ''));
        if ($customCss !== '') {
            $customCss = preg_replace('/<\/style/i', '', $customCss) ?? $customCss;
        }
        if (mb_strlen($customCss) > 5000) {
            $customCss = mb_substr($customCss, 0, 5000);
        }

        return [
            'palette' => $palette,
            'layout' => $layout,
            'typography' => [
                'font_family' => $fontFamily,
                'font_url' => $fontUrl,
            ],
            'custom_css' => $customCss,
        ];
    }

    public static function cssVars(array $settings): string
    {
        $palette = is_array($settings['palette'] ?? null) ? $settings['palette'] : [];
        $layout = is_array($settings['layout'] ?? null) ? $settings['layout'] : [];
        $typography = is_array($settings['typography'] ?? null) ? $settings['typography'] : [];

        $vars = [
            '--form-page-bg' => $palette['page_bg'] ?? '#F1F5F9',
            '--form-card-bg' => $palette['card_bg'] ?? '#FFFFFF',
            '--form-text' => $palette['text'] ?? '#0F172A',
            '--form-muted' => $palette['muted'] ?? '#64748B',
            '--form-border' => $palette['border'] ?? '#E2E8F0',
            '--form-input-bg' => $palette['input_bg'] ?? '#FFFFFF',
            '--form-input-text' => $palette['input_text'] ?? '#0F172A',
            '--form-input-border' => $palette['input_border'] ?? '#CBD5E1',
            '--form-primary' => $palette['primary'] ?? '#4F46E5',
            '--form-primary-hover' => $palette['primary_hover'] ?? '#6366F1',
            '--form-button-text' => $palette['button_text'] ?? '#FFFFFF',
            '--form-reset-bg' => $palette['reset_bg'] ?? '#FFFFFF',
            '--form-reset-text' => $palette['reset_text'] ?? '#0F172A',
            '--form-card-radius' => ((int) ($layout['card_radius'] ?? 16)).'px',
            '--form-input-radius' => ((int) ($layout['input_radius'] ?? 8)).'px',
            '--form-button-radius' => ((int) ($layout['button_radius'] ?? 10)).'px',
            '--form-max-width' => ((int) ($layout['max_width'] ?? 768)).'px',
            '--form-font-family' => (string) ($typography['font_family'] ?? 'Figtree, ui-sans-serif, system-ui'),
            '--form-primary-ring' => self::rgbaFromHex((string) ($palette['primary'] ?? '#4F46E5'), 0.24),
        ];

        return collect($vars)
            ->map(fn ($value, $key) => $key.': '.$value)
            ->implode('; ');
    }

    public static function fontUrl(array $settings): string
    {
        return trim((string) (($settings['typography']['font_url'] ?? '') ?: ''));
    }

    public static function customCss(array $settings): string
    {
        return trim((string) ($settings['custom_css'] ?? ''));
    }

    private static function normalizeColor(mixed $value, string $default): string
    {
        $value = trim((string) $value);
        if (preg_match('/^#[0-9a-fA-F]{3}$/', $value) === 1) {
            $expanded = '#'.$value[1].$value[1].$value[2].$value[2].$value[3].$value[3];
            return strtoupper($expanded);
        }

        if (preg_match('/^#[0-9a-fA-F]{6}$/', $value) === 1) {
            return strtoupper($value);
        }

        return $default;
    }

    private static function normalizeInt(mixed $value, int $default, int $min, int $max): int
    {
        if (is_numeric($value)) {
            $number = (int) $value;
            return max($min, min($max, $number));
        }

        return $default;
    }

    private static function isAllowedUrl(string $url): bool
    {
        if (! preg_match('#^https?://#i', $url)) {
            return false;
        }

        return filter_var($url, FILTER_VALIDATE_URL) !== false;
    }

    private static function rgbaFromHex(string $hex, float $alpha): string
    {
        $hex = ltrim($hex, '#');
        if (strlen($hex) === 3) {
            $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
        }

        if (strlen($hex) !== 6) {
            return 'rgba(79, 70, 229, '.$alpha.')';
        }

        $r = hexdec(substr($hex, 0, 2));
        $g = hexdec(substr($hex, 2, 2));
        $b = hexdec(substr($hex, 4, 2));

        return 'rgba('.$r.', '.$g.', '.$b.', '.$alpha.')';
    }
}
