<?php

namespace App\Support;

class JoinTokenLayoutRegistry
{
    private const DEFAULT_DESCRIPTION = 'Helft uns, diesen besonderen Tag mit euren schönen Momenten festzuhalten.';

    private const DEFAULT_INSTRUCTIONS = [
        'QR-Code scannen'."\n".'Kamera-App öffnen und auf den Code richten.',
        'Webseite öffnen'."\n".'Der Link öffnet direkt das gemeinsame Jubiläumsalbum.',
        'Fotos hochladen'."\n".'Zeigt eure Lieblingsmomente oder erfüllt kleine Fotoaufgaben, um besondere Erinnerungen beizusteuern.',
    ];

    private const SLOTS_PORTRAIT = [
        'headline' => ['x' => 0.08, 'y' => 0.1, 'w' => 0.84, 'h' => 0.12, 'fontSize' => 30, 'fontWeight' => 800, 'align' => 'center'],
        'subtitle' => ['x' => 0.1, 'y' => 0.13, 'w' => 0.8, 'h' => 0.08, 'fontSize' => 18, 'fontWeight' => 600, 'align' => 'center'],
        'description' => ['x' => 0.1, 'y' => 0.18, 'w' => 0.8, 'h' => 0.12, 'fontSize' => 16, 'lineHeight' => 1.4, 'align' => 'center'],
        'qr' => ['x' => 0.35, 'y' => 0.4, 'w' => 0.3, 'h' => 0.3],
        'instructions' => ['x' => 0.12, 'y' => 0.72, 'w' => 0.76, 'h' => 0.16, 'fontSize' => 12, 'lineHeight' => 1.3, 'align' => 'center'],
    ];

    private const SLOTS_FOLDABLE = [
        'headline' => ['x' => 0.1, 'y' => 0.1, 'w' => 0.8, 'h' => 0.12, 'fontSize' => 28, 'fontWeight' => 800, 'align' => 'center'],
        'subtitle' => ['x' => 0.12, 'y' => 0.18, 'w' => 0.76, 'h' => 0.08, 'fontSize' => 18, 'fontWeight' => 600, 'align' => 'center'],
        'description' => ['x' => 0.12, 'y' => 0.24, 'w' => 0.76, 'h' => 0.12, 'fontSize' => 15, 'lineHeight' => 1.4, 'align' => 'center'],
        'qr' => ['x' => 0.36, 'y' => 0.4, 'w' => 0.28, 'h' => 0.28],
        'instructions' => ['x' => 0.14, 'y' => 0.72, 'w' => 0.72, 'h' => 0.16, 'fontSize' => 12, 'lineHeight' => 1.3, 'align' => 'center'],
    ];

    /**
     * Layout definitions for printable invite cards.
     *
     * @var array<string, array>
     */
    private const LAYOUTS = [
        'foldable-table-a5' => [
            'id' => 'foldable-table-a5',
            'name' => 'Foldable Table Card (A5)',
            'subtitle' => 'Doppelseitige Tischkarte zum Falten – QR vorn & hinten.',
            'description' => self::DEFAULT_DESCRIPTION,
            'paper' => 'a4',
            'orientation' => 'landscape',
            'panel_mode' => 'double-mirror',
            'format_hint' => 'foldable-a5',
            'slots' => self::SLOTS_FOLDABLE,
            'container_padding_px' => 28,
            'background' => '#F8FAFC',
            'background_gradient' => [
                'angle' => 180,
                'stops' => ['#F8FAFC', '#EEF2FF', '#F8FAFC'],
            ],
            'text' => '#0F172A',
            'accent' => '#2563EB',
            'secondary' => '#E0E7FF',
            'badge' => '#1D4ED8',
            'badge_label' => 'Digitale Gästebox',
            'instructions_heading' => "So funktioniert's",
            'link_heading' => 'Alternative zum Einscannen',
            'cta_label' => 'Scan & loslegen',
            'cta_caption' => 'Kein Login nötig',
            'link_label' => 'fotospiel.app/DEINCODE',
            'qr' => ['size_px' => 520],
            'svg' => ['width' => 1754, 'height' => 1240],
            'instructions' => self::DEFAULT_INSTRUCTIONS,
        ],
        'evergreen-vows' => [
            'id' => 'evergreen-vows',
            'name' => 'Evergreen Vows',
            'subtitle' => 'Romantische Einladung für Trauung & Empfang.',
            'description' => self::DEFAULT_DESCRIPTION,
            'paper' => 'a4',
            'orientation' => 'portrait',
            'format_hint' => 'poster-a4',
            'slots' => self::SLOTS_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' => self::DEFAULT_INSTRUCTIONS,
        ],
        'midnight-gala' => [
            'id' => 'midnight-gala',
            'name' => 'Midnight Gala',
            'subtitle' => 'Eleganter Auftritt für Corporate Events & Galas.',
            'description' => self::DEFAULT_DESCRIPTION,
            'paper' => 'a4',
            'orientation' => 'portrait',
            'format_hint' => 'poster-a4',
            'slots' => self::SLOTS_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' => self::DEFAULT_INSTRUCTIONS,
        ],
        'garden-brunch' => [
            'id' => 'garden-brunch',
            'name' => 'Garden Brunch',
            'subtitle' => 'Luftiges Layout für Tages-Events & Familienfeiern.',
            'description' => self::DEFAULT_DESCRIPTION,
            'paper' => 'a4',
            'orientation' => 'portrait',
            'format_hint' => 'poster-a4',
            'slots' => self::SLOTS_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' => self::DEFAULT_INSTRUCTIONS,
        ],
        'sparkler-soiree' => [
            'id' => 'sparkler-soiree',
            'name' => 'Sparkler Soirée',
            'subtitle' => 'Abendliches Layout mit funkelndem Verlauf.',
            'description' => self::DEFAULT_DESCRIPTION,
            'paper' => 'a4',
            'orientation' => 'portrait',
            'format_hint' => 'poster-a4',
            'slots' => self::SLOTS_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' => self::DEFAULT_INSTRUCTIONS,
        ],
        'confetti-bash' => [
            'id' => 'confetti-bash',
            'name' => 'Confetti Bash',
            'subtitle' => 'Verspielter Look für Geburtstage & Jubiläen.',
            'description' => self::DEFAULT_DESCRIPTION,
            'paper' => 'a4',
            'orientation' => 'portrait',
            'format_hint' => 'poster-a4',
            'slots' => self::SLOTS_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' => self::DEFAULT_INSTRUCTIONS,
        ],
    ];

    /**
     * Get layout definitions.
     *
     * @return array<int, array<string, mixed>>
     */
    public static function all(): array
    {
        return array_values(array_map(fn ($layout) => self::normalize($layout), self::LAYOUTS));
    }

    /**
     * Find a layout definition.
     */
    public static function find(string $id): ?array
    {
        $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',
            'panel_mode' => null,
            'canvas_width' => null,
            'canvas_height' => null,
            'container_padding_px' => 48,
            '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' => self::DEFAULT_INSTRUCTIONS,
            'formats' => ['pdf', 'png'],
        ];

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

        if (($normalized['canvas_width'] === null || $normalized['canvas_height'] === null) && isset($normalized['svg']['width'], $normalized['svg']['height'])) {
            $normalized['canvas_width'] = $normalized['canvas_width'] ?? $normalized['svg']['width'];
            $normalized['canvas_height'] = $normalized['canvas_height'] ?? $normalized['svg']['height'];
        }

        $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 defaultSlotsPortrait(): array
    {
        return self::SLOTS_PORTRAIT;
    }

    private static function defaultSlotsFoldable(): array
    {
        return self::SLOTS_FOLDABLE;
    }

    private static function resolveFormatHint(?string $paper, ?string $orientation, ?string $panelMode): ?string
    {
        $paperVal = strtolower((string) $paper);
        $orientationVal = strtolower((string) $orientation);
        $panelVal = strtolower((string) $panelMode);

        if ($paperVal === 'a4' && $orientationVal === 'portrait' && $panelVal !== 'double-mirror') {
            return 'poster-a4';
        }

        if ($paperVal === 'a4' && $orientationVal === 'landscape' && $panelVal === 'double-mirror') {
            return 'foldable-a5';
        }

        return null;
    }

    /**
     * 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'],
                'paper' => $layout['paper'] ?? 'a4',
                'orientation' => $layout['orientation'] ?? 'portrait',
                'panel_mode' => $layout['panel_mode'] ?? null,
                'format_hint' => $layout['format_hint'] ?? self::resolveFormatHint($layout['paper'] ?? null, $layout['orientation'] ?? null, $layout['panel_mode'] ?? null),
                'canvas_width' => $layout['canvas_width'] ?? ($layout['svg']['width'] ?? null),
                'canvas_height' => $layout['canvas_height'] ?? ($layout['svg']['height'] ?? null),
                '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'] ?? [],
                'slots' => $layout['slots'] ?? null,
                'elements' => $layout['elements'] ?? null,
                'preview' => [
                    'background' => $layout['background'],
                    'background_gradient' => $layout['background_gradient'],
                    'accent' => $layout['accent'],
                    'text' => $layout['text'],
                    'qr_size_px' => $layout['qr']['size_px'] ?? null,
                    'aspect_ratio' => isset($layout['svg']['width'], $layout['svg']['height']) && $layout['svg']['width'] && $layout['svg']['height']
                        ? (float) $layout['svg']['width'] / (float) $layout['svg']['height']
                        : null,
                ],
                'formats' => $formats,
                'download_urls' => collect($formats)
                    ->mapWithKeys(fn ($format) => [$format => $urlResolver($layout['id'], $format)])
                    ->all(),
            ];
        }, self::all());
    }
}
