<?php

namespace App\Support;

use App\Models\InviteLayout;

class JoinTokenLayoutRegistry
{
    /**
     * Layout definitions for printable invite cards.
     *
     * @var array<string, array>
     */
    private const LAYOUTS = [
        'evergreen-vows' => [
            'id' => 'evergreen-vows',
            'name' => 'Evergreen Vows',
            'subtitle' => 'Romantische Einladung für Trauung & Empfang.',
            'description' => 'Weiche Pastelltöne, florale Akzente und viel Raum für eine herzliche Begrüßung.',
            'paper' => 'a4',
            'orientation' => 'portrait',
            'background' => '#FBF7F2',
            'background_gradient' => [
                'angle' => 165,
                'stops' => ['#FBF7F2', '#FDECEF', '#F4F0FF'],
            ],
            'text' => '#2C1A27',
            'accent' => '#B85C76',
            'secondary' => '#E7D6DC',
            'badge' => '#7A9375',
            'badge_label' => 'Digitale Gästebox',
            'instructions_heading' => 'So läuft\'s für eure Gäste',
            'link_heading' => 'Kein Scanner? Einfach Kurzlink öffnen',
            'link_label' => 'fotospiel.app/DEINCODE',
            'cta_label' => 'Fotos & Grüße teilen',
            'cta_caption' => 'Sofort starten',
            'qr' => ['size_px' => 640],
            'svg' => ['width' => 1240, 'height' => 1754],
            'instructions' => [
                'QR-Code scannen oder fotospiel.app/DEINCODE eingeben.',
                'Anzeigenamen wählen – kein Account nötig.',
                'Fotos hochladen und Aufgaben erfüllen, so oft ihr wollt.',
                'Highlights liken, Kommentare und Grüße dalassen.',
                'Datenschutz ready: anonyme Sessions, keine App-Installation.',
            ],
        ],
        'midnight-gala' => [
            'id' => 'midnight-gala',
            'name' => 'Midnight Gala',
            'subtitle' => 'Eleganter Auftritt für Corporate Events & Galas.',
            'description' => 'Dunkle Bühne mit goldenen Akzenten und kräftiger Typografie.',
            'paper' => 'a4',
            'orientation' => 'portrait',
            'background' => '#0B132B',
            'background_gradient' => [
                'angle' => 200,
                'stops' => ['#0B132B', '#1C2541', '#274690'],
            ],
            'text' => '#F8FAFC',
            'accent' => '#F9C74F',
            'secondary' => '#4E5D8F',
            'badge' => '#F94144',
            'badge_label' => 'Digitale Gästebox',
            'instructions_heading' => 'So läuft\'s für eure Gäste',
            'link_heading' => 'Kein Scanner? Einfach Kurzlink öffnen',
            'link_label' => 'fotospiel.app/DEINCODE',
            'cta_label' => 'Scan & losknipsen',
            'cta_caption' => 'Keine App nötig',
            'qr' => ['size_px' => 640],
            'svg' => ['width' => 1240, 'height' => 1754],
            'instructions' => [
                'QR-Code scannen oder fotospiel.app/DEINCODE eingeben.',
                'Anzeigenamen wählen – kein Account nötig.',
                'Fotos hochladen und Aufgaben erfüllen, so oft ihr wollt.',
                'Highlights liken, Kommentare und Grüße dalassen.',
                'Datenschutz ready: anonyme Sessions, keine App-Installation.',
            ],
        ],
        'garden-brunch' => [
            'id' => 'garden-brunch',
            'name' => 'Garden Brunch',
            'subtitle' => 'Luftiges Layout für Tages-Events & Familienfeiern.',
            'description' => 'Sanfte Grüntöne, natürliche Formen und Platz für Hinweise.',
            'paper' => 'a4',
            'orientation' => 'portrait',
            'background' => '#F6F9F4',
            'background_gradient' => [
                'angle' => 120,
                'stops' => ['#F6F9F4', '#EEF5E7', '#F8FAF0'],
            ],
            'text' => '#2F4030',
            'accent' => '#6BAA75',
            'secondary' => '#DDE9D8',
            'badge' => '#F1C376',
            'badge_label' => 'Digitale Gästebox',
            'instructions_heading' => 'So läuft\'s für eure Gäste',
            'link_heading' => 'Kein Scanner? Einfach Kurzlink öffnen',
            'link_label' => 'fotospiel.app/DEINCODE',
            'cta_label' => 'Jetzt Erinnerungen hochladen',
            'cta_caption' => 'Los geht’s',
            'qr' => ['size_px' => 660],
            'svg' => ['width' => 1240, 'height' => 1754],
            'instructions' => [
                'QR-Code scannen oder fotospiel.app/DEINCODE eingeben.',
                'Anzeigenamen wählen – kein Account nötig.',
                'Fotos hochladen und Aufgaben erfüllen, so oft ihr wollt.',
                'Highlights liken, Kommentare und Grüße dalassen.',
                'Datenschutz ready: anonyme Sessions, keine App-Installation.',
            ],
        ],
        'sparkler-soiree' => [
            'id' => 'sparkler-soiree',
            'name' => 'Sparkler Soirée',
            'subtitle' => 'Abendliches Layout mit funkelndem Verlauf.',
            'description' => 'Dynamische Typografie mit zentralem Fokus auf dem QR-Code.',
            'paper' => 'a4',
            'orientation' => 'portrait',
            'background' => '#1B1A44',
            'background_gradient' => [
                'angle' => 205,
                'stops' => ['#1B1A44', '#42275A', '#734B8F'],
            ],
            'text' => '#FDF7FF',
            'accent' => '#F9A826',
            'secondary' => '#DDB7FF',
            'badge' => '#FF6F61',
            'badge_label' => 'Digitale Gästebox',
            'instructions_heading' => 'So läuft\'s für eure Gäste',
            'link_heading' => 'Kein Scanner? Einfach Kurzlink öffnen',
            'link_label' => 'fotospiel.app/DEINCODE',
            'cta_label' => 'Galerie öffnen',
            'cta_caption' => 'Challenges spielen',
            'qr' => ['size_px' => 680],
            'svg' => ['width' => 1240, 'height' => 1754],
            'instructions' => [
                'QR-Code scannen oder fotospiel.app/DEINCODE eingeben.',
                'Anzeigenamen wählen – kein Account nötig.',
                'Fotos hochladen und Aufgaben erfüllen, so oft ihr wollt.',
                'Highlights liken, Kommentare und Grüße dalassen.',
                'Datenschutz ready: anonyme Sessions, keine App-Installation.',
            ],
        ],
        'confetti-bash' => [
            'id' => 'confetti-bash',
            'name' => 'Confetti Bash',
            'subtitle' => 'Verspielter Look für Geburtstage & Jubiläen.',
            'description' => 'Konfetti-Sprenkel, fröhliche Farben und viel Platz für Hinweise.',
            'paper' => 'a4',
            'orientation' => 'portrait',
            'background' => '#FFF9F0',
            'background_gradient' => [
                'angle' => 145,
                'stops' => ['#FFF9F0', '#FFEFEF', '#FFF5D6'],
            ],
            'text' => '#31291F',
            'accent' => '#FF6F61',
            'secondary' => '#F9D6A5',
            'badge' => '#4E88FF',
            'badge_label' => 'Digitale Gästebox',
            'instructions_heading' => 'So läuft\'s für eure Gäste',
            'link_heading' => 'Kein Scanner? Einfach Kurzlink öffnen',
            'link_label' => 'fotospiel.app/DEINCODE',
            'cta_label' => 'Uploads beginnen',
            'cta_caption' => 'Likes vergeben',
            'qr' => ['size_px' => 680],
            'svg' => ['width' => 1240, 'height' => 1754],
            'instructions' => [
                'QR-Code scannen oder fotospiel.app/DEINCODE eingeben.',
                'Anzeigenamen wählen – kein Account nötig.',
                'Fotos hochladen und Aufgaben erfüllen, so oft ihr wollt.',
                'Highlights liken, Kommentare und Grüße dalassen.',
                'Datenschutz ready: anonyme Sessions, keine App-Installation.',
            ],
        ],
    ];

    /**
     * Get layout definitions.
     *
     * @return array<int, array<string, mixed>>
     */
    public static function all(): array
    {
        $customLayouts = InviteLayout::query()
            ->where('is_active', true)
            ->orderBy('name')
            ->get();

        if ($customLayouts->isNotEmpty()) {
            return $customLayouts
                ->map(fn (InviteLayout $layout) => self::normalize(self::fromModel($layout)))
                ->values()
                ->all();
        }

        return array_values(array_map(fn ($layout) => self::normalize($layout), self::LAYOUTS));
    }

    /**
     * Find a layout definition.
     */
    public static function find(string $id): ?array
    {
        $custom = InviteLayout::query()
            ->where('slug', $id)
            ->where('is_active', true)
            ->first();

        if ($custom) {
            return self::normalize(self::fromModel($custom));
        }

        $layout = self::LAYOUTS[$id] ?? null;

        return $layout ? self::normalize($layout) : null;
    }

    /**
     * Normalize and merge default values.
     */
    private static function normalize(array $layout): array
    {
        $defaults = [
            'subtitle' => '',
            'description' => '',
            'paper' => 'a4',
            'orientation' => 'portrait',
            'background' => '#F9FAFB',
            'text' => '#0F172A',
            'accent' => '#6366F1',
            'secondary' => '#CBD5F5',
            'badge' => '#2563EB',
            'badge_label' => 'Digitale Gästebox',
            'instructions_heading' => "So funktioniert's",
            'link_heading' => 'Alternative zum Einscannen',
            'cta_label' => 'Scan mich & starte direkt',
            'cta_caption' => 'Scan mich & starte direkt',
            'link_label' => null,
            'logo_url' => null,
            'qr' => [
                'size_px' => 640,
            ],
            'svg' => [
                'width' => 1240,
                'height' => 1754,
            ],
            'background_gradient' => null,
            'instructions' => [],
            'formats' => ['pdf', 'png'],
        ];

        $normalized = array_replace_recursive($defaults, $layout);

        $formats = $normalized['formats'] ?? ['pdf', 'png'];
        if (! is_array($formats)) {
            $formats = [$formats];
        }

        $normalizedFormats = [];
        foreach ($formats as $format) {
            $value = strtolower((string) $format);
            if ($value === 'svg') {
                $value = 'png';
            }

            if (in_array($value, ['pdf', 'png'], true) && ! in_array($value, $normalizedFormats, true)) {
                $normalizedFormats[] = $value;
            }
        }

        $normalized['formats'] = $normalizedFormats ?: ['pdf', 'png'];

        return $normalized;
    }

    private static function fromModel(InviteLayout $layout): array
    {
        $preview = $layout->preview ?? [];
        $options = $layout->layout_options ?? [];
        $instructions = $layout->instructions ?? [];

        return array_filter([
            'id' => $layout->slug,
            'name' => $layout->name,
            'subtitle' => $layout->subtitle,
            'description' => $layout->description,
            'paper' => $layout->paper,
            'orientation' => $layout->orientation,
            'background' => $preview['background'] ?? null,
            'background_gradient' => $preview['background_gradient'] ?? null,
            'text' => $preview['text'] ?? null,
            'accent' => $preview['accent'] ?? null,
            'secondary' => $preview['secondary'] ?? null,
            'badge' => $preview['badge'] ?? null,
            'badge_label' => $options['badge_label'] ?? null,
            'instructions_heading' => $options['instructions_heading'] ?? null,
            'link_heading' => $options['link_heading'] ?? null,
            'cta_label' => $options['cta_label'] ?? null,
            'cta_caption' => $options['cta_caption'] ?? null,
            'link_label' => $options['link_label'] ?? null,
            'logo_url' => $options['logo_url'] ?? null,
            'qr' => array_filter([
                'size_px' => $preview['qr']['size_px'] ?? $options['qr']['size_px'] ?? $preview['qr_size_px'] ?? $options['qr_size_px'] ?? null,
            ]),
            'svg' => array_filter([
                'width' => $preview['svg']['width'] ?? $options['svg']['width'] ?? $preview['svg_width'] ?? $options['svg_width'] ?? null,
                'height' => $preview['svg']['height'] ?? $options['svg']['height'] ?? $preview['svg_height'] ?? $options['svg_height'] ?? null,
            ]),
            'formats' => $options['formats'] ?? ['pdf', 'png'],
            'instructions' => $instructions,
        ], fn ($value) => $value !== null && $value !== []);
    }

    /**
     * Map layouts into an API-ready response structure, attaching URLs.
     *
     * @param  callable(string $layoutId, string $format): string  $urlResolver
     * @return array<int, array<string, mixed>>
     */
    public static function toResponse(callable $urlResolver): array
    {
        return array_map(function (array $layout) use ($urlResolver) {
            $formats = $layout['formats'] ?? ['pdf', 'png'];

            return [
                'id' => $layout['id'],
                'name' => $layout['name'],
                'description' => $layout['description'],
                'subtitle' => $layout['subtitle'],
                'badge_label' => $layout['badge_label'] ?? null,
                'instructions_heading' => $layout['instructions_heading'] ?? null,
                'link_heading' => $layout['link_heading'] ?? null,
                'cta_label' => $layout['cta_label'] ?? null,
                'cta_caption' => $layout['cta_caption'] ?? null,
                'instructions' => $layout['instructions'] ?? [],
                'preview' => [
                    'background' => $layout['background'],
                    'background_gradient' => $layout['background_gradient'],
                    'accent' => $layout['accent'],
                    'text' => $layout['text'],
                    'qr_size_px' => $layout['qr']['size_px'] ?? null,
                ],
                'formats' => $formats,
                'download_urls' => collect($formats)
                    ->mapWithKeys(fn ($format) => [$format => $urlResolver($layout['id'], $format)])
                    ->all(),
            ];
        }, self::all());
    }
}
