<?php

declare(strict_types=1);

namespace App\Modules\PublicInvitation;

/**
 * InvitationRenderer — Compiles invitation section visibility, sort orders,
 * and theme mappings.
 *
 * No SQL queries, no HTML generation, no session access.
 *
 * @package Inveetaire
 * @ref     PILOT-004
 */
class InvitationRenderer
{
    /**
     * Prepare raw dataset for rendering.
     *
     * @param array $theme      Resolved theme row.
     * @param array $sections   List of raw sections from model.
     * @param array $guest      Resolved guest details.
     * @param array $invitation Core invitation details.
     * @param array $events     Chronological assigned events.
     * @return array Prepared bundle ready for view output.
     */
    public function prepareRenderData(
        array $theme,
        array $sections,
        array $guest,
        array $invitation,
        array $events
    ): array {
        $visibleSections = [];

        // Chronological sort on assigned events
        usort($events, function (array $a, array $b) {
            return strtotime($a['event_date']) <=> strtotime($b['event_date']);
        });

        // ── Extract media section first for cross-section bridging ────────────
        // The 'media' section is the central store for all uploaded file paths.
        // Gallery and story images live here; they must be injected into
        // their respective section configs so the renderer can access them.
        $mediaMeta = [];
        foreach ($sections as $section) {
            if ($section['section_slug'] === 'media') {
                $decoded = $section['section_config']
                    ? json_decode((string) $section['section_config'], true)
                    : [];
                if (is_array($decoded)) {
                    $mediaMeta = $decoded;
                }
                break;
            }
        }

        $processedSlugs = [];

        foreach ($sections as $section) {
            $slug = $section['section_slug'];

            // Skip duplicate section slugs to guarantee each section is rendered at most once
            if (isset($processedSlugs[$slug])) {
                continue;
            }

            $isVisible = (bool) $section['is_visible'];
            $config = $section['section_config'] ? json_decode((string) $section['section_config'], true) : [];

            // 1. Skip if database visibility is disabled
            if (!$isVisible) {
                continue;
            }

            $processedSlugs[$slug] = true;

            // 2. Bridge the 'media' section config into visibleSections for public theme music & media engine
            if ($slug === 'media') {
                $visibleSections[] = [
                    'slug'   => 'media',
                    'config' => $mediaMeta
                ];
                continue;
            }

            // 3. Bridge: inject gallery images from the media section config.
            //    Gallery images are stored as $mediaMeta['gallery'] (array of relative paths).
            //    The gallery section's own config row is empty — the paths come from media.
            if ($slug === 'gallery') {
                $galleryPaths = array_values(array_filter((array) ($mediaMeta['gallery'] ?? [])));
                if (empty($galleryPaths)) {
                    // No gallery images uploaded — hide the section
                    continue;
                }
                // Inject paths into config so identity.php can build serve URLs
                $config['images'] = $galleryPaths;
            }

            // 4. Bridge: inject couple & story images from the media section config.
            if ($slug === 'story') {
                $coupleImages = array_values(array_filter((array) ($mediaMeta['couple'] ?? [])));
                $config['couple_images'] = $coupleImages;
                $storyImages = array_values(array_filter((array) ($mediaMeta['story'] ?? [])));
                $config['story_images'] = $storyImages;
            }

            // 5. Section specific business filters
            if ($slug === 'rsvp') {
                $rsvpEnabled = (bool) ($invitation['rsvp_enabled'] ?? true);
                if (!$rsvpEnabled) {
                    // Hide RSVP section if RSVP system is disabled for this invitation
                    continue;
                }
                $config['rsvp_closes_at'] = $invitation['rsvp_closes_at'] ?? ($config['rsvp_deadline'] ?? null);
                $config['rsvp_allow_edit'] = (bool) ($invitation['rsvp_allow_edit'] ?? ($config['allow_edit'] ?? true));
                $config['notes_enabled'] = (bool) ($config['notes_enabled'] ?? true);
            }

            if ($slug === 'wishes') {
                $wishesEnabled = (bool) ($invitation['wish_wall_enabled'] ?? ($section['is_visible'] ?? true));
                if (!$wishesEnabled) {
                    // Hide Guest Book section if disabled
                    continue;
                }

                $displayPublic = (bool) ($config['display_public'] ?? true);
                $requireModeration = (bool) ($config['require_moderation'] ?? false);
                $maxCharLimit = max(50, min(5000, (int) ($config['max_char_limit'] ?? 1000)));
                $sortOrder = in_array(($config['sort_order'] ?? ''), ['newest', 'oldest'], true) ? $config['sort_order'] : 'newest';

                $config['display_public'] = $displayPublic;
                $config['require_moderation'] = $requireModeration;
                $config['max_char_limit'] = $maxCharLimit;
                $config['sort_order'] = $sortOrder;

                // Fetch approved public wishes if public display is enabled
                $approvedWishes = [];
                if ($displayPublic) {
                    // workspace_id is already present in the $invitation array,
                    // which is passed as a parameter to prepareRenderData().
                    // The renderer remains stateless — no new parameters required.
                    $invWorkspaceId = (int) ($invitation['workspace_id'] ?? 0);
                    $db = \App\Core\Database::getConnection();
                    $orderDirection = ($sortOrder === 'oldest') ? 'ASC' : 'DESC';
                    $stmtWishes = $db->prepare('
                        SELECT sender_name, message, submitted_at 
                        FROM wishes 
                        WHERE workspace_id = :workspace_id 
                          AND is_visible = 1 
                          AND (status = \'approved\' OR status IS NULL)
                        ORDER BY submitted_at ' . $orderDirection . ' 
                        LIMIT 50
                    ');
                    $stmtWishes->execute(['workspace_id' => $invWorkspaceId]);
                    $approvedWishes = $stmtWishes->fetchAll(\PDO::FETCH_ASSOC);
                }
                $config['approved_wishes'] = $approvedWishes;
            }

            if ($slug === 'gift') {
                $qrisPath = $mediaMeta['gift'] ?? null;
                $config['qris_image'] = $qrisPath;
                // Hide gift section if both bank details and QRIS are missing
                if (empty($config) || (empty($config['bank_name']) && empty($config['account_number']) && empty($qrisPath))) {
                    continue;
                }
            }

            // Store section details
            $visibleSections[] = [
                'slug'   => $slug,
                'config' => $config
            ];
        }

        if (!isset($processedSlugs['media']) && !empty($mediaMeta)) {
            $visibleSections[] = [
                'slug'   => 'media',
                'config' => $mediaMeta
            ];
        }

        // Return prepared dataset
        return [
            'theme'      => $theme,
            'sections'   => $visibleSections,
            'guest'      => $guest,
            'invitation' => $invitation,
            'events'     => $events
        ];
    }
}
