<?php
/**
 * Route Manager
 *
 * Manages integration routes with caching and validation.
 * Performance-optimized with query caching.
 *
 * @package FleekDash\Integration
 * @since 2.3.0
 */

namespace FleekDash\Integration;

defined('ABSPATH') || exit;

class RouteManager
{
    /**
     * Cache key for routes
     */
    const CACHE_KEY = 'fleekdash_integration_routes';

    /**
     * Cache expiration (30 minutes)
     */
    const CACHE_EXPIRATION = 1800;

    /**
     * Get all routes
     *
     * With caching for performance (prevents repeated DB queries).
     *
     * @param bool $active_only Only active routes
     * @param bool $use_cache Use cached data
     * @return array List of routes
     */
    public static function getAll(bool $active_only = true, bool $use_cache = true): array
    {
        // Try cache first
        if ($use_cache) {
            $cache_key = self::CACHE_KEY . ($active_only ? '_active' : '_all');
            $cached = wp_cache_get($cache_key, 'fleekdash_integration');

            if ($cached !== false) {
                return $cached;
            }
        }

        global $wpdb;

        $table = $wpdb->prefix . 'fleekdash_integration_routes';

        $sql = "SELECT r.*, reg.name as integration_name, reg.integration_type
                FROM `{$table}` r
                LEFT JOIN `{$wpdb->prefix}fleekdash_integration_registry` reg
                    ON r.integration_id = reg.integration_id";

        if ($active_only) {
            $sql .= " WHERE r.is_active = 1 AND reg.is_active = 1";
        }

        $sql .= " ORDER BY r.menu_order ASC, r.route_title ASC";

        $results = $wpdb->get_results($sql, ARRAY_A);

        // Decode JSON fields
        foreach ($results as &$route) {
            $route['permissions'] = isset($route['permissions'])
                ? json_decode($route['permissions'], true)
                : ['authenticated'];

            $route['capabilities'] = isset($route['capabilities'])
                ? json_decode($route['capabilities'], true)
                : [];

            if (!empty($route['menu_badge'])) {
                $route['menu_badge'] = json_decode($route['menu_badge'], true);
            }
        }

        // Cache results
        if ($use_cache) {
            $cache_key = self::CACHE_KEY . ($active_only ? '_active' : '_all');
            wp_cache_set($cache_key, $results, 'fleekdash_integration', self::CACHE_EXPIRATION);
        }

        return $results;
    }

    /**
     * Get routes for specific integration
     *
     * @param string $integration_id Integration ID
     * @return array Routes
     */
    public static function getByIntegration(string $integration_id): array
    {
        global $wpdb;

        $integration_id = \sanitize_text_field($integration_id);
        $table = $wpdb->prefix . 'fleekdash_integration_routes';

        $results = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM `{$table}` WHERE `integration_id` = %s ORDER BY `menu_order` ASC",
                $integration_id
            ),
            ARRAY_A
        );

        // Decode JSON fields
        foreach ($results as &$route) {
            $route['permissions'] = isset($route['permissions'])
                ? json_decode($route['permissions'], true)
                : ['authenticated'];
        }

        return $results;
    }

    /**
     * Validate route path
     *
     * Called by frontend to validate if route exists and user has permission.
     *
     * @param string $path Route path (e.g., "standalone-example/dashboard")
     * @return array Validation result
     */
    public static function validateRoute(string $path): array
    {
        global $wpdb;

        // Clean path
        $path = trim($path, '/');

        if (empty($path)) {
            return [
                'success' => false,
                'error' => 'Empty route path',
            ];
        }

        $table = $wpdb->prefix . 'fleekdash_integration_routes';

        // Query route by full path (route_path stored as "integration-id/page")
        $route = $wpdb->get_row(
            $wpdb->prepare(
                "SELECT r.*, reg.integration_type, reg.name as integration_name
                 FROM `{$table}` r
                 LEFT JOIN `{$wpdb->prefix}fleekdash_integration_registry` reg
                     ON r.integration_id = reg.integration_id
                 WHERE r.route_path = %s
                 AND r.is_active = 1
                 AND reg.is_active = 1",
                $path
            ),
            ARRAY_A
        );

        if (!$route) {
            return [
                'success' => false,
                'error' => 'Route not found or inactive',
            ];
        }

        // Check permissions
        $permissions = json_decode($route['permissions'] ?? '[]', true);
        $has_permission = self::checkPermissions($permissions);

        if (!$has_permission) {
            return [
                'success' => false,
                'error' => 'Permission denied',
                'required_permissions' => $permissions,
            ];
        }

        // Get sandbox config
        $sandbox_config = SandboxManager::getSandboxConfig(
            $route['integration_type'],
            $route['sandbox_mode'] ?? null
        );

        return [
            'success' => true,
            'route' => [
                'integration_id' => $route['integration_id'],
                'integration_name' => $route['integration_name'],
                'integration_type' => $route['integration_type'],
                'route_path' => $route['route_path'],
                'route_title' => $route['route_title'],
                'component_url' => $route['component_url'],
                'icon' => $route['icon'],
                'sandbox_config' => $sandbox_config,
            ],
        ];
    }

    /**
     * Check if user has required permissions
     *
     * @param array $required_permissions Required permissions
     * @return bool True if user has permission
     */
    private static function checkPermissions(array $required_permissions): bool
    {
        // Empty permissions = public
        if (empty($required_permissions)) {
            return true;
        }

        foreach ($required_permissions as $permission) {
            switch ($permission) {
                case 'public':
                    return true;

                case 'authenticated':
                    if (!\is_user_logged_in()) {
                        return false;
                    }
                    break;

                case 'admin':
                    if (!\current_user_can('manage_options')) {
                        return false;
                    }
                    break;

                default:
                    // Custom capability
                    if (!\current_user_can($permission)) {
                        return false;
                    }
            }
        }

        return true;
    }

    /**
     * Clear route cache
     *
     * Called after route changes.
     *
     * @return void
     */
    public static function clearCache(): void
    {
        wp_cache_delete(self::CACHE_KEY . '_active', 'fleekdash_integration');
        wp_cache_delete(self::CACHE_KEY . '_all', 'fleekdash_integration');
    }

    /**
     * Get routes grouped by integration
     *
     * Useful for menu rendering.
     *
     * @return array Routes grouped by integration
     */
    public static function getGroupedByIntegration(): array
    {
        $routes = self::getAll(true, true);
        $grouped = [];

        foreach ($routes as $route) {
            $integration_id = $route['integration_id'];

            if (!isset($grouped[$integration_id])) {
                $grouped[$integration_id] = [
                    'integration_id' => $integration_id,
                    'integration_name' => $route['integration_name'],
                    'integration_type' => $route['integration_type'],
                    'routes' => [],
                ];
            }

            $grouped[$integration_id]['routes'][] = $route;
        }

        return $grouped;
    }
}
