<?php

declare(strict_types=1);

/**
 * APO-226 - Unified creative library catalog.
 *
 * Wraps the established scene and motion catalogs while giving operators and
 * MCP clients a single discovery surface for section and site creative effects.
 */
final class MyronCreativeLibraryCatalog
{
    /** @var list<array<string, mixed>>|null */
    private ?array $entries = null;

    public function __construct(
        private readonly MyronMotionProfileCatalog $motionProfiles,
        private readonly MyronSceneCatalog $scenes,
    ) {
    }

    /**
     * @return list<array<string, mixed>>
     */
    public function list(): array
    {
        if ($this->entries !== null) {
            return $this->entries;
        }

        $entries = [];
        foreach ($this->motionProfiles->list() as $profile) {
            $id = (string) ($profile['id'] ?? '');
            $entries[] = array_merge($profile, [
                'id' => $id,
                'category' => 'motion',
                'description' => $this->motionDescription($id),
                'tier' => 'section',
                'compatibleSectionKeys' => ['*'],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => (string) ($profile['cssClass'] ?? ('mc-motion--' . $id)),
            ]);
        }

        foreach ($this->scenes->list() as $scene) {
            $id = (string) ($scene['id'] ?? '');
            $entries[] = array_merge($scene, [
                'id' => $id,
                'category' => 'scene',
                'description' => $this->sceneDescription($id),
                'tier' => 'section',
                'compatibleSectionKeys' => ['*'],
                'requiresJs' => true,
                'cssClass' => 'mc-scene--' . $id,
            ]);
        }

        $entries[] = [
            'id' => 'gradient-bloom',
            'category' => 'scene',
            'label' => 'Gradient Bloom',
            'description' => 'A soft token-driven radial bloom rising from the bottom edge of the section.',
            'tier' => 'section',
            'compatibleSectionKeys' => ['*'],
            'supportedParams' => [
                ['key' => 'colorA', 'label' => 'Bloom color (hex)', 'type' => 'string', 'default' => ''],
                ['key' => 'intensity', 'label' => 'Intensity', 'type' => 'number', 'default' => 0.5, 'min' => 0.3, 'max' => 1.0, 'step' => 0.05],
                ['key' => 'blur', 'label' => 'Blur (px)', 'type' => 'number', 'default' => 20, 'min' => 0, 'max' => 80],
            ],
            'implementationType' => 'css',
            'requiresJs' => true,
            'cssClass' => 'mc-scene--gradient-bloom',
        ];

        $entries[] = [
            'id' => 'aurora-mesh',
            'category' => 'scene',
            'label' => 'Aurora Mesh',
            'description' => 'A slow drifting diagonal gradient mesh for ambient hero and section backgrounds.',
            'tier' => 'section',
            'compatibleSectionKeys' => ['*'],
            'supportedParams' => [
                ['key' => 'colorA', 'label' => 'Color A (hex)', 'type' => 'string', 'default' => ''],
                ['key' => 'colorB', 'label' => 'Color B (hex)', 'type' => 'string', 'default' => ''],
                ['key' => 'duration', 'label' => 'Duration (s)', 'type' => 'number', 'default' => 20, 'min' => 8, 'max' => 60],
            ],
            'implementationType' => 'css',
            'requiresJs' => true,
            'cssClass' => 'mc-scene--aurora-mesh',
        ];

        foreach ($this->cardSceneEntries() as $entry) {
            $entries[] = $entry;
        }

        foreach ($this->newMotionEntries() as $entry) {
            $entries[] = $entry;
        }

        foreach ($this->scrollEntries() as $entry) {
            $entries[] = $entry;
        }

        foreach ($this->featureCardEntries() as $entry) {
            $entries[] = $entry;
        }

        foreach ($this->navigationEntries() as $entry) {
            $entries[] = $entry;
        }

        foreach ($this->buttonEntries() as $entry) {
            $entries[] = $entry;
        }

        $entries[] = [
            'id' => 'scrolljack-hero',
            'category' => 'hero',
            'label' => 'Scrolljack Hero',
            'description' => 'A landing hero with 2-4 CMS-managed states and sticky scroll transitions.',
            'tier' => 'section',
            'compatibleSectionKeys' => ['hero', 'hero-primary', 'landing-hero', 'funnel-hero', '*'],
            'supportedParams' => [
                ['key' => 'transition', 'label' => 'Transition', 'type' => 'select', 'default' => 'fade', 'options' => ['fade', 'slide']],
            ],
            'implementationType' => 'js',
            'requiresJs' => true,
            'cssClass' => 'myron-scrolljack-hero',
        ];

        $this->entries = $entries;
        return $this->entries;
    }

    /**
     * @return list<array<string, mixed>>
     */
    public function listByCategory(string $category): array
    {
        $category = myronNormalizeSlug($category);
        return array_values(array_filter(
            $this->list(),
            static fn (array $entry): bool => (string) ($entry['category'] ?? '') === $category
        ));
    }

    /**
     * @return array<string, mixed>|null
     */
    public function find(string $id): ?array
    {
        $id = trim($id);
        foreach ($this->list() as $entry) {
            if ((string) ($entry['id'] ?? '') === $id) {
                return $entry;
            }
        }

        return null;
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function cardSceneEntries(): array
    {
        return [
            [
                'id' => 'card-laser-grid',
                'category' => 'scene',
                'label' => 'Card Laser Grid',
                'description' => 'A canvas dot grid with a token-colored scanning horizontal laser line.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [
                    ['key' => 'dotSpacing', 'label' => 'Dot spacing (px)', 'type' => 'number', 'default' => 28, 'min' => 12, 'max' => 80],
                    ['key' => 'scanSpeed', 'label' => 'Scan speed', 'type' => 'number', 'default' => 1.5, 'min' => 0.2, 'max' => 5, 'step' => 0.1],
                    ['key' => 'laserColor', 'label' => 'Laser color (hex)', 'type' => 'string', 'default' => ''],
                ],
                'implementationType' => 'canvas',
                'requiresJs' => true,
                'cssClass' => 'mc-scene--card-laser-grid',
            ],
            [
                'id' => 'card-ekg-pulse',
                'category' => 'scene',
                'label' => 'Card EKG Pulse',
                'description' => 'An inline SVG waveform that traces continuously with stroke dash animation.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [
                    ['key' => 'lineColor', 'label' => 'Line color (hex)', 'type' => 'string', 'default' => ''],
                    ['key' => 'duration', 'label' => 'Duration (s)', 'type' => 'number', 'default' => 3, 'min' => 1, 'max' => 12],
                ],
                'implementationType' => 'svg',
                'requiresJs' => true,
                'cssClass' => 'mc-scene--card-ekg-pulse',
            ],
            [
                'id' => 'card-geo-rotator',
                'category' => 'scene',
                'label' => 'Card Geo Rotator',
                'description' => 'A low-opacity rotating geometric SVG motif for decorative section depth.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [
                    ['key' => 'strokeColor', 'label' => 'Stroke color (hex)', 'type' => 'string', 'default' => ''],
                    ['key' => 'opacity', 'label' => 'Opacity', 'type' => 'number', 'default' => 0.08, 'min' => 0.02, 'max' => 0.24, 'step' => 0.01],
                    ['key' => 'duration', 'label' => 'Duration (s)', 'type' => 'number', 'default' => 40, 'min' => 8, 'max' => 120],
                ],
                'implementationType' => 'svg',
                'requiresJs' => true,
                'cssClass' => 'mc-scene--card-geo-rotator',
            ],
        ];
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function featureCardEntries(): array
    {
        return [
            [
                'id' => 'card-shuffler',
                'category' => 'cards',
                'label' => 'Card Shuffler',
                'description' => 'Cycles peer feature cards through an overlapping vertical stack with spring-bounce easing.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['feature-grid', 'services-grid', 'testimonial-grid', '*'],
                'supportedParams' => [
                    ['key' => 'interval', 'label' => 'Interval (ms)', 'type' => 'number', 'default' => 3000, 'min' => 800, 'max' => 20000],
                ],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'mc-card-shuffler',
            ],
            [
                'id' => 'card-typewriter',
                'category' => 'cards',
                'label' => 'Card Typewriter',
                'description' => 'Types and cycles pipe-delimited CMS text lines in a monospace live feed treatment.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['card', 'feature-grid', 'services-grid', '*'],
                'supportedParams' => [
                    ['key' => 'speed', 'label' => 'Speed (ms/char)', 'type' => 'number', 'default' => 40, 'min' => 10, 'max' => 200],
                    ['key' => 'pause', 'label' => 'Pause (ms)', 'type' => 'number', 'default' => 1200, 'min' => 300, 'max' => 6000],
                ],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'mc-card-typewriter',
            ],
            [
                'id' => 'card-protocol-stacker',
                'category' => 'cards',
                'label' => 'Card Protocol Stacker',
                'description' => 'Turns peer cards into a sticky scroll stack where buried cards scale, blur, and fade.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['feature-grid', 'services-grid', 'testimonial-grid', '*'],
                'supportedParams' => [],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'mc-protocol-stack',
            ],
        ];
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function newMotionEntries(): array
    {
        return [
            [
                'id' => 'typewriter-headline',
                'category' => 'motion',
                'label' => 'Typewriter Headline',
                'description' => 'Reveals the section headline one character at a time on first intersection.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [
                    ['key' => 'speed', 'label' => 'Speed (ms/char)', 'type' => 'number', 'default' => 40, 'min' => 10, 'max' => 120],
                    ['key' => 'delay', 'label' => 'Delay (ms)', 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 2000],
                    ['key' => 'cursor', 'label' => 'Cursor', 'type' => 'string', 'default' => '|'],
                ],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'mc-motion--typewriter-headline',
            ],
            [
                'id' => 'rotate-words',
                'category' => 'motion',
                'label' => 'Rotate Words',
                'description' => 'Cycles through pipe-delimited headline words using slide or fade transitions.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [
                    ['key' => 'interval', 'label' => 'Interval (ms)', 'type' => 'number', 'default' => 2500, 'min' => 800, 'max' => 10000],
                    ['key' => 'transition', 'label' => 'Transition', 'type' => 'select', 'default' => 'slide', 'options' => ['slide', 'fade']],
                ],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'mc-motion--rotate-words',
            ],
            [
                'id' => 'shutter-reveal',
                'category' => 'motion',
                'label' => 'Shutter Reveal',
                'description' => 'Opens section content with a clip-path wipe from top, left, or center.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [
                    ['key' => 'direction', 'label' => 'Direction', 'type' => 'select', 'default' => 'top', 'options' => ['top', 'left', 'center']],
                    ['key' => 'duration', 'label' => 'Duration (ms)', 'type' => 'number', 'default' => 700, 'min' => 300, 'max' => 2000],
                    ['key' => 'delay', 'label' => 'Delay (ms)', 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 2000],
                ],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'mc-motion--shutter-reveal',
            ],
            [
                'id' => 'split-lines',
                'category' => 'motion',
                'label' => 'Split Lines',
                'description' => 'Splits the headline into staggered word or line spans that rise into view.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [
                    ['key' => 'splitBy', 'label' => 'Split by', 'type' => 'select', 'default' => 'word', 'options' => ['word', 'line']],
                    ['key' => 'duration', 'label' => 'Duration (ms)', 'type' => 'number', 'default' => 600, 'min' => 200, 'max' => 2000],
                    ['key' => 'stagger', 'label' => 'Stagger (ms)', 'type' => 'number', 'default' => 80, 'min' => 20, 'max' => 400],
                    ['key' => 'delay', 'label' => 'Delay (ms)', 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 2000],
                ],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'mc-motion--split-lines',
            ],
        ];
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function scrollEntries(): array
    {
        return [
            [
                'id' => 'text-parallax-scroll',
                'category' => 'scroll',
                'label' => 'Text Parallax Scroll',
                'description' => 'Moves the CMS-managed section background image at a slower rate than overlaid text.',
                'tier' => 'section',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [
                    ['key' => 'intensity', 'label' => 'Intensity', 'type' => 'number', 'default' => 0.2, 'min' => 0.05, 'max' => 0.4, 'step' => 0.05],
                ],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'mc-motion--text-parallax-scroll',
            ],
        ];
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function navigationEntries(): array
    {
        return [
            [
                'id' => 'floating-nav',
                'category' => 'navigation',
                'label' => 'Floating Nav',
                'description' => 'A fixed centered navigation bar that morphs from transparent hero chrome into a blurred surface after hero exit.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [
                    ['key' => 'navRadius', 'label' => 'Navigation radius', 'type' => 'select', 'default' => 'pill', 'options' => ['pill', 'lg', 'md', 'sm', 'none']],
                ],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'mc-nav--floating',
            ],
            [
                'id' => 'sticky-compact-nav',
                'category' => 'navigation',
                'label' => 'Sticky Compact Nav',
                'description' => 'A sticky navigation bar that keeps full spacing at the hero and compresses after the hero threshold.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'mc-nav--sticky-compact',
            ],
            [
                'id' => 'mobile-bottom-nav',
                'category' => 'navigation',
                'label' => 'Mobile Bottom Nav',
                'description' => 'A mobile-only fixed bottom home-row navigation bar sourced from the published primary navigation.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [],
                'implementationType' => 'css',
                'requiresJs' => false,
                'cssClass' => 'mc-nav--mobile-bottom',
            ],
        ];
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function buttonEntries(): array
    {
        return [
            [
                'id' => 'btn-shimmer-sweep',
                'category' => 'button',
                'label' => 'Button Shimmer Sweep',
                'description' => 'A continuous diagonal highlight band sweeps across site buttons.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [],
                'implementationType' => 'css',
                'requiresJs' => false,
                'cssClass' => 'btn-shimmer-sweep',
            ],
            [
                'id' => 'btn-3d-press',
                'category' => 'button',
                'label' => 'Button 3D Press',
                'description' => 'Buttons lift on hover and compress on press with a tactile shadow response.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [],
                'implementationType' => 'css',
                'requiresJs' => false,
                'cssClass' => 'btn-3d-press',
            ],
            [
                'id' => 'btn-shiny-sheen',
                'category' => 'button',
                'label' => 'Button Shiny Sheen',
                'description' => 'A diagonal sheen slides across button surfaces on hover.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [],
                'implementationType' => 'css',
                'requiresJs' => false,
                'cssClass' => 'btn-shiny-sheen',
            ],
            [
                'id' => 'btn-magnetic-follow',
                'category' => 'button',
                'label' => 'Button Magnetic Follow',
                'description' => 'Desktop pointer proximity gently pulls buttons toward the cursor.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [
                    ['key' => 'strength', 'label' => 'Strength', 'type' => 'number', 'default' => 0.4, 'min' => 0.1, 'max' => 0.8, 'step' => 0.05],
                ],
                'implementationType' => 'js',
                'requiresJs' => true,
                'cssClass' => 'btn-magnetic-follow',
            ],
            [
                'id' => 'btn-fill-expand',
                'category' => 'button',
                'label' => 'Button Fill Expand',
                'description' => 'The accent color expands from the center of outlined buttons on hover.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [],
                'implementationType' => 'css',
                'requiresJs' => false,
                'cssClass' => 'btn-fill-expand',
            ],
            [
                'id' => 'btn-glow-pulse',
                'category' => 'button',
                'label' => 'Button Glow Pulse',
                'description' => 'A token-colored ambient glow breathes around buttons and intensifies on hover.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [],
                'implementationType' => 'css',
                'requiresJs' => false,
                'cssClass' => 'btn-glow-pulse',
            ],
            [
                'id' => 'btn-arrow-slide',
                'category' => 'button',
                'label' => 'Button Arrow Slide',
                'description' => 'A forward arrow slides in while the label shifts left on hover.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [],
                'implementationType' => 'css',
                'requiresJs' => false,
                'cssClass' => 'btn-arrow-slide',
            ],
            [
                'id' => 'btn-border-trace',
                'category' => 'button',
                'label' => 'Button Border Trace',
                'description' => 'An SVG stroke traces the button perimeter on hover without affecting tab order.',
                'tier' => 'site',
                'compatibleSectionKeys' => ['*'],
                'supportedParams' => [],
                'implementationType' => 'svg',
                'requiresJs' => true,
                'cssClass' => 'btn-border-trace',
            ],
        ];
    }

    private function motionDescription(string $id): string
    {
        return match ($id) {
            'fade-up' => 'Fades a section upward on scroll intersection.',
            'slide-in' => 'Slides a section into view from the configured side.',
            'stagger' => 'Staggers direct child elements into view.',
            'zoom-in' => 'Scales a section into place on reveal.',
            'blur-in' => 'Fades a section from blurred to sharp on first intersection.',
            'flip-up' => 'Tilts a section upward into flat perspective on reveal.',
            'scale-pop' => 'Scales a section into place with a spring overshoot.',
            'count-up' => 'Animates CMS-rendered numeric text from zero to its final value.',
            'parallax-bg' => 'Maps scroll position to a background parallax offset.',
            default => 'Section motion profile.',
        };
    }

    private function sceneDescription(string $id): string
    {
        return match ($id) {
            'gradient-flow' => 'Animated two-color gradient flow background.',
            'dot-grid' => 'Static token-colored dot grid overlay.',
            'noise-overlay' => 'Static inline SVG noise texture overlay.',
            'canvas-particles' => 'Canvas particle field behind section content.',
            default => 'Decorative section scene background.',
        };
    }
}
