<?php
// components/Ui/PerformanceDashboard.php
namespace Components\Ui;

use Components\Base;
use Components\Data\DataRegistry;
use Components\Support\FlowHtmlCache;
use Components\Router;
use Components\Newsletter\PageConfig;

class PerformanceDashboard
{
    public const CONTEXT_TRIGGER = 'trigger';
    public const CONTEXT_TRIGGER_TYPE_REVIEW = 'trigger_type_review';
    public const CONTEXT_NEWSLETTER = PageConfig::MODE_NEWSLETTER;
    public const CONTEXT_AUTOMATION = PageConfig::MODE_AUTOMATION;
    public const CONTEXT_AUDIENCE = 'audience';

    /**
     * Get the metrics definition for a given context.
     *
     * @param string $context
     * @return array
     */
    public static function getMetricsDefinition(string $context = self::CONTEXT_TRIGGER): array
    {
        switch ($context) {
            case self::CONTEXT_AUDIENCE:
                return [
                    'total' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_TOTAL', 'Subscribers'), 'type' => 'number'],
                ];
            case self::CONTEXT_TRIGGER_TYPE_REVIEW:
                return [
                    'lastSent' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_LAST_SENT', 'Last Sent'), 'type' => 'timeago'],
                    'sent' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_SENT', 'Sent'), 'type' => 'number', 'dotColor' => 'bg-event-sent'],
                    'opened' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_OPENED', 'Opened'), 'type' => 'number', 'dotColor' => 'bg-event-opened'],
                    'clicked' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_CLICKED', 'Clicked'), 'type' => 'number', 'dotColor' => 'bg-event-clicked'],
                    'orders' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_ORDERS', 'Orders'), 'type' => 'number', 'dotColor' => 'bg-event-ordered'],
                    'revenue' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_REVENUE', 'Revenue'), 'type' => 'currency', 'dotColor' => 'bg-event-ordered'],
                    'bounceRate' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_BOUNCE_RATE', 'Bounces'), 'type' => 'percentage', 'dotColor' => 'bg-event-bounced'],
                    'mobileRate' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_MOBILE_RATE', 'Mobile'), 'type' => 'percentage', 'dotColor' => 'bg-event-opened'],
                ];
            case self::CONTEXT_NEWSLETTER:
                return [
                    'lastSent' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_LAST_SENT', 'Last Sent'), 'type' => 'timeago'],
                    'sent' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_SENT', 'Sent'), 'type' => 'number', 'dotColor' => 'bg-event-sent'],
                    'openRate' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_OPEN_RATE', 'Open Rate'), 'type' => 'percentage', 'dotColor' => 'bg-event-opened'],
                    'clickRate' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_CLICK_RATE', 'Click Rate'), 'type' => 'percentage', 'dotColor' => 'bg-event-clicked'],
                    'revenue' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_REVENUE', 'Revenue'), 'type' => 'currency', 'dotColor' => 'bg-event-ordered'],
                    'bounceRate' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_BOUNCE_RATE', 'Bounces'), 'type' => 'percentage', 'dotColor' => 'bg-event-bounced'],
                    'mobileRate' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_MOBILE_RATE', 'Mobile'), 'type' => 'percentage', 'dotColor' => 'bg-event-opened'],
                ];
            case self::CONTEXT_AUTOMATION:
            case self::CONTEXT_TRIGGER:
            default:
                return [
                    'lastSent' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_LAST_SENT', 'Last Sent'), 'type' => 'timeago'],
                    'sent' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_SENT', 'Sent'), 'type' => 'number', 'dotColor' => 'bg-event-sent'],
                    'orders' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_ORDERS', 'Orders'), 'type' => 'number', 'dotColor' => 'bg-event-ordered'],
                    'revenue' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_REVENUE', 'Revenue'), 'type' => 'currency', 'dotColor' => 'bg-event-ordered'],
                    'openRate' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_OPEN_RATE', 'Open Rate'), 'type' => 'percentage', 'dotColor' => 'bg-event-opened'],
                    'clickRate' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_CLICK_RATE', 'Click Rate'), 'type' => 'percentage', 'dotColor' => 'bg-event-clicked'],
                    'bounceRate' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_BOUNCE_RATE', 'Bounces'), 'type' => 'percentage', 'dotColor' => 'bg-event-bounced'],
                    'mobileRate' => ['label' => mh_lng('MAILBEEZ_PERFORMANCE_MOBILE_RATE', 'Mobile'), 'type' => 'percentage', 'dotColor' => 'bg-event-opened'],
                ];
        }
    }

    /**
     * Get performance data for a module or newsletter item.
     *
     * @param string $modKey
     * @param int    $itemId
     * @param string $context
     * @return array
     */
    public static function getPerformanceData(string $modKey = '', int $itemId = 0, string $context = self::CONTEXT_TRIGGER, array $options = []): array
    {
        switch ($context) {
            case self::CONTEXT_AUDIENCE:
                $perfData = self::getAudienceData($modKey, $itemId, $options);
                break;
            case self::CONTEXT_NEWSLETTER:
                $perfData = self::getNewsletterData($modKey, $itemId, $options);
                break;
            case self::CONTEXT_AUTOMATION:
                $perfData = self::getAutomationData($modKey, $itemId, $options);
                break;
            case self::CONTEXT_TRIGGER_TYPE_REVIEW:
                $perfData = self::getTriggerTypeReviewData($modKey, $itemId, $options);
                break;
            case self::CONTEXT_TRIGGER:
            default:
                $perfData = self::getTriggerData($modKey, $itemId, $options);
                break;
        }

        if (isset($options['metrics_data']) && is_array($options['metrics_data'])) {
            $perfData = array_merge($perfData, $options['metrics_data']);
        }

        $definition = self::getMetricsDefinition($context);

        $metrics = [];
        foreach ($definition as $key => $config) {
            $value = $perfData[$key] ?? 0;
            $metrics[] = [
                'isFiller' => false,
                'label' => $config['label'],
                'value' => self::formatValue($value, $config['type']),
                'color' => $config['color'] ?? 'text-primary',
                'type' => $config['type'],
                'dotColor' => $config['dotColor'] ?? '',
            ];
        }

        return $metrics;
    }

    public static function getTriggerData(string $modKey, int $itemId, array $options = []): array
    {
        return DataRegistry::analytics()->getModulePerformanceData($modKey, $itemId);
    }

    public static function getTriggerTypeReviewData(string $modKey, int $itemId, array $options = []): array
    {
        return DataRegistry::analytics()->getModulePerformanceData($modKey, $itemId);
    }

    public static function getNewsletterData(string $modKey, int $itemId, array $options = []): array
    {
        return DataRegistry::analytics()->getModulePerformanceData($modKey, $itemId);
    }

    public static function getAutomationData(string $modKey, int $itemId, array $options = []): array
    {
        return DataRegistry::analytics()->getModulePerformanceData($modKey, $itemId);
    }

    public static function getAudienceData(string $modKey, int $itemId, array $options = []): array
    {
        return DataRegistry::analytics()->getAudiencePerformanceData($itemId);
    }

    public static function getEmptyMetrics(string $context = self::CONTEXT_TRIGGER): array
    {
        $definition = self::getMetricsDefinition($context);

        $metrics = [];
        foreach ($definition as $key => $config) {
            $metrics[] = [
                'isFiller' => false,
                'label' => $config['label'],
                'value' => self::formatValue(0, $config['type']),
                'color' => $config['color'] ?? 'text-primary',
                'type' => $config['type'],
                'dotColor' => $config['dotColor'] ?? '',
            ];
        }

        return $metrics;
    }

    /**
     * Format a metric value based on its type.
     *
     * @param mixed  $value
     * @param string $type
     * @return string
     */
    protected static function formatValue($value, string $type): string
    {
        switch ($type) {
            case 'currency':
                if (function_exists('mh_price')) {
                    return mh_price((float)$value);
                }
                return number_format((float)$value, 2) . ' EUR';
            case 'percentage':
                return number_format((float)$value, 1) . '%';
            case 'timeago':
                return $value ? (string)$value : '';
            case 'number':
            default:
                return (string)$value;
        }
    }

    /**
     * Render the Performance micro-dashboard.
     *
     * @param string $modKey
     * @param int    $itemId
     * @param array  $options
     * @return string
     */
    public static function render(string $modKey = '', int $itemId = 0, array $options = []): string
    {
        $context = $options['context'] ?? null;
        $item = null;
        if ($context === null) {
            if ($itemId > 0) {
                $item = \Components\Models\NewsletterItem::find($itemId);
                $context = $item ? $item->getPageMode() : self::CONTEXT_NEWSLETTER;
            } else {
                $context = self::CONTEXT_TRIGGER;
            }
        }

        $useCache = $options['use_cache'] ?? true;
        $refresh = $options['refresh'] ?? (mh_get('refresh') === '1');
        $lazy = $options['lazy'] ?? false;
        $format = $options['format'] ?? mh_get('format');

        $ownerType = FlowHtmlCache::OWNER_MODULE_PERFORMANCE;
        if ($context === self::CONTEXT_AUDIENCE) {
            $ownerType = FlowHtmlCache::OWNER_AUDIENCE_PERFORMANCE;
        } elseif ($itemId > 0 || $context === self::CONTEXT_NEWSLETTER || $context === self::CONTEXT_AUTOMATION) {
            $ownerType = FlowHtmlCache::OWNER_NEWSLETTER_ITEM_PERFORMANCE;
        }

        $ownerId = $itemId > 0 ? $itemId : $modKey;

        // If context is provided and not default, include it in ownerId to avoid cache collisions
        if ($context !== self::CONTEXT_TRIGGER) {
            $ownerId .= '_' . $context;
        }

        $lang = $_SESSION['language'] ?? 'default';

        $metrics = null;
        $triggerRefresh = false;

        if ($useCache && !$refresh) {
            $cached = FlowHtmlCache::get($ownerType, $ownerId, $lang);
            if (is_string($cached) && $cached !== '') {
                $metrics = json_decode($cached, true);
            }
        }

        if ($metrics === null) {
            if ($lazy && !$refresh) {
                $metrics = self::getEmptyMetrics($context);
                $triggerRefresh = true;
            } else {
                // Some legacy layers may emit HTML comments during computation; suppress incidental output
                ob_start();
                try {
                    $metrics = self::getPerformanceData($modKey, $itemId, $context, $options);
                } finally {
                    ob_end_clean();
                }

                if ($useCache) {
                    FlowHtmlCache::set($ownerType, $ownerId, $lang, json_encode($metrics));
                }
            }
        }

        $realCount = count($metrics);
        $xlCols = max(1, $realCount);
        $lgCols = min(4, $xlCols);
        $smCols = 2;

        $totalForLg = ceil($realCount / $lgCols) * $lgCols;
        $totalForSm = ceil($realCount / $smCols) * $smCols;
        $maxTotal = max($totalForLg, $totalForSm);

        for ($i = $realCount; $i < $maxTotal; $i++) {
            $showSm = ($i < $totalForSm);
            $showLg = ($i < $totalForLg);
/*
            $class = 'hidden';
            if ($showSm && $showLg) $class = 'hidden sm:flex xl:hidden';
            elseif ($showSm)        $class = 'hidden sm:flex lg:hidden';
            elseif ($showLg)        $class = 'hidden lg:flex xl:hidden';
*/
            $metrics[] = [
                'isFiller' => true,
                'label' => 'filler-' . $i,
                'value' => '',
                'color' => '',
                'type' => 'filler',
//                'fillerClass' => $class,
            ];
        }

        if ($format === 'json') {
            // Ensure no incidental output (e.g. legacy comments) pollutes the JSON response
            if (ob_get_level() > 0) {
                ob_clean();
            }
            return json_encode($metrics);
        }

        $refreshUrl = $options['refresh_url'] ?? '';
        if ($refreshUrl === '') {
            $params = ['partial' => 1, 'view_mode' => 'performance', 'refresh' => 1, 'format' => 'json'];
            if ($context !== self::CONTEXT_TRIGGER) {
                $params['context'] = $context;
            }

            if ($itemId > 0) {
                $params['id'] = $itemId;
                $routeName = ($context === self::CONTEXT_AUDIENCE) ? 'audience_list_flow' : 'newsletter_item_flow';
                $refreshUrl = Router::url($routeName, $params);
            } elseif ($modKey !== '') {
                $params['module'] = $modKey;
                $refreshUrl = Router::url('trigger_module', $params);
            }
        }


        $metricsJson = json_encode($metrics);
        $title = $options['title'] ?? '';

        $analyticsUrl = '';
        if (class_exists('Components\\Legacy\\LegacyRouter')) {
            /** @var \Components\Legacy\LegacyRouter $router */
            $router = 'Components\\Legacy\\LegacyRouter';
            if (in_array($context, [self::CONTEXT_TRIGGER, self::CONTEXT_TRIGGER_TYPE_REVIEW]) && $modKey !== '') {
                $analyticsUrl = $router::url('reportAnalyticsAdvanced', ['selected_module' => $modKey]);
            } elseif (in_array($context, [self::CONTEXT_NEWSLETTER, self::CONTEXT_AUTOMATION]) && $itemId > 0) {
                $item = $item ?? \Components\Models\NewsletterItem::find($itemId);
                if ($item) {
                    $analyticsUrl = $router::url('reportAnalyticsAdvanced', [
                        'selected_module' => 'mb_newsletter',
                        'selected_campaign' => $item->newsletter_campaign_id,
                        'selected_campaign_item' => $itemId,
                    ]);
                }
            }
        }

        ob_start();
        ?>
        <div class="relative group/perf" x-data="{
            metrics: <?= Base::h($metricsJson, false); ?>,
            refreshing: false,
            async refresh() {
                if (this.refreshing) return;
                this.refreshing = true;
                try {
                    const res = await fetch('<?= Base::h($refreshUrl); ?>');
                    this.metrics = await res.json();
                } catch (e) { console.error('Performance refresh failed', e); }
                this.refreshing = false;
            }
        }"
        <?php if ($triggerRefresh): ?>
            x-init="refresh()"
        <?php endif; ?>
        >
            <?php if ($refreshUrl): ?>
                <div class="absolute right-2 top-2 z-20 opacity-0 group-hover/perf:opacity-100 transition-opacity" x-show="!refreshing">
                    <button class="p-1 rounded-md text-secondary hover:bg-gray-200 dark:hover:bg-white/10 transition-colors"
                            @click.stop="refresh()"
                            title="<?= mh_lng('UI_REFRESH', 'Refresh'); ?>">
                        <?= Base::SVG_REFRESH; ?>
                    </button>
                </div>
                <div class="absolute right-2 top-2 z-20" x-show="refreshing" x-cloak>
                    <div class="p-1 text-secondary animate-spin">
                        <?= Base::SVG_SPINNER; ?>
                    </div>
                </div>
            <?php endif; ?>

            <?php if ($title): ?>
                <h3 class="text-base font-semibold text-primary mt-5 mb-5"><?= Base::h($title); ?></h3>
            <?php endif; ?>

            <dl class="grid grid-cols-1 gap-px overflow-hidden rounded-xl border border-divider/50 bg-divider/50 sm:grid-cols-2 lg:grid-cols-<?= $lgCols; ?> xl:grid-cols-<?= $xlCols; ?>">
                <template x-for="(metric, idx) in metrics" :key="metric.label || 'filler-' + idx">
                    <div class="contents">
                        <?php
                        $commonClass = 'p-4 bg-white dark:bg-zinc-800/50 flex flex-col text-left appearance-none w-full border-none transition-colors';
                        $cardAttrs = [
                            'class' => $commonClass,
                            ':class' => "metric.isFiller ? metric.fillerClass : '" . ($analyticsUrl ? 'cursor-pointer hover:bg-zinc-50 dark:hover:bg-zinc-800/80 group/card' : '') . "'",
                        ];
                        if ($analyticsUrl) {
                            $cardAttrs[':command'] = "!metric.isFiller ? 'show-modal' : null";
                            $cardAttrs[':commandfor'] = "!metric.isFiller ? 'config-modal' : null";
                            $cardAttrs[':data-title'] = "!metric.isFiller ? '" . addslashes(Base::lng('MAILBEEZ_BUTTON_ANALYTICS_LABEL', 'Analytics')) . "' : null";
                            $cardAttrs[':data-size'] = "!metric.isFiller ? (['" . self::CONTEXT_TRIGGER . "', '" . self::CONTEXT_TRIGGER_TYPE_REVIEW . "'].includes('" . $context . "') ? 'full' : 'full-margin') : null";
                            $cardAttrs[':data-url'] = "!metric.isFiller ? '" . $analyticsUrl . "' : null";
                            $cardAttrs['hx-target'] = '#config-modal-body';
                            $cardAttrs['hx-swap'] = 'innerHTML';
                        }
                        ?>
                        <?php if ($analyticsUrl): ?>
                        <button type="button" <?= Base::attrs($cardAttrs); ?> :disabled="metric.isFiller">
                        <?php else: ?>
                        <div <?= Base::attrs($cardAttrs); ?>>
                        <?php endif; ?>
                            <div class="contents" x-show="!metric.isFiller">
                                <dt class="text-xs text-secondary/70 uppercase font-medium mb-1 line-clamp-1 flex items-center" :title="metric.label">
                                    <template x-if="metric.dotColor">
                                        <span class="inline-block w-2 h-2 rounded-full mr-1.5" :class="metric.dotColor"></span>
                                    </template>
                                    <span x-text="metric.label"></span>
                                </dt>
                                <dd class="text-lg font-bold" :class="metric.color">
                                    <template x-if="metric.type === 'timeago'">
                                        <span>
                                            <template x-if="metric.value">
                                                <time :datetime="metric.value" x-data="{ date: new Date(metric.value) }" x-timeago="date" class="whitespace-nowrap"></time>
                                            </template>
                                            <template x-if="!metric.value">
                                                <span>-</span>
                                            </template>
                                        </span>
                                    </template>

                                    <template x-if="metric.type !== 'timeago'">
                                        <span x-text="metric.value"></span>
                                    </template>
                                </dd>
                            </div>
                            <div x-show="metric.isFiller">&nbsp;</div>
                        <?php if ($analyticsUrl): ?>
                        </button>
                        <?php else: ?>
                        </div>
                        <?php endif; ?>
                    </div>
                </template>
            </dl>
        </div>
        <?php
        return (string)ob_get_clean();
    }
}
