<?php
namespace Components\Ui;

use Components\Button;
use Components\Router;
use Components\Base;

/**
 * FlowHelpers: reusable UI elements for Flow visualization cards.
 */
class FlowHelpers
{
    /**
     * Returns the Alpine.js data object string for flow scroll containers.
     * Expects $refs.scroller to be the scrollable element.
     */
    public static function alpineData(string $behavior = 'smooth'): string
    {
        return '{
            canScrollX: false,
            atStart: true,
            atEnd: false,
            refreshing: false,
            init() {
                this.update();
                if (window.IntersectionObserver) {
                    const observer = new IntersectionObserver(() => {
                        this.update();
                    }, { threshold: [0, 1] });
                    observer.observe(this.$el);
                }
            },
            update() {
                const el = this.$refs.scroller || this.$el;
                if (!el) return;
                this.canScrollX = el.scrollWidth > (el.clientWidth + 2);
                const max = Math.max(0, el.scrollWidth - el.clientWidth);
                this.atStart = el.scrollLeft <= 1;
                this.atEnd = el.scrollLeft >= (max - 1);
            },
            scrollBy(dx) {
                const el = this.$refs.scroller || this.$el;
                if (!el) return;
                el.scrollBy({ left: dx, behavior: \'' . $behavior . '\' });
            }
        }';
    }

    /**
     * Renders a single scroll button.
     */
    public static function renderScrollButton(string $direction, int $amount = 280, string $class = ''): string
    {
        $dx = ($direction === 'left' ? -$amount : $amount);
        $icon = ($direction === 'left'
            ? '<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" />'
            : '<path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />');

        ob_start();
        ?>
        <button type="button" @click.stop="scrollBy(<?= $dx ?>)"
                class="pointer-events-auto inline-flex items-center justify-center shrink-0 <?= $class ?>"
                x-cloak x-show="canScrollX && <?= $direction === 'left' ? '!atStart' : '!atEnd' ?>" x-transition.opacity>
            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" class="size-5">
                <?= $icon ?>
            </svg>
        </button>
        <?php
        return ob_get_clean();
    }

    /**
     * Renders the "Refresh Flow" button that triggers invalidate_flow_cache.
     */
    public static function renderRefreshButton(string $type, int $id = 0, string $eventPrefix = ''): string
    {
        $refreshUrl = Router::url('invalidate_flow_cache', [
            'partial' => 1,
            'id' => $id,
            'type' => $type,
            'event_prefix' => $eventPrefix,
        ]);
        ob_start();
        ?>
        <div class="absolute top-0 right-1 z-30">
            <?php
            echo Button::render('', [
                'size' => 'xs',
                'variant' => 'ghost',
                'icon' => '<span class="when-idle p-0.5 [&_svg]:size-4">' . Base::SVG_REFRESH . '</span><span class="when-request hidden p-0.5 [&_svg]:size-4">' . Base::SVG_SPINNER . '</span>',
                'class' => 'opacity-30 text-secondary/30 hover:text-secondary [&.htmx-request_.when-idle]:hidden [&.htmx-request_.when-request]:inline-flex disabled:opacity-50 ',
                'attrs' => [
                    'hx-post' => $refreshUrl,
                    'hx-swap' => 'none',
                    'hx-indicator' => '#' . ('refresh-btn-' . substr(md5($type . '|' . (string)$id . '|' . $eventPrefix), 0, 8)),
                    'hx-disabled-elt' => '#' . ('refresh-btn-' . substr(md5($type . '|' . (string)$id . '|' . $eventPrefix), 0, 8)),
                    ':disabled' => 'refreshing',
                    'data-no-global-loader' => '1',
                    'title' => 'Refresh Flow',
                    'id' => 'refresh-btn-' . substr(md5($type . '|' . (string)$id . '|' . $eventPrefix), 0, 8),
                ],
            ]);
            ?>
        </div>
        <?php
        return ob_get_clean();
    }

    /**
     * Renders horizontal scroll hint overlays (chevrons).
     * Expects Alpine data from alpineData().
     */
    public static function renderScrollHints(): string
    {
        ob_start();
        ?>
        <!-- Horizontal scroll hint overlays (fixed within the area) -->
        <div x-cloak x-show="canScrollX && !atStart" x-transition.opacity
             class="pointer-events-none absolute inset-y-0 left-0 flex items-center z-20">
            <button type="button" @click.stop="scrollBy(-280)"
                    class="pointer-events-auto inline-flex items-center justify-center w-6 h-full bg-secondary/20 text-white shadow-sm ring-1 ring-white/20 hover:bg-secondary/30 focus:outline-none">
                <!-- left chevron -->
                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" />
                </svg>
            </button>
        </div>
        <div x-cloak x-show="canScrollX && !atEnd" x-transition.opacity
             class="pointer-events-none absolute inset-y-0 right-0 flex items-center z-20">
            <button type="button" @click.stop="scrollBy(280)"
                    class="pointer-events-auto inline-flex items-center justify-center w-6 h-full bg-secondary/20 text-white shadow-sm ring-1 ring-white/20 hover:bg-secondary/30 focus:outline-none">
                <!-- right chevron -->
                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
                    <path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />
                </svg>
            </button>
        </div>
        <?php
        return ob_get_clean();
    }

    /**
     * Returns the Alpine.js initialization string for syncing localViewMode with global stores.
     */
    public static function viewModeInit(string $openKey): string
    {
        $openKeyEsc = Base::h($openKey);
        return "localViewMode = (\$store.trigger && \$store.trigger.viewMode) ? \$store.trigger.viewMode : ((\$store.newsletter && \$store.newsletter.viewMode) ? \$store.newsletter.viewMode : ((\$store.audience && \$store.audience.viewMode) ? \$store.audience.viewMode : (typeof viewMode !== 'undefined' ? viewMode : 'journey'))); " .
            "if (\$store.trigger) \$watch('\$store.trigger.viewMode', v => localViewMode = v); " .
            "if (\$store.newsletter) \$watch('\$store.newsletter.viewMode', v => localViewMode = v); " .
            "if (\$store.audience) \$watch('\$store.audience.viewMode', v => localViewMode = v); " .
            "if (typeof viewMode !== 'undefined') \$watch('viewMode', v => localViewMode = v); " .
            "\$watch('localViewMode', v => { if (v === 'journey') { \$nextTick(() => update()); } }); " .
            "if (openMap['$openKeyEsc']) { update(); \$nextTick(() => update()); setTimeout(() => update(), 60); }";
    }

    /**
     * Renders the Journey/Performance toggle sub-header.
     */
    public static function renderViewModeToggle(array $options = []): string
    {
        $editUrl = $options['edit_url'] ?? '';
        $detailsUrl = $options['details_url'] ?? '';
        $compact = $options['compact'] ?? false;
        $openKey = $options['open_key'] ?? '';

        ob_start();
        ?>
        <div class="<?= $compact ? 'flex items-center' : 'px-3 py-2 flex items-center justify-between shrink-0' ?>" @click.stop="">
            <?= TabsGroup::render([
                ['value' => 'performance', 'label' => mh_lng('MAILBEEZ_VIEW_PERFORMANCE', 'Performance')],
                ['value' => 'journey', 'label' => mh_lng('MAILBEEZ_VIEW_JOURNEY', 'Journey')],
            ], [
                'model' => 'localViewMode',
                'size' => 'xs',
                'attrs' => $openKey ? ['x-effect' => "openMap['" . Base::h((string)$openKey) . "'] && \$nextTick(() => sync())"] : []
            ]); ?>
        </div>
        <?php
        return ob_get_clean();
    }

    /**
     * Renders the background patterns container.
     */
    public static function renderBackground(string $id, string $type = 'dots'): string
    {
        ob_start();
        ?>
        <div x-show="localViewMode === 'journey'" class="absolute inset-0 pointer-events-none z-0">
            <div class="absolute inset-0 bg-divider/20 bg_dotted_pattern"></div>
            <?php if ($type === 'lines'): ?>
                <svg class="absolute inset-0 rounded-2xl size-full stroke-divider/90 dark:stroke-muted/10" fill="none"
                     aria-hidden="true">
                    <defs>
                        <pattern id="pattern-<?= Base::h($id) ?>" x="0" y="0" width="8" height="8"
                                 patternUnits="userSpaceOnUse">
                            <path d="M-1 5L5 -1M3 9L8.5 3.5" stroke-width="0.5"></path>
                        </pattern>
                    </defs>
                    <rect stroke="none" fill="url(#pattern-<?= Base::h($id) ?>)" width="100%" height="100%"></rect>
                </svg>
            <?php endif; ?>
        </div>
        <?php
        return ob_get_clean();
    }

    /**
     * Renders the global Journey/Performance toggle for page headers.
     */
    public static function renderGlobalToggle(string $page): string
    {
        $store = ($page === 'trigger' ? 'trigger' : ($page === 'audience' ? 'audience' : 'newsletter'));
        $saveUrl = Router::url('save_module_config', ['partial' => 1, 'module' => 'ui', 'context' => $page]);

        return TabsGroup::render([
            ['value' => 'performance', 'label' => mh_lng('MAILBEEZ_VIEW_PERFORMANCE', 'Performance'), 'icon' => Base::SVG_ROCKET],
            ['value' => 'journey', 'label' => mh_lng('MAILBEEZ_VIEW_JOURNEY', 'Flow'), 'icon' => Base::SVG_ROUTE],
        ], [
            'model' => '$store.' . $store . '.viewMode',
            'size' => 'sm',
            'class' => 'mr-2',
            'attrs' => [
                '@click' => '$nextTick(() => htmx.ajax(\'POST\', \'' . $saveUrl . '\', { values: { view_mode: $store.' . $store . '.viewMode }, swap: \'none\' }))'
            ]
        ]);
    }

    /**
     * Renders the Performance (KPI) panel wrapper for lazy loading via HTMX.
     */
    public static function renderPerformancePanel(string $url, string $loaderId, string $initialContent = '', string $id = ''): string
    {
        ob_start();
        ?>
        <template x-if="localViewMode === 'performance'">
            <div <?= $id ? 'id="performance-panel-' . Base::h($id) . '"' : '' ?>
                 class="min-h-[90px] rounded-lg relative z-10"
            >
                <?= $initialContent ?>
            </div>
        </template>
        <?php
        return ob_get_clean();
    }
}
