<?php

declare(strict_types=1);

namespace App\Application\LiveComponents\MetricsDashboard;

use App\Application\LiveComponents\Services\MetricsDataProvider;
use App\Application\LiveComponents\ValueObjects\TimeRange;
use App\Framework\LiveComponents\Attributes\LiveComponent;
use App\Framework\LiveComponents\Contracts\LiveComponentContract;
use App\Framework\LiveComponents\DataProviderResolver;
use App\Framework\LiveComponents\ValueObjects\ComponentId;
use App\Framework\LiveComponents\ValueObjects\ComponentRenderData;

/**
 * MetricsDashboardComponent - Real-time business metrics dashboard
 *
 * Demonstrates:
 * - Type-safe state management with MetricsDashboardState Value Object
 * - Multiple metric cards with trends and goals
 * - Time range selection and comparison
 * - Auto-refresh capability
 * - Percentage changes and trend indicators
 * - Goal progress tracking
 * - Compile-time type safety for data access
 *
 * Uses MetricsDataProvider for flexible data sources (Demo, Database, API, etc.)
 */
#[LiveComponent('metrics-dashboard')]
final readonly class MetricsDashboardComponent implements LiveComponentContract
{
    public function __construct(
        public ComponentId $id,
        public MetricsDashboardState $state,
        private readonly DataProviderResolver $dataProviderResolver
    ) {}

    private function getDataProvider(): MetricsDataProvider
    {
        $resolvedProvider = $this->dataProviderResolver->resolve(
            MetricsDataProvider::class,
            $this->state->dataSource
        );

        if ($resolvedProvider === null) {
            throw new \RuntimeException(
                "No MetricsDataProvider found for data source: {$this->state->dataSource}"
            );
        }

        return $resolvedProvider;
    }

    public function getRenderData(): ComponentRenderData
    {
        $dataProvider = $this->getDataProvider();

        // Always load metrics from data provider for rendering
        // (State may have empty metrics array on initial load)
        $timeRangeEnum = TimeRange::fromString($this->state->timeRange);
        $metricsData = $dataProvider->getMetricsForTimeRange($timeRangeEnum);
        $metrics = $this->metricsToArray($metricsData);

        // Update state with loaded metrics
        $updatedState = new MetricsDashboardState(
            metrics: $metrics,
            timeRange: $this->state->timeRange,
            lastUpdated: $this->state->lastUpdated === 0 ? time() : $this->state->lastUpdated,
            autoRefresh: $this->state->autoRefresh,
            refreshInterval: $this->state->refreshInterval,
            dataSource: $this->state->dataSource
        );

        $metricsSummary = $updatedState->getMetricsSummary();
        $hasMetrics = $updatedState->hasMetrics();

        return new ComponentRenderData(
            templatePath: 'livecomponent-metrics-dashboard',
            data: [
                // Raw data
                'metrics' => $metrics,
                'time_range' => $this->state->timeRange,
                'last_updated' => $this->state->lastUpdated,
                'auto_refresh' => $this->state->autoRefresh,
                'refresh_interval' => $this->state->refreshInterval,

                // Display-specific properties (use updatedState with loaded metrics)
                'prepared_metrics' => $updatedState->getPreparedMetrics(),
                'has_metrics' => $hasMetrics,
                'is_empty' => ! $hasMetrics,
                'time_range_label' => $updatedState->getTimeRangeLabel(),
                'time_range_options' => $updatedState->getTimeRangeOptions(),

                // Last updated - both absolute and relative
                'last_updated_formatted' => $updatedState->getFormattedLastUpdated(),
                'last_updated_label' => $updatedState->lastUpdated > 0 ? date('d.m.Y H:i:s', $updatedState->lastUpdated) : 'Noch nicht aktualisiert',
                'last_updated_relative' => $updatedState->getFormattedLastUpdated(),

                // Auto-refresh controls
                'auto_refresh_enabled' => $updatedState->autoRefresh,
                'auto_refresh_text' => $updatedState->getAutoRefreshText(),
                'auto_refresh_label' => $updatedState->getAutoRefreshButtonText(),
                'auto_refresh_button_text' => $updatedState->getAutoRefreshButtonText(),
                'auto_refresh_button_class' => $updatedState->autoRefresh ? 'active' : '',
                'refresh_interval_seconds' => $updatedState->refreshInterval,

                // Metrics summary
                'total_metrics' => $metricsSummary['total'],
                'positive_metrics' => $metricsSummary['positive'],
                'negative_metrics' => $metricsSummary['negative'],
                'neutral_metrics' => $metricsSummary['stable'],
            ]
        );
    }

    // Action methods - Type-safe parameters

    public function setTimeRange(string $timeRange): MetricsDashboardState
    {
        $dataProvider = $this->getDataProvider();
        $timeRangeEnum = TimeRange::fromString($timeRange);
        $metricsData = $dataProvider->getMetricsForTimeRange($timeRangeEnum);
        $metrics = $this->metricsToArray($metricsData);

        return $this->state->withTimeRange($timeRange, $metrics);
    }

    public function refreshMetrics(): MetricsDashboardState
    {
        $dataProvider = $this->getDataProvider();
        $timeRangeEnum = TimeRange::fromString($this->state->timeRange);
        $metricsData = $dataProvider->getMetricsForTimeRange($timeRangeEnum);
        $metrics = $this->metricsToArray($metricsData);

        return $this->state->withRefreshedMetrics($metrics);
    }

    public function toggleAutoRefresh(): MetricsDashboardState
    {
        return $this->state->withToggledAutoRefresh();
    }

    // Helper methods

    private function metricsToArray(array $metricsData): array
    {
        return array_map(function ($metric) {
            return [
                'key' => $metric->getKey(),
                'label' => $metric->getLabel(),
                'value' => $metric->getValue(),
                'type' => $metric->getType(),
                'change_percentage' => $metric->getChangePercentage(),
                'goal' => $metric->getGoal(),
                'color' => $metric->getColor(),
                'icon' => $metric->getIcon(),
            ];
        }, $metricsData);
    }
}
