<?php
/**
 * 🏢 DASHBOARD UNIFIED CONTROLLER - V2.2 PURE
 *
 * Enterprise dashboard endpoint with:
 * - Unified data consolidation
 * - Intelligent caching with TTL
 * - Performance preset system
 * - Enterprise scalability
 *
 * @package FleekDash\Controllers
 * @since 2.2.0
 */

namespace FleekDash\Controllers;

use WP_REST_Request;
use WP_Error;
use FleekDash\Services\ResponseService;

/**
 * Class DashboardUnifiedController
 *
 * Pure V2.2 Controller - No legacy dependencies
 *
 * @package FleekDash\Controllers
 */
class DashboardUnifiedController
{
    /**
     * 🎯 PRESETS ENTERPRISE - Performance optimized
     */
    private const PRESETS = [
        '7d' => [
            'days' => 7,
            'period' => 'daily',
            'cache_ttl' => 300, // 5 minutes
            'priority' => 'high'
        ],
        '30d' => [
            'days' => 30,
            'period' => 'daily',
            'cache_ttl' => 900, // 15 minutes
            'priority' => 'high'
        ],
        '90d' => [
            'days' => 90,
            'period' => 'weekly',
            'cache_ttl' => 1800, // 30 minutes
            'priority' => 'medium'
        ],
        '1y' => [
            'days' => 365,
            'period' => 'monthly',
            'cache_ttl' => 3600, // 1 hour
            'priority' => 'low'
        ]
    ];

    /**
     * 🚀 Get unified dashboard data
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response|WP_Error
     */
    public function get_unified_dashboard_data(WP_REST_Request $request)
    {
        $start_time = microtime(true);

        // Rate limiting protection
        $request_id = $request->get_header('X-Request-ID') ?: uniqid('req_', true);
        $lock_key = "dashboard_unified_lock_{$request_id}";

        if (\get_transient($lock_key)) {
            return ResponseService::error(
                'Request already in progress, please wait',
                null,
                429
            );
        }

        \set_transient($lock_key, true, 30);

        try {
            $time_range = $request->get_param('time_range') ?: '30d';
            $force_refresh = $request->get_param('force_refresh');
            $start_date = $request->get_param('start_date');
            $end_date = $request->get_param('end_date');

            // Determine configuration based on range type
            if ($time_range === 'custom') {
                if (!$start_date || !$end_date) {
                    \delete_transient($lock_key);
                    return ResponseService::error(
                        'Custom time range requires start_date and end_date parameters',
                        null,
                        400
                    );
                }

                $days = (strtotime($end_date) - strtotime($start_date)) / (60 * 60 * 24);
                $preset_config = [
                    'days' => (int)$days,
                    'period' => $days <= 7 ? 'daily' : ($days <= 90 ? 'weekly' : 'monthly'),
                    'cache_ttl' => 300,
                    'priority' => 'medium',
                    'start_date' => $start_date,
                    'end_date' => $end_date
                ];
            } else {
                if (!isset(self::PRESETS[$time_range])) {
                    \delete_transient($lock_key);
                    return ResponseService::error(
                        'Invalid time range preset',
                        null,
                        400
                    );
                }
                $preset_config = self::PRESETS[$time_range];
            }

            // Check cache first
            $cache_key = $time_range === 'custom'
                ? "dashboard_unified_custom_{$start_date}_{$end_date}"
                : "dashboard_unified_{$time_range}";

            if (!$force_refresh) {
                $cached_data = $this->get_cached_data($cache_key);
                if ($cached_data) {
                    $cache_execution_time = microtime(true) - $start_time;

                    if (isset($cached_data['metadata'])) {
                        $cached_data['metadata']['execution_time'] = $cache_execution_time;
                        $cached_data['metadata']['from_cache'] = true;
                    }

                    \delete_transient($lock_key);
                    return ResponseService::success('Dashboard data retrieved from cache', $cached_data);
                }
            }

            // Collect unified data
            $dashboard_data = $this->collect_unified_data($time_range, $preset_config);

            // Cache the result
            $this->set_cached_data($cache_key, $dashboard_data, $preset_config['cache_ttl']);

            $execution_time = microtime(true) - $start_time;

            if (isset($dashboard_data['metadata'])) {
                $dashboard_data['metadata']['execution_time'] = $execution_time;
                $dashboard_data['metadata']['from_cache'] = false;
            }

            \delete_transient($lock_key);

            return ResponseService::success('Dashboard data retrieved', $dashboard_data);

        } catch (\Exception $e) {
            \delete_transient($lock_key);

            return ResponseService::error(
                'Failed to fetch dashboard data',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 🚀 Collect unified data
     *
     * @param string $time_range
     * @param array $preset_config
     * @return array
     */
    private function collect_unified_data($time_range, $preset_config)
    {
        $start_time = microtime(true);

        // Collect data from multiple sources
        $data_collectors = [
            'chart_data' => fn() => $this->get_chart_data($time_range, $preset_config),
            'published_content' => fn() => $this->get_published_content_kpi($time_range, $preset_config),
            'user_engagement' => fn() => $this->get_user_engagement_kpi($time_range, $preset_config),
            'user_registrations' => fn() => $this->get_user_registrations_kpi($time_range, $preset_config)
        ];

        $results = [];
        foreach ($data_collectors as $key => $collector) {
            try {
                $results[$key] = $collector();
            } catch (\Exception $e) {
                $results[$key] = $this->get_fallback_data($key);
            }
        }

        return [
            'time_range' => $time_range,
            'chart_data' => $results['chart_data']['data'] ?? [],
            'kpis' => [
                'published_content' => $results['published_content'],
                'user_engagement' => $results['user_engagement'],
                'user_registrations' => $results['user_registrations']
            ],
            'metadata' => [
                'period' => $preset_config['period'],
                'total_days' => $preset_config['days'],
                'cache_expires' => time() + $preset_config['cache_ttl'],
                'last_updated' => time(),
                'collection_time' => microtime(true) - $start_time
            ]
        ];
    }

    /**
     * 📊 Get chart data
     */
    private function get_chart_data($time_range, $preset_config = null)
    {
        try {
            global $wpdb;

            if ($preset_config && isset($preset_config['start_date'])) {
                $start_date = $preset_config['start_date'];
                $end_date = $preset_config['end_date'];
                $days = $preset_config['days'];
            } else {
                $days = self::PRESETS[$time_range]['days'];
                $start_date = date('Y-m-d', strtotime("-{$days} days"));
                $end_date = date('Y-m-d');
            }

            // Posts data - Use DATE() for proper date comparison
            // FIX: '2025-11-29 14:30:00' <= '2025-11-29' is FALSE because MySQL interprets as '2025-11-29 00:00:00'
            $posts_data = $wpdb->get_results($wpdb->prepare(
                "SELECT DATE(post_date) as date, COUNT(*) as count
                 FROM {$wpdb->posts}
                 WHERE post_status = 'publish'
                 AND DATE(post_date) >= %s
                 AND DATE(post_date) <= %s
                 GROUP BY DATE(post_date)
                 ORDER BY date ASC",
                $start_date,
                $end_date
            ));

            // Comments data - Use DATE() for proper date comparison
            $comments_data = $wpdb->get_results($wpdb->prepare(
                "SELECT DATE(comment_date) as date, COUNT(*) as count
                 FROM {$wpdb->comments}
                 WHERE comment_approved = '1'
                 AND DATE(comment_date) >= %s
                 AND DATE(comment_date) <= %s
                 GROUP BY DATE(comment_date)
                 ORDER BY date ASC",
                $start_date,
                $end_date
            ));

            // Users data - Use DATE() for proper date comparison
            $users_data = $wpdb->get_results($wpdb->prepare(
                "SELECT DATE(user_registered) as date, COUNT(*) as count
                 FROM {$wpdb->users}
                 WHERE DATE(user_registered) >= %s
                 AND DATE(user_registered) <= %s
                 GROUP BY DATE(user_registered)
                 ORDER BY date ASC",
                $start_date,
                $end_date
            ));

            // Build date array
            $data = [];
            $current_date = new \DateTime($start_date);
            $end_date_obj = new \DateTime($end_date);

            while ($current_date <= $end_date_obj) {
                $date_str = $current_date->format('Y-m-d');

                $posts_count = 0;
                $comments_count = 0;
                $users_count = 0;

                foreach ($posts_data as $post) {
                    if ($post->date === $date_str) {
                        $posts_count = (int)$post->count;
                        break;
                    }
                }

                foreach ($comments_data as $comment) {
                    if ($comment->date === $date_str) {
                        $comments_count = (int)$comment->count;
                        break;
                    }
                }

                foreach ($users_data as $user) {
                    if ($user->date === $date_str) {
                        $users_count = (int)$user->count;
                        break;
                    }
                }

                $data[] = [
                    'date' => $date_str,
                    'value' => $posts_count,
                    'current' => $users_count,
                    'previous' => $comments_count
                ];

                $current_date->add(new \DateInterval('P1D'));
            }

            return [
                'data' => $data,
                'source' => 'real_data'
            ];

        } catch (\Exception $e) {
            return ['data' => [], 'source' => 'fallback'];
        }
    }

    /**
     * 📈 Published content KPI
     */
    private function get_published_content_kpi($time_range, $preset_config = null)
    {
        try {
            global $wpdb;

            if ($preset_config && isset($preset_config['start_date'])) {
                $start_date = $preset_config['start_date'];
                $end_date = $preset_config['end_date'];
                $days = $preset_config['days'];
            } else {
                $days = self::PRESETS[$time_range]['days'];
                $start_date = date('Y-m-d', strtotime("-{$days} days"));
                $end_date = date('Y-m-d');
            }

            // FIX: Use DATE() for proper date comparison
            $current_posts = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->posts}
                 WHERE post_status = 'publish'
                 AND DATE(post_date) >= %s
                 AND DATE(post_date) <= %s",
                $start_date,
                $end_date
            ));

            $previous_start = date('Y-m-d', strtotime("-{$days} days", strtotime($start_date)));
            $previous_end = date('Y-m-d', strtotime("-1 day", strtotime($start_date)));

            $previous_posts = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->posts}
                 WHERE post_status = 'publish'
                 AND DATE(post_date) >= %s
                 AND DATE(post_date) <= %s",
                $previous_start,
                $previous_end
            ));

            $current = (int)$current_posts;
            $previous = (int)$previous_posts;
            $change_percent = $previous > 0 ? (($current - $previous) / $previous) * 100 : 0;

            return [
                'current' => $current,
                'previous' => $previous,
                'change_percent' => $change_percent,
                'trend' => $this->determine_trend($change_percent),
                'formatted_value' => number_format($current),
                'formatted_change' => $this->format_percentage($change_percent)
            ];

        } catch (\Exception $e) {
            return $this->get_fallback_kpi('published_content');
        }
    }

    /**
     * 👥 User engagement KPI
     */
    private function get_user_engagement_kpi($time_range, $preset_config = null)
    {
        try {
            global $wpdb;

            if ($preset_config && isset($preset_config['start_date'])) {
                $start_date = $preset_config['start_date'];
                $end_date = $preset_config['end_date'];
                $days = $preset_config['days'];
            } else {
                $days = self::PRESETS[$time_range]['days'];
                $start_date = date('Y-m-d', strtotime("-{$days} days"));
                $end_date = date('Y-m-d');
            }

            // FIX: Use DATE() for proper date comparison
            $current_comments = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->comments}
                 WHERE comment_approved = '1'
                 AND DATE(comment_date) >= %s
                 AND DATE(comment_date) <= %s",
                $start_date,
                $end_date
            ));

            $previous_start = date('Y-m-d', strtotime("-{$days} days", strtotime($start_date)));
            $previous_end = date('Y-m-d', strtotime("-1 day", strtotime($start_date)));

            $previous_comments = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->comments}
                 WHERE comment_approved = '1'
                 AND DATE(comment_date) >= %s
                 AND DATE(comment_date) <= %s",
                $previous_start,
                $previous_end
            ));

            $current = (int)$current_comments;
            $previous = (int)$previous_comments;
            $change_percent = $previous > 0 ? (($current - $previous) / $previous) * 100 : 0;

            return [
                'current' => $current,
                'previous' => $previous,
                'change_percent' => $change_percent,
                'trend' => $this->determine_trend($change_percent),
                'formatted_value' => number_format($current),
                'formatted_change' => $this->format_percentage($change_percent)
            ];

        } catch (\Exception $e) {
            return $this->get_fallback_kpi('user_engagement');
        }
    }

    /**
     * 🆕 User registrations KPI
     */
    private function get_user_registrations_kpi($time_range, $preset_config = null)
    {
        try {
            global $wpdb;

            if ($preset_config && isset($preset_config['start_date'])) {
                $start_date = $preset_config['start_date'];
                $end_date = $preset_config['end_date'];
                $days = $preset_config['days'];
            } else {
                $days = self::PRESETS[$time_range]['days'];
                $start_date = date('Y-m-d', strtotime("-{$days} days"));
                $end_date = date('Y-m-d');
            }

            $current_users = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->users}
                 WHERE user_registered >= %s
                 AND user_registered <= %s",
                $start_date,
                $end_date
            ));

            $previous_start = date('Y-m-d', strtotime("-{$days} days", strtotime($start_date)));
            $previous_end = date('Y-m-d', strtotime("-1 day", strtotime($start_date)));

            $previous_users = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->users}
                 WHERE user_registered >= %s
                 AND user_registered <= %s",
                $previous_start,
                $previous_end
            ));

            $current = (int)$current_users;
            $previous = (int)$previous_users;
            $change_percent = $previous > 0 ? (($current - $previous) / $previous) * 100 : 0;

            return [
                'current' => $current,
                'previous' => $previous,
                'change_percent' => $change_percent,
                'trend' => $this->determine_trend($change_percent),
                'formatted_value' => number_format($current),
                'formatted_change' => $this->format_percentage($change_percent)
            ];

        } catch (\Exception $e) {
            return $this->get_fallback_kpi('user_registrations');
        }
    }

    /**
     * 📊 Get performance metrics
     */
    public function get_performance_metrics(WP_REST_Request $request)
    {
        $metrics = [
            'cache_stats' => $this->get_cache_stats(),
            'api_performance' => $this->get_api_performance_stats(),
            'preset_stats' => $this->get_preset_stats()
        ];

        return ResponseService::success('Performance metrics retrieved', $metrics);
    }

    /**
     * 🎯 Manage cache
     */
    public function manage_cache(WP_REST_Request $request)
    {
        $action = $request->get_param('action');
        $preset = $request->get_param('preset');

        switch ($action) {
            case 'clear':
                $this->clear_all_cache();
                break;
            case 'invalidate':
                if ($preset) {
                    $this->invalidate_preset_cache($preset);
                } else {
                    $this->clear_all_cache();
                }
                break;
            case 'warm':
                if ($preset) {
                    $this->warm_preset_cache($preset);
                } else {
                    $this->warm_all_cache();
                }
                break;
        }

        return ResponseService::success("Cache {$action} completed");
    }

    /**
     * 🎯 Cache utilities
     */
    private function get_cached_data($cache_key)
    {
        $cached = wp_cache_get($cache_key, 'fleekdash_dashboard');

        if ($cached && isset($cached['expires']) && $cached['expires'] > time()) {
            return $cached['data'];
        }

        return null;
    }

    private function set_cached_data($cache_key, $data, $ttl)
    {
        wp_cache_set($cache_key, [
            'data' => $data,
            'expires' => time() + $ttl,
            'created' => time()
        ], 'fleekdash_dashboard', $ttl);
    }

    private function clear_all_cache()
    {
        wp_cache_flush_group('fleekdash_dashboard');
    }

    private function invalidate_preset_cache($preset)
    {
        $cache_key = "dashboard_unified_{$preset}";
        wp_cache_delete($cache_key, 'fleekdash_dashboard');
    }

    private function warm_preset_cache($preset)
    {
        // Pre-warm cache by simulating request
        $request = new WP_REST_Request('GET', '/fleekdash/v1/dashboard/unified');
        $request->set_param('time_range', $preset);
        $this->get_unified_dashboard_data($request);
    }

    private function warm_all_cache()
    {
        foreach (array_keys(self::PRESETS) as $preset) {
            $this->warm_preset_cache($preset);
        }
    }

    /**
     * 📊 Stats utilities
     */
    private function get_cache_stats()
    {
        return [
            'hit_rate' => 0,
            'miss_rate' => 0,
            'total_requests' => 0
        ];
    }

    private function get_api_performance_stats()
    {
        return [
            'avg_response_time' => 0,
            'total_requests' => 0,
            'error_rate' => 0
        ];
    }

    private function get_preset_stats()
    {
        $stats = [];
        foreach (array_keys(self::PRESETS) as $preset) {
            $stats[$preset] = [
                'cache_status' => 'unknown',
                'last_updated' => 0,
                'hit_count' => 0
            ];
        }
        return $stats;
    }

    /**
     * 🎯 Fallback data
     */
    private function get_fallback_data($data_type)
    {
        $fallbacks = [
            'chart_data' => ['data' => [], 'source' => 'fallback'],
            'published_content' => $this->get_fallback_kpi('published_content'),
            'user_engagement' => $this->get_fallback_kpi('user_engagement'),
            'user_registrations' => $this->get_fallback_kpi('user_registrations')
        ];

        return $fallbacks[$data_type] ?? null;
    }

    private function get_fallback_kpi($kpi_type)
    {
        return [
            'current' => 0,
            'previous' => 0,
            'change_percent' => 0,
            'trend' => 'stable',
            'formatted_value' => '0',
            'formatted_change' => '0%'
        ];
    }

    /**
     * 🔧 Utilities
     */
    private function determine_trend($percentage)
    {
        if ($percentage > 5) return 'up';
        if ($percentage < -5) return 'down';
        return 'stable';
    }

    private function format_percentage($percentage)
    {
        $sign = $percentage >= 0 ? '+' : '';
        return $sign . number_format($percentage, 1) . '%';
    }
}
