<?php
declare(strict_types=1);

if (!defined('ABSPATH')) { exit; }

/**
 * Price list element renderer (shared).
 *
 * Phase 1, step 16. Restaurant-menu-style title…dots…price rows.
 *
 * Pre-extraction this was another "frontend-was-the-prototype" case:
 *
 *   - Editor renders 9 separator styles (dashed, solid, fade, wave,
 *     zigzag, dots, pulse, shimmer, none) including animated SVG
 *     backgrounds for wave/zigzag and CSS-keyframe pulse/shimmer.
 *   - Frontend only honoured 4 (dots, line, dashes, default empty)
 *     and used a totally different rendering technique (border-bottom
 *     on a flex spacer instead of background-image separators).
 *
 *   - Item field-name drift (PRODUCTION BUG): editor reads
 *     `$item['desc']` while frontend reads `$item['description']`.
 *     Whichever name the panel happened to save would only render in
 *     ONE renderer. Both keys are now accepted; preference is `desc`
 *     (editor canonical).
 *
 * Frontend now gains the editor's richer separators + animated
 * variants. CSS vars on container styles preserved for editor live-
 * preview; frontend uses literals (same per-context split as the
 * other extractions).
 *
 * @sideeffect Emits `@keyframes impulsePlWaveBg`, `impulsePlPulse`,
 *             `impulsePlShimmer` once per page (singleton flag) when
 *             those separator types are in use.
 */
/**
 * Per-page singleton keyframes for animated separators. Shared by the
 * price_list renderer and the Products block's "menu" display mode so both
 * emit the @keyframes exactly once. No-op unless $sep is an animated style.
 */
function impulse_pl_sep_keyframes(string $sep): void {
    if (function_exists('wp_add_inline_style')
        && in_array($sep, ['wave', 'zigzag', 'pulse', 'shimmer'], true)
        && empty($GLOBALS['impulse_pl_keyframes_emitted'])) {
        $GLOBALS['impulse_pl_keyframes_emitted'] = true;
        wp_add_inline_style('instinctor-page-inline',
              '@keyframes impulsePlWaveBg{0%{background-position:0 50%}100%{background-position:200px 50%}}'
            . '@keyframes impulsePlPulse{0%,100%{opacity:0.35}50%{opacity:1}}'
            . '@keyframes impulsePlShimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}'
        );
    }
}

/**
 * Restaurant-menu leader separator (title…………price). The 9 styles
 * (dashed/solid/fade/wave/zigzag/dots/pulse/shimmer/none) extracted from the
 * price_list renderer so the Products block's "menu" mode reuses them
 * verbatim. $sepColorAttr must already be esc_attr()'d; animation phase
 * delays depend on the row $idx. Colour is wrapped in the same CSS var the
 * editor injects into so live colour preview keeps working.
 */
function impulse_pl_separator_html(string $sep, int $idx, string $sepColorAttr): void {
    // Echo-internal + full-style esc_attr (NOT wp_kses): the separator styles use
    // gradient/data-URI/animation which safecss_filter_attr would strip. esc_attr on
    // the whole style value preserves all CSS (only escapes &<>"', absent here), so
    // output is byte-identical while satisfying EscapeOutput at the echo. v2.1.2032.
    $sepBase = 'flex:1;min-width:20px;margin:0 8px;position:relative;top:-4px';
    $sc      = $sepColorAttr;
    $scVar   = 'var(--impulse-pl-sep-color,' . $sc . ')';
    if ($sep === 'dashed' || $sep === 'solid') {
        echo '<span class="impulse-pl-sep" style="' . esc_attr($sepBase . ';border-bottom:1px ' . $sep . ' ' . $scVar) . '"></span>';
        return;
    }
    if ($sep === 'fade') {
        echo '<span class="impulse-pl-sep" style="' . esc_attr($sepBase . ';height:1px;background:linear-gradient(90deg, transparent, ' . $scVar . ' 30%, ' . $scVar . ' 70%, transparent)') . '"></span>';
        return;
    }
    if ($sep === 'wave') {
        $scEnc = str_replace('#', '%23', $sc);
        $waveUri = 'data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22200%22%20height=%226%22%20viewBox=%220%200%20200%206%22%3E%3Cpath%20d=%22M0%2C3%20C8%2C0%2012%2C0%2020%2C3%20C28%2C6%2032%2C6%2040%2C3%20C48%2C0%2052%2C0%2060%2C3%20C68%2C6%2072%2C6%2080%2C3%20C88%2C0%2092%2C0%20100%2C3%20C108%2C6%20112%2C6%20120%2C3%20C128%2C0%20132%2C0%20140%2C3%20C148%2C6%20152%2C6%20160%2C3%20C168%2C0%20172%2C0%20180%2C3%20C188%2C6%20192%2C6%20200%2C3%22%20fill=%22none%22%20stroke=%22' . $scEnc . '%22%20stroke-width=%221%22%20vector-effect=%22non-scaling-stroke%22%2F%3E%3C%2Fsvg%3E';
        echo '<span class="impulse-pl-sep" style="' . esc_attr($sepBase . ';height:6px;background-image:url(' . $waveUri . ');background-repeat:repeat-x;background-size:200px 100%;animation:impulsePlWaveBg 6s linear infinite') . '"></span>';
        return;
    }
    if ($sep === 'zigzag') {
        $scEnc = str_replace('#', '%23', $sc);
        $zigUri = 'data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22200%22%20height=%226%22%20viewBox=%220%200%20200%206%22%3E%3Cpath%20d=%22M0%2C5%20L5%2C1%20L10%2C5%20L15%2C1%20L20%2C5%20L25%2C1%20L30%2C5%20L35%2C1%20L40%2C5%20L45%2C1%20L50%2C5%20L55%2C1%20L60%2C5%20L65%2C1%20L70%2C5%20L75%2C1%20L80%2C5%20L85%2C1%20L90%2C5%20L95%2C1%20L100%2C5%20L105%2C1%20L110%2C5%20L115%2C1%20L120%2C5%20L125%2C1%20L130%2C5%20L135%2C1%20L140%2C5%20L145%2C1%20L150%2C5%20L155%2C1%20L160%2C5%20L165%2C1%20L170%2C5%20L175%2C1%20L180%2C5%20L185%2C1%20L190%2C5%20L195%2C1%20L200%2C5%22%20fill=%22none%22%20stroke=%22' . $scEnc . '%22%20stroke-width=%221%22%20vector-effect=%22non-scaling-stroke%22%2F%3E%3C%2Fsvg%3E';
        echo '<span class="impulse-pl-sep" style="' . esc_attr($sepBase . ';height:6px;background-image:url(' . $zigUri . ');background-repeat:repeat-x;background-size:200px 100%;animation:impulsePlWaveBg 16s linear infinite') . '"></span>';
        return;
    }
    if ($sep === 'dots') {
        echo '<span class="impulse-pl-sep" style="' . esc_attr($sepBase . ';border-bottom:2px dotted ' . $scVar) . '"></span>';
        return;
    }
    if ($sep === 'pulse') {
        $delay = $idx * 0.5;
        echo '<span class="impulse-pl-sep" style="' . esc_attr($sepBase . ';height:1px;background:' . $scVar . ';animation:impulsePlPulse 2.5s ease-in-out ' . $delay . 's infinite') . '"></span>';
        return;
    }
    if ($sep === 'shimmer') {
        $delay = $idx * 0.4;
        echo '<span class="impulse-pl-sep" style="' . esc_attr($sepBase . ';height:1px;background:linear-gradient(90deg, transparent 0%, ' . $scVar . ' 50%, transparent 100%);background-size:200% 100%;animation:impulsePlShimmer 3.5s linear ' . $delay . 's infinite') . '"></span>';
        return;
    }
    echo '<span class="impulse-pl-sep" style="flex:1;min-width:20px"></span>';
}

function impulse_element_render_price_list($el, array $settings, string $context): string {
    if (is_object($el)) $el = (array) $el;
    $elId     = preg_replace('/[^A-Za-z0-9_-]/', '', (string) ($el['id'] ?? '0'));
    $isEditor = ($context === 'editor');
    $device   = $isEditor ? ($GLOBALS['impulse_preview_device'] ?? 'desktop') : 'desktop';

    $read = function (string $key, $default) use ($settings, $isEditor) {
        if ($isEditor && function_exists('impulse_device_val')) {
            return impulse_device_val($settings, $key, $device = $GLOBALS['impulse_preview_device'] ?? 'desktop', $default);
        }
        return $settings[$key] ?? $default;
    };

    $plItems = $settings['pl_items'] ?? [];
    if (is_string($plItems)) $plItems = json_decode($plItems, true) ?: [];

    // Editor: default to a 3-item demo so blank blocks look intentional.
    if (empty($plItems)) {
        if ($isEditor) {
            $plItems = [
                ['title'=>'Consultation','desc'=>'','price'=>'$50','icon'=>'circle'],
                ['title'=>'Basic Package','desc'=>'Includes setup and training','price'=>'$199','icon'=>'circle'],
                ['title'=>'Premium Package','desc'=>'Full service with priority support','price'=>'$499','icon'=>'circle'],
            ];
        } else {
            return ''; // Frontend: render nothing if the block has no items.
        }
    }

    $plSep         = (string) ($settings['pl_separator'] ?? 'dashed');
    if ($plSep === 'dotted') $plSep = 'dashed'; // backward compat
    $plTitleSize   = intval($read('pl_title_size',  16));
    $plPriceSize   = intval($read('pl_price_size',  16));
    $plDescSize    = intval($read('pl_desc_size',   13));
    $plSpacing     = intval($read('pl_spacing',     16));
    $plIconSize    = intval($read('pl_icon_size',   18));
    $plTitleColor  = (string) ($settings['pl_title_color']  ?? '#1d2327');
    $plPriceColor  = (string) ($settings['pl_price_color']  ?? '#1d2327');
    $plDescColor   = (string) ($settings['pl_desc_color']   ?? '#888888');
    $plSepColor    = (string) ($settings['pl_sep_color']    ?? '#cccccc');
    $plBorderColor = (string) ($settings['pl_border_color'] ?? '#e0e0e0');
    $plIconColor   = (string) ($settings['pl_icon_color']   ?? $plTitleColor);
    $plMaxWidth    = intval($settings['section_max_width']  ?? 800);
    $plShowDivider = !isset($settings['pl_show_divider']) || !empty($settings['pl_show_divider']);

    $sc = esc_attr($plSepColor);

    // Per-page singleton keyframes for animated separators (shared helper).
    impulse_pl_sep_keyframes($plSep);

    // ── Compose HTML ─────────────────────────────────────────────
    // v2.1.1367: explicit `width: 100%` because `margin: 0 auto` on a flex
    // child cancels `align-self: stretch` (CSS Flexbox spec: "If a flex item
    // has margin: auto on the cross axis, then align-self: stretch has no
    // effect"). Without the explicit width the wrapper shrinks to its content's
    // intrinsic max-content width and the rows bunch into a narrow column at
    // the centre of any compact section that's wider than the rows themselves.
    // max-width still caps it on wider parents; auto margins then centre.
    $plWrapStyle = $isEditor
        ? 'width:100%;max-width:var(--impulse-section-max-width,' . $plMaxWidth . 'px);margin:0 auto'
        : 'width:100%;max-width:' . $plMaxWidth . 'px;margin:0 auto';

    ob_start();
    echo '<div class="impulse-price-list" style="' . esc_attr($plWrapStyle) . '">';

    $idx = 0;
    foreach ($plItems as $item) {
        $title = (string) ($item['title'] ?? '');
        $price = (string) ($item['price'] ?? '');
        // Field-name drift fix: pre-extraction frontend read 'description',
        // editor wrote 'desc' — items saved via the panel never showed
        // their description on the frontend. Accept both, prefer 'desc'.
        $desc  = (string) ($item['desc'] ?? ($item['description'] ?? ''));
        $icon  = (string) ($item['icon'] ?? 'circle');
        $hasIcon = $icon !== '' && $icon !== 'none';

        $dividerStyle = $plShowDivider
            ? ($isEditor
                ? 'border-bottom:1px solid var(--impulse-pl-border-color,' . esc_attr($plBorderColor) . ')'
                : 'border-bottom:1px solid ' . esc_attr($plBorderColor))
            : 'border-bottom:none';
        $spacingClause = $isEditor
            ? 'padding:var(--impulse-pl-spacing,' . $plSpacing . 'px) 0;'
            : 'padding:' . $plSpacing . 'px 0;';

        echo '<div class="impulse-price-item" style="' . esc_attr($spacingClause . $dividerStyle) . '">';
        echo '<div style="display:flex;align-items:baseline;gap:8px">';

        if ($hasIcon && function_exists('impulse_lucide_svg')) {
            if ($isEditor) {
                $iconCssStyle = 'flex-shrink:0;position:relative;top:1px;width:var(--impulse-pl-icon-size,' . $plIconSize . 'px);height:var(--impulse-pl-icon-size,' . $plIconSize . 'px);color:var(--impulse-pl-icon-color,' . esc_attr($plIconColor) . ')';
                echo wp_kses(impulse_lucide_svg($icon, $plIconSize, 'currentColor', ['style' => $iconCssStyle]), impulse_svg_allowed());
            } else {
                echo '<span style="color:' . esc_attr($plIconColor) . ';flex-shrink:0;display:flex;align-items:center">' . wp_kses(impulse_lucide_svg($icon, $plIconSize, 'currentColor'), impulse_svg_allowed()) . '</span>';
            }
        }

        $titleStyleE = 'font-weight:600;color:var(--impulse-pl-title-color,' . esc_attr($plTitleColor) . ');font-size:var(--impulse-pl-title-size,' . $plTitleSize . 'px);flex-shrink:0';
        $titleStyleF = 'font-size:' . $plTitleSize . 'px;font-weight:600;color:' . esc_attr($plTitleColor);
        echo '<span class="impulse-pl-title" style="' . esc_attr($isEditor ? $titleStyleE : $titleStyleF) . '">' . esc_html($title) . '</span>';

        impulse_pl_separator_html($plSep, $idx, $sc);

        $priceStyleE = 'font-weight:700;color:var(--impulse-pl-price-color,' . esc_attr($plPriceColor) . ');font-size:var(--impulse-pl-price-size,' . $plPriceSize . 'px);white-space:nowrap;flex-shrink:0';
        $priceStyleF = 'font-size:' . $plPriceSize . 'px;font-weight:600;color:' . esc_attr($plPriceColor) . ';white-space:nowrap';
        echo '<span class="impulse-pl-price" style="' . esc_attr($isEditor ? $priceStyleE : $priceStyleF) . '">' . esc_html($price) . '</span>';

        echo '</div>';

        if ($desc !== '') {
            $descPad = $hasIcon ? ($plIconSize + 8) : 0;
            $descStyleE = 'font-size:var(--impulse-pl-desc-size,' . $plDescSize . 'px);color:var(--impulse-pl-desc-color,' . esc_attr($plDescColor) . ');margin-top:2px;padding-left:' . $descPad . 'px';
            $descStyleF = 'font-size:' . $plDescSize . 'px;color:' . esc_attr($plDescColor) . ';margin-top:4px;line-height:1.4;padding-left:' . $descPad . 'px';
            echo '<div class="impulse-pl-desc" style="' . esc_attr($isEditor ? $descStyleE : $descStyleF) . '">' . esc_html($desc) . '</div>';
        }

        echo '</div>';
        $idx++;
    }

    echo '</div>';
    return ob_get_clean();
}
