<?php
/**
 * Base Controller for API endpoints
 * Provides common functionality for all API controllers
 */

namespace FleekDash\API;

// Load debug helpers
if (!function_exists('fleekdash_log_debug')) {
    require_once FLEEKDASH_PLUGIN_DIR . 'includes/Core/debug-helpers.php';
}

if (class_exists('\WP_REST_Controller')) {
abstract class BaseController extends \WP_REST_Controller
{
    /**
     * Namespace
     */
    protected $namespace = 'fleekdash/v1';

    /**
     * Check permissions with graceful fallback
     */
    public function get_items_permissions_check($request)
    {
        unset($request);
        // Security-first default: deny when auth cannot be validated.
        $is_allowed = false;

        try {
            if (class_exists('\FleekDash\Core\AuthMiddleware')) {
                $auth_check = \FleekDash\Core\AuthMiddleware::check('authenticated');
                $is_allowed = !empty($auth_check['authenticated']);

                if (!$is_allowed) {
                    // Debug-only: unauthenticated request
                    fleekdash_log_debug("FleekDash API: Access without auth - Reason: " . $auth_check['reason']);
                }
            } else {
                fleekdash_log_error('FleekDash API: AuthMiddleware class not available for permission check');
            }
        } catch (\Exception $e) {
            // Deny when auth validation fails unexpectedly.
            fleekdash_log_error("FleekDash API: AuthMiddleware error: " . $e->getMessage());
            $is_allowed = false;
        }

        return $is_allowed;
    }

    /**
     * Get date range and days from parameters
     * Supports both time_range (7d, 30d, etc.) and specific dates (start_date/end_date)
     */
    protected function get_date_range_info(\WP_REST_Request $request): array
    {
        $start_date = $request->get_param('start_date');
        $end_date = $request->get_param('end_date');
        $time_range = $request->get_param('time_range');

        // If specific dates are provided, use them
        if ($start_date && $end_date) {
            $start = new \DateTime($start_date);
            $end = new \DateTime($end_date);
            $interval = $start->diff($end);
            $days = $interval->days + 1; // +1 to include both start and end dates

            return [
                'days' => $days,
                'start_date' => $start_date,
                'end_date' => $end_date,
                'time_range' => 'custom'
            ];
        }

        // Fallback to time_range parameter
        $days = $this->get_days_from_range($time_range ?: '30d');

        return [
            'days' => $days,
            'start_date' => null,
            'end_date' => null,
            'time_range' => $time_range ?: '30d'
        ];
    }

    /**
     * Get days from time range
     */
    protected function get_days_from_range(string $time_range): int
    {
        $days_map = [
            '7d' => 7,
            '30d' => 30,
            '90d' => 90,
            '1y' => 365,
        ];

        return $days_map[$time_range] ?? 30;
    }

    /**
     * Get comparison dates based on comparison type
     */
    protected function get_comparison_dates(array $range_info, string $comparison_type): array
    {
        $days = $range_info['days'];
        $start_date = $range_info['start_date'];
        $end_date = $range_info['end_date'];

        if ($start_date && $end_date) {
            // Use specific dates
            $current_start = new \DateTime($start_date);
            $current_end = new \DateTime($end_date);
        } else {
            // Use relative dates
            $current_end = new \DateTime();
            $current_start = (new \DateTime())->modify("-{$days} days");
        }

        switch ($comparison_type) {
            case 'previous_year':
                $comparison_start = clone $current_start;
                $comparison_start->modify('-1 year');
                $comparison_end = clone $current_end;
                $comparison_end->modify('-1 year');
                break;

            case 'previous_month':
                $comparison_start = clone $current_start;
                $comparison_start->modify('-1 month');
                $comparison_end = clone $current_end;
                $comparison_end->modify('-1 month');
                break;
            default:
                $interval = $current_start->diff($current_end);
                $comparison_end = clone $current_start;
                $comparison_start = clone $comparison_end;
                $comparison_start->modify("-{$interval->days} days");
                break;
        }

        $comparison_interval = $comparison_start->diff($comparison_end);

        return [
            'days' => $comparison_interval->days + 1,
            'start_date' => $comparison_start->format('Y-m-d'),
            'end_date' => $comparison_end->format('Y-m-d')
        ];
    }

    /**
     * Generate time series data
     */
    protected function generate_time_series_data(int $days, array $fields, ?string $start_date = null, ?string $end_date = null): array
    {
        $dates = [];
        $data = [];
        if ($start_date !== null && $end_date !== null) {
            $dates = $this->generateDateSeries($start_date, $end_date);
        } else {
            $dates = $this->generateRelativeDateSeries($days);
        }

        foreach ($dates as $date) {
            $data[] = $this->buildSeriesItem($date, $fields);
        }

        return $data;
    }

    /**
     * @return string[]
     */
    private function generateDateSeries(string $startDate, string $endDate): array
    {
        $dates = [];
        $start = new \DateTime($startDate);
        $end = new \DateTime($endDate);
        $current = clone $start;

        while ($current <= $end) {
            $dates[] = $current->format('Y-m-d');
            $current->add(new \DateInterval('P1D'));
        }

        return $dates;
    }

    /**
     * @return string[]
     */
    private function generateRelativeDateSeries(int $days): array
    {
        $dates = [];
        for ($i = 0; $i < $days; $i++) {
            $dates[] = date('Y-m-d', strtotime('-' . ($days - $i - 1) . ' days'));
        }

        return $dates;
    }

    /**
     * @param array<string, mixed> $fields
     * @return array<string, mixed>
     */
    private function buildSeriesItem(string $date, array $fields): array
    {
        $item = ['date' => $date];
        foreach ($fields as $field => $range) {
            if (!is_array($range) || count($range) < 2) {
                continue;
            }

            $item[$field] = is_float($range[0])
                ? round(rand($range[0] * 100, $range[1] * 100) / 100, 2)
                : rand($range[0], $range[1]);
        }

        return $item;
    }

    /**
     * Generate simple trend data
     */
    protected function generate_simple_trend(int $days): array
    {
        $trend = [];
        for ($i = 0; $i < $days; $i++) {
            $trend[] = [
                'date' => date('Y-m-d', strtotime('-' . ($days - $i - 1) . ' days')),
                'value' => rand(800, 1200),
            ];
        }
        return $trend;
    }

    /**
     * Generate breakdown data
     */
    protected function generate_breakdown(int $count): array
    {
        $categories = ['Technology', 'Business', 'Design', 'Marketing', 'Education', 'Health', 'Sports', 'Entertainment'];
        $breakdown = [];
        for ($i = 0; $i < $count; $i++) {
            $breakdown[] = [
                'category' => $categories[$i % count($categories)],
                'value' => rand(100, 5000),
                'percentage' => round(rand(5, 30) + rand(0, 99) / 100, 2),
            ];
        }
        return $breakdown;
    }

    /**
     * Generate top goals data
     */
    protected function generate_top_goals(int $count): array
    {
        $goals = [];
        for ($i = 0; $i < $count; $i++) {
            $target = rand(100, 1000);
            $current = rand(50, $target);
            $goals[] = [
                'id' => rand(1, 100),
                'name' => 'Goal ' . chr(65 + $i),
                'target' => $target,
                'current' => $current,
                'completion_rate' => round(($current / $target) * 100, 2),
                'growth_rate' => round(rand(-20, 50) + rand(0, 99) / 100, 2),
            ];
        }
        return $goals;
    }

    /**
     * Generate leaderboard data
     */
    protected function generate_leaderboard(int $count): array
    {
        $leaderboard = [];
        for ($i = 0; $i < $count; $i++) {
            $leaderboard[] = [
                'id' => rand(1, 100),
                'name' => $this->get_random_name(),
                'score' => rand(100, 1000),
                'events' => rand(50, 500),
                'goals_completed' => rand(5, 25),
                'rank' => $i + 1,
            ];
        }
        return $leaderboard;
    }

    /**
     * Get random title
     */
    protected function get_random_title()
    {
        $titles = [
            'Getting Started with React',
            'Advanced TypeScript Patterns',
            'Modern JavaScript Features',
            'Web Development Best Practices',
            'CSS Grid Layout Guide',
            'Node.js Performance Tips',
            'Vue.js Component Design',
            'Angular State Management',
            'Python Web Development',
            'Database Design Principles',
        ];
        return $titles[array_rand($titles)];
    }

    /**
     * Get random name
     */
    protected function get_random_name()
    {
        $names = [
            'John Doe',
            'Jane Smith',
            'Mike Johnson',
            'Sarah Wilson',
            'David Brown',
            'Lisa Davis',
            'Tom Miller',
            'Emma Garcia',
            'Chris Rodriguez',
            'Anna Martinez'
        ];
        return $names[array_rand($names)];
    }

    /**
     * Get random email
     */
    protected function get_random_email()
    {
        $domains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com', 'company.com'];
        $user = strtolower(str_replace(' ', '.', $this->get_random_name()));
        return $user . '@' . $domains[array_rand($domains)];
    }

    /**
     * Get random status
     */
    protected function get_random_status()
    {
        $statuses = ['publish', 'draft', 'pending', 'private'];
        return $statuses[array_rand($statuses)];
    }

    /**
     * Get random role
     */
    protected function get_random_role()
    {
        $roles = ['subscriber', 'author', 'editor', 'administrator'];
        return $roles[array_rand($roles)];
    }

    /**
     * Get random slug
     */
    protected function get_random_slug()
    {
        return \sanitize_title($this->get_random_title());
    }
}
}
